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 }