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