Permalink
Browse files

Use JCommander for CommandLineRunner args

  • Loading branch information...
1 parent 106fd2f commit 8fe986a9aa412c16fe7a7c82b058f229f62a8490 @srowen srowen committed May 3, 2015
View
@@ -9,3 +9,9 @@ Copyright 2005-2006 Dietmar Bürkle
Portions of this software were contributed under section 5 of the
Apache License. Contributors are listed under:
http://barcode4j.sourceforge.net/contributors.html
+
+--------------------------------------------------------------------------------
+NOTICES FOR JCOMMANDER
+--------------------------------------------------------------------------------
+
+Copyright 2010 Cedric Beust cedric@beust.com
View
@@ -26,6 +26,11 @@
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.beust</groupId>
+ <artifactId>jcommander</artifactId>
+ <version>1.48</version>
+ </dependency>
</dependencies>
<parent>
@@ -16,25 +16,22 @@
package com.google.zxing.client.j2se;
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.DecodeHintType;
-
+import com.beust.jcommander.JCommander;
import java.io.IOException;
import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.EnumMap;
-import java.util.Map;
+import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import java.util.regex.Pattern;
/**
* This simple command line utility decodes files, directories of files, or URIs which are passed
@@ -47,188 +44,109 @@
*/
public final class CommandLineRunner {
- private static final Pattern COMMA = Pattern.compile(",");
-
private CommandLineRunner() {
}
public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- printUsage();
+ DecoderConfig config = new DecoderConfig();
+ JCommander jCommander = new JCommander(config, args);
+ jCommander.setProgramName(CommandLineRunner.class.getSimpleName());
+ if (config.help) {
+ jCommander.usage();
return;
}
- Config config = new Config();
- Queue<URI> inputs = new ConcurrentLinkedQueue<>();
-
- for (String arg : args) {
- String[] argValue = arg.split("=");
- switch (argValue[0]) {
- case "--try_harder":
- config.setTryHarder(true);
- break;
- case "--pure_barcode":
- config.setPureBarcode(true);
- break;
- case "--products_only":
- config.setProductsOnly(true);
- break;
- case "--dump_results":
- config.setDumpResults(true);
- break;
- case "--dump_black_point":
- config.setDumpBlackPoint(true);
- break;
- case "--multi":
- config.setMulti(true);
- break;
- case "--brief":
- config.setBrief(true);
- break;
- case "--recursive":
- config.setRecursive(true);
- break;
- case "--crop":
- int[] crop = new int[4];
- String[] tokens = COMMA.split(argValue[1]);
- for (int i = 0; i < crop.length; i++) {
- crop[i] = Integer.parseInt(tokens[i]);
- }
- config.setCrop(crop);
- break;
- case "--possibleFormats":
- config.setPossibleFormats(COMMA.split(argValue[1]));
- break;
- default:
- if (arg.startsWith("-")) {
- System.err.println("Unknown command line option " + arg);
- printUsage();
- return;
- }
- URI argURI = URI.create(arg);
- if (argURI.getScheme() == null) {
- argURI = new URI("file", argURI.getSchemeSpecificPart(), argURI.getFragment());
- }
- addArgumentToInputs(argURI, config, inputs);
- break;
- }
- }
+ List<URI> inputs = config.inputPaths;
+ do {
+ inputs = retainValid(expand(inputs), config.recursive);
+ } while (config.recursive && isExpandable(inputs));
int numInputs = inputs.size();
if (numInputs == 0) {
- System.err.println("No inputs specified");
- printUsage();
+ jCommander.usage();
return;
}
- config.setHints(buildHints(config));
-
+ Queue<URI> syncInputs = new ConcurrentLinkedQueue<>(inputs);
int numThreads = Math.min(numInputs, Runtime.getRuntime().availableProcessors());
int successful = 0;
if (numThreads > 1) {
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
Collection<Future<Integer>> futures = new ArrayList<>(numThreads);
for (int x = 0; x < numThreads; x++) {
- futures.add(executor.submit(new DecodeWorker(config, inputs)));
+ futures.add(executor.submit(new DecodeWorker(config, syncInputs)));
}
executor.shutdown();
for (Future<Integer> future : futures) {
successful += future.get();
}
} else {
- successful += new DecodeWorker(config, inputs).call();
+ successful += new DecodeWorker(config, syncInputs).call();
}
- if (numInputs > 1) {
+ if (!config.brief && numInputs > 1) {
System.out.println("\nDecoded " + successful + " files out of " + numInputs +
" successfully (" + (successful * 100 / numInputs) + "%)\n");
}
}
- /**
- * Build all the inputs up front into a single flat list, so the threads can atomically pull
- * paths/URLs off the queue.
- */
- private static void addArgumentToInputs(URI input, Config config, Queue<URI> inputs) throws IOException {
- // Special case: a local directory
- if ("file".equals(input.getScheme()) && Files.isDirectory(Paths.get(input))) {
- try (DirectoryStream<Path> childPaths = Files.newDirectoryStream(Paths.get(input))) {
- for (Path childPath : childPaths) {
- Path realChildPath = childPath.toRealPath();
- // Skip hidden files and directories (e.g. svn stuff).
- if (!realChildPath.getFileName().toString().startsWith(".")) {
- // Recur on nested directories if requested, otherwise skip them.
- if (config.isRecursive() && Files.isDirectory(realChildPath)) {
- addArgumentToInputs(realChildPath.toUri(), config, inputs);
- } else {
- inputs.add(realChildPath.toUri());
+ private static List<URI> expand(List<URI> inputs) throws IOException, URISyntaxException {
+ List<URI> expanded = new ArrayList<>();
+ for (URI input : inputs) {
+ if (isFileOrDir(input)) {
+ Path inputPath = Paths.get(input);
+ if (Files.isDirectory(inputPath)) {
+ try (DirectoryStream<Path> childPaths = Files.newDirectoryStream(inputPath)) {
+ for (Path childPath : childPaths) {
+ expanded.add(childPath.toUri());
}
}
+ } else {
+ expanded.add(input);
}
+ } else {
+ expanded.add(input);
+ }
+ }
+ for (int i = 0; i < expanded.size(); i++) {
+ URI input = expanded.get(i);
+ if (input.getScheme() == null) {
+ expanded.set(i, new URI("file", input.getSchemeSpecificPart(), input.getFragment()));
}
- } else {
- inputs.add(input);
}
+ return expanded;
}
- private static Map<DecodeHintType,?> buildHints(Config config) {
- Collection<BarcodeFormat> possibleFormats = new ArrayList<>();
- String[] possibleFormatsNames = config.getPossibleFormats();
- if (possibleFormatsNames != null && possibleFormatsNames.length > 0) {
- for (String format : possibleFormatsNames) {
- possibleFormats.add(BarcodeFormat.valueOf(format));
+ private static List<URI> retainValid(List<URI> inputs, boolean recursive) {
+ List<URI> retained = new ArrayList<>();
+ for (URI input : inputs) {
+ boolean retain;
+ if (isFileOrDir(input)) {
+ Path inputPath = Paths.get(input);
+ retain =
+ !inputPath.getFileName().toString().startsWith(".") &&
+ (recursive || !Files.isDirectory(inputPath));
+ } else {
+ retain = true;
}
- } else {
- possibleFormats.add(BarcodeFormat.UPC_A);
- possibleFormats.add(BarcodeFormat.UPC_E);
- possibleFormats.add(BarcodeFormat.EAN_13);
- possibleFormats.add(BarcodeFormat.EAN_8);
- possibleFormats.add(BarcodeFormat.RSS_14);
- possibleFormats.add(BarcodeFormat.RSS_EXPANDED);
- if (!config.isProductsOnly()) {
- possibleFormats.add(BarcodeFormat.CODE_39);
- possibleFormats.add(BarcodeFormat.CODE_93);
- possibleFormats.add(BarcodeFormat.CODE_128);
- possibleFormats.add(BarcodeFormat.ITF);
- possibleFormats.add(BarcodeFormat.QR_CODE);
- possibleFormats.add(BarcodeFormat.DATA_MATRIX);
- possibleFormats.add(BarcodeFormat.AZTEC);
- possibleFormats.add(BarcodeFormat.PDF_417);
- possibleFormats.add(BarcodeFormat.CODABAR);
- possibleFormats.add(BarcodeFormat.MAXICODE);
+ if (retain) {
+ retained.add(input);
}
}
- Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
- hints.put(DecodeHintType.POSSIBLE_FORMATS, possibleFormats);
- if (config.isTryHarder()) {
- hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
- }
- if (config.isPureBarcode()) {
- hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
- }
- return hints;
+ return retained;
}
- private static void printUsage() {
- System.err.println("Decode barcode images using the ZXing library");
- System.err.println();
- System.err.println("usage: CommandLineRunner { file | dir | url } [ options ]");
- System.err.println(" --try_harder: Use the TRY_HARDER hint, default is normal (mobile) mode");
- System.err.println(" --pure_barcode: Input image is a pure monochrome barcode image, not a photo");
- System.err.println(" --products_only: Only decode the UPC and EAN families of barcodes");
- System.err.println(" --dump_results: Write the decoded contents to input.txt");
- System.err.println(" --dump_black_point: Compare black point algorithms as input.mono.png");
- System.err.println(" --multi: Scans image for multiple barcodes");
- System.err.println(" --brief: Only output one line per file, omitting the contents");
- System.err.println(" --recursive: Descend into subdirectories");
- System.err.println(" --crop=left,top,width,height: Only examine cropped region of input image(s)");
- StringBuilder builder = new StringBuilder();
- builder.append(" --possibleFormats=barcodeFormat[,barcodeFormat2...] where barcodeFormat is any of: ");
- for (BarcodeFormat format : BarcodeFormat.values()) {
- builder.append(format).append(',');
+ private static boolean isExpandable(List<URI> inputs) {
+ for (URI input : inputs) {
+ if (isFileOrDir(input) && Files.isDirectory(Paths.get(input))) {
+ return true;
+ }
}
- builder.setLength(builder.length() - 1);
- System.err.println(builder);
+ return false;
+ }
+
+ private static boolean isFileOrDir(URI uri) {
+ return "file".equals(uri.getScheme());
}
}
Oops, something went wrong.

0 comments on commit 8fe986a

Please sign in to comment.