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 }