java/copy-image-resizer/src/cz/frantovo/copyImageResizer/cli/CLIParser.java
author František Kučera <franta-hg@frantovo.cz>
Sun, 16 Nov 2014 21:59:13 +0100
changeset 4 f3b4caf1d05d
parent 3 java/copy-image-resizer/src/cz/frantovo/copyImageResizer/CLIParser.java@e417b37e6c08
child 5 5019e3e93a4e
permissions -rw-r--r--
move to java package: cli
     1 /**
     2  * copy-image-resizer
     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.copyImageResizer.cli;
    19 
    20 import java.io.File;
    21 import java.util.Arrays;
    22 import java.util.Collection;
    23 
    24 /**
    25  *
    26  * @author Ing. František Kučera (frantovo.cz)
    27  */
    28 public class CLIParser {
    29 
    30 	public CLIOptions parseOptions(String[] args) throws CLIParserException {
    31 		CLIOptions options = new CLIOptions();
    32 
    33 		for (int i = 0; i < args.length; i++) {
    34 			String arg = args[i];
    35 
    36 			boolean matches = false;
    37 
    38 			for (Token t : Token.values()) {
    39 				if (t.matches(arg)) {
    40 					int parsedArgs = t.parse(args, i, options);
    41 					i = i + parsedArgs;
    42 					matches = true;
    43 				}
    44 			}
    45 
    46 			if (!matches) {
    47 				throw new CLIParserException("Unknown option: " + arg);
    48 			}
    49 		}
    50 
    51 		return options;
    52 	}
    53 
    54 	private static String fetchNext(String[] args, int index) throws CLIParserException {
    55 		if (index < args.length) {
    56 			return args[index];
    57 		} else {
    58 			throw new CLIParserException("Expecting value for option: " + args[index - 1]);
    59 		}
    60 	}
    61 
    62 	private static enum Token {
    63 
    64 		INPUT_DIR("--input-dir") { // bash-completion: option
    65 					@Override
    66 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    67 						int originalIndex = index;
    68 						String name = fetchNext(args, ++index);
    69 						options.setInput(new File(name));
    70 						return index - originalIndex;
    71 					}
    72 				},
    73 		OUTPUT_DIR("--output-dir") { // bash-completion: option
    74 					@Override
    75 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    76 						int originalIndex = index;
    77 						String name = fetchNext(args, ++index);
    78 						options.setOutput(new File(name));
    79 						return index - originalIndex;
    80 					}
    81 				},
    82 		SIZE("--size") { // bash-completion: option
    83 					@Override
    84 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    85 						int originalIndex = index;
    86 						int width = parseInt(fetchNext(args, ++index));
    87 						int height = parseInt(fetchNext(args, ++index));
    88 						String directory = width + "x" + height;
    89 						options.addSize(new CLIOptions.SizeSpecification(width, height, directory));
    90 						return index - originalIndex;
    91 					}
    92 				},
    93 		SIZE_NAMED("--size-named") { // bash-completion: option
    94 					@Override
    95 					public int parse(String[] args, int index, CLIOptions options) throws CLIParserException {
    96 						int originalIndex = index;
    97 						int width = parseInt(fetchNext(args, ++index));
    98 						int height = parseInt(fetchNext(args, ++index));
    99 						String directory = fetchNext(args, ++index);
   100 						options.addSize(new CLIOptions.SizeSpecification(width, height, directory));
   101 						return index - originalIndex;
   102 					}
   103 				};
   104 
   105 		private final Collection<String> options;
   106 
   107 		private Token(String... options) {
   108 			this.options = Arrays.asList(options);
   109 		}
   110 
   111 		/**
   112 		 * @param option e.g. „--input-file“
   113 		 * @return whether option is this token
   114 		 */
   115 		public boolean matches(String option) {
   116 			return options.contains(option);
   117 		}
   118 
   119 		private static int parseInt(String number) throws CLIParserException {
   120 			try {
   121 				return Integer.parseInt(number);
   122 			} catch (Exception e) {
   123 				throw new CLIParserException("Unable to parse integer: " + number, e);
   124 			}
   125 		}
   126 
   127 		/**
   128 		 * Parse String arguments and fill values into the options object.
   129 		 *
   130 		 * @param args CLI arguments
   131 		 * @param index index of the option matched by this token, like „--input-file“
   132 		 * @param options object to be filled
   133 		 * @return number of parsed arguments – if option has no arguments (just boolean flag),
   134 		 * return 0, otherwise return positive integer: number of eaten arguments.
   135 		 * @throws CLIParserException
   136 		 */
   137 		public abstract int parse(String[] args, int index, CLIOptions options) throws CLIParserException;
   138 	}
   139 }