1 /* 2 * Copyright 2016, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package org.jf.util.jcommander; 33 34 import com.beust.jcommander.JCommander; 35 import com.beust.jcommander.ParameterDescription; 36 import com.beust.jcommander.Parameterized; 37 import com.beust.jcommander.Parameters; 38 39 import javax.annotation.Nonnull; 40 import javax.annotation.Nullable; 41 import java.lang.reflect.Field; 42 43 /** 44 * Utilities related to "extended" commands - JCommander commands with additional information 45 */ 46 public class ExtendedCommands { 47 48 @Nonnull getExtendedParameters(Object command)49 private static ExtendedParameters getExtendedParameters(Object command) { 50 ExtendedParameters anno = command.getClass().getAnnotation(ExtendedParameters.class); 51 if (anno == null) { 52 throw new IllegalStateException("All extended commands should have an ExtendedParameters annotation: " + 53 command.getClass().getCanonicalName()); 54 } 55 return anno; 56 } 57 58 @Nonnull commandName(JCommander jc)59 public static String commandName(JCommander jc) { 60 return getExtendedParameters(jc.getObjects().get(0)).commandName(); 61 } 62 63 @Nonnull commandName(Object command)64 public static String commandName(Object command) { 65 return getExtendedParameters(command).commandName(); 66 } 67 68 @Nonnull commandAliases(JCommander jc)69 public static String[] commandAliases(JCommander jc) { 70 return commandAliases(jc.getObjects().get(0)); 71 } 72 73 @Nonnull commandAliases(Object command)74 public static String[] commandAliases(Object command) { 75 return getExtendedParameters(command).commandAliases(); 76 } 77 includeParametersInUsage(JCommander jc)78 public static boolean includeParametersInUsage(JCommander jc) { 79 return includeParametersInUsage(jc.getObjects().get(0)); 80 } 81 includeParametersInUsage(Object command)82 public static boolean includeParametersInUsage(Object command) { 83 return getExtendedParameters(command).includeParametersInUsage(); 84 } 85 86 @Nonnull postfixDescription(JCommander jc)87 public static String postfixDescription(JCommander jc) { 88 return postfixDescription(jc.getObjects().get(0)); 89 } 90 91 @Nonnull postfixDescription(Object command)92 public static String postfixDescription(Object command) { 93 return getExtendedParameters(command).postfixDescription(); 94 } 95 addExtendedCommand(JCommander jc, Command command)96 public static void addExtendedCommand(JCommander jc, Command command) { 97 jc.addCommand(commandName(command), command, commandAliases(command)); 98 command.setupCommand(command.getJCommander()); 99 } 100 101 @Nonnull parameterArgumentNames(ParameterDescription parameterDescription)102 public static String[] parameterArgumentNames(ParameterDescription parameterDescription) { 103 Parameterized parameterized = parameterDescription.getParameterized(); 104 105 Class cls = parameterDescription.getObject().getClass(); 106 Field field = null; 107 while (cls != Object.class) { 108 try { 109 field = cls.getDeclaredField(parameterized.getName()); 110 } catch (NoSuchFieldException ex) { 111 cls = cls.getSuperclass(); 112 continue; 113 } 114 break; 115 } 116 117 assert field != null; 118 ExtendedParameter extendedParameter = field.getAnnotation(ExtendedParameter.class); 119 if (extendedParameter != null) { 120 return extendedParameter.argumentNames(); 121 } 122 123 return new String[0]; 124 } 125 126 @Nullable getSubcommand(JCommander jc, String commandName)127 public static JCommander getSubcommand(JCommander jc, String commandName) { 128 if (jc.getCommands().containsKey(commandName)) { 129 return jc.getCommands().get(commandName); 130 } else { 131 for (JCommander command : jc.getCommands().values()) { 132 for (String alias: commandAliases(command)) { 133 if (commandName.equals(alias)) { 134 return command; 135 } 136 } 137 } 138 } 139 return null; 140 } 141 142 @Nullable getCommandDescription(@onnull JCommander jc)143 public static String getCommandDescription(@Nonnull JCommander jc) { 144 Parameters parameters = jc.getObjects().get(0).getClass().getAnnotation(Parameters.class); 145 if (parameters == null) { 146 return null; 147 } 148 return parameters.commandDescription(); 149 } 150 } 151