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