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.type.ValueTypeFactory;
090
091 import java.lang.reflect.Type;
092 import java.util.Arrays;
093 import java.util.LinkedHashMap;
094 import java.util.Map;
095
096 /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
097 public class HelpDescriptor<T> extends CommandDescriptor<T> {
098
099 public static <T> HelpDescriptor<T> create(CommandDescriptor<T> descriptor) {
100 return new HelpDescriptor<T>(descriptor);
101 }
102
103 /** . */
104 static final OptionDescriptor HELP_OPTION = new OptionDescriptor(
105 ParameterType.create(ValueTypeFactory.DEFAULT, Boolean.class),
106 Arrays.asList("h", "help"),
107 new Description("this help", "Display this help message"),
108 false,
109 false,
110 false,
111 null,
112 null
113 );
114
115 /** . */
116 private final HelpDescriptor<T> owner;
117
118 /** . */
119 private final CommandDescriptor<T> delegate;
120
121 /** . */
122 private final LinkedHashMap<String, HelpDescriptor<T>> subordinates;
123
124 public HelpDescriptor(CommandDescriptor<T> delegate) throws IntrospectionException {
125 this(null, delegate);
126 }
127
128 private HelpDescriptor(HelpDescriptor<T> owner, CommandDescriptor<T> delegate) throws IntrospectionException {
129 super(delegate.getName(), delegate.getDescription());
130
131 //
132 for (ParameterDescriptor parameter : delegate.getParameters()) {
133 addParameter(parameter);
134 }
135
136 // Override the help parameter only for the root level
137 // otherwise it may be repeated several times
138 if (owner == null) {
139 addParameter(HELP_OPTION);
140 }
141
142 // Wrap subordinates
143 LinkedHashMap<String, HelpDescriptor<T>> subordinates = new LinkedHashMap<String, HelpDescriptor<T>>();
144 for (CommandDescriptor<T> subordinate : delegate.getSubordinates().values()) {
145 subordinates.put(subordinate.getName(), new HelpDescriptor<T>(this, subordinate));
146 }
147
148 //
149 this.owner = owner;
150 this.delegate = delegate;
151 this.subordinates = subordinates;
152 }
153
154 public CommandDescriptor<T> getDelegate() {
155 return delegate;
156 }
157
158 @Override
159 public CommandInvoker<T, ?> getInvoker(final InvocationMatch<T> match) {
160
161 //
162 final CommandInvoker<T, ?> invoker = delegate.getInvoker(match);
163
164 // Get the option from the top match
165 ParameterMatch<OptionDescriptor> helpDesc = null;
166 for (InvocationMatch<T> current = match;current != null && helpDesc == null;current = current.owner()) {
167 helpDesc = current.getParameter(HELP_OPTION);
168 }
169
170 //
171 final boolean help = helpDesc != null || invoker == null;
172
173 //
174 if (help) {
175 return new CommandInvoker<T, Help>(match) {
176 @Override
177 public Class<Help> getReturnType() {
178 return Help.class;
179 }
180 @Override
181 public Type getGenericReturnType() {
182 return Help.class;
183 }
184 @Override
185 public Help invoke(T command) throws InvocationException, SyntaxException {
186 return new Help<T>(HelpDescriptor.this);
187 }
188 };
189 } else {
190 return invoker;
191 }
192 }
193
194 @Override
195 public CommandDescriptor<T> getOwner() {
196 return owner;
197 }
198
199 @Override
200 public Map<String, ? extends HelpDescriptor<T>> getSubordinates() {
201 return subordinates;
202 }
203
204 }