Terms of Service | Privacy Policy | Cookie Policy

Skip to content
Commits on Source (2)
......@@ -10,6 +10,7 @@ random:
-
type: qrcode
size: 120x120
errorcorrection: M
filetype: png
encoding: hex
url: https://www.example.org/{code}
......
......@@ -19,6 +19,7 @@ package org.sw4j.tool.barcode.random.codedata;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.sw4j.tool.barcode.random.config.CodeType;
/**
*
......@@ -50,6 +51,6 @@ public interface CodeData {
* @return
* @throws IOException
*/
OutputStream getOutputForIdent(String type, String format, String ident, String suffix) throws IOException;
OutputStream getOutputForIdent(CodeType type, String format, String ident, String suffix) throws IOException;
}
......@@ -22,6 +22,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.sw4j.tool.barcode.random.config.CodeType;
import org.sw4j.tool.barcode.random.config.Config;
/**
......@@ -49,11 +50,12 @@ public class FileCodeData implements CodeData {
}
@Override
public OutputStream getOutputForIdent(String type, String format, String ident, String suffix) throws IOException {
public OutputStream getOutputForIdent(CodeType type, String format, String ident, String suffix)
throws IOException {
File folder = new File(config.getOutput().getFolder());
folder.mkdirs();
return new FileOutputStream(new File(folder,
String.format("%s-%s-%s.%s", type, format, ident, suffix)));
String.format("%s-%s-%s.%s", type.getType(), format, ident, suffix)));
}
}
......@@ -29,12 +29,14 @@ public class CodeConfig {
private static final Logger logger = Logger.getLogger(CodeConfig.class.getName());
private final String type;
private final CodeType type;
private final int width;
private final int height;
private final String errorCorrection;
private final String filetype;
private final String encoding;
......@@ -44,6 +46,7 @@ public class CodeConfig {
public CodeConfig(
@JsonProperty("type") String type,
@JsonProperty("size") String size,
@JsonProperty("errorcorrection") String errorCorrection,
@JsonProperty("filetype") String filetype,
@JsonProperty("encoding") String encoding,
@JsonProperty("url") String url
......@@ -54,7 +57,11 @@ public class CodeConfig {
if (encoding == null) {
throw new IllegalArgumentException(String.format("%s: Missing encoding", getClass().getSimpleName()));
}
this.type = type;
this.type = CodeType.lookup(type);
if (this.type == null) {
throw new IllegalArgumentException(
String.format("%s: Unknown type '%s'", getClass().getSimpleName(), type));
}
if (size == null || !size.matches("\\d+(x\\d+)?")) {
width = 200;
height = 200;
......@@ -69,12 +76,13 @@ public class CodeConfig {
height = Integer.parseInt(m.group(3));
}
}
this.errorCorrection = errorCorrection;
this.filetype = filetype == null ? "png" : filetype;
this.encoding = encoding;
this.url = url;
}
public String getType() {
public CodeType getType() {
return type;
}
......@@ -86,6 +94,10 @@ public class CodeConfig {
return height;
}
public String getErrorCorrection() {
return errorCorrection;
}
public String getFiletype() {
return filetype;
}
......@@ -111,6 +123,8 @@ public class CodeConfig {
private int height;
private String errorCorrection;
private String filetype;
private String encoding;
......@@ -135,6 +149,11 @@ public class CodeConfig {
return this;
}
public Builder setErrorCorrection(String errorCorrection) {
this.errorCorrection = errorCorrection;
return this;
}
public Builder setFiletype(String filetype) {
this.filetype = filetype;
return this;
......@@ -161,7 +180,7 @@ public class CodeConfig {
}
size = sb.toString();
}
return new CodeConfig(type, size, filetype, encoding, url);
return new CodeConfig(type, size, errorCorrection, filetype, encoding, url);
}
}
......
/*
* Copyright (C) 2019 sw4j.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sw4j.tool.barcode.random.config;
import com.google.zxing.BarcodeFormat;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author Uwe Plonus &lt;u.plonus@gmail.com&gt;
*/
public enum CodeType {
QRCODE("qrcode", BarcodeFormat.QR_CODE);
private final String type;
private final BarcodeFormat format;
private static final Map<String, CodeType> codeTypes = new HashMap<>();
static {
for (CodeType codeType: CodeType.values()) {
codeTypes.put(codeType.getType(), codeType);
}
}
private CodeType(String type, BarcodeFormat format) {
this.type = type;
this.format = format;
}
public String getType() {
return type;
}
public BarcodeFormat getFormat() {
return format;
}
public static CodeType lookup(String type) {
return codeTypes.get(type);
}
}
......@@ -20,12 +20,11 @@ import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.SequenceWriter;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.io.FileNotFoundException;
import java.io.IOException;
......@@ -49,6 +48,8 @@ import org.sw4j.tool.barcode.random.config.RandomConfig;
import org.sw4j.tool.barcode.random.encoder.ByteArrayEncoder;
import org.sw4j.tool.barcode.random.input.Identifier;
import org.sw4j.tool.barcode.random.codedata.CodeData;
import org.sw4j.tool.barcode.random.config.CodeConfig;
import org.sw4j.tool.barcode.random.config.CodeType;
/**
*
......@@ -105,24 +106,24 @@ public class CodeGenerator {
randomValues.parallelStream()
.forEach(randomIdent -> {
config.getCode().forEach(code -> {
String codeType = code.getType();
CodeType codeType = code.getType();
String codeEncoding = code.getEncoding();
String codeUrl = code.getUrl();
codeUrl = codeUrl.replace("{code}", randomIdent.getEncoded(codeEncoding));
try {
OutputStream os = codeData.getOutputForIdent(codeType, codeEncoding,
randomIdent.getIdent(), code.getFiletype());
QRCodeWriter codeWriter = new QRCodeWriter();
MultiFormatWriter codeWriter = new MultiFormatWriter();
Map<EncodeHintType, Object> encodingParameters = new HashMap<>();
encodingParameters.put(EncodeHintType.CHARACTER_SET, "utf-8");
encodingParameters.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
BitMatrix matrix = codeWriter.encode(codeUrl, BarcodeFormat.QR_CODE,
setErrorCorrection(code, encodingParameters);
BitMatrix matrix = codeWriter.encode(codeUrl, codeType.getFormat(),
code.getWidth(), code.getHeight());
MatrixToImageWriter.writeToStream(matrix, code.getFiletype(), os);
} catch (IOException | WriterException exc) {
logger.log(Level.WARNING,
String.format("Writing of Code 'type: %s / encoding: %s / ident: %s' failed.",
codeType, codeEncoding, randomIdent.getIdent()),
codeType.getType(), codeEncoding, randomIdent.getIdent()),
exc);
}
});
......@@ -148,6 +149,21 @@ public class CodeGenerator {
}
}
private void setErrorCorrection(CodeConfig codeConfig, Map<EncodeHintType, Object> encodingParameters) {
switch (codeConfig.getType()) {
case QRCODE:
try {
encodingParameters.put(EncodeHintType.ERROR_CORRECTION,
ErrorCorrectionLevel.valueOf(codeConfig.getErrorCorrection()));
} catch (IllegalArgumentException | NullPointerException exc) {
encodingParameters.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
}
default:
// Do nothing
}
encodingParameters.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
}
public Set<RandomIdent> createCodes(Collection<String> inputValues, Set<String> encodings) {
Map<String, Set<String>> encodedRandoms = new HashMap<>();
encodings.forEach(encoding -> encodedRandoms.put(encoding, new HashSet<>()));
......
......@@ -67,7 +67,14 @@ public class CodeConfigNGTest {
@Test
public void setHeightIsFuild() {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setHeight(100);
CodeConfig.Builder b = builder.setHeight(120);
assertNotNull(b, "Expected a builder to be returned by setHeight.");
}
@Test
public void setErrorCorrectionIsFuild() {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setErrorCorrection("M");
assertNotNull(b, "Expected a builder to be returned by setHeight.");
}
......@@ -97,6 +104,21 @@ public class CodeConfigNGTest {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b = b.setUrl("http://example.org");
b.build();
fail("Expected an exception to be thrown when no type is set.");
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void buildingWithUnknownTypeFails() {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("never");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b = b.setUrl("http://example.org");
......@@ -109,6 +131,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b = b.setUrl("http://example.org");
......@@ -121,6 +144,20 @@ public class CodeConfigNGTest {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b = b.setUrl("http://example.org");
CodeConfig config = b.build();
assertNotNull(config, "Expected a config to be built.");
}
@Test
public void buildingWithoutErrorCorrectionSucceeds() {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setFiletype("png");
b = b.setEncoding("hex");
b = b.setUrl("http://example.org");
......@@ -134,6 +171,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setEncoding("hex");
b = b.setUrl("http://example.org");
CodeConfig config = b.build();
......@@ -146,6 +184,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setUrl("http://example.org");
b.build();
......@@ -158,6 +197,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
CodeConfig config = b.build();
......@@ -170,11 +210,12 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
CodeConfig config = b.build();
assertEquals(config.getType(), "qrcode", "Expected the type to be set.");
assertEquals(config.getType(), CodeType.QRCODE, "Expected the type to be set.");
}
@Test
......@@ -183,6 +224,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -195,6 +237,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -208,6 +251,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -220,6 +264,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -232,6 +277,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -239,12 +285,27 @@ public class CodeConfigNGTest {
assertEquals(config.getHeight(), 100, "Expected the height to be set.");
}
@Test
public void buildingSetsErrorCorrection() {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("jpg");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
CodeConfig config = b.build();
assertEquals(config.getErrorCorrection(), "M", "Expected the error correction to be set.");
}
@Test
public void buildingSetsFiletype() {
CodeConfig.Builder builder = CodeConfig.builder();
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("jpg");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -258,6 +319,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
CodeConfig config = b.build();
......@@ -270,6 +332,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......@@ -283,6 +346,7 @@ public class CodeConfigNGTest {
CodeConfig.Builder b = builder.setType("qrcode");
b = b.setWidth(100);
b = b.setHeight(120);
b = b.setErrorCorrection("M");
b = b.setFiletype("png");
b = b.setEncoding("hex");
b.setUrl("http://example.org");
......
......@@ -66,7 +66,7 @@ public class CodeGeneratorNGTest {
}
@Test
public void testRandomIdentCreatesEncoded() {
public void randomIdentCreatesEncoded() {
RandomIdent ri = new RandomIdent("00000", 128, new Random(), new HashSet<>(Arrays.asList("hex")));
assertNotNull(ri.getEncoded("hex"), "Expected an encoded string to be created");
assertEquals(ri.getEncoded("hex").length(), 32,
......@@ -74,7 +74,7 @@ public class CodeGeneratorNGTest {
}
@Test
public void testRandomIdentCreatesShortenedEncoded() {
public void randomIdentCreatesShortenedEncoded() {
RandomIdent ri = new RandomIdent("00000", 128, new Random(), new HashSet<>(Arrays.asList("hex{12}")));
assertNotNull(ri.getEncoded("hex{12}"), "Expected an encoded string to be created");
assertEquals(ri.getEncoded("hex{12}").length(), 12,
......@@ -85,7 +85,7 @@ public class CodeGeneratorNGTest {
}
@Test
public void testRandomIdentCreatesShortenedReverseEncoded() {
public void randomIdentCreatesShortenedReverseEncoded() {
RandomIdent ri = new RandomIdent("00000", 128, new Random(), new HashSet<>(Arrays.asList("hex{-14}")));
assertNotNull(ri.getEncoded("hex{-14}"), "Expected an encoded string to be created");
assertEquals(ri.getEncoded("hex{-14}").length(), 14,
......@@ -96,7 +96,7 @@ public class CodeGeneratorNGTest {
}
@Test
public void testRandomIdentCreatesStartEndEncoded() {
public void randomIdentCreatesStartEndEncoded() {
RandomIdent ri = new RandomIdent("00000", 128, new Random(), new HashSet<>(Arrays.asList("hex{10-14}")));
assertNotNull(ri.getEncoded("hex{10-14}"), "Expected an encoded string to be created");
assertEquals(ri.getEncoded("hex{10-14}").length(), 4,
......@@ -107,7 +107,7 @@ public class CodeGeneratorNGTest {
}
@Test
public void testCreateCodesFromList() {
public void createCodesFromList() {
CodeConfig codeConfig = CodeConfig.builder()
.setType("qrcode")
.setEncoding("hex")
......@@ -148,7 +148,7 @@ public class CodeGeneratorNGTest {
}
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*[dD]uplicate.*")
public void testDuplicateIdentInCsvThrowsException() throws IOException {
public void duplicateIdentInCsvThrowsException() throws IOException {
InputStream is = new ByteArrayInputStream("00001\n00001\n".getBytes(Charset.forName("ISO-8859-15")));
RandomConfig config = new RandomConfig(128, Collections.emptyList(), Arrays.asList("hex"));
CodeData codeData = new TestCodeData(is, null);
......@@ -160,7 +160,7 @@ public class CodeGeneratorNGTest {
}
@Test
public void testCreateCodeWithoutIdent() throws IOException {
public void createCodeWithoutIdent() throws IOException {
InputStream is = new ByteArrayInputStream("".getBytes(Charset.forName("ISO-8859-15")));
OutputStream os = new ByteArrayOutputStream();
CodeConfig codeConfig = CodeConfig.builder()
......@@ -220,8 +220,46 @@ public class CodeGeneratorNGTest {
generator.createCodes();
ByteArrayOutputStream baos = (ByteArrayOutputStream)codeData.getOutput();
String generatedCsv = new String(baos.toByteArray(), Charset.forName("UTF-8"));
assertEquals(codeData.getOutputs().size(), 1, "Expected 1 barcode to be created.");
}
@Test
public void createCodeWithValidErrorCorrection() throws IOException {
InputStream is = new ByteArrayInputStream("01\n".getBytes(Charset.forName("UTF-8")));
OutputStream os = new ByteArrayOutputStream();
CodeConfig codeConfig = CodeConfig.builder()
.setType("qrcode")
.setErrorCorrection("M")
.setEncoding("hex")
.setUrl("https://example.org/{code}")
.build();
RandomConfig config = new RandomConfig(128, Arrays.asList(codeConfig), Arrays.asList("base58{10}"));
TestCodeData codeData = new TestCodeData(is, os);
CodeGenerator generator = new CodeGenerator(config, codeData);
generator.createCodes();
assertEquals(codeData.getOutputs().size(), 1, "Expected 1 barcode to be created.");
}
@Test
public void createCodeWithInvalidErrorCorrection() throws IOException {
InputStream is = new ByteArrayInputStream("01\n".getBytes(Charset.forName("UTF-8")));
OutputStream os = new ByteArrayOutputStream();
CodeConfig codeConfig = CodeConfig.builder()
.setType("qrcode")
.setErrorCorrection("X")
.setEncoding("hex")
.setUrl("https://example.org/{code}")
.build();
RandomConfig config = new RandomConfig(128, Arrays.asList(codeConfig), Arrays.asList("base58{10}"));
TestCodeData codeData = new TestCodeData(is, os);
CodeGenerator generator = new CodeGenerator(config, codeData);
generator.createCodes();
assertEquals(codeData.getOutputs().size(), 1, "Expected 1 barcode to be created.");
}
......
......@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.sw4j.tool.barcode.random.codedata.CodeData;
import org.sw4j.tool.barcode.random.config.CodeType;
/**
*
......@@ -54,8 +55,9 @@ public class TestCodeData implements CodeData {
}
@Override
public OutputStream getOutputForIdent(String type, String format, String ident, String suffix) throws IOException {
String key = String.format("%s-%s-%s.suffix", type, format, ident, suffix);
public OutputStream getOutputForIdent(CodeType type, String format, String ident, String suffix)
throws IOException {
String key = String.format("%s-%s-%s.suffix", type.getType(), format, ident, suffix);
ByteArrayOutputStream os = new ByteArrayOutputStream();
outputs.put(key, os);
return os;
......