1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.sw4j.tool.barcode.random.generator;
18
19 import com.fasterxml.jackson.databind.MappingIterator;
20 import com.fasterxml.jackson.databind.SequenceWriter;
21 import com.fasterxml.jackson.dataformat.csv.CsvMapper;
22 import com.fasterxml.jackson.dataformat.csv.CsvSchema;
23 import java.io.IOException;
24 import java.security.SecureRandom;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.LinkedHashMap;
29 import java.util.LinkedHashSet;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Random;
34 import java.util.Set;
35 import java.util.logging.Logger;
36 import java.util.stream.Collectors;
37 import org.sw4j.tool.barcode.random.codedata.CodeData;
38 import org.sw4j.tool.barcode.random.config.EncodingConfig;
39 import org.sw4j.tool.barcode.random.config.GenerationConfig;
40 import org.sw4j.tool.barcode.random.input.Identifier;
41 import org.sw4j.tool.barcode.random.input.Predefined;
42
43
44
45
46
47
48
49
50
51
52
53 public class CodeGenerator {
54
55
56
57
58
59
60 private final Logger logger = Logger.getLogger(CodeGenerator.class.getName());
61
62
63
64
65
66
67 private final GenerationConfig config;
68
69
70
71
72
73
74 private final CodeData codeData;
75
76
77
78
79
80
81 private final Random random;
82
83
84
85
86
87
88
89
90
91
92
93
94 public CodeGenerator(final GenerationConfig config, final CodeData codeData) {
95 this(config, codeData, new SecureRandom());
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 public CodeGenerator(final GenerationConfig config, final CodeData codeData, final Random random) {
116 this.config = config;
117 this.codeData = codeData;
118 this.random = random;
119 }
120
121
122
123
124
125
126
127
128
129 public void createCodes() throws IOException {
130 Set<EncodingConfig> encodings = new HashSet<>();
131 config.getCodes().forEach((codeConfig) -> {
132 encodings.add(codeConfig.getEncoding());
133 });
134 config.getEncodings().forEach((encoding) -> {
135 encodings.add(encoding);
136 });
137
138 CsvMapper csvMapper = new CsvMapper();
139 Set<IdentValue> values;
140
141 if (config.getEncoding() != null) {
142 Map<String, String> inputValues = new LinkedHashMap<>();
143 MappingIterator<Predefined> mappingIterator = csvMapper.readerWithSchemaFor(Predefined.class)
144 .readValues(codeData.getInput());
145 while (mappingIterator.hasNext()) {
146 Predefined ident = mappingIterator.next();
147 inputValues.put(ident.getIdent(), ident.getCode());
148 }
149 values = convertCodes(inputValues, config.getEncoding(), encodings);
150 } else {
151 Set<String> inputValues = new LinkedHashSet<>();
152 MappingIterator<Identifier> mappingIterator = csvMapper.readerWithSchemaFor(Identifier.class)
153 .readValues(codeData.getInput());
154 while (mappingIterator.hasNext()) {
155 Identifier ident = mappingIterator.next();
156 if (!inputValues.add(ident.getIdent())) {
157 throw new IllegalArgumentException(
158 String.format("Duplicated input value '%s' found", ident.getIdent()));
159 }
160 }
161 values = createCodes(inputValues, encodings);
162 }
163
164 config.getCodes().forEach(codeConfig -> {
165 values.parallelStream().forEach(new BarcodeWriter(codeConfig, codeData));
166 });
167 CsvSchema.Builder schemaBuilder = CsvSchema.builder().addColumn("ident");
168
169 encodings.forEach(encoding -> schemaBuilder.addColumn(encoding.toString()));
170 CsvSchema schema = schemaBuilder.build().withHeader();
171 CsvMapper mapper = new CsvMapper();
172 List<Map<String, String>> outData = new LinkedList<>();
173 values.stream().map((value) -> {
174 Map<String, String> dataValues = new HashMap<>();
175 dataValues.put("ident", value.getIdent());
176 encodings.forEach((encoding) -> {
177 dataValues.put(encoding.toString(), value.getEncoded(encoding));
178 });
179 return dataValues;
180 }).forEachOrdered((dataValues) -> {
181 outData.add(dataValues);
182 });
183 try (SequenceWriter writer = mapper.writer(schema).writeValues(codeData.getOutput())) {
184 writer.writeAll(outData);
185 }
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 public Set<IdentValue> convertCodes(final Map<String, String> inputValues, final EncodingConfig encoding,
202 final Set<EncodingConfig> encodings) {
203 Map<EncodingConfig, Set<String>> encoded = new HashMap<>();
204 encodings.forEach(enc -> encoded.put(enc, new HashSet<>()));
205 return inputValues.keySet().stream()
206 .map(ident -> {
207 PredefinedIdentm/generator/PredefinedIdent.html#PredefinedIdent">PredefinedIdent pi = new PredefinedIdent(ident, inputValues.get(ident), encoding, encodings);
208 for (EncodingConfig enc: encodings) {
209 encoded.get(enc).add(pi.getEncoded(enc));
210 }
211 return pi;
212 })
213 .collect(Collectors.toSet());
214 }
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 public Set<IdentValue> createCodes(final Collection<String> inputValues, final Set<EncodingConfig> encodings) {
230 Map<EncodingConfig, Set<String>> encodedRandoms = new HashMap<>();
231 encodings.forEach(encoding -> encodedRandoms.put(encoding, new HashSet<>()));
232
233 return inputValues.stream()
234 .map(ident -> {
235 RandomIdentandom/generator/RandomIdent.html#RandomIdent">RandomIdent ri = new RandomIdent(ident, config.getSize(), random, encodings);
236 while (encodedRandomExists(ri, encodedRandoms)) {
237 ri = new RandomIdent(ident, config.getSize(), random, encodings);
238 }
239 for (EncodingConfig encoding: encodings) {
240 encodedRandoms.get(encoding).add(ri.getEncoded(encoding));
241 }
242 return ri;
243 })
244 .collect(Collectors.toSet());
245 }
246
247
248
249
250
251
252
253
254
255
256 private boolean encodedRandomExists(final RandomIdent randomIdent,
257 final Map<EncodingConfig, Set<String>> encodedRandoms) {
258 boolean valueExists = false;
259 for (Map.Entry<EncodingConfig, Set<String>> entry: encodedRandoms.entrySet()) {
260 valueExists |= entry.getValue().contains(randomIdent.getEncoded(entry.getKey()));
261 }
262 return valueExists;
263 }
264
265 }