java/alt2xml-cli/src/cz/frantovo/alt2xml/cli/CLIParser.java
author František Kučera <franta-hg@frantovo.cz>
Thu, 03 Jul 2014 00:18:35 +0200
changeset 54 3d5cc308e268
child 55 c703fb7f088f
permissions -rw-r--r--
CLIOptions, CLIParser – basics
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
import java.io.InputStream;
franta-hg@54
    22
franta-hg@54
    23
/**
franta-hg@54
    24
 * Converts command line arguments from String array to object.
franta-hg@54
    25
 * Checks basic constraints (if only supported options are used and if they have correct number of
franta-hg@54
    26
 * parameters)
franta-hg@54
    27
 *
franta-hg@54
    28
 * @author Ing. František Kučera (frantovo.cz)
franta-hg@54
    29
 */
franta-hg@54
    30
public class CLIParser {
franta-hg@54
    31
franta-hg@54
    32
	public CLIOptions parseOptions(String[] args, InputStream in) throws CLIParserException {
franta-hg@54
    33
		CLIOptions options = new CLIOptions();
franta-hg@54
    34
franta-hg@54
    35
		for (int i = 0; i < args.length; i++) {
franta-hg@54
    36
			String arg = args[i];
franta-hg@54
    37
franta-hg@54
    38
			for (Token t : Token.values()) {
franta-hg@54
    39
				if (t.matches(arg)) {
franta-hg@54
    40
					t.parse(args, i, options);
franta-hg@54
    41
				}
franta-hg@54
    42
			}
franta-hg@54
    43
franta-hg@54
    44
			throw new CLIParserException("Unknown option: " + arg);
franta-hg@54
    45
		}
franta-hg@54
    46
franta-hg@54
    47
		// Default output: STDOUT
franta-hg@54
    48
		options.setOutputStream(System.out);
franta-hg@54
    49
franta-hg@54
    50
		return options;
franta-hg@54
    51
	}
franta-hg@54
    52
franta-hg@54
    53
	private static String fetchNext(String[] args, int index) throws CLIParserException {
franta-hg@54
    54
		if (index < args.length) {
franta-hg@54
    55
			return args[index];
franta-hg@54
    56
		} else {
franta-hg@54
    57
			throw new CLIParserException("Expecting value for option: " + args[index - 1]);
franta-hg@54
    58
		}
franta-hg@54
    59
	}
franta-hg@54
    60
franta-hg@54
    61
	private static enum Token {
franta-hg@54
    62
franta-hg@54
    63
		INPUT_FILE("--input-file") {
franta-hg@54
    64
					@Override
franta-hg@54
    65
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    66
						int originalIndex = index;
franta-hg@54
    67
						options.setInputFile(new File(fetchNext(args, ++index)));
franta-hg@54
    68
						return index - originalIndex;
franta-hg@54
    69
					}
franta-hg@54
    70
				},
franta-hg@54
    71
		INPUT_STDIN("--input-stdin") {
franta-hg@54
    72
					@Override
franta-hg@54
    73
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    74
						options.setInputStream(System.in);
franta-hg@54
    75
						return 0;
franta-hg@54
    76
					}
franta-hg@54
    77
				},
franta-hg@54
    78
		INPUT_URL("--input-url") {
franta-hg@54
    79
					@Override
franta-hg@54
    80
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    81
						int originalIndex = index;
franta-hg@54
    82
						options.setInputUrl(fetchNext(args, ++index));
franta-hg@54
    83
						return index - originalIndex;
franta-hg@54
    84
					}
franta-hg@54
    85
				},
franta-hg@54
    86
		SYSTEM_ID("--system-id") {
franta-hg@54
    87
					@Override
franta-hg@54
    88
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    89
						int originalIndex = index;
franta-hg@54
    90
						options.setSystemId(fetchNext(args, ++index));
franta-hg@54
    91
						return index - originalIndex;
franta-hg@54
    92
					}
franta-hg@54
    93
				},
franta-hg@54
    94
		READER_PROPERTY("--reader-property") {
franta-hg@54
    95
					@Override
franta-hg@54
    96
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    97
						int originalIndex = index;
franta-hg@54
    98
						String name = fetchNext(args, ++index);
franta-hg@54
    99
						String value = fetchNext(args, ++index);
franta-hg@54
   100
						options.addReaderProperty(name, value);
franta-hg@54
   101
						return index - originalIndex;
franta-hg@54
   102
					}
franta-hg@54
   103
				},
franta-hg@54
   104
		ACTION("--action") {
franta-hg@54
   105
					@Override
franta-hg@54
   106
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
   107
						int originalIndex = index;
franta-hg@54
   108
						options.setAction(fetchNext(args, ++index));
franta-hg@54
   109
						return index - originalIndex;
franta-hg@54
   110
					}
franta-hg@54
   111
				},
franta-hg@54
   112
		ACTION_PROPERTY("--action-property") {
franta-hg@54
   113
					@Override
franta-hg@54
   114
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
   115
						int originalIndex = index;
franta-hg@54
   116
						String name = fetchNext(args, ++index);
franta-hg@54
   117
						String value = fetchNext(args, ++index);
franta-hg@54
   118
						options.addActionProperty(name, value);
franta-hg@54
   119
						return index - originalIndex;
franta-hg@54
   120
					}
franta-hg@54
   121
				},
franta-hg@54
   122
		ACTION_DATA("--") {
franta-hg@54
   123
					@Override
franta-hg@54
   124
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
   125
						int originalIndex = index;
franta-hg@54
   126
						for (index++; index < args.length; index++) {
franta-hg@54
   127
							options.addActionData(args[index]);
franta-hg@54
   128
						}
franta-hg@54
   129
						return index - originalIndex;
franta-hg@54
   130
					}
franta-hg@54
   131
				};
franta-hg@54
   132
franta-hg@54
   133
		private final String option;
franta-hg@54
   134
franta-hg@54
   135
		private Token(String option) {
franta-hg@54
   136
			this.option = option;
franta-hg@54
   137
		}
franta-hg@54
   138
franta-hg@54
   139
		/**
franta-hg@54
   140
		 * @param option e.g. „--input-file“
franta-hg@54
   141
		 * @return whether option is this token
franta-hg@54
   142
		 */
franta-hg@54
   143
		public boolean matches(String option) {
franta-hg@54
   144
			return this.option.equals(option);
franta-hg@54
   145
		}
franta-hg@54
   146
franta-hg@54
   147
		/**
franta-hg@54
   148
		 * Parse String arguments and fill values into the options object.
franta-hg@54
   149
		 *
franta-hg@54
   150
		 * @param args CLI arguments
franta-hg@54
   151
		 * @param index index of the option matched by this token, like „--input-file“
franta-hg@54
   152
		 * @param options object to be filled
franta-hg@54
   153
		 * @return number of parsed arguments – if option has no arguments (just boolean flag),
franta-hg@54
   154
		 * return 0, otherwise return positive integer: number of eaten arguments.
franta-hg@54
   155
		 * @throws CLIParserException
franta-hg@54
   156
		 */
franta-hg@54
   157
		public abstract int parse(String[] args, int index, CLIOptions options) throws CLIParserException;
franta-hg@54
   158
	}
franta-hg@54
   159
}