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