View Javadoc
1   /*
2    * Copyright (C) 2019 sw4j.org
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  package org.sw4j.tool.barcode.random.generator;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.regex.Matcher;
26  import java.util.regex.Pattern;
27  import org.sw4j.tool.barcode.random.config.EncodingConfig;
28  import org.sw4j.tool.barcode.random.decoder.ByteArrayDecoder;
29  import org.sw4j.tool.barcode.random.encoder.ByteArrayEncoder;
30  
31  /**
32   * <p>
33   * This class contains the value and the encoded representations for a single ident.
34   * </p>
35   * <p>
36   * This class is immutable.
37   * </p>
38   * @author Uwe Plonus &lt;u.plonus@gmail.com&gt;
39   */
40  public class PredefinedIdent implements IdentValue {
41  
42      /**
43       * <p>
44       * The ident number.
45       * </p>
46       */
47      private final String ident;
48  
49      /**
50       * <p>
51       * The raw value.
52       * </p>
53       */
54      private final byte[] rawValue;
55  
56      /**
57       * <p>
58       * A map containing all encoded values for the ident. The key is the encoding and the value the encoded value.
59       * </p>
60       */
61      private final Map<EncodingConfig, String> encoded;
62  
63      /**
64       * <p>
65       * Create a new {@code PredefinedIdent} and the value for the {@code ident}. The value will be encoded in all given
66       * {@code encodings}.
67       * </p>
68       * @param ident the ident for which the random number will be generated for.
69       * @param value the value of the ident.
70       * @param encoding the encoding of the given value.
71       * @param encodings the encodings that are used for the encoded representation of the random number.
72       * @throws IllegalArgumentException if no encoder for a given encoding can be found.
73       */
74      public PredefinedIdent(final String ident, final String value, final EncodingConfig encoding,
75              final Set<EncodingConfig> encodings) {
76          this.ident = ident;
77          ByteArrayDecoder decoder = ByteArrayDecoder.forEncoding(encoding.getType());
78          if (decoder == null) {
79              throw new IllegalArgumentException(
80                      String.format("Cannot find a decoder for encoding %s", encoding.getType()));
81          }
82          rawValue = decoder.decode(value);
83          encoded = new HashMap<>();
84          encodings.forEach((enc) -> {
85              String rawEncoding = enc.getType();
86              int endIndex = -1;
87              int startIndex = -1;
88              boolean hasMinus = false;
89              if (rawEncoding.matches(".+\\{\\d*-?\\d+\\}")) {
90                  Pattern p = Pattern.compile("(.+)\\{((\\d*)-)?(\\d+)\\}");
91                  Matcher m = p.matcher(rawEncoding);
92                  m.matches();
93                  rawEncoding = m.group(1);
94                  if (m.group(2) != null && m.group(2).length() > 1) {
95                      startIndex = Integer.parseInt(m.group(2).substring(0, m.group(2).length() - 1));
96                  }
97                  String startIndexGroup = m.group(2);
98                  hasMinus = m.group(3) != null;
99                  endIndex = Integer.parseInt(m.group(4));
100             }
101             ByteArrayEncoder encoder = ByteArrayEncoder.forEncoding(rawEncoding);
102             if (encoder == null) {
103                 throw new IllegalArgumentException(
104                         String.format("Cannot find an encoder for encoding %s", rawEncoding));
105             }
106             String encodedValue = encoder.encode(rawValue);
107             if (endIndex > 0) {
108                 if (hasMinus) {
109                     if (startIndex >= 0) {
110                         encodedValue = encodedValue.substring(startIndex, endIndex);
111                     } else {
112                         encodedValue = encodedValue.substring(encodedValue.length() - endIndex);
113                     }
114                 } else {
115                     encodedValue = encodedValue.substring(0, endIndex);
116                 }
117             }
118             if (enc.getSepCount() != null) {
119                 int partsCount = encodedValue.length() / enc.getSepCount();
120                 if (encodedValue.length() % enc.getSepCount() != 0) {
121                     partsCount++;
122                 }
123                 List<String> parts = new ArrayList<>(partsCount);
124                 for (int i = 0; i < partsCount; i++) {
125                     int endPos = (i + 1) * enc.getSepCount() < encodedValue.length() ? (i + 1) * enc.getSepCount() :
126                             encodedValue.length();
127                     parts.add(encodedValue.substring(i * enc.getSepCount(),
128                             endPos));
129                 }
130                 StringBuilder sb = new StringBuilder();
131                 for (int i = 0; i < parts.size(); i++) {
132                     if (i > 0) {
133                         sb.append(enc.getSepChar());
134                     }
135                     sb.append(parts.get(i));
136                 }
137                 encodedValue = sb.toString();
138             }
139             encoded.put(enc, encodedValue);
140         });
141     }
142 
143     /**
144      * <p>
145      * Return the ident number.
146      * </p>
147      * @return the ident number.
148      */
149     @Override
150     public String getIdent() {
151         return ident;
152     }
153 
154     /**
155      * <p>
156      * Return the raw random number generated.
157      * </p>
158      * @return the raw random number.
159      */
160     @Override
161     public byte[] getValue() {
162         return Arrays.copyOf(rawValue, rawValue.length);
163     }
164 
165     /**
166      * <p>
167      * Return the random number in the given {@code encoding}. Only the encodings that were given during construction
168      * can be returned.
169      * </p>
170      * @param encoding the encoding for which the encoded value should be returned.
171      * @return the encoded value or {@code null} if the encoding is unknown.
172      */
173     @Override
174     public String getEncoded(final EncodingConfig encoding) {
175         return encoded.get(encoding);
176     }
177 
178 }