CommandlineProcessor.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /**
  2. * MCS Media Computer Software
  3. * Copyright 2018 by Wilfried Klaas
  4. * Project: MCSUtils
  5. * File: ProcessCommandline.java
  6. * EMail: W.Klaas@gmx.de
  7. * Created: 29.11.2018 wklaa_000
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>
  21. */
  22. package de.mcs.utils.jsap;
  23. import java.lang.annotation.Annotation;
  24. import java.lang.reflect.InvocationTargetException;
  25. import java.lang.reflect.Method;
  26. import java.util.ArrayList;
  27. import java.util.HashMap;
  28. import java.util.Iterator;
  29. import java.util.List;
  30. import java.util.Map;
  31. import com.martiansoftware.jsap.FlaggedOption;
  32. import com.martiansoftware.jsap.JSAP;
  33. import com.martiansoftware.jsap.JSAPException;
  34. import com.martiansoftware.jsap.JSAPResult;
  35. import com.martiansoftware.jsap.UnflaggedOption;
  36. import com.martiansoftware.jsap.stringparsers.FileStringParser;
  37. import com.martiansoftware.jsap.stringparsers.StringStringParser;
  38. /**
  39. * @author wklaa_000
  40. *
  41. */
  42. public class CommandlineProcessor {
  43. private static JSAP parser;
  44. private static JSAPResult commandLineArgs;
  45. private static Map<String, Method> parameterMethods;
  46. private static Command helpContext;
  47. public static void processCommandline(Class class1, String[] args) {
  48. parameterMethods = new HashMap<>();
  49. parseParameters(class1, args);
  50. checkParams();
  51. processParameters();
  52. };
  53. private static void processParameters() {
  54. parameterMethods.entrySet().forEach(e -> {
  55. String name = e.getKey();
  56. Method method = e.getValue();
  57. processSwitchOption(name, method);
  58. processStringOption(name, method);
  59. processFileOption(name, method);
  60. });
  61. }
  62. private static void processFileOption(String name, Method method) {
  63. FileOption annotation = method.getAnnotation(FileOption.class);
  64. if (annotation != null) {
  65. try {
  66. method.invoke(null, commandLineArgs.getFile(annotation.name()));
  67. } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
  68. e1.printStackTrace();
  69. }
  70. }
  71. }
  72. private static void processStringOption(String name, Method method) {
  73. StringOption annotation = method.getAnnotation(StringOption.class);
  74. if (annotation != null) {
  75. try {
  76. method.invoke(null, commandLineArgs.getString(annotation.name()));
  77. } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
  78. e1.printStackTrace();
  79. }
  80. }
  81. }
  82. private static void processSwitchOption(String name, Method method) {
  83. SwitchOption annotation = method.getAnnotation(SwitchOption.class);
  84. if (annotation != null) {
  85. try {
  86. method.invoke(null, commandLineArgs.getBoolean(name));
  87. } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
  88. e1.printStackTrace();
  89. }
  90. }
  91. }
  92. /**
  93. * checking commandline parameters.
  94. */
  95. private static void checkParams() {
  96. if (!commandLineArgs.success()) {
  97. System.err.println();
  98. // print out specific error messages describing the problems
  99. // with the command line, THEN print usage, THEN print full
  100. // help. This is called "beating the user with a clue stick."
  101. for (@SuppressWarnings("rawtypes")
  102. Iterator errs = commandLineArgs.getErrorMessageIterator(); errs.hasNext();) {
  103. System.err.println("Error: " + errs.next());
  104. }
  105. showHelp("error");
  106. System.exit(-1);
  107. }
  108. }
  109. /**
  110. * showing the actual help page in console.
  111. */
  112. public static void showHelp() {
  113. showHelp(null);
  114. }
  115. /**
  116. * showing the actual help page in console.
  117. */
  118. public static void showHelp(String message) {
  119. if (helpContext != null) {
  120. System.out.println(helpContext.help());
  121. }
  122. if (message != null) {
  123. System.out.println(message);
  124. }
  125. System.out.println(parser.getHelp());
  126. }
  127. /**
  128. * This function parses the commandline parameters. If the parameter -h or
  129. * --help is avalible, generate a little help text.
  130. *
  131. * @param mainClass
  132. *
  133. * @param args
  134. * Commadline arguments
  135. */
  136. public static void parseParameters(Class mainClass, final String[] args) {
  137. parser = new JSAP();
  138. try {
  139. // registering the main help context, if availble
  140. registerHelpContext(mainClass);
  141. // registering the parameters with default values
  142. registerDefaultParameter(mainClass);
  143. // parsing the commadline
  144. commandLineArgs = parser.parse(args);
  145. } catch (JSAPException e) {
  146. // Something goes wrong
  147. System.out.println("Parsing exception:" + e.getMessage());
  148. e.printStackTrace();
  149. System.exit(1);
  150. }
  151. }
  152. private static void registerHelpContext(Class mainClass) {
  153. Command annotation = (Command) mainClass.getAnnotation(Command.class);
  154. if (annotation != null) {
  155. helpContext = annotation;
  156. }
  157. }
  158. /**
  159. * registering the parameters to the JSAP Parser.
  160. *
  161. * @param mainClass
  162. *
  163. * @throws JSAPException
  164. * Something is going wrong
  165. */
  166. private static void registerDefaultParameter(Class mainClass) throws JSAPException {
  167. Map<Integer, UnflaggedOption> unflaggedOptions = new HashMap<>();
  168. List<Method> methodes = getMethodsAnnotatedWith(mainClass, SwitchOption.class);
  169. for (Method method : methodes) {
  170. SwitchOption annotation = method.getAnnotation(SwitchOption.class);
  171. com.martiansoftware.jsap.Switch swtOption = new com.martiansoftware.jsap.Switch(annotation.name(),
  172. annotation.shortKey(), annotation.longKey());
  173. if (annotation.defaultValue()) {
  174. swtOption.setDefault(Boolean.TRUE.toString());
  175. }
  176. swtOption.setHelp(annotation.help());
  177. parser.registerParameter(swtOption);
  178. parameterMethods.put(annotation.name(), method);
  179. }
  180. methodes = getMethodsAnnotatedWith(mainClass, StringOption.class);
  181. for (Method method : methodes) {
  182. StringOption annotation = method.getAnnotation(StringOption.class);
  183. StringStringParser stringParser = StringStringParser.getParser();
  184. if (annotation.index() > 0) {
  185. UnflaggedOption unflgopt = new UnflaggedOption(annotation.name(), stringParser, annotation.defaultValue(),
  186. annotation.required(), false, annotation.help());
  187. unflaggedOptions.put(annotation.index(), unflgopt);
  188. parameterMethods.put(Integer.toString(annotation.index()), method);
  189. } else {
  190. FlaggedOption flgopt = new FlaggedOption(annotation.name(), stringParser, annotation.defaultValue(),
  191. annotation.required(), annotation.shortKey(), annotation.longKey());
  192. flgopt.setHelp(annotation.help());
  193. parser.registerParameter(flgopt);
  194. parameterMethods.put(annotation.name(), method);
  195. }
  196. }
  197. methodes = getMethodsAnnotatedWith(mainClass, FileOption.class);
  198. for (Method method : methodes) {
  199. FileOption annotation = method.getAnnotation(FileOption.class);
  200. FileStringParser fileStringParser = FileStringParser.getParser();
  201. fileStringParser.setMustBeDirectory(annotation.mustBeDirectory());
  202. fileStringParser.setMustExist(annotation.mustExists());
  203. if (annotation.index() > 0) {
  204. UnflaggedOption unflgopt = new UnflaggedOption(annotation.name(), fileStringParser, annotation.defaultValue(),
  205. annotation.required(), false, annotation.help());
  206. unflaggedOptions.put(annotation.index(), unflgopt);
  207. parameterMethods.put(Integer.toString(annotation.index()), method);
  208. } else {
  209. FlaggedOption flgopt = new FlaggedOption(annotation.name(), fileStringParser, annotation.defaultValue(),
  210. annotation.required(), annotation.shortKey(), annotation.longKey());
  211. flgopt.setHelp(annotation.help());
  212. parser.registerParameter(flgopt);
  213. parameterMethods.put(annotation.name(), method);
  214. }
  215. }
  216. // sorting unflagged options
  217. List<Integer> indexes = new ArrayList<>();
  218. unflaggedOptions.keySet().forEach(e -> indexes.add(e));
  219. indexes.sort((x, y) -> {
  220. int diff = x - y;
  221. return (diff == 0) ? 1 : diff;
  222. });
  223. // registering the unflagged options in the right order
  224. for (Integer e : indexes) {
  225. parser.registerParameter(unflaggedOptions.get(e));
  226. }
  227. }
  228. private static List<Method> getMethodsAnnotatedWith(Class class1, Class annotationClass) {
  229. List<Method> list = new ArrayList<>();
  230. Method[] methods = class1.getMethods();
  231. for (Method method : methods) {
  232. Annotation[] annotations = method.getAnnotationsByType(annotationClass);
  233. if (annotations.length > 0) {
  234. list.add(method);
  235. }
  236. }
  237. return list;
  238. }
  239. }