# Source code
source: package: co.aikar.commands, class: ACFUtil

    001/*
    002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    003 *
    004 *  Permission is hereby granted, free of charge, to any person obtaining
    005 *  a copy of this software and associated documentation files (the
    006 *  "Software"), to deal in the Software without restriction, including
    007 *  without limitation the rights to use, copy, modify, merge, publish,
    008 *  distribute, sublicense, and/or sell copies of the Software, and to
    009 *  permit persons to whom the Software is furnished to do so, subject to
    010 *  the following conditions:
    011 *
    012 *  The above copyright notice and this permission notice shall be
    013 *  included in all copies or substantial portions of the Software.
    014 *
    015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    022 */
    023
    024package co.aikar.commands;
    025
    026
    027import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    028import org.jetbrains.annotations.Nullable;
    029
    030import java.math.BigDecimal;
    031import java.text.Normalizer;
    032import java.text.Normalizer.Form;
    033import java.text.NumberFormat;
    034import java.util.ArrayList;
    035import java.util.Collection;
    036import java.util.Iterator;
    037import java.util.List;
    038import java.util.Locale;
    039import java.util.Random;
    040import java.util.function.Consumer;
    041import java.util.regex.Matcher;
    042import java.util.regex.Pattern;
    043import java.util.stream.Collectors;
    044import java.util.stream.Stream;
    045
    046@SuppressWarnings({"WeakerAccess", "unused"})
    047public final class ACFUtil {
    048
    049    public static final Random RANDOM = new Random();
    050
    051    private ACFUtil() {
    052    }
    053
    054    public static String padRight(String s, int n) {
    055        return String.format("%1$-" + n + "s", s);
    056    }
    057
    058    public static String padLeft(String s, int n) {
    059        return String.format("%1$" + n + "s", s);
    060    }
    061
    062    public static String formatNumber(Integer balance) {
    063        return NumberFormat.getInstance().format(balance);
    064    }
    065
    066    public static <T extends Enum> T getEnumFromName(T[] types, String name) {
    067        return getEnumFromName(types, name, null);
    068    }
    069
    070    public static <T extends Enum> T getEnumFromName(T[] types, String name, T def) {
    071        for (T type : types) {
    072            if (type.name().equalsIgnoreCase(name)) {
    073                return type;
    074            }
    075        }
    076        return def;
    077    }
    078
    079    public static <T extends Enum> T getEnumFromOrdinal(T[] types, int ordinal) {
    080        for (T type : types) {
    081            if (type.ordinal() == ordinal) {
    082                return type;
    083            }
    084        }
    085        return null;
    086    }
    087
    088    public static String ucfirst(String str) {
    089        return ApacheCommonsLangUtil.capitalizeFully(str);
    090    }
    091
    092    public static Double parseDouble(String var) {
    093        return parseDouble(var, null);
    094    }
    095
    096    public static Double parseDouble(String var, Double def) {
    097        if (var == null) {
    098            return def;
    099        }
    100        try {
    101            return Double.parseDouble(var);
    102        } catch (NumberFormatException ignored) {
    103        }
    104        return def;
    105    }
    106
    107    public static Float parseFloat(String var) {
    108        return parseFloat(var, null);
    109    }
    110
    111    public static Float parseFloat(String var, Float def) {
    112        if (var == null) {
    113            return def;
    114        }
    115        try {
    116            return Float.parseFloat(var);
    117        } catch (NumberFormatException ignored) {
    118        }
    119        return def;
    120    }
    121
    122    public static Long parseLong(String var) {
    123        return parseLong(var, null);
    124    }
    125
    126    public static Long parseLong(String var, Long def) {
    127        if (var == null) {
    128            return def;
    129        }
    130        try {
    131            return Long.parseLong(var);
    132        } catch (NumberFormatException ignored) {
    133        }
    134        return def;
    135    }
    136
    137    public static Integer parseInt(String var) {
    138        return parseInt(var, null);
    139    }
    140
    141    public static Integer parseInt(String var, Integer def) {
    142        if (var == null) {
    143            return def;
    144        }
    145        try {
    146            return Integer.parseInt(var);
    147        } catch (NumberFormatException ignored) {
    148        }
    149        return def;
    150    }
    151
    152    public static boolean randBool() {
    153        return RANDOM.nextBoolean();
    154    }
    155
    156    public static <T> T nullDefault(Object val, Object def) {
    157        //noinspection unchecked
    158        return (T) (val != null ? val : def);
    159    }
    160
    161    public static String join(Collection<String> args) {
    162        return ApacheCommonsLangUtil.join(args, " ");
    163    }
    164
    165    public static String join(Collection<String> args, String sep) {
    166        return ApacheCommonsLangUtil.join(args, sep);
    167    }
    168
    169    public static String join(String[] args) {
    170        return join(args, 0, ' ');
    171    }
    172
    173    public static String join(String[] args, String sep) {
    174        return ApacheCommonsLangUtil.join(args, sep);
    175    }
    176
    177    public static String join(String[] args, char sep) {
    178        return join(args, 0, sep);
    179    }
    180
    181    public static String join(String[] args, int index) {
    182        return join(args, index, ' ');
    183    }
    184
    185    public static String join(String[] args, int index, char sep) {
    186        return ApacheCommonsLangUtil.join(args, sep, index, args.length);
    187    }
    188
    189    public static String simplifyString(String str) {
    190        if (str == null) {
    191            return null;
    192        }
    193        return ACFPatterns.NON_ALPHA_NUMERIC.matcher(str.toLowerCase(Locale.ENGLISH)).replaceAll("");
    194    }
    195
    196    public static double round(double x, int scale) {
    197        try {
    198            return (new BigDecimal
    199                    (Double.toString(x))
    200                    .setScale(scale, BigDecimal.ROUND_HALF_UP))
    201                    .doubleValue();
    202        } catch (NumberFormatException ex) {
    203            if (Double.isInfinite(x)) {
    204                return x;
    205            } else {
    206                return Double.NaN;
    207            }
    208        }
    209    }
    210
    211    public static int roundUp(int num, int multiple) {
    212        if (multiple == 0) {
    213            return num;
    214        }
    215
    216        int remainder = num % multiple;
    217        if (remainder == 0) {
    218            return num;
    219        }
    220        return num + multiple - remainder;
    221
    222    }
    223
    224    public static String limit(String str, int limit) {
    225        return str.length() > limit ? str.substring(0, limit) : str;
    226    }
    227
    228    /**
    229     * Plain string replacement, escapes replace value.
    230     *
    231     * @param string
    232     * @param pattern
    233     * @param repl
    234     * @return
    235     */
    236    public static String replace(String string, Pattern pattern, String repl) {
    237        return pattern.matcher(string).replaceAll(Matcher.quoteReplacement(repl));
    238    }
    239
    240    /**
    241     * Regex version of {@link #replace(String, Pattern, String)}
    242     *
    243     * @param string
    244     * @param pattern
    245     * @param repl
    246     * @return
    247     */
    248    public static String replacePattern(String string, Pattern pattern, String repl) {
    249        return pattern.matcher(string).replaceAll(repl);
    250    }
    251
    252    /**
    253     * Plain String replacement. If you need regex patterns, see {@link #replacePattern(String, String, String)}
    254     *
    255     * @param string
    256     * @param pattern
    257     * @param repl
    258     * @return
    259     */
    260    public static String replace(String string, String pattern, String repl) {
    261        return replace(string, ACFPatterns.getPattern(Pattern.quote(pattern)), repl);
    262    }
    263
    264    /**
    265     * Regex version of {@link #replace(String, String, String)}
    266     *
    267     * @param string
    268     * @param pattern
    269     * @param repl
    270     * @return
    271     */
    272    public static String replacePattern(String string, String pattern, String repl) {
    273        return replace(string, ACFPatterns.getPattern(pattern), repl);
    274    }
    275
    276    /**
    277     * Pure Regex Pattern matching and replacement, no escaping
    278     *
    279     * @param string
    280     * @param pattern
    281     * @param repl
    282     * @return
    283     */
    284    public static String replacePatternMatch(String string, Pattern pattern, String repl) {
    285        return pattern.matcher(string).replaceAll(repl);
    286    }
    287
    288    /**
    289     * Pure Regex Pattern matching and replacement, no escaping
    290     *
    291     * @param string
    292     * @param pattern
    293     * @param repl
    294     * @return
    295     */
    296    public static String replacePatternMatch(String string, String pattern, String repl) {
    297        return replacePatternMatch(string, ACFPatterns.getPattern(pattern), repl);
    298    }
    299
    300    public static String replaceStrings(String string, String... replacements) {
    301        if (replacements.length < 2 || replacements.length % 2 != 0) {
    302            throw new IllegalArgumentException("Invalid Replacements");
    303        }
    304        for (int i = 0; i < replacements.length; i += 2) {
    305            String key = replacements[i];
    306            String value = replacements[i + 1];
    307            if (value == null) value = "";
    308            string = replace(string, key, value);
    309        }
    310        return string;
    311    }
    312
    313    public static String replacePatterns(String string, String... replacements) {
    314        if (replacements.length < 2 || replacements.length % 2 != 0) {
    315            throw new IllegalArgumentException("Invalid Replacements");
    316        }
    317        for (int i = 0; i < replacements.length; i += 2) {
    318            String key = replacements[i];
    319            String value = replacements[i + 1];
    320            if (value == null) value = "";
    321            string = replacePattern(string, key, value);
    322        }
    323        return string;
    324    }
    325
    326    public static String capitalize(String str, char[] delimiters) {
    327        return ApacheCommonsLangUtil.capitalize(str, delimiters);
    328    }
    329
    330    private static boolean isDelimiter(char ch, char[] delimiters) {
    331        return ApacheCommonsLangUtil.isDelimiter(ch, delimiters);
    332    }
    333
    334    public static <T> T random(List<T> arr) {
    335        if (arr == null || arr.isEmpty()) {
    336            return null;
    337        }
    338        return arr.get(RANDOM.nextInt(arr.size()));
    339    }
    340
    341    public static <T> T random(T[] arr) {
    342        if (arr == null || arr.length == 0) {
    343            return null;
    344        }
    345        return arr[RANDOM.nextInt(arr.length)];
    346    }
    347
    348    /**
    349     * Added as im sure we will try to "Find this" again. This is no different than Enum.values() passed to above method logically
    350     * but the array version is slightly faster.
    351     *
    352     * @param enm
    353     * @param <T>
    354     * @return
    355     */
    356    @Deprecated
    357    public static <T extends Enum<?>> T random(Class<? extends T> enm) {
    358        return random(enm.getEnumConstants());
    359    }
    360
    361    public static String normalize(String s) {
    362        if (s == null) {
    363            return null;
    364        }
    365        return ACFPatterns.NON_PRINTABLE_CHARACTERS.matcher(Normalizer.normalize(s, Form.NFD)).replaceAll("");
    366    }
    367
    368    public static int indexOf(String arg, String[] split) {
    369        for (int i = 0; i < split.length; i++) {
    370            if (arg == null) {
    371                if (split[i] == null) {
    372                    return i;
    373                }
    374            } else if (arg.equals(split[i])) {
    375                return i;
    376            }
    377        }
    378        return -1;
    379    }
    380
    381    public static String capitalizeFirst(String name) {
    382        return capitalizeFirst(name, '_');
    383    }
    384
    385    public static String capitalizeFirst(String name, char separator) {
    386        name = name.toLowerCase(Locale.ENGLISH);
    387        String[] split = name.split(Character.toString(separator));
    388        StringBuilder total = new StringBuilder(3);
    389        for (String s : split) {
    390            total.append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).append(' ');
    391        }
    392
    393        return total.toString().trim();
    394    }
    395
    396    public static String ltrim(String s) {
    397        int i = 0;
    398        while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
    399            i++;
    400        }
    401        return s.substring(i);
    402    }
    403
    404    public static String rtrim(String s) {
    405        int i = s.length() - 1;
    406        while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
    407            i--;
    408        }
    409        return s.substring(0, i + 1);
    410    }
    411
    412    public static List<String> enumNames(Enum<?>[] values) {
    413        return Stream.of(values).map(Enum::name).collect(Collectors.toList());
    414    }
    415
    416    public static List<String> enumNames(Class<? extends Enum<?>> cls) {
    417        return enumNames(cls.getEnumConstants());
    418    }
    419
    420    public static String combine(String[] args) {
    421        return combine(args, 0);
    422    }
    423
    424    public static String combine(String[] args, int start) {
    425        int size = 0;
    426        for (int i = start; i < args.length; i++) {
    427            size += args[i].length();
    428        }
    429        StringBuilder sb = new StringBuilder(size);
    430        for (int i = start; i < args.length; i++) {
    431            sb.append(args[i]);
    432        }
    433        return sb.toString();
    434    }
    435
    436
    437    @Nullable
    438    public static <E extends Enum<E>> E simpleMatch(Class<? extends Enum<?>> list, String item) {
    439        if (item == null) {
    440            return null;
    441        }
    442        item = ACFUtil.simplifyString(item);
    443        for (Enum<?> s : list.getEnumConstants()) {
    444            String simple = ACFUtil.simplifyString(s.name());
    445            if (item.equals(simple)) {
    446                //noinspection unchecked
    447                return (E) s;
    448            }
    449        }
    450
    451        return null;
    452    }
    453
    454    public static boolean isTruthy(String test) {
    455        switch (test) {
    456            case "t":
    457            case "true":
    458            case "on":
    459            case "y":
    460            case "yes":
    461            case "1":
    462                return true;
    463        }
    464        return false;
    465    }
    466
    467
    468    public static Number parseNumber(String num, boolean suffixes) {
    469        if (ACFPatterns.getPattern("^0x([0-9A-Fa-f]*)$").matcher(num).matches()) {
    470            return Long.parseLong(num.substring(2), 16);
    471        } else if (ACFPatterns.getPattern("^0b([01]*)$").matcher(num).matches()) {
    472            return Long.parseLong(num.substring(2), 2);
    473        } else {
    474            ApplyModifierToNumber applyModifierToNumber = new ApplyModifierToNumber(num, suffixes).invoke();
    475            num = applyModifierToNumber.getNum();
    476            double mod = applyModifierToNumber.getMod();
    477
    478            return Double.parseDouble(num) * mod;
    479        }
    480    }
    481
    482    public static BigDecimal parseBigNumber(String num, boolean suffixes) {
    483        ApplyModifierToNumber applyModifierToNumber = new ApplyModifierToNumber(num, suffixes).invoke();
    484        num = applyModifierToNumber.getNum();
    485        double mod = applyModifierToNumber.getMod();
    486
    487        BigDecimal big = new BigDecimal(num);
    488        return (mod == 1) ? big : big.multiply(new BigDecimal(mod));
    489    }
    490
    491    public static <T> boolean hasIntersection(Collection<T> list1, Collection<T> list2) {
    492        for (T t : list1) {
    493            if (list2.contains(t)) {
    494                return true;
    495            }
    496        }
    497
    498        return false;
    499    }
    500
    501    public static <T> Collection<T> intersection(Collection<T> list1, Collection<T> list2) {
    502        List<T> list = new ArrayList<>();
    503
    504        for (T t : list1) {
    505            if (list2.contains(t)) {
    506                list.add(t);
    507            }
    508        }
    509
    510        return list;
    511    }
    512
    513    public static int rand(int min, int max) {
    514        return min + RANDOM.nextInt(max - min + 1);
    515    }
    516
    517    /**
    518     * Calculate random between 2 points, excluding a center
    519     * ex: Util.rand(-12, -6, 6, 12) would not return -5 to 5
    520     *
    521     * @param min1
    522     * @param max1
    523     * @param min2
    524     * @param max2
    525     * @return
    526     */
    527    public static int rand(int min1, int max1, int min2, int max2) {
    528        return randBool() ? rand(min1, max1) : rand(min2, max2);
    529    }
    530
    531    public static double rand(double min, double max) {
    532        return RANDOM.nextDouble() * (max - min) + min;
    533    }
    534
    535    public static boolean isNumber(String str) {
    536        return ApacheCommonsLangUtil.isNumeric(str);
    537    }
    538
    539    public static String intToRoman(int integer) {
    540        if (integer == 1) {
    541            return "I";
    542        }
    543        if (integer == 2) {
    544            return "II";
    545        }
    546        if (integer == 3) {
    547            return "III";
    548        }
    549        if (integer == 4) {
    550            return "IV";
    551        }
    552        if (integer == 5) {
    553            return "V";
    554        }
    555        if (integer == 6) {
    556            return "VI";
    557        }
    558        if (integer == 7) {
    559            return "VII";
    560        }
    561        if (integer == 8) {
    562            return "VIII";
    563        }
    564        if (integer == 9) {
    565            return "IX";
    566        }
    567        if (integer == 10) {
    568            return "X";
    569        }
    570        return null;
    571    }
    572
    573    public static boolean isInteger(String string) {
    574        return ACFPatterns.INTEGER.matcher(string).matches();
    575    }
    576
    577    public static boolean isFloat(String string) {
    578        try {
    579            Float.parseFloat(string);
    580            return true;
    581        } catch (Exception e) {
    582            return false;
    583        }
    584    }
    585
    586    public static boolean isDouble(String string) {
    587        try {
    588            Double.parseDouble(string);
    589            return true;
    590        } catch (Exception e) {
    591            return false;
    592        }
    593    }
    594
    595    public static boolean isBetween(float num, double min, double max) {
    596        return num >= min && num <= max;
    597    }
    598
    599    @SuppressWarnings("SameParameterValue")
    600    public static double precision(double x, int p) {
    601        double pow = Math.pow(10, p);
    602        return Math.round(x * pow) / pow;
    603    }
    604
    605    public static void sneaky(Throwable t) {
    606        //noinspection RedundantTypeArguments
    607        throw ACFUtil.<RuntimeException>superSneaky(t);
    608    }
    609
    610    private static <T extends Throwable> T superSneaky(Throwable t) throws T {
    611        // noinspection unchecked
    612        throw (T) t;
    613    }
    614
    615    public static <T> List<T> preformOnImmutable(List<T> list, Consumer<List<T>> action) {
    616        try {
    617            action.accept(list);
    618        } catch (UnsupportedOperationException ex) {
    619            list = new ArrayList<>(list);
    620            action.accept(list);
    621        }
    622
    623        return list;
    624    }
    625
    626    public static <T> T getFirstElement(Iterable<T> iterable) {
    627        if (iterable == null) {
    628            return null;
    629        }
    630        Iterator<T> iterator = iterable.iterator();
    631        if (iterator.hasNext()) {
    632            return iterator.next();
    633        }
    634
    635        return null;
    636    }
    637
    638    private static class ApplyModifierToNumber {
    639        private String num;
    640        private boolean suffixes;
    641        private double mod;
    642
    643        public ApplyModifierToNumber(String num, boolean suffixes) {
    644            this.num = num;
    645            this.suffixes = suffixes;
    646        }
    647
    648        public String getNum() {
    649            return num;
    650        }
    651
    652        public double getMod() {
    653            return mod;
    654        }
    655
    656        public ApplyModifierToNumber invoke() {
    657            mod = 1;
    658            if (suffixes) {
    659                switch (num.charAt(num.length() - 1)) {
    660                    case 'M':
    661                    case 'm':
    662                        mod = 1000000D;
    663                        num = num.substring(0, num.length() - 1);
    664                        break;
    665                    case 'K':
    666                    case 'k':
    667                        mod = 1000D;
    668                        num = num.substring(0, num.length() - 1);
    669                }
    670            }
    671            return this;
    672        }
    673    }
    674}