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