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

ninja.params.ParamParsers Maven / Gradle / Ivy

/**
 * Copyright (C) 2012-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ninja.params;

import java.lang.reflect.Array;
import java.util.Map;

import ninja.validation.ConstraintViolation;
import ninja.validation.IsEnum;
import ninja.validation.IsFloat;
import ninja.validation.IsInteger;
import ninja.validation.Validation;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

/**
 * Built in parsers for parameters
 *
 * @author James Roper
 */
public class ParamParsers {
    private static final Map, ParamParser> PARAM_PARSERS =
            ImmutableMap., ParamParser>builder()
                    .put(Integer.class, new IntegerParamParser())
                    .put(int.class, new PrimitiveIntegerParamParser())
                    .put(Boolean.class, new BooleanParamParser())
                    .put(boolean.class, new PrimitiveBooleanParamParser())
                    .put(Long.class, new LongParamParser())
                    .put(long.class, new PrimitiveLongParamParser())
                    .put(Float.class, new FloatParamParser())
                    .put(float.class, new PrimitiveFloatParamParser())
                    .put(Double.class, new DoubleParamParser())
                    .put(double.class, new PrimitiveDoubleParamParser())
                    .put(String.class, new StringParamParser())
                    .put(Byte.class, new ByteParamParser())
                    .put(byte.class, new PrimitiveByteParamParser())
                    .put(Short.class, new ShortParamParser())
                    .put(short.class, new PrimitiveShortParamParser())
                    .put(Character.class, new CharacterParamParser())
                    .put(char.class, new PrimitiveCharacterParamParser())
                    .build();

    private static final Map>, ParamParser> ENUM_PARSERS = Maps.newHashMap();

    public static ParamParser getParamParser(Class targetType) {

        if (targetType.isArray()) {
            // check for array of registered types
            Class componentType = targetType.getComponentType();
            ParamParser componentParser = getParamParser(componentType);

            if (componentParser != null) {
                // return CSV parser
                return new CsvParamParser(targetType, componentParser);
            }
        }

        if (ENUM_PARSERS.containsKey(targetType)) {
            return ENUM_PARSERS.get(targetType);
        }

        return PARAM_PARSERS.get(targetType);
    }

    public static > void unregisterEnum(final Class enumClass) {
        ENUM_PARSERS.remove(enumClass);
    }

    public static > void registerEnum(final Class enumClass) {
        registerEnum(enumClass, true);
    }

    public static > void registerEnum(final Class enumClass, final boolean caseSensitive) {
        EnumParamParser parser = new EnumParamParser() {

            @Override
            public Class getParsedType() {
                return enumClass;
            }

            @Override
            protected boolean isCaseSensitive() {
                return caseSensitive;
            }

        };

        ENUM_PARSERS.put(enumClass, parser);
    }

    public static ArrayParamParser getArrayParser(Class targetType) {
        if (targetType.isArray()) {
            // check for array of registered types
            Class componentType = targetType.getComponentType();
            ParamParser componentParser = getParamParser(componentType);

            if (componentParser != null) {
                // return multi-valued parameter parser
                return new ArrayParamParser(targetType, componentParser);
            }
        }

        return null;
    }

    public static class PrimitiveIntegerParamParser implements ParamParser {
        @Override
        public Integer parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return 0;
            } else {
                try {
                    return Integer.parseInt(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return 0;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Integer.class;
        }
    }

    public static class IntegerParamParser implements ParamParser {
        @Override
        public Integer parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                try {
                    return Integer.parseInt(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return null;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Integer.class;
        }
    }

    public static class BooleanParamParser implements ParamParser {
        @Override
        public Boolean parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                return Boolean.parseBoolean(parameterValue);
            }
        }

        @Override
        public Class getParsedType() {
            return Boolean.class;
        }
    }

    public static class PrimitiveBooleanParamParser implements ParamParser {
        @Override
        public Boolean parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return false;
            } else {
                return Boolean.parseBoolean(parameterValue);
            }
        }

        @Override
        public Class getParsedType() {
            return Boolean.class;
        }
    }

    public static class LongParamParser implements ParamParser {
        @Override
        public Long parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                try {
                    return Long.parseLong(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return null;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Long.class;
        }
    }

    public static class PrimitiveLongParamParser implements ParamParser {
        @Override
        public Long parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return 0L;
            } else {
                try {
                    return Long.parseLong(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return 0L;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Long.class;
        }
    }

    public static class FloatParamParser implements ParamParser {
        @Override
        public Float parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                try {
                    return Float.parseFloat(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsFloat.KEY, field, IsFloat.MESSAGE, parameterValue));
                    return null;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Float.class;
        }
    }

    public static class PrimitiveFloatParamParser implements ParamParser {
        @Override
        public Float parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return 0f;
            } else {
                try {
                    return Float.parseFloat(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsFloat.KEY, field, IsFloat.MESSAGE, parameterValue));
                    return 0f;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Float.class;
        }
    }

    public static class DoubleParamParser implements ParamParser {
        @Override
        public Double parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                try {
                    return Double.parseDouble(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsFloat.KEY, field, IsFloat.MESSAGE, parameterValue));
                    return null;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Double.class;
        }
    }

    public static class PrimitiveDoubleParamParser implements ParamParser {
        @Override
        public Double parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return 0d;
            } else {
                try {
                    return Double.parseDouble(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsFloat.KEY, field, IsFloat.MESSAGE, parameterValue));
                    return 0d;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Double.class;
        }
    }

    public static class StringParamParser implements ParamParser {
        @Override
        public String parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                return parameterValue;
            }
        }

        @Override
        public Class getParsedType() {
            return String.class;
        }
    }

    public static class ByteParamParser implements ParamParser {
        @Override
        public Byte parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                try {
                    return Byte.parseByte(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return null;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Byte.class;
        }
    }

    public static class PrimitiveByteParamParser implements ParamParser {
        @Override
        public Byte parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return 0;
            } else {
                try {
                    return Byte.parseByte(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return 0;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Byte.class;
        }
    }

    public static class ShortParamParser implements ParamParser {
        @Override
        public Short parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                try {
                    return Short.parseShort(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return null;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Short.class;
        }
    }

    public static class PrimitiveShortParamParser implements ParamParser {
        @Override
        public Short parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return 0;
            } else {
                try {
                    return Short.parseShort(parameterValue);
                } catch (NumberFormatException e) {
                    validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                            IsInteger.KEY, field, IsInteger.MESSAGE, parameterValue));
                    return 0;
                }
            }
        }

        @Override
        public Class getParsedType() {
            return Short.class;
        }
    }

    public static class CharacterParamParser implements ParamParser {
        @Override
        public Character parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || parameterValue.isEmpty() || validation.hasFieldViolation(field)) {
                return null;
            } else {
                return parameterValue.charAt(0);
            }
        }

        @Override
        public Class getParsedType() {
            return Character.class;
        }
    }

    public static class PrimitiveCharacterParamParser implements ParamParser {
        @Override
        public Character parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || parameterValue.isEmpty() || validation.hasFieldViolation(field)) {
                return '\0';
            } else {
                return parameterValue.charAt(0);
            }
        }

        @Override
        public Class getParsedType() {
            return Character.class;
        }
    }

    /**
     * Converts a parameter to an Enum value by (case-insensitive) value matching.
     *
     * @param 
     */
    public static abstract class EnumParamParser> implements ParamParser {
        @Override
        public E parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                final boolean caseSensitive = isCaseSensitive();

                E[] values = getParsedType().getEnumConstants();
                for (E value : values) {
                    if (caseSensitive) {
                        if (value.name().equals(parameterValue)) {
                            return value;
                        }
                    } else {
                        if (value.name().equalsIgnoreCase(parameterValue)) {
                            return value;
                        }
                    }
                }

                validation.addFieldViolation(field, ConstraintViolation.createForFieldWithDefault(
                        IsEnum.KEY, field, IsEnum.MESSAGE, new Object[] {parameterValue, getParsedType().getName()}));

                return null;
            }
        }

        @Override
        public abstract Class getParsedType();

        /**
         * Determines if the enum parser is case-sensitive.
         */
        protected abstract boolean isCaseSensitive();
    }

    /**
     * Parses a single string value as a CSV array of registered types.
     */
    public static class CsvParamParser implements ParamParser {

        private final Class arrayType;
        private final ParamParser itemParser;

        public CsvParamParser(Class arrayType, ParamParser parser) {
            this.arrayType = arrayType;
            this.itemParser = parser;
        }

        @Override
        public T[] parseParameter(String field, String parameterValue, Validation validation) {
            if (parameterValue == null || parameterValue.isEmpty() || validation.hasFieldViolation(field)) {
                return null;
            } else {
                // split the string value as a csv
                String [] values = parameterValue.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");

                // parse the individual values as the target item type
                Class itemType = (Class) arrayType.getComponentType();
                T[] array = (T[]) Array.newInstance(itemType, values.length);
                for (int i = 0; i < values.length; i++) {
                    T t = itemParser.parseParameter(field, values[i], validation);
                    Array.set(array, i, t);
                }

                if (validation.hasFieldViolation(field)) {
                    return null;
                }

                return array;
            }
        }

        @Override
        public Class getParsedType() {
            return arrayType;
        }
    }

    /**
     * Parses a multi-valued parameter as an array of registered types.
     */
    public static class ArrayParamParser {

        private final Class arrayType;
        private final ParamParser itemParser;

        public ArrayParamParser(Class arrayType, ParamParser parser) {
            this.arrayType = arrayType;
            this.itemParser = parser;
        }

        public T[] parseParameter(String field, String[] parameterValues, Validation validation) {
            if (parameterValues == null || validation.hasFieldViolation(field)) {
                return null;
            } else {
                // parse the individual values as the target item type
                Class itemType = getItemType();
                T[] array = (T[]) Array.newInstance(itemType, parameterValues.length);
                for (int i = 0; i < parameterValues.length; i++) {
                    T t = itemParser.parseParameter(field, parameterValues[i], validation);
                    Array.set(array, i, t);
                }

                if (validation.hasFieldViolation(field)) {
                    return null;
                }

                return array;
            }
        }

        public Class getArrayType() {
            return arrayType;
        }

        public Class getItemType() {
            return (Class) arrayType.getComponentType();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy