PredefinedIdent.java
/*
* 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.generator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.sw4j.tool.barcode.random.config.EncodingConfig;
import org.sw4j.tool.barcode.random.decoder.ByteArrayDecoder;
import org.sw4j.tool.barcode.random.encoder.ByteArrayEncoder;
/**
* <p>
* This class contains the value and the encoded representations for a single ident.
* </p>
* <p>
* This class is immutable.
* </p>
* @author Uwe Plonus <u.plonus@gmail.com>
*/
public class PredefinedIdent implements IdentValue {
/**
* <p>
* The ident number.
* </p>
*/
private final String ident;
/**
* <p>
* The raw value.
* </p>
*/
private final byte[] rawValue;
/**
* <p>
* A map containing all encoded values for the ident. The key is the encoding and the value the encoded value.
* </p>
*/
private final Map<EncodingConfig, String> encoded;
/**
* <p>
* Create a new {@code PredefinedIdent} and the value for the {@code ident}. The value will be encoded in all given
* {@code encodings}.
* </p>
* @param ident the ident for which the random number will be generated for.
* @param value the value of the ident.
* @param encoding the encoding of the given value.
* @param encodings the encodings that are used for the encoded representation of the random number.
* @throws IllegalArgumentException if no encoder for a given encoding can be found.
*/
public PredefinedIdent(final String ident, final String value, final EncodingConfig encoding,
final Set<EncodingConfig> encodings) {
this.ident = ident;
ByteArrayDecoder decoder = ByteArrayDecoder.forEncoding(encoding.getType());
if (decoder == null) {
throw new IllegalArgumentException(
String.format("Cannot find a decoder for encoding %s", encoding.getType()));
}
rawValue = decoder.decode(value);
encoded = new HashMap<>();
encodings.forEach((enc) -> {
String rawEncoding = enc.getType();
int endIndex = -1;
int startIndex = -1;
boolean hasMinus = false;
if (rawEncoding.matches(".+\\{\\d*-?\\d+\\}")) {
Pattern p = Pattern.compile("(.+)\\{((\\d*)-)?(\\d+)\\}");
Matcher m = p.matcher(rawEncoding);
m.matches();
rawEncoding = m.group(1);
if (m.group(2) != null && m.group(2).length() > 1) {
startIndex = Integer.parseInt(m.group(2).substring(0, m.group(2).length() - 1));
}
String startIndexGroup = m.group(2);
hasMinus = m.group(3) != null;
endIndex = Integer.parseInt(m.group(4));
}
ByteArrayEncoder encoder = ByteArrayEncoder.forEncoding(rawEncoding);
if (encoder == null) {
throw new IllegalArgumentException(
String.format("Cannot find an encoder for encoding %s", rawEncoding));
}
String encodedValue = encoder.encode(rawValue);
if (endIndex > 0) {
if (hasMinus) {
if (startIndex >= 0) {
encodedValue = encodedValue.substring(startIndex, endIndex);
} else {
encodedValue = encodedValue.substring(encodedValue.length() - endIndex);
}
} else {
encodedValue = encodedValue.substring(0, endIndex);
}
}
if (enc.getSepCount() != null) {
int partsCount = encodedValue.length() / enc.getSepCount();
if (encodedValue.length() % enc.getSepCount() != 0) {
partsCount++;
}
List<String> parts = new ArrayList<>(partsCount);
for (int i = 0; i < partsCount; i++) {
int endPos = (i + 1) * enc.getSepCount() < encodedValue.length() ? (i + 1) * enc.getSepCount() :
encodedValue.length();
parts.add(encodedValue.substring(i * enc.getSepCount(),
endPos));
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.size(); i++) {
if (i > 0) {
sb.append(enc.getSepChar());
}
sb.append(parts.get(i));
}
encodedValue = sb.toString();
}
encoded.put(enc, encodedValue);
});
}
/**
* <p>
* Return the ident number.
* </p>
* @return the ident number.
*/
@Override
public String getIdent() {
return ident;
}
/**
* <p>
* Return the raw random number generated.
* </p>
* @return the raw random number.
*/
@Override
public byte[] getValue() {
return Arrays.copyOf(rawValue, rawValue.length);
}
/**
* <p>
* Return the random number in the given {@code encoding}. Only the encodings that were given during construction
* can be returned.
* </p>
* @param encoding the encoding for which the encoded value should be returned.
* @return the encoded value or {@code null} if the encoding is unknown.
*/
@Override
public String getEncoded(final EncodingConfig encoding) {
return encoded.get(encoding);
}
}