001 /*
002 * JAPI - (Yet another (hopefully) useful) Java API
003 *
004 * Copyright (C) 2006 Christian Hujer
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU General Public License as
008 * published by the Free Software Foundation; either version 2 of the
009 * License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful, but
012 * WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program; if not, write to the Free Software
018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
019 * 02111-1307, USA.
020 */
021
022 package net.sf.japi.io.args;
023
024 import java.lang.reflect.InvocationTargetException;
025 import java.lang.reflect.Method;
026 import java.util.ArrayList;
027 import java.util.Arrays;
028 import java.util.HashMap;
029 import java.util.Iterator;
030 import java.util.List;
031 import java.util.Map;
032
033 /** Parser for command line arguments.
034 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
035 */
036 public class ArgParser {
037
038 /** Parses arguments into an arguments container and invokes the Command's {@link Command#run(List<String>)} method.
039 * @param argsContainer object to hold parsed arguments
040 * @param args Arguments to parse
041 */
042 public static void parse(final Command argsContainer, final String... args) {
043 final List<String> argList = new ArrayList<String>(Arrays.asList(args));
044 final Class<?> argsContainerClass = argsContainer.getClass();
045 final Method[] argsContainerMethods = argsContainerClass.getMethods();
046 final Map<String, Method> argumentMethods = new HashMap<String, Method>();
047 for (final Method method : argsContainerMethods) {
048 final Option option = method.getAnnotation(Option.class);
049 if (option != null) {
050 for (final String optionString : option.value()) {
051 argumentMethods.put(optionString.length() > 1 ? '-' + optionString : optionString, method);
052 }
053 }
054 }
055 for (final Iterator<String> it = argList.iterator(); it.hasNext(); ) {
056 final String arg = it.next();
057 if (arg.length() > 1 && arg.charAt(0) == '-') {
058 it.remove();
059 if ("--".equals(arg)) {
060 //noinspection BreakStatement
061 break;
062 }
063 if (arg.charAt(1) == '-') {
064 if (invokeMethod(argumentMethods.get(arg.substring(1)), argsContainer)) {
065 return;
066 }
067 } else {
068 for (final String realArg : arg.substring(1).split("")) {
069 if (invokeMethod(argumentMethods.get(arg.substring(1)), argsContainer)) {
070 return;
071 }
072 }
073 }
074 }
075 // empty arguments are intentionally not removed.
076 }
077 argsContainer.run(argList);
078 }
079
080 /** Invoke an argument method.
081 * @param method
082 * @param argsContainer
083 * @return true if the method indicated to stop parsing the arguments
084 */
085 private static boolean invokeMethod(final Method method, final Command argsContainer) {
086 if (method == null) {
087 throw new RuntimeException("Unknown argument Exception");
088 }
089 try {
090 method.invoke(argsContainer);
091 } catch (final IllegalAccessException e) {
092 System.err.println(e);
093 } catch (final InvocationTargetException e) {
094 System.err.println(e.getCause());
095 }
096 return method.getAnnotation(StopOption.class) != null;
097 }
098
099 } // class ArgParser