io.github.theangrydev.yatspeczohhakplugin.json.JsonCollectionsParameterCoercer.java Source code

Java tutorial

Introduction

Here is the source code for io.github.theangrydev.yatspeczohhakplugin.json.JsonCollectionsParameterCoercer.java

Source

/*
 * Copyright 2016 Liam Williams <liam.williams@zoho.com>.
 *
 * This file is part of yatspec-zohhak-plugin.
 *
 * 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 io.github.theangrydev.yatspeczohhakplugin.json;

import com.googlecode.zohhak.api.backend.ParameterCoercer;
import org.apache.commons.lang3.ClassUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;

import static java.lang.String.format;

class JsonCollectionsParameterCoercer implements ParameterCoercer {

    private final ParameterCoercer defaultParameterCoercer;

    JsonCollectionsParameterCoercer(ParameterCoercer defaultParameterCoercer) {
        this.defaultParameterCoercer = defaultParameterCoercer;
    }

    @Override
    public Object coerceParameter(Type type, String stringToParse) {
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Class<?> rawType = (Class<?>) parameterizedType.getRawType();
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            return coerceParameterizedType(stringToParse, actualTypeArguments, rawType);
        } else if (type instanceof Class) {
            Class<?> targetType = ClassUtils.primitiveToWrapper((Class<?>) type);
            if (targetType.isArray()) {
                return coerceCollection(stringToParse, targetType.getComponentType(), ArrayBuilder::new);
            }
            return defaultParameterCoercer.coerceParameter(targetType, stringToParse);
        } else {
            throw new IllegalArgumentException(format("Cannot interpret '%s' as a '%s'", stringToParse, type));
        }
    }

    private Object coerceParameterizedType(String stringToParse, Type[] actualTypeArguments, Class<?> rawType) {
        if (rawType == List.class) {
            return coerceCollection(stringToParse, actualTypeArguments[0],
                    (actualTypeArgument, size) -> new ListBuilder(size));
        } else if (rawType == Set.class) {
            return coerceCollection(stringToParse, actualTypeArguments[0],
                    (actualTypeArgument, size) -> new SetBuilder(size));
        } else if (rawType == Map.class) {
            return coerceMap(stringToParse, actualTypeArguments[0], actualTypeArguments[1]);
        } else {
            return coerceParameter(rawType, stringToParse);
        }
    }

    private Map<Object, Object> coerceMap(String stringToParse, Type keyType, Type valueType) {
        JSONObject jsonObject = new JSONObject(stringToParse);
        int size = jsonObject.length();
        Map<Object, Object> map = new HashMap<>(size);
        for (String jsonKey : jsonObject.keySet()) {
            String jsonValue = jsonObject.get(jsonKey).toString();
            Object key = coerceParameter(keyType, jsonKey);
            Object value = coerceParameter(valueType, jsonValue);
            map.put(key, value);
        }
        return map;
    }

    private Object coerceCollection(String stringToParse, Type actualTypeArgument,
            BiFunction<Type, Integer, CollectionBuilder> collectionBuilderConstructor) {
        JSONArray jsonArray = new JSONArray(stringToParse);
        int size = jsonArray.length();
        CollectionBuilder collectionBuilder = collectionBuilderConstructor.apply(actualTypeArgument, size);
        for (int index = 0; index < size; index++) {
            Object element = coerceParameter(actualTypeArgument, jsonArray.get(index).toString());
            collectionBuilder.add(element);
        }
        return collectionBuilder.build();
    }
}