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