1.1 --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/CopyImageResizerException.java Mon Nov 17 18:17:13 2014 +0100
1.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/CopyImageResizerException.java Mon Nov 17 20:05:57 2014 +0100
1.3 @@ -18,10 +18,11 @@
1.4 package cz.frantovo.copyImageResizer;
1.5
1.6 /**
1.7 + * Superclass for all exceptions in this program.
1.8 *
1.9 * @author Ing. František Kučera (frantovo.cz)
1.10 */
1.11 -public class CopyImageResizerException extends Exception {
1.12 +public abstract class CopyImageResizerException extends Exception {
1.13
1.14 public CopyImageResizerException() {
1.15 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/Counters.java Mon Nov 17 20:05:57 2014 +0100
2.3 @@ -0,0 +1,77 @@
2.4 +/**
2.5 + * copy-image-resizer
2.6 + * Copyright © 2014 František Kučera (frantovo.cz)
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, either version 3 of the License, or
2.11 + * (at your option) any later version.
2.12 + *
2.13 + * This program is distributed in the hope that it will be useful,
2.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.16 + * GNU General Public License for more details.
2.17 + *
2.18 + * You should have received a copy of the GNU General Public License
2.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
2.20 + */
2.21 +package cz.frantovo.copyImageResizer;
2.22 +
2.23 +import java.util.EnumMap;
2.24 +import java.util.Map;
2.25 +
2.26 +/**
2.27 + *
2.28 + * @author Ing. František Kučera (frantovo.cz)
2.29 + */
2.30 +public class Counters {
2.31 +
2.32 + private final Map<COUNTER_TYPE, Integer> data = new EnumMap(COUNTER_TYPE.class);
2.33 +
2.34 + public int increment(COUNTER_TYPE counter) {
2.35 + synchronized (data) {
2.36 + int value = get(counter);
2.37 + value++;
2.38 + data.put(counter, value);
2.39 + return value;
2.40 + }
2.41 + }
2.42 +
2.43 + public int get(COUNTER_TYPE counter) {
2.44 + Integer value = data.get(counter);
2.45 + return value == null ? 0 : value;
2.46 + }
2.47 +
2.48 + @Override
2.49 + public String toString() {
2.50 + StringBuilder sb = new StringBuilder();
2.51 +
2.52 + sb.append("Counters: ");
2.53 +
2.54 + for (COUNTER_TYPE counter : COUNTER_TYPE.values()) {
2.55 + sb.append(counter);
2.56 + sb.append("=");
2.57 + sb.append(get(counter));
2.58 + sb.append(" ");
2.59 +
2.60 + }
2.61 +
2.62 + return sb.toString();
2.63 + }
2.64 +
2.65 + public static enum COUNTER_TYPE {
2.66 +
2.67 + DIRECTORIES,
2.68 + FILES,
2.69 + RESIZED,
2.70 + SKIPPED_SMALLER,
2.71 + SKIPPED_UNKNOWN_EXTENSION,
2.72 + SKIPPED_ERROR;
2.73 +
2.74 + @Override
2.75 + public String toString() {
2.76 + return name().toLowerCase();
2.77 + }
2.78 +
2.79 + }
2.80 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/InvalidOptionsException.java Mon Nov 17 20:05:57 2014 +0100
3.3 @@ -0,0 +1,68 @@
3.4 +/**
3.5 + * copy-image-resizer
3.6 + * Copyright © 2014 František Kučera (frantovo.cz)
3.7 + *
3.8 + * This program is free software: you can redistribute it and/or modify
3.9 + * it under the terms of the GNU General Public License as published by
3.10 + * the Free Software Foundation, either version 3 of the License, or
3.11 + * (at your option) any later version.
3.12 + *
3.13 + * This program is distributed in the hope that it will be useful,
3.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.16 + * GNU General Public License for more details.
3.17 + *
3.18 + * You should have received a copy of the GNU General Public License
3.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
3.20 + */
3.21 +package cz.frantovo.copyImageResizer;
3.22 +
3.23 +import java.util.ArrayList;
3.24 +import java.util.Collection;
3.25 +import java.util.Collections;
3.26 +
3.27 +/**
3.28 + *
3.29 + * @author Ing. František Kučera (frantovo.cz)
3.30 + */
3.31 +public class InvalidOptionsException extends CopyImageResizerException {
3.32 +
3.33 + private final Collection<OptionProblem> problems = new ArrayList<>();
3.34 +
3.35 + public Collection<OptionProblem> getProblems() {
3.36 + return Collections.unmodifiableCollection(problems);
3.37 + }
3.38 +
3.39 + public void addProblem(OptionProblem p) {
3.40 + problems.add(p);
3.41 + }
3.42 +
3.43 + public boolean hasProblems() {
3.44 + return !problems.isEmpty();
3.45 + }
3.46 +
3.47 + public static class OptionProblem {
3.48 +
3.49 + private final String description;
3.50 + private final Throwable exception;
3.51 +
3.52 + public OptionProblem(String description) {
3.53 + this.description = description;
3.54 + this.exception = null;
3.55 + }
3.56 +
3.57 + public OptionProblem(String description, Throwable exception) {
3.58 + this.description = description;
3.59 + this.exception = exception;
3.60 + }
3.61 +
3.62 + public String getDescription() {
3.63 + return description;
3.64 + }
3.65 +
3.66 + public Throwable getException() {
3.67 + return exception;
3.68 + }
3.69 + }
3.70 +
3.71 +}
4.1 --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java Mon Nov 17 18:17:13 2014 +0100
4.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveImageResizer.java Mon Nov 17 20:05:57 2014 +0100
4.3 @@ -37,6 +37,8 @@
4.4 public class RecursiveImageResizer {
4.5
4.6 private static final Logger log = Logger.getLogger(RecursiveImageResizer.class.getName());
4.7 +
4.8 + private final Counters counters = new Counters();
4.9
4.10 private final SingleImageResizer resizer = new SingleImageResizer();
4.11
4.12 @@ -46,8 +48,9 @@
4.13 this.options = options;
4.14 }
4.15
4.16 - public void resize() throws RecursiveException, ResizeException {
4.17 + public Counters resize() throws RecursiveException, ResizeException {
4.18 resizeDirectory(options.getInput());
4.19 + return counters;
4.20 }
4.21
4.22 private void resizeFile(File inputFile) throws ResizeException {
4.23 @@ -70,7 +73,7 @@
4.24 resizer.resize(image, output, size, format);
4.25 }
4.26 } else {
4.27 - log.log(Level.FINER, "File: {0} has already required size → just copy", inputFileRelative);
4.28 + log.log(Level.FINER, "File: {0} has already required (or smaller) size → just copy", inputFileRelative);
4.29 justCopy(inputFile, outputFile);
4.30 }
4.31 }
5.1 --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveOptions.java Mon Nov 17 18:17:13 2014 +0100
5.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/RecursiveOptions.java Mon Nov 17 20:05:57 2014 +0100
5.3 @@ -63,4 +63,26 @@
5.4 public void addSize(SizeSpecification size) {
5.5 sizes.add(size);
5.6 }
5.7 +
5.8 + public void validate() throws InvalidOptionsException {
5.9 + InvalidOptionsException e = new InvalidOptionsException();
5.10 +
5.11 + if (input == null) {
5.12 + e.addProblem(new InvalidOptionsException.OptionProblem("input directory must be specified"));
5.13 + } else if (!input.isDirectory()) {
5.14 + e.addProblem(new InvalidOptionsException.OptionProblem("input directory must exist and be a directory: " + input));
5.15 + }
5.16 +
5.17 + if (output == null) {
5.18 + e.addProblem(new InvalidOptionsException.OptionProblem("output directory must be specified"));
5.19 + }
5.20 +
5.21 + if (sizes.isEmpty()) {
5.22 + e.addProblem(new InvalidOptionsException.OptionProblem("at least one size (output resolution) must be specified"));
5.23 + }
5.24 +
5.25 + if (e.hasProblems()) {
5.26 + throw e;
5.27 + }
5.28 + }
5.29 }
6.1 --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/cli/CLIStarter.java Mon Nov 17 18:17:13 2014 +0100
6.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/cli/CLIStarter.java Mon Nov 17 20:05:57 2014 +0100
6.3 @@ -17,11 +17,14 @@
6.4 */
6.5 package cz.frantovo.copyImageResizer.cli;
6.6
6.7 +import cz.frantovo.copyImageResizer.Counters;
6.8 +import cz.frantovo.copyImageResizer.InvalidOptionsException;
6.9 import cz.frantovo.copyImageResizer.RecursiveException;
6.10 import cz.frantovo.copyImageResizer.RecursiveImageResizer;
6.11 import cz.frantovo.copyImageResizer.RecursiveOptions;
6.12 import cz.frantovo.copyImageResizer.ResizeException;
6.13 import java.util.logging.Level;
6.14 +import java.util.logging.LogRecord;
6.15 import java.util.logging.Logger;
6.16
6.17 /**
6.18 @@ -37,10 +40,20 @@
6.19 try {
6.20 CLIParser parser = new CLIParser();
6.21 RecursiveOptions options = parser.parseOptions(args);
6.22 + options.validate();
6.23 RecursiveImageResizer resizer = new RecursiveImageResizer(options);
6.24 - resizer.resize();
6.25 + Counters counters = resizer.resize();
6.26 + log.log(Level.INFO, "Recursive copy/resize finished. {0}", counters);
6.27 } catch (CLIParserException e) {
6.28 log.log(Level.SEVERE, "Unable to parse CLI options", e);
6.29 + } catch (InvalidOptionsException e) {
6.30 + log.log(Level.SEVERE, "Invalid CLI options", e);
6.31 + for (InvalidOptionsException.OptionProblem p : e.getProblems()) {
6.32 + LogRecord r = new LogRecord(Level.SEVERE, "Option problem: {0}");
6.33 + r.setThrown(p.getException());
6.34 + r.setParameters(new Object[]{p.getDescription()});
6.35 + log.log(r);
6.36 + }
6.37 } catch (RecursiveException e) {
6.38 log.log(Level.SEVERE, "Error while processing filesystem hierarchy", e);
6.39 } catch (ResizeException e) {