001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.cli.impl;
021    
022    import org.crsh.cli.impl.descriptor.IllegalValueTypeException;
023    import org.crsh.cli.type.ValueType;
024    import org.crsh.cli.type.ValueTypeFactory;
025    
026    import java.lang.reflect.ParameterizedType;
027    import java.lang.reflect.Type;
028    import java.util.List;
029    
030    public final class ParameterType<V> {
031    
032      public static ParameterType create(ValueTypeFactory factory, Type type) throws IllegalValueTypeException {
033        Class<?> declaredType;
034        Multiplicity multiplicity;
035        if (type instanceof Class<?>) {
036          declaredType = (Class<Object>)type;
037          multiplicity = Multiplicity.SINGLE;
038        } else if (type instanceof ParameterizedType) {
039          ParameterizedType parameterizedType = (ParameterizedType)type;
040          Type rawType = parameterizedType.getRawType();
041          if (rawType instanceof Class<?>) {
042            Class<?> classRawType = (Class<Object>)rawType;
043            if (List.class.equals(classRawType)) {
044              Type elementType = parameterizedType.getActualTypeArguments()[0];
045              if (elementType instanceof Class<?>) {
046                declaredType = (Class<Object>)elementType;
047                multiplicity = Multiplicity.MULTI;
048              } else {
049                throw new IllegalValueTypeException();
050              }
051            } else {
052              throw new IllegalValueTypeException();
053            }
054          } else {
055            throw new IllegalValueTypeException();
056          }
057        } else {
058          throw new IllegalValueTypeException();
059        }
060    
061        //
062        Class<?> effectiveType;
063        ValueType valueType;
064        if (declaredType == String.class) {
065          effectiveType = String.class;
066          valueType = ValueType.STRING;
067        } else if (declaredType == Integer.class || declaredType == int.class) {
068          effectiveType = Integer.class;
069          valueType = ValueType.INTEGER;
070        } else if (declaredType == Boolean.class || declaredType == boolean.class) {
071          effectiveType = Boolean.class;
072          valueType = ValueType.BOOLEAN;
073        } else if (Enum.class.isAssignableFrom(declaredType)) {
074          effectiveType = declaredType;
075          valueType = ValueType.ENUM;
076        } else {
077          effectiveType = declaredType;
078          valueType = factory.get(declaredType);
079          if (valueType == null) {
080            throw new IllegalValueTypeException("Type " + declaredType.getName() + " is not handled at the moment");
081          }
082        }
083    
084        //
085        return new ParameterType(multiplicity, declaredType, effectiveType, valueType);
086      }
087    
088      /** . */
089      private final Multiplicity multiplicity;
090    
091      /** . */
092      private final Class<?> declaredType;
093    
094      /** . */
095      private final Class<V> effectiveType;
096    
097      /** . */
098      private final ValueType<V> valueType;
099    
100      ParameterType(Multiplicity multiplicity, Class<?> declaredType, Class<V> effectiveType, ValueType<V> valueType) {
101        this.multiplicity = multiplicity;
102        this.declaredType = declaredType;
103        this.effectiveType = effectiveType;
104        this.valueType = valueType;
105      }
106    
107      public Object parse(String s) throws Exception {
108        return valueType.parse(effectiveType, s);
109      }
110    
111      public Multiplicity getMultiplicity() {
112        return multiplicity;
113      }
114    
115      public Class<?> getDeclaredType() {
116        return declaredType;
117      }
118    
119      public Class<V> getEffectiveType() {
120        return effectiveType;
121      }
122    
123      public ValueType<V> getValueType() {
124        return valueType;
125      }
126    }