All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shade.com.alibaba.fastjson2.JSONPathFunction Maven / Gradle / Ivy

There is a newer version: 1.3.7
Show newest version
package com.alibaba.fastjson2;

import com.alibaba.fastjson2.function.impl.ToDouble;
import com.alibaba.fastjson2.util.TypeUtils;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

final class JSONPathFunction
        extends JSONPathSegment
        implements JSONPathSegment.EvalSegment {
    static final JSONPathFunction FUNC_TYPE = new JSONPathFunction(JSONPathFunction::type);
    static final JSONPathFunction FUNC_DOUBLE = new JSONPathFunction(new ToDouble(null));
    static final JSONPathFunction FUNC_FLOOR = new JSONPathFunction(JSONPathFunction::floor);
    static final JSONPathFunction FUNC_CEIL = new JSONPathFunction(JSONPathFunction::ceil);
    static final JSONPathFunction FUNC_ABS = new JSONPathFunction(JSONPathFunction::abs);
    static final JSONPathFunction FUNC_NEGATIVE = new JSONPathFunction(JSONPathFunction::negative);
    static final JSONPathFunction FUNC_EXISTS = new JSONPathFunction(JSONPathFunction::exists);
    static final JSONPathFunction FUNC_LOWER = new JSONPathFunction(JSONPathFunction::lower);
    static final JSONPathFunction FUNC_UPPER = new JSONPathFunction(JSONPathFunction::upper);
    static final JSONPathFunction FUNC_TRIM = new JSONPathFunction(JSONPathFunction::trim);
    static final JSONPathFunction FUNC_FIRST = new JSONPathFunction(JSONPathFunction::first);
    static final JSONPathFunction FUNC_LAST = new JSONPathFunction(JSONPathFunction::last);

    final Function function;

    public JSONPathFunction(Function function) {
        this.function = function;
    }

    static Object floor(Object value) {
        if (value instanceof Double) {
            return Math.floor((Double) value);
        }

        if (value instanceof Float) {
            return Math.floor((Float) value);
        }

        if (value instanceof BigDecimal) {
            return ((BigDecimal) value).setScale(0, RoundingMode.FLOOR);
        }

        if (value instanceof List) {
            List list = (List) value;
            for (int i = 0, l = list.size(); i < l; i++) {
                Object item = list.get(i);
                if (item instanceof Double) {
                    list.set(i, Math.floor((Double) item));
                } else if (item instanceof Float) {
                    list.set(i, Math.floor((Float) item));
                } else if (item instanceof BigDecimal) {
                    list.set(i, ((BigDecimal) item).setScale(0, RoundingMode.FLOOR));
                }
            }
        }

        return value;
    }

    static Object ceil(Object value) {
        if (value instanceof Double) {
            return Math.ceil((Double) value);
        }

        if (value instanceof Float) {
            return Math.ceil((Float) value);
        }

        if (value instanceof BigDecimal) {
            return ((BigDecimal) value).setScale(0, RoundingMode.CEILING);
        }

        if (value instanceof List) {
            List list = (List) value;
            for (int i = 0, l = list.size(); i < l; i++) {
                Object item = list.get(i);
                if (item instanceof Double) {
                    list.set(i, Math.ceil((Double) item));
                } else if (item instanceof Float) {
                    list.set(i, Math.ceil((Float) item));
                } else if (item instanceof BigDecimal) {
                    list.set(i, ((BigDecimal) item).setScale(0, RoundingMode.CEILING));
                }
            }
        }

        return value;
    }

    static Object exists(Object value) {
        return value != null;
    }

    static Object negative(Object value) {
        if (value == null) {
            return null;
        }

        if (value instanceof Integer) {
            int intValue = (Integer) value;
            if (intValue == Integer.MIN_VALUE) {
                return -(long) intValue;
            }
            return -intValue;
        }

        if (value instanceof Long) {
            long longValue = (Long) value;
            if (longValue == Long.MIN_VALUE) {
                return BigInteger.valueOf(longValue).negate();
            }
            return -longValue;
        }

        if (value instanceof Byte) {
            byte byteValue = (Byte) value;
            if (byteValue == Byte.MIN_VALUE) {
                return -(short) byteValue;
            }

            return (byte) -byteValue;
        }

        if (value instanceof Short) {
            short shortValue = (Short) value;
            if (shortValue == Short.MIN_VALUE) {
                return -(int) shortValue;
            }

            return (short) -shortValue;
        }

        if (value instanceof Double) {
            return -(Double) value;
        }

        if (value instanceof Float) {
            return -(Float) value;
        }

        if (value instanceof BigDecimal) {
            return ((BigDecimal) value).negate();
        }

        if (value instanceof BigInteger) {
            return ((BigInteger) value).negate();
        }

        if (value instanceof List) {
            List list = (List) value;
            JSONArray values = new JSONArray(list.size());
            for (int i = 0; i < list.size(); i++) {
                Object item = list.get(i);
                Object negativeItem = negative(item);
                values.add(negativeItem);
            }
            return values;
        }

        return value;
    }

    static Object first(Object value) {
        if (value == null) {
            return null;
        }

        if (value instanceof JSONPath.Sequence) {
            value = ((JSONPath.Sequence) value).values;
        }

        if (value instanceof List) {
            if (((List) value).isEmpty()) {
                return null;
            }

            return ((List) value).get(0);
        }

        if (value instanceof Collection) {
            Collection collection = (Collection) value;
            if (collection.isEmpty()) {
                return null;
            }

            return collection.iterator().next();
        }

        if (value.getClass().isArray()) {
            int len = Array.getLength(value);
            if (len == 0) {
                return null;
            }
            return Array.get(value, 0);
        }

        return value;
    }

    static Object last(Object value) {
        if (value == null) {
            return null;
        }

        if (value instanceof JSONPath.Sequence) {
            value = ((JSONPath.Sequence) value).values;
        }

        if (value instanceof List) {
            List list = (List) value;
            int size = list.size();
            if (size == 0) {
                return null;
            }
            return list.get(size - 1);
        }

        if (value instanceof Collection) {
            Collection collection = (Collection) value;
            if (collection.isEmpty()) {
                return null;
            }

            Object last = null;
            for (Object o : collection) {
                last = o;
            }
            return last;
        }

        if (value.getClass().isArray()) {
            int len = Array.getLength(value);
            if (len == 0) {
                return null;
            }
            return Array.get(value, len - 1);
        }

        return value;
    }

    static Object abs(Object value) {
        if (value == null) {
            return null;
        }

        if (value instanceof Integer) {
            int intValue = (Integer) value;
            if (intValue < 0) {
                return -intValue;
            }
            return value;
        }

        if (value instanceof Long) {
            long longValue = (Long) value;
            if (longValue < 0) {
                return -longValue;
            }
            return value;
        }

        if (value instanceof Byte) {
            byte byteValue = (Byte) value;
            if (byteValue < 0) {
                return (byte) -byteValue;
            }

            return value;
        }

        if (value instanceof Short) {
            short shortValue = (Short) value;
            if (shortValue < 0) {
                return (short) -shortValue;
            }

            return value;
        }

        if (value instanceof Double) {
            double doubleValue = (Double) value;
            if (doubleValue < 0) {
                return -doubleValue;
            }

            return value;
        }

        if (value instanceof Float) {
            float floatValue = (Float) value;
            if (floatValue < 0) {
                return -floatValue;
            }

            return value;
        }

        if (value instanceof BigDecimal) {
            return ((BigDecimal) value).abs();
        }

        if (value instanceof BigInteger) {
            return ((BigInteger) value).abs();
        }

        if (value instanceof List) {
            List list = (List) value;
            JSONArray values = new JSONArray(list.size());
            for (int i = 0; i < list.size(); i++) {
                Object item = list.get(i);
                values.add(abs(item));
            }
            return values;
        }

        throw new JSONException("abs not support " + value);
    }

    static String type(Object value) {
        if (value == null) {
            return "null";
        }

        if (value instanceof Collection) {
            return "array";
        }

        if (value instanceof Number) {
            return "number";
        }

        if (value instanceof Boolean) {
            return "boolean";
        }

        if (value instanceof String
                || value instanceof UUID
                || value instanceof Enum) {
            return "string";
        }

        return "object";
    }

    static Object lower(Object value) {
        if (value == null) {
            return null;
        }
        String str;
        if (value instanceof String) {
            str = (String) value;
        } else {
            str = value.toString();
        }
        return str.toLowerCase();
    }

    static Object upper(Object value) {
        if (value == null) {
            return null;
        }
        String str;
        if (value instanceof String) {
            str = (String) value;
        } else {
            str = value.toString();
        }
        return str.toUpperCase();
    }

    static Object trim(Object value) {
        if (value == null) {
            return null;
        }
        String str;
        if (value instanceof String) {
            str = (String) value;
        } else {
            str = value.toString();
        }
        return str.trim();
    }

    @Override
    public void accept(JSONReader jsonReader, JSONPath.Context context) {
        if (context.parent == null) {
            context.root = jsonReader.readAny();
            context.eval = true;
        }
        eval(context);
    }

    @Override
    public void eval(JSONPath.Context context) {
        Object value = context.parent == null
                ? context.root
                : context.parent.value;

        context.value = function.apply(value);
    }

    static final class TypeFunction
            implements Function {
        static final TypeFunction INSTANCE = new TypeFunction();

        @Override
        public Object apply(Object object) {
            return type(object);
        }
    }

    static final class SizeFunction
            implements Function {
        static final SizeFunction INSTANCE = new SizeFunction();

        @Override
        public Object apply(Object value) {
            if (value == null) {
                return -1;
            }

            if (value instanceof Collection) {
                return ((Collection) value).size();
            }

            if (value.getClass().isArray()) {
                return Array.getLength(value);
            }

            if (value instanceof Map) {
                return ((Map) value).size();
            }

            if (value instanceof JSONPath.Sequence) {
                return ((JSONPath.Sequence) value).values.size();
            }

            return 1;
        }
    }

    static final class BiFunctionAdapter
            implements BiFunction {
        private final Function function;

        BiFunctionAdapter(Function function) {
            this.function = function;
        }

        @Override
        public Object apply(Object o1, Object o2) {
            return function.apply(o2);
        }
    }

    abstract static class Index
            implements Function {
        protected abstract boolean eq(Object item);

        @Override
        public final Object apply(Object o) {
            if (o == null) {
                return null;
            }

            if (o instanceof List) {
                List list = (List) o;
                for (int i = 0; i < list.size(); i++) {
                    if (eq(list.get(i))) {
                        return i;
                    }
                }
                return -1;
            }

            if (o.getClass().isArray()) {
                int len = Array.getLength(o);
                for (int i = 0; i < len; i++) {
                    Object item = Array.get(o, i);
                    if (eq(item)) {
                        return i;
                    }
                }
                return -1;
            }

            if (eq(o)) {
                return 0;
            }

            return null;
        }
    }

    static final class IndexInt
            extends Index {
        final long value;
        transient BigDecimal decimalValue;

        public IndexInt(long value) {
            this.value = value;
        }

        protected boolean eq(Object item) {
            if (item instanceof Integer
                    || item instanceof Long
                    || item instanceof Byte
                    || item instanceof Short
            ) {
                return ((Number) item).longValue() == value;
            } else if (item instanceof Float || item instanceof Double) {
                return ((Number) item).doubleValue() == value;
            } else if (item instanceof BigDecimal) {
                BigDecimal decimal = (BigDecimal) item;
                decimal = decimal.stripTrailingZeros();
                if (decimalValue == null) {
                    decimalValue = BigDecimal.valueOf(value);
                }
                return decimalValue.equals(decimal);
            }
            return false;
        }
    }

    static final class IndexDecimal
            extends Index {
        final BigDecimal value;

        public IndexDecimal(BigDecimal value) {
            this.value = value;
        }

        @Override
        protected boolean eq(Object item) {
            if (item == null) {
                return false;
            }

            if (item instanceof BigDecimal) {
                BigDecimal decimal = (BigDecimal) item;
                decimal = decimal.stripTrailingZeros();
                return value.equals(decimal);
            }

            if (item instanceof Float || item instanceof Double) {
                double doubleValue = ((Number) item).doubleValue();
                BigDecimal decimal = new BigDecimal(doubleValue).stripTrailingZeros();
                return value.equals(decimal);
            }

            if (item instanceof String) {
                String str = (String) item;
                if (TypeUtils.isNumber(str)) {
                    BigDecimal decimal = new BigDecimal(str).stripTrailingZeros();
                    return value.equals(decimal);
                }
            }

            return false;
        }
    }

    static final class IndexString
            extends Index {
        final String value;

        public IndexString(String value) {
            this.value = value;
        }

        @Override
        protected boolean eq(Object item) {
            if (item == null) {
                return false;
            }
            return value.equals(item.toString());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy