java/alt2xml-cli/src/cz/frantovo/alt2xml/cli/CLIParser.java
author František Kučera <franta-hg@frantovo.cz>
Thu, 03 Jul 2014 00:37:38 +0200
changeset 55 c703fb7f088f
parent 54 3d5cc308e268
child 67 96ce967c0182
permissions -rw-r--r--
CLIOptions, CLIParser – first working version
     1 /**
     2  * Alt2XML
     3  * Copyright © 2014 František Kučera (frantovo.cz)
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, either version 3 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License
    16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 package cz.frantovo.alt2xml.cli;
    19 
    20 import java.io.File;
    21 
    22 /**
    23  * Converts command line arguments from String array to object.
    24  * Checks basic constraints (if only supported options are used and if they have correct number of
    25  * parameters)
    26  *
    27  * @author Ing. František Kučera (frantovo.cz)
    28  */
    29 public class CLIParser {
    30 
    31 	public CLIOptions parseOptions(String[] args) throws CLIParserException {
    32 		CLIOptions options = new CLIOptions();
    33 
    34 		for (int i = 0; i < args.length; i++) {
    35 			String arg = args[i];
    36 
    37 			boolean matches = false;
    38 
    39 			for (Token t : Token.values()) {
    40 				if (t.matches(arg)) {
    41 					int parsedArgs = t.parse(args, i, options);
    42 					i = i + parsedArgs;
    43 					matches = true;
    44 				}
    45 			}
    46 
    47 			if (!matches) {
    48 				throw new CLIParserException("Unknown option: " + arg);
    49 			}
    50 		}
    51 
    52 		// Default output:
    53 		options.setOutputStream(System.out);
    54 
    55 		return options;
    56 	}
    57 
    58 	private static String fetchNext(String[] args, int index) throws CLIParserException {
    59 		if (index < args.length) {
    60 			return args[index];
    61 		} else {
    62 			throw new CLIParserException("Expecting value for option: " + args[index - 1]);
    63 		}
    64 	}
    65 
    66 	private static enum Token {
    67 
    68 		INPUT_FILE("--input-file") {
    69 					@Override
    70 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    71 						int originalIndex = index;
    72 						options.setInputFile(new File(fetchNext(args, ++index)));
    73 						return index - originalIndex;
    74 					}
    75 				},
    76 		INPUT_STDIN("--input-stdin") {
    77 					@Override
    78 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    79 						options.setInputStream(System.in);
    80 						return 0;
    81 					}
    82 				},
    83 		SYSTEM_ID("--system-id") {
    84 					@Override
    85 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    86 						int originalIndex = index;
    87 						options.setSystemId(fetchNext(args, ++index));
    88 						return index - originalIndex;
    89 					}
    90 				},
    91 		READER_PROPERTY("--reader-property") {
    92 					@Override
    93 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    94 						int originalIndex = index;
    95 						String name = fetchNext(args, ++index);
    96 						String value = fetchNext(args, ++index);
    97 						options.addReaderProperty(name, value);
    98 						return index - originalIndex;
    99 					}
   100 				},
   101 		ACTION("--action") {
   102 					@Override
   103 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
   104 						int originalIndex = index;
   105 						options.setAction(fetchNext(args, ++index));
   106 						return index - originalIndex;
   107 					}
   108 				},
   109 		ACTION_PROPERTY("--action-property") {
   110 					@Override
   111 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
   112 						int originalIndex = index;
   113 						String name = fetchNext(args, ++index);
   114 						String value = fetchNext(args, ++index);
   115 						options.addActionProperty(name, value);
   116 						return index - originalIndex;
   117 					}
   118 				},
   119 		ACTION_DATA("--") {
   120 					@Override
   121 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
   122 						int originalIndex = index;
   123 						for (index++; index < args.length; index++) {
   124 							options.addActionData(args[index]);
   125 						}
   126 						return index - originalIndex;
   127 					}
   128 				};
   129 
   130 		private final String option;
   131 
   132 		private Token(String option) {
   133 			this.option = option;
   134 		}
   135 
   136 		/**
   137 		 * @param option e.g. „--input-file“
   138 		 * @return whether option is this token
   139 		 */
   140 		public boolean matches(String option) {
   141 			return this.option.equals(option);
   142 		}
   143 
   144 		/**
   145 		 * Parse String arguments and fill values into the options object.
   146 		 *
   147 		 * @param args CLI arguments
   148 		 * @param index index of the option matched by this token, like „--input-file“
   149 		 * @param options object to be filled
   150 		 * @return number of parsed arguments – if option has no arguments (just boolean flag),
   151 		 * return 0, otherwise return positive integer: number of eaten arguments.
   152 		 * @throws CLIParserException
   153 		 */
   154 		public abstract int parse(String[] args, int index, CLIOptions options) throws CLIParserException;
   155 	}
   156 }