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.cmdline;
021    
022    import org.crsh.cmdline.binding.TypeBinding;
023    import org.crsh.cmdline.completers.EmptyCompleter;
024    import org.crsh.cmdline.matcher.CmdSyntaxException;
025    import org.crsh.cmdline.spi.Completer;
026    import org.crsh.cmdline.spi.Value;
027    
028    import java.io.IOException;
029    import java.lang.annotation.Annotation;
030    import java.lang.reflect.ParameterizedType;
031    import java.lang.reflect.Type;
032    import java.util.List;
033    
034    public abstract class ParameterDescriptor<B extends TypeBinding> {
035    
036      /** . */
037      private final B binding;
038    
039      /** . */
040      private final Description description;
041    
042      /** . */
043      private final SimpleValueType type;
044    
045      /** . */
046      private final Multiplicity multiplicity;
047    
048      /** . */
049      private final boolean required;
050    
051      /** . */
052      private final boolean password;
053    
054      /** . */
055      private final Type javaType;
056    
057      /** . */
058      private final Class<?> javaValueType;
059    
060      /** . */
061      private final Class<? extends Completer> completerType;
062    
063      /** The annotation when it exists.  */
064      private final Annotation annotation;
065    
066      /** . */
067      private final boolean unquote;
068    
069      /** . */
070      CommandDescriptor<?, B> owner;
071    
072      public ParameterDescriptor(
073        B binding,
074        Type javaType,
075        Description description,
076        boolean required,
077        boolean password,
078        boolean unquote,
079        Class<? extends Completer> completerType,
080        Annotation annotation) throws IllegalValueTypeException, IllegalParameterException {
081    
082        //
083        Class<?> javaValueType;
084        Multiplicity multiplicity;
085        if (javaType instanceof Class<?>) {
086          javaValueType = (Class<Object>)javaType;
087          multiplicity = Multiplicity.SINGLE;
088        } else if (javaType instanceof ParameterizedType) {
089          ParameterizedType parameterizedType = (ParameterizedType)javaType;
090          Type rawType = parameterizedType.getRawType();
091          if (rawType instanceof Class<?>) {
092            Class<?> classRawType = (Class<Object>)rawType;
093            if (List.class.equals(classRawType)) {
094              Type elementType = parameterizedType.getActualTypeArguments()[0];
095              if (elementType instanceof Class<?>) {
096                javaValueType = (Class<Object>)elementType;
097                multiplicity = Multiplicity.MULTI;
098              } else {
099                throw new IllegalValueTypeException();
100              }
101            } else {
102              throw new IllegalValueTypeException();
103            }
104          } else {
105            throw new IllegalValueTypeException();
106          }
107        } else {
108          throw new IllegalValueTypeException();
109        }
110    
111        //
112        SimpleValueType valueType;
113        if (javaValueType == String.class) {
114          valueType = SimpleValueType.STRING;
115        } else if (javaValueType == Integer.class || javaValueType == int.class) {
116          valueType = SimpleValueType.INTEGER;
117        } else if (javaValueType == Boolean.class || javaValueType == boolean.class) {
118          valueType = SimpleValueType.BOOLEAN;
119        } else if (Enum.class.isAssignableFrom(javaValueType)) {
120          valueType = SimpleValueType.ENUM;
121        } else if (Value.class.isAssignableFrom(javaValueType)) {
122          valueType = SimpleValueType.VALUE;
123        } else {
124          throw new IllegalValueTypeException("Type " + javaValueType.getName() + " is not handled at the moment");
125        }
126    
127        //
128        if (completerType == EmptyCompleter.class) {
129          completerType = valueType.getCompleter();
130        }
131    
132        //
133        this.binding = binding;
134        this.javaType = javaType;
135        this.description = description;
136        this.type = valueType;
137        this.multiplicity = multiplicity;
138        this.required = required;
139        this.password = password;
140        this.completerType = completerType;
141        this.annotation = annotation;
142        this.javaValueType = javaValueType;
143        this.unquote = unquote;
144      }
145    
146      public Object parse(String s) throws Exception {
147        return type.parse(javaValueType, s);
148      }
149    
150      public abstract Object parse(List<String> values) throws CmdSyntaxException;
151    
152      public CommandDescriptor<?, B> getOwner() {
153        return owner;
154      }
155    
156      public Type getJavaType() {
157        return javaType;
158      }
159    
160      public Class<?> getJavaValueType() {
161        return javaValueType;
162      }
163    
164      public final B getBinding() {
165        return binding;
166      }
167    
168      public final String getUsage() {
169        return description != null ? description.getUsage() : "";
170      }
171    
172      public Description getDescription() {
173        return description;
174      }
175    
176      public Annotation getAnnotation() {
177        return annotation;
178      }
179    
180      public final boolean isRequired() {
181        return required;
182      }
183    
184      public boolean isUnquote() {
185        return unquote;
186      }
187    
188      public final boolean isPassword() {
189        return password;
190      }
191    
192      public final SimpleValueType getType() {
193        return type;
194      }
195    
196      public final Multiplicity getMultiplicity() {
197        return multiplicity;
198      }
199    
200      public final boolean isSingleValued() {
201        return multiplicity == Multiplicity.SINGLE;
202      }
203    
204      public final boolean isMultiValued() {
205        return multiplicity == Multiplicity.MULTI;
206      }
207    
208      public final Class<? extends Completer> getCompleterType() {
209        return completerType;
210      }
211    
212      public abstract void printUsage(Appendable writer) throws IOException;
213    }