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 /*
021 * Copyright (C) 2012 eXo Platform SAS.
022 *
023 * This is free software; you can redistribute it and/or modify it
024 * under the terms of the GNU Lesser General Public License as
025 * published by the Free Software Foundation; either version 2.1 of
026 * the License, or (at your option) any later version.
027 *
028 * This software is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
031 * Lesser General Public License for more details.
032 *
033 * You should have received a copy of the GNU Lesser General Public
034 * License along with this software; if not, write to the Free
035 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
036 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
037 */
038
039 /*
040 * Copyright (C) 2012 eXo Platform SAS.
041 *
042 * This is free software; you can redistribute it and/or modify it
043 * under the terms of the GNU Lesser General Public License as
044 * published by the Free Software Foundation; either version 2.1 of
045 * the License, or (at your option) any later version.
046 *
047 * This software is distributed in the hope that it will be useful,
048 * but WITHOUT ANY WARRANTY; without even the implied warranty of
049 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
050 * Lesser General Public License for more details.
051 *
052 * You should have received a copy of the GNU Lesser General Public
053 * License along with this software; if not, write to the Free
054 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
055 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
056 */
057
058 /*
059 * Copyright (C) 2012 eXo Platform SAS.
060 *
061 * This is free software; you can redistribute it and/or modify it
062 * under the terms of the GNU Lesser General Public License as
063 * published by the Free Software Foundation; either version 2.1 of
064 * the License, or (at your option) any later version.
065 *
066 * This software is distributed in the hope that it will be useful,
067 * but WITHOUT ANY WARRANTY; without even the implied warranty of
068 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
069 * Lesser General Public License for more details.
070 *
071 * You should have received a copy of the GNU Lesser General Public
072 * License along with this software; if not, write to the Free
073 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
074 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
075 */
076
077 package org.crsh.cli.impl.descriptor;
078
079 import org.crsh.cli.SyntaxException;
080 import org.crsh.cli.descriptor.CommandDescriptor;
081 import org.crsh.cli.descriptor.Description;
082 import org.crsh.cli.descriptor.OptionDescriptor;
083 import org.crsh.cli.descriptor.ParameterDescriptor;
084 import org.crsh.cli.impl.ParameterType;
085 import org.crsh.cli.impl.invocation.CommandInvoker;
086 import org.crsh.cli.impl.invocation.InvocationException;
087 import org.crsh.cli.impl.invocation.InvocationMatch;
088 import org.crsh.cli.impl.invocation.ParameterMatch;
089 import org.crsh.cli.impl.invocation.Resolver;
090 import org.crsh.cli.type.ValueTypeFactory;
091
092 import java.io.IOException;
093 import java.lang.reflect.Type;
094 import java.util.Arrays;
095 import java.util.LinkedHashMap;
096 import java.util.Map;
097
098 /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
099 public class HelpDescriptor<T> extends CommandDescriptorImpl<T> {
100
101 public static <T> HelpDescriptor<T> create(CommandDescriptorImpl<T> descriptor) {
102 return new HelpDescriptor<T>(descriptor);
103 }
104
105 /** . */
106 static final OptionDescriptor HELP_OPTION = new OptionDescriptor(
107 null,
108 ParameterType.create(ValueTypeFactory.DEFAULT, Boolean.class),
109 Arrays.asList("h", "help"),
110 new Description("this help", "Display this help message"),
111 false,
112 false,
113 false,
114 null,
115 null
116 );
117
118 /** . */
119 private final HelpDescriptor<T> owner;
120
121 /** . */
122 private final CommandDescriptorImpl<T> delegate;
123
124 /** . */
125 private final LinkedHashMap<String, HelpDescriptor<T>> subordinates;
126
127 public HelpDescriptor(CommandDescriptorImpl<T> delegate) throws IntrospectionException {
128 this(null, delegate);
129 }
130
131 private HelpDescriptor(HelpDescriptor<T> owner, CommandDescriptorImpl<T> delegate) throws IntrospectionException {
132 super(delegate.getName(), delegate.getDescription());
133
134 //
135 for (ParameterDescriptor parameter : delegate.getParameters()) {
136 addParameter(parameter);
137 }
138
139 // Override the help parameter only for the root level
140 // otherwise it may be repeated several times
141 if (owner == null) {
142 addParameter(HELP_OPTION);
143 }
144
145 // Wrap subordinates
146 LinkedHashMap<String, HelpDescriptor<T>> subordinates = new LinkedHashMap<String, HelpDescriptor<T>>();
147 for (CommandDescriptorImpl<T> subordinate : delegate.getSubordinates().values()) {
148 subordinates.put(subordinate.getName(), new HelpDescriptor<T>(this, subordinate));
149 }
150
151 //
152 this.owner = owner;
153 this.delegate = delegate;
154 this.subordinates = subordinates;
155 }
156
157 public CommandDescriptor<T> getDelegate() {
158 return delegate;
159 }
160
161 @Override
162 public CommandInvoker<T> getInvoker(final InvocationMatch<T> match) {
163 final CommandInvoker<T> invoker = delegate.getInvoker(match);
164 return new CommandInvoker<T>() {
165 @Override
166 public Class<?> getReturnType() {
167 return invoker != null ? invoker.getReturnType() : Void.class;
168 }
169
170 @Override
171 public Type getGenericReturnType() {
172 return invoker != null ? invoker.getGenericReturnType() : Void.class;
173 }
174
175 @Override
176 public Class<?>[] getParameterTypes() {
177 return invoker != null ? invoker.getParameterTypes() : new Class[0];
178 }
179
180 @Override
181 public Type[] getGenericParameterTypes() {
182 return invoker != null ? invoker.getGenericParameterTypes() : new Type[0];
183 }
184
185 @Override
186 public Object invoke(Resolver resolver, T command) throws InvocationException, SyntaxException {
187
188 // Get the option from the top match
189 ParameterMatch<OptionDescriptor> help = null;
190 for (InvocationMatch<T> current = match;current != null && help == null;current = current.owner()) {
191 help = current.getParameter(HELP_OPTION);
192 }
193
194 //
195 if (help == null && invoker != null) {
196 return invoker.invoke(resolver, command);
197 } else {
198 return new Help<T>(delegate);
199 }
200 }
201 };
202 }
203
204 @Override
205 public Class<T> getType() {
206 return delegate.getType();
207 }
208
209 @Override
210 public CommandDescriptor<T> getOwner() {
211 return owner;
212 }
213
214 @Override
215 public Map<String, ? extends HelpDescriptor<T>> getSubordinates() {
216 return subordinates;
217 }
218
219 @Override
220 public HelpDescriptor<T> getSubordinate(String name) {
221 return subordinates.get(name);
222 }
223 }