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