java/alt2xml-cli/src/cz/frantovo/alt2xml/cli/CLIParser.java
author František Kučera <franta-hg@frantovo.cz>
Sun, 15 Nov 2020 20:20:39 +0100
changeset 116 94081a55bf41
parent 111 e4900596abdb
permissions -rw-r--r--
Added tag v0.2 for changeset 96e1125c8500
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@111
     7
 * the Free Software Foundation, version 3 of the License.
franta-hg@54
     8
 *
franta-hg@54
     9
 * This program is distributed in the hope that it will be useful,
franta-hg@54
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@54
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
franta-hg@54
    12
 * GNU General Public License for more details.
franta-hg@54
    13
 *
franta-hg@54
    14
 * You should have received a copy of the GNU General Public License
franta-hg@54
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
franta-hg@54
    16
 */
franta-hg@54
    17
package cz.frantovo.alt2xml.cli;
franta-hg@54
    18
franta-hg@54
    19
import java.io.File;
franta-hg@67
    20
import java.util.Arrays;
franta-hg@67
    21
import java.util.Collection;
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@55
    32
	public CLIOptions parseOptions(String[] args) 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@55
    38
			boolean matches = false;
franta-hg@55
    39
franta-hg@54
    40
			for (Token t : Token.values()) {
franta-hg@54
    41
				if (t.matches(arg)) {
franta-hg@55
    42
					int parsedArgs = t.parse(args, i, options);
franta-hg@55
    43
					i = i + parsedArgs;
franta-hg@55
    44
					matches = true;
franta-hg@54
    45
				}
franta-hg@54
    46
			}
franta-hg@54
    47
franta-hg@55
    48
			if (!matches) {
franta-hg@55
    49
				throw new CLIParserException("Unknown option: " + arg);
franta-hg@55
    50
			}
franta-hg@54
    51
		}
franta-hg@54
    52
franta-hg@55
    53
		// Default output:
franta-hg@54
    54
		options.setOutputStream(System.out);
franta-hg@54
    55
franta-hg@54
    56
		return options;
franta-hg@54
    57
	}
franta-hg@54
    58
franta-hg@54
    59
	private static String fetchNext(String[] args, int index) throws CLIParserException {
franta-hg@54
    60
		if (index < args.length) {
franta-hg@54
    61
			return args[index];
franta-hg@54
    62
		} else {
franta-hg@54
    63
			throw new CLIParserException("Expecting value for option: " + args[index - 1]);
franta-hg@54
    64
		}
franta-hg@54
    65
	}
franta-hg@54
    66
franta-hg@54
    67
	private static enum Token {
franta-hg@54
    68
franta-hg@54
    69
		INPUT_FILE("--input-file") {
franta-hg@54
    70
					@Override
franta-hg@54
    71
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    72
						int originalIndex = index;
franta-hg@54
    73
						options.setInputFile(new File(fetchNext(args, ++index)));
franta-hg@54
    74
						return index - originalIndex;
franta-hg@54
    75
					}
franta-hg@54
    76
				},
franta-hg@54
    77
		INPUT_STDIN("--input-stdin") {
franta-hg@54
    78
					@Override
franta-hg@54
    79
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    80
						options.setInputStream(System.in);
franta-hg@54
    81
						return 0;
franta-hg@54
    82
					}
franta-hg@54
    83
				},
franta-hg@67
    84
		SYSTEM_ID("--system-id", "--input-url") {
franta-hg@54
    85
					@Override
franta-hg@54
    86
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    87
						int originalIndex = index;
franta-hg@54
    88
						options.setSystemId(fetchNext(args, ++index));
franta-hg@54
    89
						return index - originalIndex;
franta-hg@54
    90
					}
franta-hg@54
    91
				},
franta-hg@54
    92
		READER_PROPERTY("--reader-property") {
franta-hg@54
    93
					@Override
franta-hg@54
    94
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
    95
						int originalIndex = index;
franta-hg@54
    96
						String name = fetchNext(args, ++index);
franta-hg@54
    97
						String value = fetchNext(args, ++index);
franta-hg@54
    98
						options.addReaderProperty(name, value);
franta-hg@54
    99
						return index - originalIndex;
franta-hg@54
   100
					}
franta-hg@54
   101
				},
franta-hg@98
   102
		READER_FEATURE("--reader-feature") {
franta-hg@98
   103
					@Override
franta-hg@98
   104
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@98
   105
						int originalIndex = index;
franta-hg@98
   106
						String name = fetchNext(args, ++index);
franta-hg@98
   107
						String value = fetchNext(args, ++index);
franta-hg@98
   108
						options.addReaderFeature(name, Boolean.valueOf(value));
franta-hg@98
   109
						return index - originalIndex;
franta-hg@98
   110
					}
franta-hg@98
   111
				},
franta-hg@100
   112
		READER_NAMESPACE_AWARE("--reader-namespace-aware") {
franta-hg@100
   113
					@Override
franta-hg@100
   114
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@100
   115
						int originalIndex = index;
franta-hg@100
   116
						String value = fetchNext(args, ++index);
franta-hg@100
   117
						options.addReaderFeature(Constants.SAX_PARSER_NAMESPACE_AWARE, Boolean.valueOf(value));
franta-hg@100
   118
						return index - originalIndex;
franta-hg@100
   119
					}
franta-hg@100
   120
				},
franta-hg@54
   121
		ACTION("--action") {
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
						options.setAction(fetchNext(args, ++index));
franta-hg@54
   126
						return index - originalIndex;
franta-hg@54
   127
					}
franta-hg@54
   128
				},
franta-hg@54
   129
		ACTION_PROPERTY("--action-property") {
franta-hg@54
   130
					@Override
franta-hg@54
   131
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
   132
						int originalIndex = index;
franta-hg@54
   133
						String name = fetchNext(args, ++index);
franta-hg@54
   134
						String value = fetchNext(args, ++index);
franta-hg@54
   135
						options.addActionProperty(name, value);
franta-hg@54
   136
						return index - originalIndex;
franta-hg@54
   137
					}
franta-hg@54
   138
				},
franta-hg@54
   139
		ACTION_DATA("--") {
franta-hg@54
   140
					@Override
franta-hg@54
   141
					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
franta-hg@54
   142
						int originalIndex = index;
franta-hg@54
   143
						for (index++; index < args.length; index++) {
franta-hg@54
   144
							options.addActionData(args[index]);
franta-hg@54
   145
						}
franta-hg@54
   146
						return index - originalIndex;
franta-hg@54
   147
					}
franta-hg@54
   148
				};
franta-hg@54
   149
franta-hg@67
   150
		private final Collection<String> options;
franta-hg@54
   151
franta-hg@67
   152
		private Token(String... options) {
franta-hg@67
   153
			this.options = Arrays.asList(options);
franta-hg@54
   154
		}
franta-hg@54
   155
franta-hg@54
   156
		/**
franta-hg@54
   157
		 * @param option e.g. „--input-file“
franta-hg@54
   158
		 * @return whether option is this token
franta-hg@54
   159
		 */
franta-hg@54
   160
		public boolean matches(String option) {
franta-hg@67
   161
			return options.contains(option);
franta-hg@54
   162
		}
franta-hg@54
   163
franta-hg@54
   164
		/**
franta-hg@54
   165
		 * Parse String arguments and fill values into the options object.
franta-hg@54
   166
		 *
franta-hg@54
   167
		 * @param args CLI arguments
franta-hg@54
   168
		 * @param index index of the option matched by this token, like „--input-file“
franta-hg@54
   169
		 * @param options object to be filled
franta-hg@54
   170
		 * @return number of parsed arguments – if option has no arguments (just boolean flag),
franta-hg@54
   171
		 * return 0, otherwise return positive integer: number of eaten arguments.
franta-hg@54
   172
		 * @throws CLIParserException
franta-hg@54
   173
		 */
franta-hg@54
   174
		public abstract int parse(String[] args, int index, CLIOptions options) throws CLIParserException;
franta-hg@54
   175
	}
franta-hg@54
   176
}