/* * Copyright (C) 2014 Civilian Framework. * * Licensed under the Civilian License (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.civilian-framework.org/license.txt * * 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 org.civilian.internal.controller.arg.conv; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collection; import org.civilian.Request; import org.civilian.controller.MethodArg; import org.civilian.internal.controller.arg.StringMethodArg; import org.civilian.type.TypeLib; import org.civilian.type.fn.TypeSerializer; import org.civilian.type.fn.StandardSerializer; import org.civilian.util.Value; /** * Base class for MethodArgs whose * request value is String based and needs conversion * to the type of the method parameter. */ public class ConvertingArg<T> extends MethodArg { public static <T> MethodArg create(StringMethodArg arg, String defaultValue, boolean isLocaleValue, TypeLib typeLib, Class<?> paramType) throws Exception { return create(arg, defaultValue, isLocaleValue, typeLib, paramType, paramType); } public static <T> MethodArg create(StringMethodArg arg, String defaultValue, boolean isLocaleValue, TypeLib typeLib, Class<?> type, Type genericType) throws Exception { // 1. genericType is Value or Value<X> if (type == Value.class) return createValueArg(arg, defaultValue, isLocaleValue, typeLib, genericType); // 2. collection converters CollectionConverter<T> collConverter = CollectionConverters.create(typeLib, type, genericType); if (collConverter != null) { Collection<T> dv = defaultValue != null ? collConverter.convert(null, StandardSerializer.INSTANCE, defaultValue) : collConverter.emptyCollection(); return new ConvertingArg<>(arg, dv, isLocaleValue, collConverter); } // 3. simple converters SimpleConverter<T> simpleConverter = SimpleConverters.create(typeLib, type); if (simpleConverter != null) { T dv = defaultValue != null ? simpleConverter.convert(null, StandardSerializer.INSTANCE, defaultValue) : simpleConverter.nullValue(); return new ConvertingArg<>(arg, dv, isLocaleValue, simpleConverter); } throw new IllegalArgumentException("type '" + genericType + " is not supported"); } private static <T> MethodArg createValueArg(StringMethodArg arg, String defaultValue, boolean isLocaleValue, TypeLib typeLib, Type genericType) throws Exception { Class<?> valueType = null; Type valueGenericType = null; if (!(genericType instanceof ParameterizedType)) valueGenericType = valueType = String.class; else { ParameterizedType ptype = (ParameterizedType)genericType; Type[] ptypeArgs = ptype.getActualTypeArguments(); if (ptypeArgs.length == 1) { valueGenericType = ptypeArgs[0]; valueType = extractClass(valueGenericType); } } if (valueType == null) return null; else { MethodArg convertingArg = create(arg, defaultValue, isLocaleValue, typeLib, valueType, valueGenericType); return new ValueArg(convertingArg); } } private static Class<?> extractClass(Type type) { if (type instanceof Class) return (Class<?>)type; if (type instanceof ParameterizedType) { ParameterizedType ptype = (ParameterizedType)type; if (ptype.getRawType() instanceof Class) return (Class<?>)ptype.getRawType(); } return null; } /** * Creates a new ConvertingArg object. * @param arg the inner arg * @param defaultValue the default value, if the parameter is not part of the request */ protected ConvertingArg(StringMethodArg arg, T defaultValue, boolean isLocaleValue, Converter<T> converter) { arg_ = arg; defaultValue_ = defaultValue; isLocaleValue_ = isLocaleValue; converter_ = converter; } /** * Extracts the parameter from the request and * converts into the target value which will be injected into * argument variable. */ @Override public T getValue(Request request) throws Exception { TypeSerializer serializer = isLocaleValue_ ? request.getLocaleSerializer() : StandardSerializer.INSTANCE; return converter_.getValue(request, arg_, serializer, defaultValue_); } /** * Builds a string representation of the argument. */ @Override public String toString() { return arg_.toString(); } private StringMethodArg arg_; private T defaultValue_; private boolean isLocaleValue_; private Converter<T> converter_; }