summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pom.xml6
-rw-r--r--src/main/java/org/uic/barcode/Decoder.java2
-rw-r--r--src/main/java/org/uic/barcode/Encoder.java8
-rw-r--r--src/main/java/org/uic/barcode/asn1/datatypes/Alphabet.java1
-rw-r--r--src/main/java/org/uic/barcode/asn1/datatypes/AlphabetBuilder.java32
-rw-r--r--src/main/java/org/uic/barcode/asn1/datatypes/Bitstring.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/datatypes/Optional.java96
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/BigIntCoder.java97
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java50
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java13
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java63
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java4
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/Constants.java1
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/DataType.java2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java6
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java2
-rw-r--r--src/main/java/org/uic/barcode/ticket/UicRailTicketCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/asn/omv1/CountermarkData.java6
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/asn/omv1/ViaStationType.java2
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/asn/omv2/CountermarkData.java6
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/asn/omv2/ViaStationType.java2
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/asn/omv3/CountermarkData.java6
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/asn/omv3/ViaStationType.java2
-rw-r--r--src/main/java/org/uic/barcode/ticket/api/spec/uicBarcodeHeader0.1.asn151
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/GenAlphabet.java11
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/UperEncodeBitStringTest.java82
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/UperEncodeStringCustomAlphabetTest.java82
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/UperEncodeVarBitStringTest.java81
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java169
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java258
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java174
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java174
-rw-r--r--src/test/java/org/uic/barcode/test/StaticFrameBarcodeTestFCB3.java193
-rw-r--r--src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV1.java95
-rw-r--r--src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV3.java111
-rw-r--r--src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV1.java509
-rw-r--r--src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV3.java544
37 files changed, 2574 insertions, 471 deletions
diff --git a/pom.xml b/pom.xml
index 97460c1..f82b70b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.uic.barcode</groupId>
<artifactId>org.uic.barcode</artifactId>
- <version>1.2.7-SNAPSHOT</version>
+ <version>1.2.8-SNAPSHOT</version>
<packaging>jar</packaging>
<name>UIC barcode</name>
<description>encoding and decoding of bar code content according to UIC IRS 90918-9</description>
@@ -23,8 +23,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
- <source>${jdk.version}</source>
- <target>${jdk.version}</target>
+ <source>1.8</source>
+ <target>1.8</target>
</configuration>
</plugin>
<plugin>
diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java
index 09ee839..9f102d3 100644
--- a/src/main/java/org/uic/barcode/Decoder.java
+++ b/src/main/java/org/uic/barcode/Decoder.java
@@ -172,6 +172,8 @@ public class Decoder {
uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 1);
} else if (level1Content.getFormat().equals("FCB2")) {
uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 2);
+ } else if (level1Content.getFormat().equals("FCB3")) {
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 3);
}
}
diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java
index e906881..f0f8d14 100644
--- a/src/main/java/org/uic/barcode/Encoder.java
+++ b/src/main/java/org/uic/barcode/Encoder.java
@@ -100,7 +100,13 @@ public class Encoder {
DataType ticketData = new DataType();
UicRailTicketCoder uicTicketCoder = new UicRailTicketCoder();
- ticketData.setFormat(Constants.DATA_TYPE_FCB_VERSION_1);
+ if (fcbVersion == 1 || fcbVersion == 13) {
+ ticketData.setFormat(Constants.DATA_TYPE_FCB_VERSION_1);
+ } else if (fcbVersion == 2) {
+ ticketData.setFormat(Constants.DATA_TYPE_FCB_VERSION_2);
+ } else if (fcbVersion == 3) {
+ ticketData.setFormat(Constants.DATA_TYPE_FCB_VERSION_3);
+ }
ticketData.setData(new OctetString(uicTicketCoder.encode(ticket, fcbVersion)));
dynamicFrame.getLevel2SignedData().getLevel1Data().getData().add(ticketData);
diff --git a/src/main/java/org/uic/barcode/asn1/datatypes/Alphabet.java b/src/main/java/org/uic/barcode/asn1/datatypes/Alphabet.java
index 2b153ae..0202e16 100644
--- a/src/main/java/org/uic/barcode/asn1/datatypes/Alphabet.java
+++ b/src/main/java/org/uic/barcode/asn1/datatypes/Alphabet.java
@@ -3,7 +3,6 @@ package org.uic.barcode.asn1.datatypes;
/**
* Alphabet class for Restricted Strings.
*
- * Use {@link AlphabetBuilder} for convenient construction of restriction alphabets.
*/
public abstract class Alphabet {
diff --git a/src/main/java/org/uic/barcode/asn1/datatypes/AlphabetBuilder.java b/src/main/java/org/uic/barcode/asn1/datatypes/AlphabetBuilder.java
deleted file mode 100644
index b768897..0000000
--- a/src/main/java/org/uic/barcode/asn1/datatypes/AlphabetBuilder.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.uic.barcode.asn1.datatypes;
-
-
-public class AlphabetBuilder {
-
- private final StringBuilder sb = new StringBuilder();
-
- public AlphabetBuilder() {}
-
- public String chars() {
- return sb.toString();
- }
-
- public AlphabetBuilder withRange(char from, char to) {
- for (char c = from; c <= to; c++) {
- sb.append(c);
- }
- return this;
- }
-
- public AlphabetBuilder withChars(String str) {
- sb.append(str);
- return this;
- }
-
- public AlphabetBuilder withChars(Character... chars) {
- for (char c : chars) {
- sb.append(c);
- }
- return this;
- }
-}
diff --git a/src/main/java/org/uic/barcode/asn1/datatypes/Bitstring.java b/src/main/java/org/uic/barcode/asn1/datatypes/Bitstring.java
index 1543f64..4771931 100644
--- a/src/main/java/org/uic/barcode/asn1/datatypes/Bitstring.java
+++ b/src/main/java/org/uic/barcode/asn1/datatypes/Bitstring.java
@@ -9,7 +9,7 @@ import java.lang.annotation.Target;
* In UPER, a SEQUENCE OF Booleans would look exactly as bitstring, so this annotation can be
* omitted for {@code List<Boolean>}.
*/
-@Target({ElementType.TYPE})
+@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Bitstring {
diff --git a/src/main/java/org/uic/barcode/asn1/datatypes/Optional.java b/src/main/java/org/uic/barcode/asn1/datatypes/Optional.java
deleted file mode 100644
index 757ba29..0000000
--- a/src/main/java/org/uic/barcode/asn1/datatypes/Optional.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.uic.barcode.asn1.datatypes;
-
-import java.util.NoSuchElementException;
-import java.util.Objects;
-
-/** Represents optional values.
- *
- * Should be replaced by java.util.Optional from Java 8, when project moves to Java 8.
- *
- * @param <T> type of contained elements */
-public class Optional<T> {
-
- private final T element;
- private final boolean isPresent;
-
- private Optional(T element, boolean isPresent) {
- this.element = element;
- this.isPresent = isPresent;
- }
-
- /** @return true if the Option contains a value */
- public boolean isPresent() {
- return isPresent;
- }
-
- /** @return the element if the option is not empty
- * @throws java.util.NoSuchElementException if the option is empty */
- public T get() {
- if (isPresent) {
- return element;
- } else {
- throw new NoSuchElementException("None.get");
- }
- }
-
- /** @return the value, if present, otherwise return {@code other}
- * @param other the value to be returned if there is no value present */
- public T orElse(T other) {
- return isPresent() ? get() : other;
- }
-
- /**
- * Indicates whether some other object is "equal to" this Optional. The
- * other object is considered equal if:
- * <ul>
- * <li>it is also an {@code Optional} and;
- * <li>both instances have no value present or;
- * <li>the present values are "equal to" each other via {@code equals()}.
- * </ul>
- *
- * @param obj an object to be tested for equality
- * @return {code true} if the other object is "equal to" this object
- * otherwise {@code false}
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (!(obj instanceof Optional)) {
- return false;
- }
-
- Optional<?> other = (Optional<?>) obj;
- return Objects.equals(element, other.element);
- }
-
- /**
- * Returns the hash code value of the present value, if any, or 0 (zero) if
- * no value is present.
- *
- * @return hash code value of the present value or 0 if no value is present
- */
- @Override
- public int hashCode() {
- return Objects.hashCode(element);
- }
-
- /** Returns an Option containing the value.
- *
- * @param <A> the type of the value
- * @param element contained value
- * @return a new Option that contains the value */
- public static <A> Optional<A> of(final A element) {
- return new Optional<A>(element, true);
- }
-
- /** Returns an empty option.
- *
- * @param <A>
- * @return an empty Option */
- public static <A> Optional<A> empty() {
- return new Optional<A>(null, false);
- }
-}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/BigIntCoder.java b/src/main/java/org/uic/barcode/asn1/uper/BigIntCoder.java
deleted file mode 100644
index 94e4b05..0000000
--- a/src/main/java/org/uic/barcode/asn1/uper/BigIntCoder.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.uic.barcode.asn1.uper;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.math.BigInteger;
-
-import org.uic.barcode.asn1.datatypes.Asn1BigInteger;
-import org.uic.barcode.asn1.datatypes.Asn1Default;
-import org.uic.barcode.asn1.datatypes.IntRange;
-
-class BigIntCoder implements Encoder, Decoder {
-
- @Override public <T> boolean canDecode(Class<T> classOfT, Annotation[] extraAnnotations) {
- return Asn1BigInteger.class.isAssignableFrom(classOfT);
- }
-
- @Override public <T> T decode(BitBuffer bitbuffer,
- Class<T> classOfT, Field f,
- Annotation[] extraAnnotations) {
- AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),
- extraAnnotations);
-
- String pos = String.format("%d.%d", bitbuffer.position()/8 , bitbuffer.position() % 8);
- UperEncoder.logger.debug(String.format("Position %s BIG INT",pos));
- IntRange intRange = annotations.getAnnotation(IntRange.class);
- if (intRange != null && intRange.maxValue() > 0) {
- throw new UnsupportedOperationException("Big int with upper range is not supported yet");
- }
-
- int lengthInOctets = (int) UperEncoder.decodeLengthDeterminant(bitbuffer);
- BitBuffer valueBits = ByteBitBuffer.allocate(lengthInOctets * 8);
- for (int i = 0; i < lengthInOctets * 8; i++) {
- valueBits.put(bitbuffer.get());
- }
- valueBits.flip();
- BigInteger resultValue = new BigInteger(+1, valueBits.array());
- UperEncoder.logger.debug(String.format("big int Decoded as %s", resultValue));
-
-
- //CG support for int range
- if (intRange != null){
- resultValue.add(BigInteger.valueOf(intRange.minValue()));
- }
-
-
- return UperEncoder.instantiate(classOfT, resultValue);
- }
-
- @Override public <T> boolean canEncode(T obj, Annotation[] extraAnnotations) {
- return obj instanceof Asn1BigInteger;
- }
-
- @Override public <T> void encode(BitBuffer bitbuffer, T obj, Annotation[] extraAnnotations) throws Asn1EncodingException {
- Class<?> type = obj.getClass();
- AnnotationStore annotations = new AnnotationStore(type.getAnnotations(), extraAnnotations);
- IntRange range = annotations.getAnnotation(IntRange.class);
-
- //CG implementation with lower range limit added
- BigInteger bint = ((Asn1BigInteger) obj).toBigInteger();
- if (range != null) {
- throw new UnsupportedOperationException("Asn1 BigInteger with range is not supported");
- }
- byte[] array = bint.toByteArray();
- int lengthInOctets = array.length;
- int position1 = bitbuffer.position();
- try {
- UperEncoder.encodeLengthDeterminant(bitbuffer, lengthInOctets);
- } catch (Asn1EncodingException e) {
- throw new Asn1EncodingException(" length determinant of " + type.getName(), e);
- }
- int position2 = bitbuffer.position();
- for (byte b : array) {
- bitbuffer.putByte(b);
- }
- UperEncoder.logger.debug(String.format("Big Int(%s): len %s, val %s", obj,
- bitbuffer.toBooleanString(position1, position2 - position1),
- bitbuffer.toBooleanStringFromPosition(position2)));
- return;
- }
-
- @Override
- public <T> T getDefault(Class<T> classOfT, Annotation[] extraAnnotations) {
- AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations);
- Asn1Default defaultAnnotation = annotations.getAnnotation(Asn1Default.class);
- if (defaultAnnotation == null) return null;
- //check whether the class has a constructor for numeric types
- String valueString = defaultAnnotation.value();
- long value = Long.parseLong(valueString);
- UperEncoder.logger.debug(String.format("Default INTEGER: %d",value ));
-
- @SuppressWarnings("unchecked")
- T t = (T) new Asn1BigInteger(value);
- return t;
-
- }
-
-} \ No newline at end of file
diff --git a/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java b/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java
index ba1692c..19aac9b 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java
@@ -4,12 +4,12 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.List;
import org.uic.barcode.asn1.datatypes.Asn1VarSizeBitstring;
import org.uic.barcode.asn1.datatypes.Bitstring;
import org.uic.barcode.asn1.datatypes.FixedSize;
import org.uic.barcode.asn1.datatypes.SizeRange;
-import org.uic.barcode.asn1.uper.UperEncoder.Asn1ContainerFieldSorter;
class BitStringCoder implements Decoder, Encoder {
@@ -29,18 +29,24 @@ class BitStringCoder implements Decoder, Encoder {
throw new UnsupportedOperationException(
"Bitstring with extensions is not implemented yet");
}
- FixedSize size = type.getAnnotation(FixedSize.class);
+ FixedSize size = annotations.getAnnotation(FixedSize.class);
int position = bitbuffer.position();
if (size != null) {
- Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(type);
- if (sorter.ordinaryFields.size() != size.value()) { throw new AssertionError(
+ if (!List.class.isAssignableFrom(type)) {
+ throw new AssertionError("Field should be a list of booleans!");
+ }
+
+ List<Boolean> list = (List<Boolean>)obj;
+ if (list.size() != size.value()) {
+ throw new AssertionError(
"Declared size (" + size.value() +
- ") and number of fields (" + sorter.ordinaryFields.size() +
- ") do not match!"); }
- for (Field f : sorter.ordinaryFields) {
+ ") and number of fields (" + list.size() +
+ ") do not match!");
+ }
+ for (Boolean f : list) {
try {
- bitbuffer.put(f.getBoolean(obj));
- } catch (IllegalArgumentException | IllegalAccessException e) {
+ bitbuffer.put(f);
+ } catch (IllegalArgumentException e) {
throw new IllegalArgumentException("can't encode" + obj, e);
}
}
@@ -100,26 +106,28 @@ class BitStringCoder implements Decoder, Encoder {
if (fixedSize == null) { throw new UnsupportedOperationException(
"bitstrings of non-fixed size that do not extend Asn1VarSizeBitstring are not supported yet");
}
- Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT);
- if (fixedSize.value() != sorter.ordinaryFields.size()) { throw new IllegalArgumentException(
- "Fixed size annotation " + fixedSize.value()
- + " does not match the number of fields "
- + sorter.ordinaryFields.size() + " in " + classOfT.getName()); }
if (UperEncoder.hasExtensionMarker(annotations)) {
boolean extensionPresent = bitbuffer.get();
if (extensionPresent) { throw new UnsupportedOperationException(
"extensions in fixed-size bitlist are not supported yet"); }
}
T result = UperEncoder.instantiate(classOfT);
- for (Field f : sorter.ordinaryFields) {
- boolean value = bitbuffer.get();
- UperEncoder.logger.debug(String.format("Field %s set to %s", f.getName(), value));
+
+ Method addBooleanMethod;
+ try {
+ addBooleanMethod = classOfT.getDeclaredMethod("add", Object.class);
+ addBooleanMethod.setAccessible(true);
+ } catch (SecurityException | NoSuchMethodException e) {
+ throw new AssertionError("Can't find/access add " + e);
+ }
+
+ for (int i = 0; i < fixedSize.value(); i++) {
try {
- f.set(result, value);
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new IllegalArgumentException("can't decode " + classOfT, e);
+ addBooleanMethod.invoke(result, bitbuffer.get());
+ } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
+ throw new IllegalArgumentException("Can't invoke add", e);
}
- }
+ }
return result;
} else {
UperEncoder.logger.debug("Bitlist(var-size)");
diff --git a/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java b/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java
index a5ef5c5..bba64e2 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java
@@ -162,7 +162,6 @@ public final class UperEncoder {
static {
encoders.add(new IntCoder());
- //encoders.add(new BigIntCoder());
encoders.add(new ByteCoder());
encoders.add(new BooleanCoder());
encoders.add(new SequenceCoder());
@@ -173,7 +172,6 @@ public final class UperEncoder {
encoders.add(new StringCoder());
decoders.add(new IntCoder());
- //decoders.add(new BigIntCoder());
decoders.add(new ByteCoder());
decoders.add(new BooleanCoder());
decoders.add(new SequenceCoder());
@@ -691,17 +689,6 @@ public final class UperEncoder {
return sb.toString();
}
- public static byte[] bytesFromBinaryString(String s) {
- int len = s.length();
- byte[] result = new byte[(len + Byte.SIZE - 1) / Byte.SIZE];
- char c;
- for (int i = 0; i < len; i++)
- if ((c = s.charAt(i)) == '1') result[i / Byte.SIZE] = (byte) (result[i / Byte.SIZE] | (0x80 >>> (i % Byte.SIZE)));
- else if (c != '0')
- throw new IllegalArgumentException();
- return result;
- }
-
private static BitBuffer bitBufferFromBinaryString(String s) {
ByteBitBuffer result = ByteBitBuffer.allocate(s.length());
for (int i = 0; i < s.length(); i++) {
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
index 32cce65..ecbb226 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
@@ -1,16 +1,17 @@
package org.uic.barcode.dynamicContent.fdc1;
import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;
-import java.util.Calendar;
import java.util.Date;
-import java.util.TimeZone;
import org.uic.barcode.asn1.datatypes.FieldOrder;
import org.uic.barcode.asn1.datatypes.IntRange;
import org.uic.barcode.asn1.datatypes.Sequence;
-// TODO: Auto-generated Javadoc
+
/**
* The Class TimeStamp.
*/
@@ -20,16 +21,10 @@ public class TimeStamp {
/*
-- Moment of generation of the dynamic content, expressed in UTC :
- -- * dynamicContentDay is the number of days from issuing date
- -- (UicRailTicketData.issuingDetail.issuingYear and issuingDay)
- -- The range 0..1070 allows a validity equal to that of the validFrom (700) plus
- -- validUntil (370) elements of the different transport documents of UicRailTicketData.
+ -- * dynamicContentDay is the number of day in the year
-- * dynamicContentTime is the number of seconds of the day
-- (from 0 = 0:00:00 to 86399 = 23:59:59)
- -- These two elements shall be either both present, either both absent
- dynamicContentDay INTEGER (0..366),
- *
- */
+ */
@FieldOrder(order = 0)
@IntRange(minValue=1, maxValue=366)
public Long day;
@@ -46,7 +41,7 @@ public class TimeStamp {
* Instantiates a new time stamp and sets the time-stamp to now.
*/
public TimeStamp() {
- Instant now = Instant.now();
+ ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC"));
day = new Long(now.get(ChronoField.DAY_OF_YEAR));
secondOfDay = new Long(now.get(ChronoField.SECOND_OF_DAY));
}
@@ -55,7 +50,7 @@ public class TimeStamp {
* Sets the the time-stamp to now.
*/
public void setNow() {
- Instant now = Instant.now();
+ ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC"));
day = new Long(now.get(ChronoField.DAY_OF_YEAR));
secondOfDay = new Long(now.get(ChronoField.SECOND_OF_DAY));
}
@@ -102,25 +97,26 @@ public class TimeStamp {
* @return the date and time of content creation in UTC
*/
public Date getTimeAsDate() {
-
- Calendar cal = Calendar.getInstance();
- int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
-
+
+ ZonedDateTime now = Instant.now().atZone(ZoneOffset.UTC);
+ int dayOfYear = now.getDayOfYear();
+
if (dayOfYear - day.intValue() > 250) {
- cal.add(Calendar.YEAR, 1);
+ now = now.plusDays(1);
}
if (day.intValue() - dayOfYear > 250) {
- cal.add(Calendar.YEAR, -1);
+ now = now.minusDays(1);
}
-
- cal.setTimeZone(TimeZone.getTimeZone("UTC"));
- cal.set(Calendar.SECOND,0);
- cal.set(Calendar.HOUR,0);
- cal.set(Calendar.MINUTE,0);
- cal.set(Calendar.DAY_OF_YEAR, day.intValue());
- cal.add(Calendar.SECOND, secondOfDay.intValue());
+
+ now = now.withDayOfYear(1);
+ now = now.withSecond(0);
+ now = now.withHour(0);
+ now = now.withMinute(0);
+ now = now.withDayOfYear(dayOfYear);
+ now = now.plusSeconds(secondOfDay);
- return cal.getTime();
+ return Date.from(now.toInstant());
+
}
/**
@@ -129,15 +125,14 @@ public class TimeStamp {
* @param dateUTC the current date and time in UTC
*/
public void setDateTime(Date dateUTC) {
-
- Calendar cal = Calendar.getInstance();
- cal.setTime(dateUTC);
- day = Long.valueOf(cal.get(Calendar.DAY_OF_YEAR));
+ ZonedDateTime date = dateUTC.toInstant().atZone(ZoneOffset.UTC);
+
+ day = (long) date.getDayOfYear();
- secondOfDay = (long) cal.get(Calendar.SECOND);
- secondOfDay = secondOfDay + 60 * (long) cal.get(Calendar.MINUTE);
- secondOfDay = secondOfDay + 60 * 60 * (long) cal.get(Calendar.HOUR_OF_DAY);
+ secondOfDay = (long) date.getSecond();
+ secondOfDay = secondOfDay + 60 * (long) date.getMinute();
+ secondOfDay = secondOfDay + 60 * 60 * (long) date.getHour();
}
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
index ae352d1..c658448 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
@@ -161,13 +161,13 @@ public class UicDynamicContentDataFDC1 {
return null;
}
- public void setPassIdHash(byte[] phoneIdHash) {
+ public void setPassIdHash(byte[] passIdHash) {
if (extensions == null) {
extensions = new SequenceOfExtension();
};
ExtensionData ed = new ExtensionData();
ed.setExtensionId("pass");
- ed.setExtensionData(phoneIdHash);
+ ed.setExtensionData(passIdHash);
extensions.add(ed);
}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
index 774475a..8f47986 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
@@ -16,6 +16,7 @@ public class Constants {
public static String DATA_TYPE_FCB_VERSION_1 = "FCB1";
public static String DATA_TYPE_FCB_VERSION_2 = "FCB2";
+ public static String DATA_TYPE_FCB_VERSION_3 = "FCB3";
public static String DYNAMIC_BARCODE_FORMAT_DEFAULT = "U1";
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/DataType.java
index 2d6d984..2ea63ca 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/DataType.java
@@ -1,6 +1,5 @@
package org.uic.barcode.dynamicFrame;
-import org.uic.barcode.asn1.datatypes.Asn1Default;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
@@ -20,7 +19,6 @@ public class DataType {
* -- FCB2 FCB version 2
* -- RICS company code + ...
**/
- @Asn1Default("FCB1")
@RestrictedString(CharacterRestriction.IA5String)
public String format;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
index 6cc1eaa..c74215d 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
@@ -14,7 +14,6 @@ import java.security.spec.X509EncodedKeySpec;
import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
import org.uic.barcode.asn1.datatypes.FieldOrder;
-import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.OctetString;
@@ -29,7 +28,6 @@ import org.uic.barcode.utils.AlgorithmNameResolver;
* Implementation of the Draft under discussion, not final.
*/
@Sequence
-@HasExtensionMarker
public class DynamicFrame extends Object{
public DynamicFrame() {}
@@ -152,7 +150,9 @@ public class DynamicFrame extends Object{
byte[] keyBytes = this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
- } catch (InvalidKeySpecException | NoSuchAlgorithmException e1) {
+ } catch (InvalidKeySpecException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ } catch (NoSuchAlgorithmException e1) {
return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java
index aac0188..958cafc 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java
@@ -34,7 +34,7 @@ public class Level1DataType {
/** The key id. */
@FieldOrder(order = 2)
- @IntRange(minValue=1,maxValue=99999)
+ @IntRange(minValue=0,maxValue=99999)
@Asn1Optional public Long keyId;
diff --git a/src/main/java/org/uic/barcode/ticket/UicRailTicketCoder.java b/src/main/java/org/uic/barcode/ticket/UicRailTicketCoder.java
index e9d2eb4..0586ed4 100644
--- a/src/main/java/org/uic/barcode/ticket/UicRailTicketCoder.java
+++ b/src/main/java/org/uic/barcode/ticket/UicRailTicketCoder.java
@@ -33,7 +33,7 @@ public class UicRailTicketCoder {
public byte[] encode (IUicRailTicket uicRailTicket, int version) throws IOException, EncodingFormatException{
- if (version == 13) {
+ if (version == 13 || version == 1) {
Api2OpenAsnEncoder uicEncoder = new Api2OpenAsnEncoder();
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv1/CountermarkData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv1/CountermarkData.java
index 76625d4..579342e 100644
--- a/src/main/java/org/uic/barcode/ticket/api/asn/omv1/CountermarkData.java
+++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv1/CountermarkData.java
@@ -72,15 +72,15 @@ public class CountermarkData extends Object {
@FieldOrder(order = 8)
@IntRange(minValue=1,maxValue=200)
- @Asn1Optional public Long numberOfCountermark;
+ public Long numberOfCountermark;
@FieldOrder(order = 9)
@IntRange(minValue=1,maxValue=200)
- @Asn1Optional public Long totalOfCountermarks;
+ public Long totalOfCountermarks;
@FieldOrder(order = 10)
@RestrictedString(CharacterRestriction.UTF8String)
- @Asn1Optional public String groupName;
+ public String groupName;
@FieldOrder(order = 11)
@Asn1Default("stationUIC")
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv1/ViaStationType.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv1/ViaStationType.java
index dfc1e56..ddabf0b 100644
--- a/src/main/java/org/uic/barcode/ticket/api/asn/omv1/ViaStationType.java
+++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv1/ViaStationType.java
@@ -55,7 +55,7 @@ public class ViaStationType extends Object {
@Asn1Optional public SequenceOfViaStationType route;
@FieldOrder(order = 5)
- @Asn1Optional public Boolean border = false;
+ public Boolean border = false;
@FieldOrder(order = 6)
@Asn1Optional public SequenceOfCarrierNum carriersNum;
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv2/CountermarkData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv2/CountermarkData.java
index aefdc3b..4c5a961 100644
--- a/src/main/java/org/uic/barcode/ticket/api/asn/omv2/CountermarkData.java
+++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv2/CountermarkData.java
@@ -72,15 +72,15 @@ public class CountermarkData extends Object {
@FieldOrder(order = 8)
@IntRange(minValue=1,maxValue=200)
- @Asn1Optional public Long numberOfCountermark;
+ public Long numberOfCountermark;
@FieldOrder(order = 9)
@IntRange(minValue=1,maxValue=200)
- @Asn1Optional public Long totalOfCountermarks;
+ public Long totalOfCountermarks;
@FieldOrder(order = 10)
@RestrictedString(CharacterRestriction.UTF8String)
- @Asn1Optional public String groupName;
+ public String groupName;
@FieldOrder(order = 11)
@Asn1Default("stationUIC")
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv2/ViaStationType.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv2/ViaStationType.java
index 0e2ca6c..f7aa1bb 100644
--- a/src/main/java/org/uic/barcode/ticket/api/asn/omv2/ViaStationType.java
+++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv2/ViaStationType.java
@@ -55,7 +55,7 @@ public class ViaStationType extends Object {
@Asn1Optional public SequenceOfViaStationType route;
@FieldOrder(order = 5)
- @Asn1Optional public Boolean border = false;
+ public Boolean border = false;
@FieldOrder(order = 6)
@Asn1Optional public SequenceOfCarrierNum carriersNum;
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/CountermarkData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/CountermarkData.java
index 733ccf0..510ec6f 100644
--- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/CountermarkData.java
+++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/CountermarkData.java
@@ -72,15 +72,15 @@ public class CountermarkData extends Object {
@FieldOrder(order = 8)
@IntRange(minValue=1,maxValue=200)
- @Asn1Optional public Long numberOfCountermark;
+ public Long numberOfCountermark;
@FieldOrder(order = 9)
@IntRange(minValue=1,maxValue=200)
- @Asn1Optional public Long totalOfCountermarks;
+ public Long totalOfCountermarks;
@FieldOrder(order = 10)
@RestrictedString(CharacterRestriction.UTF8String)
- @Asn1Optional public String groupName;
+ String groupName;
@FieldOrder(order = 11)
@Asn1Default("stationUIC")
diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/ViaStationType.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/ViaStationType.java
index d47bd98..2d8b751 100644
--- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/ViaStationType.java
+++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/ViaStationType.java
@@ -55,7 +55,7 @@ public class ViaStationType extends Object {
@Asn1Optional public SequenceOfViaStationType route;
@FieldOrder(order = 5)
- @Asn1Optional public Boolean border = false;
+ public Boolean border = false;
@FieldOrder(order = 6)
@Asn1Optional public SequenceOfCarrierNum carriersNum;
diff --git a/src/main/java/org/uic/barcode/ticket/api/spec/uicBarcodeHeader0.1.asn b/src/main/java/org/uic/barcode/ticket/api/spec/uicBarcodeHeader0.1.asn
deleted file mode 100644
index 2999d18..0000000
--- a/src/main/java/org/uic/barcode/ticket/api/spec/uicBarcodeHeader0.1.asn
+++ /dev/null
@@ -1,151 +0,0 @@
--- Creator: ASN.1 Editor (http://asneditor.sourceforge.net)
--- Author: ClemensGantert
--- Created: Tue Aug 11 11:40:28 CEST 2015
-ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN
-
--- imports and exports
--- EXPORTS ALL;
-
-
--- ##############################################################################################
--- #
--- # UIC barcode header - first draft
--- #
--- ##############################################################################################
-
-
--- ##############################################################################################
--- #
--- # Naming and encoding conventions
--- #
--- # Elements included as String and as Numeric values:
--- # Some elements are included in different formats to reduce the data size.
--- # These elements must be included only once.
--- # These elements are named with the same name and appendix
--- # Num (numeric values)
--- # IA5 (String values according to ASN IA5String (7Bit))
--- #
--- # RICS codes must be used to encode companies (issuer, product owner, ...) where available
--- # other codes are possible based on bilateral agreements
--- # the format is kept more flexible to cover upcoming extensions of the RICS code by ERA
--- #
--- # Stations can be coded using the UIC and upcoming ERA code lists. Proprietary codes are
--- # possible based on bilateral agreements. Format: 1..9999999 or alphanumeric without
--- # special character (IA5String)
--- #
--- #
--- # ! INTEGERS must not exceed the value of 9,223,372,036,854,775,807 (64 bit) even in case
--- # ! they are unrestricted!!!
--- # !
--- # ! Some elements like ReferenceNum or cardIdNum are defined as an unrestricted integer.
--- # ! Unlike other numerical values the cardIdNum and referenceNum can be larger than a usual 32 bit Integer
--- # ! Some ASN.1 implementation tools are limited to 32 bit integers which is too small.
--- # ! Please ensure to use a tool capable of dealing with larger numbers.
--- #
--- # BOOLEAN is always non optional
--- #
--- # Encoding of time:
--- # time is encoded as the number of minutes of the day 0 = 00:00, 1440 = 24:00,
--- # time data elements end with "time" in their name
--- #
--- # Encoding of date:
--- # .........................................................................................................
--- # The issuing date is given in UTC, but some other date values are given in local time where the exact time zone is not known.
--- #
--- #
--- #
--- # ASN.1 Extensions:
--- #
--- # The specification makes use of extension (",...").
--- # These extesions might be defined in future versions of the UIC specification
--- # Implementations must support the extension feature of ASN.1, at least they must be able to ignore extensions while decoding the data
--- # ASN.1 extensions will be defined by UIC. It is not allowed to define bilateral extensions.
--- #
--- # Bilateral Extensions:
--- # Bilateral extensions can be included in the data element "ExtensionData".
--- #
--- #
--- #
--- #########################################################################################
-
-
--- ############################################################################################
-
-
--- type assignments
-
- -- #########################################################################################
- -- the basic entry point of the data structure
- -- the data include:
- -- -issuer informations
- -- -the details of the transport document
- -- -informations required for the control process
- -- -informations on the travelers independent from the transport document
- -- -proprietary extensions
- --
- -- ##########################################################################################
- UicBarcodeHeader ::= SEQUENCE {
- -- format type
- format IA5String,
- -- "UIC" = UIC ticket
-
- version Integer (1..16),
-
- -- provider of the signature (RICS code)
- securityProviderNum INTEGER (1..32000) OPTIONAL,
- securityProviderIA5 IA5String OPTIONAL,
-
-
- staticData SEQUENCE OF DataType,
- staticSignature SignatureType OPTIONAL,
-
-
-
- -- additional dynamic data i.e. phone number, IMEI, timestamp , .... --> To be defined separately
- dynamicDataFormat IA5String OPTIONAL,
- dynamicData OCTET STRING OPTIONAL,
- dynamicPublicKey OCTET STRING OPTIONAL,
- dynamicSignature SignatureType OPTIONAL
-
- -- proprietary data defined bilaterally
- extension SEQUENCE OF ExtensionData OPTIONAL
- ,...
-
- }
-
- DataType ::= SEQUENCE {
- staticDataFormat IA5String DEFAULT "FCB1",
- -- FCB1 FCB version 1
- -- 1080XYZ
- staticData OCTET STRING
- }
-
-
-
- SignatureType ::= SEQUENCE {
- signingAlg IA5String,
- keyId IA5String (SIZE(1..5)),
- signature OCTET STRING,
- }
-
-
-
- -- ###########################################################################################
- -- generic non standard extension element
- -- the generic non - standard element contains:
- -- - an extension id to distinguish different extensions
- -- - the extension data as binary data
- -- proprietary extensions are by definition proprietary. This standard provides
- -- the means to identify these extensions
- -- within the data and to skip these data.
- -- the evaluation of these data and the unique identification of the extensions
- -- via the extension id is in the
- -- responsibility of the railways which use these extensions.
- -- ###########################################################################################
- ExtensionData ::= SEQUENCE {
- extensionId IA5String,
- extensionData OCTET STRING
- }
-
-
-END \ No newline at end of file
diff --git a/src/test/java/org/uic/barcode/asn1/test/GenAlphabet.java b/src/test/java/org/uic/barcode/asn1/test/GenAlphabet.java
new file mode 100644
index 0000000..a08392e
--- /dev/null
+++ b/src/test/java/org/uic/barcode/asn1/test/GenAlphabet.java
@@ -0,0 +1,11 @@
+package org.uic.barcode.asn1.test;
+
+import org.uic.barcode.asn1.datatypes.Alphabet;
+
+public class GenAlphabet extends Alphabet {
+
+ public GenAlphabet() {
+ super("ACGT");
+ }
+
+}
diff --git a/src/test/java/org/uic/barcode/asn1/test/UperEncodeBitStringTest.java b/src/test/java/org/uic/barcode/asn1/test/UperEncodeBitStringTest.java
new file mode 100644
index 0000000..94f29c2
--- /dev/null
+++ b/src/test/java/org/uic/barcode/asn1/test/UperEncodeBitStringTest.java
@@ -0,0 +1,82 @@
+package org.uic.barcode.asn1.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.logging.Level;
+
+import org.junit.Test;
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.Bitstring;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.FixedSize;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+
+public class UperEncodeBitStringTest {
+
+ /**
+ * Example from the Standard on UPER.
+ <pre>
+ World-Schema DEFINITIONS AUTOMATIC TAGS ::=
+ BEGIN
+ TestRecord ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+ value BIT STRING (SIZE(3)) OPTIONAL
+ }
+ END
+
+
+ rec1value TestRecord ::= {
+ value '001'B
+ }
+ </pre>
+
+
+
+ */
+ @Sequence
+ public static class TestRecord {
+
+ @FieldOrder(order = 0)
+ @Asn1Optional()
+ @Bitstring()
+ @FixedSize(3)
+ ArrayList<Boolean> booleans = null;
+
+ public TestRecord() {
+ this(false,false,true);
+ }
+
+ public TestRecord(Boolean value1,Boolean value2,Boolean value3 ) {
+ booleans = new ArrayList<Boolean>();
+ booleans.add(value1);
+ booleans.add(value2);
+ booleans.add(value3);
+ }
+ }
+
+
+ @Test public void testEncode() throws IllegalArgumentException, IllegalAccessException {
+ TestRecord record = new TestRecord(false,false,true);
+ byte[] encoded = UperEncoder.encode(record);
+ String hex = UperEncoder.hexStringFromBytes(encoded);
+ UperEncoder.logger.log(Level.FINEST,String.format("data hex: %s", hex));
+ assertEquals("90",hex);
+ }
+
+
+ @Test public void testDecode() throws IllegalArgumentException, IllegalAccessException {
+ TestRecord record = new TestRecord(false,false,true);
+ byte[] encoded = UperEncoder.encode(record);
+ String hex = UperEncoder.hexStringFromBytes(encoded);
+ UperEncoder.logger.log(Level.FINEST,String.format("data hex: %s", hex));
+ assertEquals("90",hex);
+ TestRecord result = UperEncoder.decode(encoded, TestRecord.class);
+ assertEquals(result.booleans.get(0),record.booleans.get(0));
+ assertEquals(result.booleans.get(1),record.booleans.get(1));
+ assertEquals(result.booleans.get(2),record.booleans.get(2));
+
+ }
+
+}
diff --git a/src/test/java/org/uic/barcode/asn1/test/UperEncodeStringCustomAlphabetTest.java b/src/test/java/org/uic/barcode/asn1/test/UperEncodeStringCustomAlphabetTest.java
new file mode 100644
index 0000000..03b8bac
--- /dev/null
+++ b/src/test/java/org/uic/barcode/asn1/test/UperEncodeStringCustomAlphabetTest.java
@@ -0,0 +1,82 @@
+package org.uic.barcode.asn1.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.logging.Level;
+
+import org.junit.Test;
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+
+public class UperEncodeStringCustomAlphabetTest {
+
+ /**
+ * Example from the Standard on UPER.
+ <pre>
+ World-Schema DEFINITIONS AUTOMATIC TAGS ::=
+ BEGIN
+ TestRecord ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+ value1 PrintableString ( FROM ("ACGT") ) OPTIONAL,
+ value2 PrintableString ( FROM ("ACGT") ) OPTIONAL
+ }
+ END
+
+ rec1value TestRecord ::= {
+ value1 "ACGT",
+ value2 "ACTGCATCGA"
+ }
+ </pre>
+ */
+ @Sequence
+ public static class TestRecord {
+
+ @FieldOrder(order = 0)
+ @RestrictedString(value = CharacterRestriction.VisibleString, alphabet = GenAlphabet.class)
+ @Asn1Optional() String value1;
+
+ @FieldOrder(order = 1)
+ @RestrictedString(value = CharacterRestriction.VisibleString, alphabet = GenAlphabet.class)
+ @Asn1Optional() String value2;
+
+ public TestRecord() {
+ }
+
+ public TestRecord(String v1, String v2) {
+ this.value1 = v1;
+ this.value2 = v2;
+ }
+ }
+
+
+ @Test public void testEncode() throws IllegalArgumentException, IllegalAccessException {
+
+
+ TestRecord record = new TestRecord("ACGT", "ACTGCATCGA");
+ byte[] encoded = UperEncoder.encode(record);
+ String hex = UperEncoder.hexStringFromBytes(encoded);
+ UperEncoder.logger.log(Level.FINEST,String.format("data hex: %s", hex));
+ assertEquals("C106C2879360",hex);
+
+ }
+
+
+ @Test public void testDecode() throws IllegalArgumentException, IllegalAccessException {
+
+ TestRecord record = new TestRecord("ACGT", "ACTGCATCGA");
+ byte[] encoded = UperEncoder.encode(record);
+ String hex = UperEncoder.hexStringFromBytes(encoded);
+ UperEncoder.logger.log(Level.FINEST,String.format("data hex: %s", hex));
+ assertEquals("C106C2879360",hex);
+ TestRecord result = UperEncoder.decode(encoded, TestRecord.class);
+ assertEquals(result.value1,record.value1);
+ assertEquals(result.value2,record.value2);
+ }
+
+
+
+}
diff --git a/src/test/java/org/uic/barcode/asn1/test/UperEncodeVarBitStringTest.java b/src/test/java/org/uic/barcode/asn1/test/UperEncodeVarBitStringTest.java
new file mode 100644
index 0000000..d6212e2
--- /dev/null
+++ b/src/test/java/org/uic/barcode/asn1/test/UperEncodeVarBitStringTest.java
@@ -0,0 +1,81 @@
+package org.uic.barcode.asn1.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.junit.Test;
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.Asn1VarSizeBitstring;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+
+public class UperEncodeVarBitStringTest {
+
+ /**
+ * Example from the Standard on UPER.
+ <pre>
+ World-Schema DEFINITIONS AUTOMATIC TAGS ::=
+ BEGIN
+ TestRecord ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+ value BIT STRING OPTIONAL,
+ }
+ END
+
+
+ rec1value TestRecord ::= {
+ value '001'B
+ }
+ </pre>
+
+
+
+ */
+ @Sequence
+ public static class TestRecord {
+
+ @FieldOrder(order = 0)
+ @Asn1Optional() Asn1VarSizeBitstring value;
+
+ public TestRecord() {
+ this(false,false,true);
+ }
+
+ public TestRecord(Boolean value1,Boolean value2,Boolean value3 ) {
+ List<Boolean> booleans = new ArrayList<Boolean>();
+ booleans.add(value1);
+ booleans.add(value2);
+ booleans.add(value3);
+ this.value = new Asn1VarSizeBitstring(booleans);
+
+ }
+ }
+
+
+ @Test public void testEncode() throws IllegalArgumentException, IllegalAccessException {
+ TestRecord record = new TestRecord(false,false,true);
+ byte[] encoded = UperEncoder.encode(record);
+ String hex = UperEncoder.hexStringFromBytes(encoded);
+ UperEncoder.logger.log(Level.FINEST,String.format("data hex: %s", hex));
+ assertEquals("8190",hex);
+ }
+
+
+ @Test public void testDecode() throws IllegalArgumentException, IllegalAccessException {
+ TestRecord record = new TestRecord(false,false,true);
+ byte[] encoded = UperEncoder.encode(record);
+ String hex = UperEncoder.hexStringFromBytes(encoded);
+ UperEncoder.logger.log(Level.FINEST,String.format("data hex: %s", hex));
+ assertEquals("8190",hex);
+ TestRecord result = UperEncoder.decode(encoded, TestRecord.class);
+ assertEquals(result.value.get(0),record.value.get(0));
+ assertEquals(result.value.get(1),record.value.get(1));
+ assertEquals(result.value.get(2),record.value.get(2));
+
+ }
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
new file mode 100644
index 0000000..84f7795
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
@@ -0,0 +1,169 @@
+package org.uic.barcode.test;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.util.Arrays;
+import java.util.zip.DataFormatException;
+
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.Decoder;
+import org.uic.barcode.Encoder;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.test.utils.Level2TestDataFactory;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public class DynamicFrameDoubleSignatureProviderSelectionTest {
+
+ public String signatureAlgorithmOID = null;
+ public String elipticCurve = null;
+ public String keyPairAlgorithmOID = null;
+
+ public KeyPair keyPairLevel1 = null;
+ public KeyPair keyPairLevel2 = null;
+
+ public IUicRailTicket testFCBticket = null;
+
+ public Provider prov = null;
+
+ @Before public void initialize() {
+
+ signatureAlgorithmOID = Constants.ECDSA_SHA256;
+ keyPairAlgorithmOID = Constants.KG_EC_256;
+ elipticCurve = "secp256k1";
+
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+
+ prov = new BouncyCastleProvider();
+
+ Security.addProvider(prov);
+
+ try {
+ keyPairLevel1 = generateECKeys(keyPairAlgorithmOID, elipticCurve);
+ keyPairLevel2 = generateECKeys(keyPairAlgorithmOID, elipticCurve);
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(keyPairLevel1 != null);
+
+ assert(keyPairLevel2 != null);
+
+ }
+
+
+
+ @Test public void testDynamicHeaderBarcodeDecoding() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 13);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ try {
+ enc.setLevel1Algs(signatureAlgorithmOID, keyPairAlgorithmOID);
+ enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID,keyPairLevel2.getPublic());
+ enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1",prov);
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+
+ DataType level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
+ try {
+ enc.setLevel2Data(level2Data);
+ enc.signLevel2(keyPairLevel2.getPrivate(),prov);
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ Decoder dec = null;
+ try {
+ dec = new Decoder(encoded);
+ } catch (IOException e) {
+ assert(false);
+ } catch (EncodingFormatException e) {
+ assert(false);
+ } catch (DataFormatException e) {
+ assert(false);
+ }
+ assert(dec != null);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPairLevel1.getPublic(), null, prov);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel2(prov);
+ } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ assert(false);
+ }
+ assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK);
+
+ DataType level2DataDec = dec.getLevel2Data();
+
+ assert(level2Data.getFormat().equals(level2DataDec.getFormat()));
+ assert(Arrays.equals(level2Data.getData().toByteArray(),level2DataDec.getData().toByteArray()));
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+ }
+
+ public KeyPair generateECDSAKeys(String keyAlgorithmName, String paramName) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(paramName);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+ public KeyPair generateECKeys(String keyAlgorithmOid, String curve) throws Exception{
+
+ String keyAlgorithmName = "ECDSA";
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curve);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
new file mode 100644
index 0000000..f3e4f54
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
@@ -0,0 +1,258 @@
+package org.uic.barcode.test;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.zip.DataFormatException;
+
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.Decoder;
+import org.uic.barcode.Encoder;
+import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateSystemType;
+import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateType;
+import org.uic.barcode.dynamicContent.fdc1.TimeStamp;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public class DynamicFrameDynamicContentTest {
+
+ public String signatureAlgorithmOID = null;
+ public String elipticCurve = null;
+ public String keyPairAlgorithmOID = null;
+
+ public KeyPair keyPairLevel1 = null;
+ public KeyPair keyPairLevel2 = null;
+
+ public byte[] passIdHash = "PassId".getBytes();
+ public byte[] phoneIdHash = "myPhone".getBytes();
+
+ ZonedDateTime originalTimeStamp = ZonedDateTime.now(ZoneId.of("UTC"));
+
+ public IUicRailTicket testFCBticket = null;
+
+
+ @Before public void initialize() {
+
+ signatureAlgorithmOID = Constants.ECDSA_SHA256;
+ keyPairAlgorithmOID = Constants.KG_EC_256;
+ elipticCurve = "secp256k1";
+
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ try {
+ keyPairLevel1 = generateECKeys(keyPairAlgorithmOID, elipticCurve);
+ keyPairLevel2 = generateECKeys(keyPairAlgorithmOID, elipticCurve);
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(keyPairLevel1 != null);
+
+ assert(keyPairLevel2 != null);
+
+ }
+
+
+ @Test public void testDynamicContentEncoding() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 13);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID, keyPairLevel2.getPublic());
+
+ try {
+ enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ try {
+ UicDynamicContentDataFDC1 dcd = new UicDynamicContentDataFDC1();
+ dcd.setChallengeString("CHALLENGE");
+ dcd.setAppId("MyApp");
+ dcd.setPhoneIdHash(phoneIdHash);
+ dcd.setPassIdHash(passIdHash);
+ TimeStamp ts = new TimeStamp();
+ ts.setDateTime(Date.from(originalTimeStamp.toInstant()));
+ dcd.setTimeStamp(ts);
+
+ GeoCoordinateType geo = new GeoCoordinateType();
+ geo.setLatitude(123456L);
+ geo.setLongitude(823456L);
+ dcd.setGeoCoordinate(geo);
+
+ enc.setDynamicContentDataUIC1(dcd);
+ enc.signLevel2(keyPairLevel2.getPrivate());
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+
+
+ }
+
+ @Test public void testDynamicContentDecoding() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 13);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID, keyPairLevel2.getPublic());
+
+ try {
+ enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ try {
+ UicDynamicContentDataFDC1 dcd = new UicDynamicContentDataFDC1();
+ dcd.setChallengeString("CHALLENGE");
+ dcd.setAppId("MyApp");
+ dcd.setPhoneIdHash(phoneIdHash);
+ dcd.setPassIdHash(passIdHash);
+
+ GeoCoordinateType geo = new GeoCoordinateType();
+ geo.setLatitude(123456L);
+ geo.setLongitude(823456L);
+ dcd.setGeoCoordinate(geo);
+
+ TimeStamp ts = new TimeStamp();
+ ts.setDateTime(Date.from(originalTimeStamp.toInstant()));
+ dcd.setTimeStamp(ts);
+
+ enc.setDynamicContentDataUIC1(dcd);
+ enc.signLevel2(keyPairLevel2.getPrivate());
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ Decoder dec = null;
+ try {
+ dec = new Decoder(encoded);
+ } catch (IOException e) {
+ assert(false);
+ } catch (EncodingFormatException e) {
+ assert(false);
+ } catch (DataFormatException e) {
+ assert(false);
+ }
+ assert(dec != null);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPairLevel1.getPublic(),null);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+ int level2check = 0;
+ try {
+ level2check = dec.validateLevel2();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(level2check == Constants.LEVEL2_VALIDATION_OK);
+
+ UicDynamicContentDataFDC1 dynamicData = dec.getDynamicHeader().getDynamicDataFDC1();
+
+ assert(dynamicData.getChallengeString().equals("CHALLENGE"));
+
+ assert(dynamicData.getAppId().equals("MyApp"));
+
+ assert(Arrays.equals(dynamicData.getPassIdHash(),passIdHash));
+
+ assert(Arrays.equals(dynamicData.getPhoneIdHash(),phoneIdHash));
+
+ assert(dynamicData.getGeoCoordinate().getLatitude() == 123456L);
+ assert(dynamicData.getGeoCoordinate().getLongitude() == 823456L);
+
+ Date timeStamp = dynamicData.getTimeStamp().getTimeAsDate();
+ ZonedDateTime retrievedTimeStamp = timeStamp.toInstant().atZone(ZoneId.of("UTC"));
+ long diff = ChronoUnit.SECONDS.between(originalTimeStamp, retrievedTimeStamp);
+
+ assert(diff == 0);
+ }
+
+ public KeyPair generateECDSAKeys(String keyAlgorithmName, String paramName) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(paramName);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+ public KeyPair generateECKeys(String keyAlgorithmOid, String curve) throws Exception{
+
+ String keyAlgorithmName = "ECDSA";
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curve);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
new file mode 100644
index 0000000..63ba68e
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
@@ -0,0 +1,174 @@
+package org.uic.barcode.test;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.util.zip.DataFormatException;
+
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.Decoder;
+import org.uic.barcode.Encoder;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public class DynamicFrameFcbVersion1Test {
+
+ public String signatureAlgorithmOID = null;
+ public String elipticCurve = null;
+ public String keyPairAlgorithmOID = null;
+
+ public KeyPair keyPair = null;
+
+ public IUicRailTicket testFCBticket = null;
+
+
+ @Before public void initialize() {
+
+ signatureAlgorithmOID = Constants.ECDSA_SHA256;
+ keyPairAlgorithmOID = Constants.KG_EC_256;
+ elipticCurve = "secp256k1";
+
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ try {
+ keyPair = generateECKeys(Constants.KG_EC, elipticCurve);
+ //keyPair = generateECDSAKeys("ECDSA", "B-571");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(keyPair != null);
+
+ }
+
+
+ @Test public void testDynamicHeaderBarcodeEncodingFCB3() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 1);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+
+ }
+
+ @Test public void testDynamicHeaderBarcodeDecodingFCB3() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 1);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ Decoder dec = null;
+ try {
+ dec = new Decoder(encoded);
+ } catch (IOException e) {
+ assert(false);
+ } catch (EncodingFormatException e) {
+ assert(false);
+ } catch (DataFormatException e) {
+ assert(false);
+ }
+ assert(dec != null);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPair.getPublic(),null);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ assert(dec.getDynamicHeader().getFormat().equals("U1"));
+
+ assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB1"));
+
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+
+
+
+ }
+
+ public KeyPair generateECDSAKeys(String keyAlgorithmName, String paramName) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(paramName);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+ public KeyPair generateECKeys(String keyAlgorithmOid, String curve) throws Exception{
+
+ String keyAlgorithmName = "ECDSA";
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curve);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
new file mode 100644
index 0000000..4f0897e
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
@@ -0,0 +1,174 @@
+package org.uic.barcode.test;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.util.zip.DataFormatException;
+
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.Decoder;
+import org.uic.barcode.Encoder;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public class DynamicFrameFcbVersion3Test {
+
+ public String signatureAlgorithmOID = null;
+ public String elipticCurve = null;
+ public String keyPairAlgorithmOID = null;
+
+ public KeyPair keyPair = null;
+
+ public IUicRailTicket testFCBticket = null;
+
+
+ @Before public void initialize() {
+
+ signatureAlgorithmOID = Constants.ECDSA_SHA256;
+ keyPairAlgorithmOID = Constants.KG_EC_256;
+ elipticCurve = "secp256k1";
+
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ try {
+ keyPair = generateECKeys(Constants.KG_EC, elipticCurve);
+ //keyPair = generateECDSAKeys("ECDSA", "B-571");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(keyPair != null);
+
+ }
+
+
+ @Test public void testDynamicHeaderBarcodeEncodingFCB3() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 3);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+
+ }
+
+ @Test public void testDynamicHeaderBarcodeDecodingFCB3() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 3);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ Decoder dec = null;
+ try {
+ dec = new Decoder(encoded);
+ } catch (IOException e) {
+ assert(false);
+ } catch (EncodingFormatException e) {
+ assert(false);
+ } catch (DataFormatException e) {
+ assert(false);
+ }
+ assert(dec != null);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPair.getPublic(),null);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ assert(dec.getDynamicHeader().getFormat().equals("U1"));
+
+ assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB3"));
+
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+
+
+
+ }
+
+ public KeyPair generateECDSAKeys(String keyAlgorithmName, String paramName) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(paramName);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+ public KeyPair generateECKeys(String keyAlgorithmOid, String curve) throws Exception{
+
+ String keyAlgorithmName = "ECDSA";
+ ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curve);
+ KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC");
+ g.initialize(ecSpec, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/StaticFrameBarcodeTestFCB3.java b/src/test/java/org/uic/barcode/test/StaticFrameBarcodeTestFCB3.java
new file mode 100644
index 0000000..41ce365
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/StaticFrameBarcodeTestFCB3.java
@@ -0,0 +1,193 @@
+package org.uic.barcode.test;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.util.zip.DataFormatException;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.Decoder;
+import org.uic.barcode.Encoder;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.staticFrame.ticketLayoutBarcode.TicketLayout;
+import org.uic.barcode.test.utils.SimpleTestTicketLayout;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+/**
+ * The Class StaticFrameBarcodeTest.
+ */
+public class StaticFrameBarcodeTestFCB3 {
+
+ /** The algorithm OID. */
+ public String algorithmOID = Constants.DSA_SHA224;
+
+ public int keySize = 2048;
+
+ /** The key pair. */
+ public KeyPair keyPair = null;
+
+
+ public IUicRailTicket testFCBticket = null;
+
+ public TicketLayout testLayout = null;
+
+
+ /**
+ * Initialize.
+ *
+ * set the signature algorithm
+ * generate a key pair
+ * set the test content
+ * for ticket and layout
+ */
+ @Before public void initialize() {
+
+ algorithmOID = Constants.DSA_SHA224;
+ keySize = 2048;
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+ testLayout = SimpleTestTicketLayout.getSimpleTestTicketLayout();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ try {
+ keyPair = generateDSAKeys(keySize);
+ } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
+ e.printStackTrace();
+ }
+
+ assert(keyPair != null);
+
+ }
+
+
+ /**
+ * Test dynamic header barcode encoding.
+ */
+ @Test public void testStaticHeaderBarcodeEncoding() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ TicketLayout layout = testLayout;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, layout, Encoder.UIC_BARCODE_TYPE_CLASSIC, 2, 3);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ enc.setStaticHeaderParams("123456789012", "de");
+
+ assert(enc != null);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ }
+
+ /**
+ * Test dynamic header barcode decoding.
+ */
+ @Test public void testStaticHeaderBarcodeDecoding() {
+
+
+ IUicRailTicket ticket = testFCBticket;
+
+ TicketLayout layout = testLayout;
+
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, layout, Encoder.UIC_BARCODE_TYPE_CLASSIC, 2, 3);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ enc.setStaticHeaderParams("123456789012", "de");
+
+ assert(enc != null);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ Decoder dec = null;
+ try {
+ dec = new Decoder(encoded);
+ } catch (IOException e) {
+ assert(false);
+ } catch (EncodingFormatException e) {
+ assert(false);
+ } catch (DataFormatException e) {
+ assert(false);
+ }
+ assert(dec != null);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPair.getPublic(),algorithmOID);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+ SimpleTestTicketLayout.compare(layout, dec.getLayout());
+
+ }
+
+ /**
+ * Generate DSA keys.
+ *
+ * @return the key pair
+ * @throws NoSuchAlgorithmException the no such algorithm exception
+ * @throws NoSuchProviderException the no such provider exception
+ * @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception
+ */
+ public KeyPair generateDSAKeys(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{
+ KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC");
+ g.initialize(keySize, new SecureRandom());
+ return g.generateKeyPair();
+ }
+
+}
diff --git a/src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV1.java b/src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV1.java
new file mode 100644
index 0000000..5226880
--- /dev/null
+++ b/src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV1.java
@@ -0,0 +1,95 @@
+package org.uic.barcode.ticket.api.test;
+
+import java.text.ParseException;
+import java.util.TimeZone;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.ticket.api.asn.omv1.UicRailTicketData;
+import org.uic.barcode.ticket.api.test.testtickets.CountermarkTestComplexTicketV1;
+
+
+/**
+ * The Class FipTimeZoneTestV3.
+ *
+ *
+ *
+ */
+public class CountermarkComplexTestV1 {
+
+
+
+ /** The ticket decoded 1. */
+ UicRailTicketData ticket = null;
+
+ byte[] encodedInTimeZone1 = null;
+
+
+ TimeZone defaulttimeZone = null;
+
+ /**
+ * Prepare tickets.
+ */
+ @Before public void prepare() {
+
+ defaulttimeZone = TimeZone.getDefault();
+
+ //encode in UTC time zone
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+
+ }
+
+ /**
+ * clean up
+ */
+ @After public void resetTimeZone() {
+ TimeZone.setDefault(defaulttimeZone);
+ }
+
+
+ /**
+ * Test encode test tickets in UTC and decode in CET.
+ *
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws ParseException
+ */
+ @Test public void decoding() {
+
+ //get tickets
+ String hex = CountermarkTestComplexTicketV1.getEncodingHex();
+ byte[] content = UperEncoder.bytesFromHexString(hex);
+ ticket = UperEncoder.decode(content, UicRailTicketData.class);
+
+ assert(ticket != null);
+
+ }
+
+ @Test public void encoding() throws IllegalArgumentException, IllegalAccessException, ParseException {
+
+ //get tickets
+ String hex = CountermarkTestComplexTicketV1.getEncodingHex();
+ byte[] content = UperEncoder.bytesFromHexString(hex);
+ ticket = UperEncoder.decode(content, UicRailTicketData.class);
+
+
+ //ticket = OpenTestComplexTicketV2.getUicTestTicket();
+ byte[] encoded = UperEncoder.encode(ticket);
+
+
+
+ assert(encoded != null);
+ assert(encoded.length > 20);
+
+ String encodedHex = UperEncoder.hexStringFromBytes(encoded);
+ String expectedHex = CountermarkTestComplexTicketV1.getEncodingHex();
+
+ assert(expectedHex.equals(encodedHex));
+
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV3.java b/src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV3.java
new file mode 100644
index 0000000..86495f0
--- /dev/null
+++ b/src/test/java/org/uic/barcode/ticket/api/test/CountermarkComplexTestV3.java
@@ -0,0 +1,111 @@
+package org.uic.barcode.ticket.api.test;
+
+import java.text.ParseException;
+import java.util.TimeZone;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.ticket.api.asn.omv3.UicRailTicketData;
+import org.uic.barcode.ticket.api.test.testtickets.CountermarkTestComplexTicketV3;
+
+
+/**
+ * The Class FipTimeZoneTestV3.
+ *
+ *
+ *
+ */
+public class CountermarkComplexTestV3 {
+
+
+
+ /** The ticket decoded 1. */
+ UicRailTicketData ticket = null;
+
+ byte[] encodedInTimeZone1 = null;
+
+
+ TimeZone defaulttimeZone = null;
+
+ /**
+ * Prepare tickets.
+ */
+ @Before public void prepare() {
+
+ defaulttimeZone = TimeZone.getDefault();
+
+ //encode in UTC time zone
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+
+ }
+
+ /**
+ * clean up
+ */
+ @After public void resetTimeZone() {
+ TimeZone.setDefault(defaulttimeZone);
+ }
+
+
+ /**
+ * Test encode test tickets in UTC and decode in CET.
+ *
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws ParseException
+ */
+ @Test public void decoding() {
+
+ //get tickets
+ String hex = CountermarkTestComplexTicketV3.getEncodingHex();
+ byte[] content = UperEncoder.bytesFromHexString(hex);
+ ticket = UperEncoder.decode(content, UicRailTicketData.class);
+
+ assert(ticket != null);
+
+ }
+
+ @Test public void encoding() throws IllegalArgumentException, IllegalAccessException, ParseException {
+
+ //get tickets
+ String hex = CountermarkTestComplexTicketV3.getEncodingHex();
+ byte[] content = UperEncoder.bytesFromHexString(hex);
+ ticket = UperEncoder.decode(content, UicRailTicketData.class);
+
+
+ //ticket = OpenTestComplexTicketV2.getUicTestTicket();
+ byte[] encoded = UperEncoder.encode(ticket);
+
+
+
+ assert(encoded != null);
+ assert(encoded.length > 20);
+
+ String encodedHex = UperEncoder.hexStringFromBytes(encoded);
+ String expectedHex = CountermarkTestComplexTicketV3.getEncodingHex();
+
+ assert(expectedHex.equals(encodedHex));
+
+ }
+
+ @Test public void encodingDecoding() throws IllegalArgumentException, IllegalAccessException, ParseException {
+
+ //get tickets
+ ticket = CountermarkTestComplexTicketV3.getUicTestTicket();
+ byte[] encoded = UperEncoder.encode(ticket);
+
+
+
+ assert(encoded != null);
+ assert(encoded.length > 20);
+
+ String encodedHex = UperEncoder.hexStringFromBytes(encoded);
+ String expectedHex = CountermarkTestComplexTicketV3.getEncodingHex();
+
+ assert(expectedHex.equals(encodedHex));
+
+ }
+}
diff --git a/src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV1.java b/src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV1.java
new file mode 100644
index 0000000..4e6fd8e
--- /dev/null
+++ b/src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV1.java
@@ -0,0 +1,509 @@
+package org.uic.barcode.ticket.api.test.testtickets;
+
+import org.uic.barcode.asn1.datatypesimpl.SequenceOfUnrestrictedLong;
+import org.uic.barcode.ticket.api.asn.omv1.CardReferenceType;
+import org.uic.barcode.ticket.api.asn.omv1.ControlData;
+import org.uic.barcode.ticket.api.asn.omv1.CountermarkData;
+import org.uic.barcode.ticket.api.asn.omv1.CustomerStatusType;
+import org.uic.barcode.ticket.api.asn.omv1.DocumentData;
+import org.uic.barcode.ticket.api.asn.omv1.ExtensionData;
+import org.uic.barcode.ticket.api.asn.omv1.IssuingData;
+import org.uic.barcode.ticket.api.asn.omv1.LinkMode;
+import org.uic.barcode.ticket.api.asn.omv1.RegionalValidityType;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfCardReferenceType;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfCustomerStatusType;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfDocumentData;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfExtensionData;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfRegionalValidityType;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfTicketLinkType;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfTravelerType;
+import org.uic.barcode.ticket.api.asn.omv1.SequenceOfViaStationType;
+import org.uic.barcode.ticket.api.asn.omv1.TicketDetailData;
+import org.uic.barcode.ticket.api.asn.omv1.TicketLinkType;
+import org.uic.barcode.ticket.api.asn.omv1.TicketType;
+import org.uic.barcode.ticket.api.asn.omv1.TravelClassType;
+import org.uic.barcode.ticket.api.asn.omv1.TravelerData;
+import org.uic.barcode.ticket.api.asn.omv1.TravelerType;
+import org.uic.barcode.ticket.api.asn.omv1.UicRailTicketData;
+import org.uic.barcode.ticket.api.asn.omv1.ViaStationType;
+import org.uic.barcode.ticket.api.asn.omv1.ZoneType;
+
+
+ public class CountermarkTestComplexTicketV1 {
+
+ public static UicRailTicketData getUicTestTicket() {
+ UicRailTicketData ticket = new UicRailTicketData();
+ populateTicket(ticket);
+ return ticket;
+ }
+
+ /*
+value UicRailTicketData ::= {
+ issuingDetail {
+ issuingYear 2018
+ issuingDay 1
+ issuingTime 600
+ specimen TRUE,
+ securePaperTicket FALSE,
+ activated TRUE,
+ issuerPNR "issuerTestPNR",
+ issuedOnLine 12
+ }
+ ,travelerDetail{
+ traveler {
+ {
+ firstName "John"
+ ,secondName "Dow"
+ ,idCard "12345"
+ ,ticketHolder TRUE
+ ,status {{customerStatusDescr "senior" }}
+ }
+ }
+ ,groupName "myGroup"
+ }
+ ,transportDocument {
+ {
+ ticket counterMark : {
+ numberOfCountermark 12
+ ,totalOfCountermarks 24
+ ,groupName "groupName"
+ ,validRegion
+ { viaStations {
+ route {
+ { stationNum 123455, border FALSE }
+ ,{ stationNum 123456, border FALSE }
+ ,{ alternativeRoutes {
+ { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE }
+ ,{ route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE }
+ }
+ ,border FALSE
+ }
+ ,{ stationNum 123457, border FALSE }
+ }
+ ,border FALSE
+ ,seriesId 999
+ }
+ ,zones { zoneId {100,200}}
+ }
+ ,returnIncluded FALSE
+ ,classCode first
+ ,infoText "counterMark"
+ }
+ }
+ }
+ ,controlDetail {
+ identificationByCardReference {{ trailingCardIdNum 100 } }
+ ,identificationByIdCard FALSE
+ ,identificationByPassportId FALSE
+ ,passportValidationRequired FALSE
+ ,onlineValidationRequired FALSE
+ ,ageCheckRequired FALSE
+ ,reductionCardCheckRequired FALSE
+ ,infoText "cd"
+ ,includedTickets {
+ { referenceIA5 "UED12435867"
+ ,issuerName "OEBB"
+ ,issuerPNR "PNR"
+ ,productOwnerIA5 "test"
+ ,ticketType pass
+ ,linkMode onlyValidInCombination
+ }
+ }
+ }
+ ,extension {
+ { extensionId "1", extensionData '82DA'H }
+ ,{ extensionId "2", extensionData '83DA'H }
+ }
+ }
+
+Encoding to the file 'data.uper' using PER UNALIGNED encoding rule...
+UicRailTicketData SEQUENCE [root fieldcount (not encoded) = 5]
+ issuingDetail IssuingData SEQUENCE [root fieldcount (not encoded) = 8]
+ issuingYear INTEGER [length (not encoded) = 1.0]
+ 2018
+ issuingDay INTEGER [length (not encoded) = 1.1]
+ 1
+ issuingTime INTEGER [length (not encoded) = 1.3]
+ 600
+ specimen BOOLEAN [length (not encoded) = 0.1]
+ TRUE
+ securePaperTicket BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ activated BOOLEAN [length (not encoded) = 0.1]
+ TRUE
+ issuerPNR IA5String [length = 13.0]
+ "issuerTestPNR"
+ issuedOnLine INTEGER [length = 1.0]
+ 12
+ travelerDetail TravelerData SEQUENCE [root fieldcount (not encoded) = 2]
+ traveler SEQUENCE OF [count = 1]
+ TravelerType SEQUENCE [root fieldcount (not encoded) = 5]
+ firstName UTF8String [length = 4.0]
+ 0x4a6f686e
+ secondName UTF8String [length = 3.0]
+ 0x446f77
+ idCard IA5String [length = 5.0]
+ "12345"
+ ticketHolder BOOLEAN [length (not encoded) = 0.1]
+ TRUE
+ status SEQUENCE OF [count = 1]
+ CustomerStatusType SEQUENCE [fieldcount (not encoded) = 1]
+ customerStatusDescr IA5String [length = 6.0]
+ "senior"
+ groupName UTF8String [length = 7.0]
+ 0x6d7947726f7570
+ transportDocument SEQUENCE OF [count = 1]
+ DocumentData SEQUENCE [root fieldcount (not encoded) = 1]
+ ticket CHOICE [index = 6]
+ counterMark CountermarkData SEQUENCE [root fieldcount (not encoded) = 7]
+ numberOfCountermark INTEGER [length (not encoded) = 1.0]
+ 12
+ totalOfCountermarks INTEGER [length (not encoded) = 1.0]
+ 24
+ groupName UTF8String [length = 9.0]
+ 0x67726f75704e616d65
+ validRegion SEQUENCE OF [count = 2]
+ RegionalValidityType CHOICE [index = 1]
+ viaStations ViaStationType SEQUENCE [root fieldcount (not encoded) = 3]
+ route SEQUENCE OF [count = 4]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 123455
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 123456
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ alternativeRoutes SEQUENCE OF [count = 2]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ route SEQUENCE OF [count = 2]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 23455
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 23456
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ route SEQUENCE OF [count = 2]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 3455
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 3456
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 123457
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ seriesId INTEGER [length = 2.0]
+ 999
+ RegionalValidityType CHOICE [index = 2]
+ zones ZoneType SEQUENCE [root fieldcount (not encoded) = 1]
+ zoneId SEQUENCE OF [count = 2]
+ INTEGER [length = 1.0]
+ 100
+ INTEGER [length = 2.0]
+ 200
+ returnIncluded BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ classCode TravelClassType ENUMERATED [length (not encoded) = 0.3]
+ 1
+ infoText UTF8String [length = 11.0]
+ 0x636f756e7465724d61726b
+ controlDetail ControlData SEQUENCE [root fieldcount (not encoded) = 9]
+ identificationByCardReference SEQUENCE OF [count = 1]
+ CardReferenceType SEQUENCE [root fieldcount (not encoded) = 1]
+ trailingCardIdNum INTEGER [length = 1.0]
+ 100
+ identificationByIdCard BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ identificationByPassportId BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ passportValidationRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ onlineValidationRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ageCheckRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ reductionCardCheckRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ infoText UTF8String [length = 2.0]
+ 0x6364
+ includedTickets SEQUENCE OF [count = 1]
+ TicketLinkType SEQUENCE [root fieldcount (not encoded) = 6]
+ referenceIA5 IA5String [length = 11.0]
+ "UED12435867"
+ issuerName UTF8String [length = 4.0]
+ 0x4f454242
+ issuerPNR IA5String [length = 3.0]
+ "PNR"
+ productOwnerIA5 IA5String [length = 4.0]
+ "test"
+ ticketType TicketType ENUMERATED [length (not encoded) = 0.2]
+ 1
+ linkMode LinkMode ENUMERATED [length (not encoded) = 0.1]
+ 1
+ extension SEQUENCE OF [count = 2]
+ ExtensionData SEQUENCE [fieldcount (not encoded) = 2]
+ extensionId IA5String [length = 1.0]
+ "1"
+ extensionData OCTET STRING [length = 2.0]
+ 0x82da
+ ExtensionData SEQUENCE [fieldcount (not encoded) = 2]
+ extensionId IA5String [length = 1.0]
+ "2"
+ extensionData OCTET STRING [length = 2.0]
+ 0x83da
+Total encoded length = 184.1
+Encoded successfully in 185 bytes:
+78222020 0258A1BA 79F3EB97 954CBCFA 509D4804 31405A00 1044A6F6 86E03446
+F770562C 99B46B01 106E7977 69DFC81D B5E51DC9 BDD5C004 30000202 1058B84B
+3B937BAB 82730B6B 28108240 84000F11 F08001E2 3F040040 80110000 B73C2000
+16E7C040 0880000D 7E100001 AFE08001 E2400080 F9C80100 80590080 320216C6
+DEEADCE8 CAE49AC2 E4D69804 0100B200 04C6C802 B70BAB16 23164D19 B570D9B8
+227A2A12 101D09D4 813A65E7 D0A0402C 40A0B680 590141ED 00
+
+ */
+
+
+
+ public static String getEncodingHex() {
+ return
+ "782220200258A1BA79F3EB97954CBCFA509D480431405A001044A6F686E03446" +
+ "F770562C99B46B01106E797769DFC81DB5E51DC9BDD5C004300002021058B84B" +
+ "3B937BAB82730B6B2810824084000F11F08001E23F04004080110000B73C2000" +
+ "16E7C0400880000D7E100001AFE08001E2400080F9C8010080590080320216C6" +
+ "DEEADCE8CAE49AC2E4D698040100B20004C6C802B70BAB1623164D19B570D9B8" +
+ "227A2A12101D09D4813A65E7D0A0402C40A0B680590141ED00";
+ }
+
+
+
+ private static void populateTicket(UicRailTicketData ticket) {
+
+ ticket.setControlDetail(new ControlData());
+ populate(ticket.getControlDetail());
+
+
+ ticket.setIssuingDetail(new IssuingData());
+ populateIssuingData(ticket.getIssuingDetail());
+
+ TravelerData td = new TravelerData();
+ populateTravelerData(td);
+ ticket.setTravelerDetail(td);
+
+ SequenceOfDocumentData ds = new SequenceOfDocumentData();
+
+
+ //OpenTicket
+ DocumentData do1 = new DocumentData();
+ addCounterMark(do1);
+ ds.add(do1);
+ ticket.setTransportDocument(ds);
+
+ SequenceOfExtensionData ed = new SequenceOfExtensionData();
+ populateExtensionSequence(ed);
+ ticket.setExtension(ed);
+
+ }
+
+
+ private static void addCounterMark(DocumentData dd) {
+
+ TicketDetailData tdd = new TicketDetailData();
+ CountermarkData otd = new CountermarkData();
+ otd.setInfoText("counterMark");
+ otd.setClassCode(TravelClassType.first);
+ otd.setReturnIncluded(false);
+
+ otd.setNumberOfCountermark(12L);
+ otd.setTotalOfCountermarks(24L);;
+ otd.setGroupName("groupName");
+
+ otd.setValidRegion(getValidRegion());
+
+ tdd.setCounterMark(otd);
+ dd.setTicket(tdd);
+
+ }
+
+ private static SequenceOfRegionalValidityType getValidRegion() {
+ SequenceOfRegionalValidityType sr = new SequenceOfRegionalValidityType();
+ sr.add(getRegionalValidity());
+ sr.add(getZone());
+ return sr;
+ }
+
+ private static RegionalValidityType getRegionalValidity() {
+ RegionalValidityType r = new RegionalValidityType();
+ r.setViaStations(getRoute());
+ return r;
+ }
+
+ private static ViaStationType getRoute() {
+ ViaStationType m = new ViaStationType();
+ m.setRoute(getMainRoute());
+ m.setSeriesId(999L);
+ return m;
+ }
+
+
+
+ private static ViaStationType getAlternativeRoute() {
+ ViaStationType s = new ViaStationType();
+ s.setAlternativeRoutes(new SequenceOfViaStationType());
+ s.getAlternativeRoutes().add(getAltRoute1());
+ s.getAlternativeRoutes().add(getAltRoute2());
+ return s;
+ }
+
+ /*
+ * { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE }
+ */
+ private static ViaStationType getAltRoute1() {
+ ViaStationType m = new ViaStationType();
+ m.setRoute(new SequenceOfViaStationType());
+ m.getRoute().add(getViaStation(23455L));
+ m.getRoute().add(getViaStation(23456L));
+ return m;
+ }
+
+ /*
+ * { route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE }
+ */
+
+
+ private static ViaStationType getAltRoute2() {
+ ViaStationType m = new ViaStationType();
+ m.setRoute(new SequenceOfViaStationType());
+ m.getRoute().add(getViaStation(3455L));
+ m.getRoute().add(getViaStation(3456L));
+ return m;
+ }
+
+
+ private static ViaStationType getViaStation(long i) {
+ ViaStationType s = new ViaStationType();
+ s.setStationNum(i);
+ return s;
+ }
+
+ private static SequenceOfViaStationType getMainRoute() {
+ SequenceOfViaStationType s = new SequenceOfViaStationType();
+ s.add(getViaStation(123455L));
+ s.add(getViaStation(123456L));
+ s.add(getAlternativeRoute());
+ s.add(getViaStation(123457L));
+ return s;
+ }
+
+ private static RegionalValidityType getZone() {
+ RegionalValidityType r = new RegionalValidityType();
+ ZoneType z = new ZoneType();
+ z.setZoneId(new SequenceOfUnrestrictedLong());
+ z.getZoneId().add(100L);
+ z.getZoneId().add(200L);
+ r.setZones(z);
+ return r;
+ }
+
+ private static void populateTravelerData(TravelerData td) {
+ td.setGroupName("myGroup");
+ SequenceOfTravelerType trs = new SequenceOfTravelerType();
+ TravelerType tr = new TravelerType();
+ tr.setIdCard("12345");
+ tr.setFirstName("John");
+ tr.setSecondName("Dow");
+ tr.setTicketHolder(true);
+ SequenceOfCustomerStatusType ts = new SequenceOfCustomerStatusType();
+ CustomerStatusType cst = new CustomerStatusType();
+ cst.setCustomerStatusDescr("senior");
+ ts.add(cst);
+ tr.setStatus(ts);
+ trs.add(tr);
+ td.setTraveler(trs);
+ }
+
+ private static void populateIssuingData(IssuingData issuingDetail) {
+ issuingDetail.setIssuingYear(2018L);
+ issuingDetail.setIssuingDay(1L);
+ issuingDetail.setIssuingTime(600L);
+ issuingDetail.setIssuerPNR("issuerTestPNR");
+ issuingDetail.setSpecimen(true);
+ issuingDetail.setSecurePaperTicket(false);
+ issuingDetail.setActivated(true);
+ issuingDetail.setIssuedOnLine(12L);
+ }
+
+
+ private static void populateExtensionSequence(SequenceOfExtensionData ed) {
+ ExtensionData ed1 = new ExtensionData();
+ ed1.setExtensionId("1");
+ byte[] ba1 = { (byte) 0x82, (byte) 0xDA };
+ ed1.setExtensionData(ba1);
+ ExtensionData ed2 = new ExtensionData();
+ ed2.setExtensionId("2");
+ byte[] ba2 = { (byte) 0x83, (byte) 0xDA };
+ ed2.setExtensionData(ba2);
+ ed.add(ed1);
+ ed.add(ed2);
+ }
+
+
+ private static void populate(ControlData controlDetail) {
+ controlDetail.infoText = "cd";
+ controlDetail.setAgeCheckRequired(false);
+ controlDetail.setIdentificationByIdCard(false);
+ controlDetail.setIdentificationByPassportId(false);
+ controlDetail.setOnlineValidationRequired(false);
+ controlDetail.setPassportValidationRequired(false);
+ controlDetail.setReductionCardCheckRequired(false);
+ controlDetail.setIdentificationByCardReference(new SequenceOfCardReferenceType());
+ controlDetail.getIdentificationByCardReference().add(populateCardRefrence());
+ SequenceOfTicketLinkType sit = new SequenceOfTicketLinkType();
+ populateLinkedTickets(sit);
+ controlDetail.setIncludedTickets(sit);
+ }
+
+
+ /*
+ *
+ */
+ private static void populateLinkedTickets(SequenceOfTicketLinkType sequenceOfTicketLinkType) {
+ TicketLinkType tlt = new TicketLinkType();
+ tlt.productOwnerIA5="test";
+ tlt.setTicketType(TicketType.pass);
+ tlt.setIssuerPNR("PNR");
+ tlt.setReferenceIA5("UED12435867");
+ tlt.setLinkMode(LinkMode.onlyValidInCombination);
+ tlt.setIssuerName("OEBB");
+ sequenceOfTicketLinkType.add(tlt);
+ }
+
+ private static CardReferenceType populateCardRefrence() {
+ CardReferenceType cr = new CardReferenceType();
+ cr.setTrailingCardIdNum(100L);
+ return cr;
+ }
+
+ }
diff --git a/src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV3.java b/src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV3.java
new file mode 100644
index 0000000..1843ec3
--- /dev/null
+++ b/src/test/java/org/uic/barcode/ticket/api/test/testtickets/CountermarkTestComplexTicketV3.java
@@ -0,0 +1,544 @@
+package org.uic.barcode.ticket.api.test.testtickets;
+
+import org.uic.barcode.asn1.datatypesimpl.SequenceOfUnrestrictedLong;
+import org.uic.barcode.ticket.api.asn.omv3.CardReferenceType;
+import org.uic.barcode.ticket.api.asn.omv3.ControlData;
+import org.uic.barcode.ticket.api.asn.omv3.CountermarkData;
+import org.uic.barcode.ticket.api.asn.omv3.CustomerStatusType;
+import org.uic.barcode.ticket.api.asn.omv3.DocumentData;
+import org.uic.barcode.ticket.api.asn.omv3.ExtensionData;
+import org.uic.barcode.ticket.api.asn.omv3.IssuingData;
+import org.uic.barcode.ticket.api.asn.omv3.LinkMode;
+import org.uic.barcode.ticket.api.asn.omv3.RegionalValidityType;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfCardReferenceType;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfCustomerStatusType;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfDocumentData;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfExtensionData;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfRegionalValidityType;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfTicketLinkType;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfTravelerType;
+import org.uic.barcode.ticket.api.asn.omv3.SequenceOfViaStationType;
+import org.uic.barcode.ticket.api.asn.omv3.TicketDetailData;
+import org.uic.barcode.ticket.api.asn.omv3.TicketLinkType;
+import org.uic.barcode.ticket.api.asn.omv3.TicketType;
+import org.uic.barcode.ticket.api.asn.omv3.TravelClassType;
+import org.uic.barcode.ticket.api.asn.omv3.TravelerData;
+import org.uic.barcode.ticket.api.asn.omv3.TravelerType;
+import org.uic.barcode.ticket.api.asn.omv3.UicRailTicketData;
+import org.uic.barcode.ticket.api.asn.omv3.ViaStationType;
+import org.uic.barcode.ticket.api.asn.omv3.ZoneType;
+
+
+ public class CountermarkTestComplexTicketV3 {
+
+ public static UicRailTicketData getUicTestTicket() {
+ UicRailTicketData ticket = new UicRailTicketData();
+ populateTicket(ticket);
+ return ticket;
+ }
+
+ /*
+value UicRailTicketData ::= {
+ issuingDetail {
+ issuingYear 2018
+ issuingDay 1
+ issuingTime 600
+ specimen TRUE,
+ securePaperTicket FALSE,
+ activated TRUE,
+ issuerPNR "issuerTestPNR",
+ issuedOnLine 12
+ }
+ ,travelerDetail{
+ traveler {
+ {
+ firstName "John"
+ ,secondName "Dow"
+ ,idCard "12345"
+ ,ticketHolder TRUE
+ ,status {{customerStatusDescr "senior" }}
+ }
+ }
+ ,groupName "myGroup"
+ }
+ ,transportDocument {
+ {
+ ticket counterMark : {
+ numberOfCountermark 12
+ ,totalOfCountermarks 24
+ ,groupName "groupName"
+ ,validRegion
+ { viaStations {
+ route {
+ { stationNum 123455, border FALSE }
+ ,{ stationNum 123456, border FALSE }
+ ,{ alternativeRoutes {
+ { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE }
+ ,{ route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE }
+ }
+ ,border FALSE
+ }
+ ,{ stationNum 123457, border FALSE }
+ }
+ ,border FALSE
+ ,seriesId 999
+ }
+ ,zones { zoneId {100,200}}
+ }
+ ,returnIncluded FALSE
+ ,classCode first
+ ,infoText "counterMark"
+ }
+ }
+ }
+ ,controlDetail {
+ identificationByCardReference {{ trailingCardIdNum 100 } }
+ ,identificationByIdCard FALSE
+ ,identificationByPassportId FALSE
+ ,passportValidationRequired FALSE
+ ,onlineValidationRequired FALSE
+ ,ageCheckRequired FALSE
+ ,reductionCardCheckRequired FALSE
+ ,infoText "cd"
+ ,includedTickets {
+ { referenceIA5 "UED12435867"
+ ,issuerName "OEBB"
+ ,issuerPNR "PNR"
+ ,productOwnerIA5 "test"
+ ,ticketType pass
+ ,linkMode onlyValidInCombination
+ }
+ }
+ }
+ ,extension {
+ { extensionId "1", extensionData '82DA'H }
+ ,{ extensionId "2", extensionData '83DA'H }
+ }
+ }
+
+Encoding to the file 'data.uper' using PER UNALIGNED encoding rule...
+UicRailTicketData SEQUENCE [root fieldcount (not encoded) = 5]
+ issuingDetail IssuingData SEQUENCE [root fieldcount (not encoded) = 8]
+ issuingYear INTEGER [length (not encoded) = 1.0]
+ 2018
+ issuingDay INTEGER [length (not encoded) = 1.1]
+ 1
+ issuingTime INTEGER [length (not encoded) = 1.3]
+ 600
+ specimen BOOLEAN [length (not encoded) = 0.1]
+ TRUE
+ securePaperTicket BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ activated BOOLEAN [length (not encoded) = 0.1]
+ TRUE
+ issuerPNR IA5String [length = 13.0]
+ "issuerTestPNR"
+ issuedOnLine INTEGER [length = 1.0]
+ 12
+ travelerDetail TravelerData SEQUENCE [root fieldcount (not encoded) = 2]
+ traveler SEQUENCE OF [count = 1]
+ TravelerType SEQUENCE [root fieldcount (not encoded) = 5]
+ firstName UTF8String [length = 4.0]
+ 0x4a6f686e
+ secondName UTF8String [length = 3.0]
+ 0x446f77
+ idCard IA5String [length = 5.0]
+ "12345"
+ ticketHolder BOOLEAN [length (not encoded) = 0.1]
+ TRUE
+ status SEQUENCE OF [count = 1]
+ CustomerStatusType SEQUENCE [fieldcount (not encoded) = 1]
+ customerStatusDescr IA5String [length = 6.0]
+ "senior"
+ groupName UTF8String [length = 7.0]
+ 0x6d7947726f7570
+ transportDocument SEQUENCE OF [count = 1]
+ DocumentData SEQUENCE [root fieldcount (not encoded) = 1]
+ ticket CHOICE [index = 6]
+ counterMark CountermarkData SEQUENCE [root fieldcount (not encoded) = 7]
+ numberOfCountermark INTEGER [length (not encoded) = 1.0]
+ 12
+ totalOfCountermarks INTEGER [length (not encoded) = 1.0]
+ 24
+ groupName UTF8String [length = 9.0]
+ 0x67726f75704e616d65
+ validRegion SEQUENCE OF [count = 2]
+ RegionalValidityType CHOICE [index = 1]
+ viaStations ViaStationType SEQUENCE [root fieldcount (not encoded) = 3]
+ route SEQUENCE OF [count = 4]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 123455
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 123456
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ alternativeRoutes SEQUENCE OF [count = 2]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ route SEQUENCE OF [count = 2]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 23455
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 23456
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ route SEQUENCE OF [count = 2]
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 3455
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 3456
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ViaStationType SEQUENCE [root fieldcount (not encoded) = 2]
+ stationNum INTEGER [length (not encoded) = 3.0]
+ 123457
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ border BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ seriesId INTEGER [length = 2.0]
+ 999
+ RegionalValidityType CHOICE [index = 2]
+ zones ZoneType SEQUENCE [root fieldcount (not encoded) = 1]
+ zoneId SEQUENCE OF [count = 2]
+ INTEGER [length = 1.0]
+ 100
+ INTEGER [length = 2.0]
+ 200
+ returnIncluded BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ classCode TravelClassType ENUMERATED [length (not encoded) = 0.4]
+ 1
+ infoText UTF8String [length = 11.0]
+ 0x636f756e7465724d61726b
+ controlDetail ControlData SEQUENCE [root fieldcount (not encoded) = 9]
+ identificationByCardReference SEQUENCE OF [count = 1]
+ CardReferenceType SEQUENCE [root fieldcount (not encoded) = 1]
+ trailingCardIdNum INTEGER [length = 1.0]
+ 100
+ identificationByIdCard BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ identificationByPassportId BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ passportValidationRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ onlineValidationRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ ageCheckRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ reductionCardCheckRequired BOOLEAN [length (not encoded) = 0.1]
+ FALSE
+ infoText UTF8String [length = 2.0]
+ 0x6364
+ includedTickets SEQUENCE OF [count = 1]
+ TicketLinkType SEQUENCE [root fieldcount (not encoded) = 6]
+ referenceIA5 IA5String [length = 11.0]
+ "UED12435867"
+ issuerName UTF8String [length = 4.0]
+ 0x4f454242
+ issuerPNR IA5String [length = 3.0]
+ "PNR"
+ productOwnerIA5 IA5String [length = 4.0]
+ "test"
+ ticketType TicketType ENUMERATED [length (not encoded) = 0.2]
+ 1
+ linkMode LinkMode ENUMERATED [length (not encoded) = 0.1]
+ 1
+ extension SEQUENCE OF [count = 2]
+ ExtensionData SEQUENCE [fieldcount (not encoded) = 2]
+ extensionId IA5String [length = 1.0]
+ "1"
+ extensionData OCTET STRING [length = 2.0]
+ 0x82da
+ ExtensionData SEQUENCE [fieldcount (not encoded) = 2]
+ extensionId IA5String [length = 1.0]
+ "2"
+ extensionData OCTET STRING [length = 2.0]
+ 0x83da
+Total encoded length = 187.0
+Encoded successfully in 187 bytes:
+78044040 04B14374 F3E7D72F 2A9979F4 A13A9008 6280B400 1044A6F6 86E03446
+F770562C 99B46B01 106E7977 69DFC81D B5E51DC9 BDD5C004 30000202 1058B84B
+3B937BAB 82730B6B 28108240 210000F1 1F080007 88FC1000 40800440 000B73C2
+00005B9F 01000880 00035F84 00001AFE 08000789 000203E7 20040201 640200C8
+042D8DBD D5B9D195 C93585C9 AD300802 01640009 8D90056E 17562C46 2C9A336A
+E1B37044 F4542420 3A13A902 74CBCFA1 40805881 416D00B2 0283DA
+
+ */
+
+
+
+ public static String getEncodingHex() {
+ return
+ "7804404004B14374F3E7D72F2A9979F4A13A90086280B4001044A6F686E03446" +
+ "F770562C99B46B01106E797769DFC81DB5E51DC9BDD5C004300002021058B84B" +
+ "3B937BAB82730B6B28108240210000F11F08000788FC100040800440000B73C2" +
+ "00005B9F0100088000035F8400001AFE08000789000203E720040201640200C8" +
+ "042D8DBDD5B9D195C93585C9AD300802016400098D90056E17562C462C9A336A" +
+ "E1B37044F45424203A13A90274CBCFA140805881416D00B20283DA";
+ }
+
+
+
+ private static void populateTicket(UicRailTicketData ticket) {
+
+ ticket.setControlDetail(new ControlData());
+ populate(ticket.getControlDetail());
+
+
+ ticket.setIssuingDetail(new IssuingData());
+ populateIssuingData(ticket.getIssuingDetail());
+
+ TravelerData td = new TravelerData();
+ populateTravelerData(td);
+ ticket.setTravelerDetail(td);
+
+ SequenceOfDocumentData ds = new SequenceOfDocumentData();
+
+
+ //OpenTicket
+ DocumentData do1 = new DocumentData();
+ addCounterMark(do1);
+ ds.add(do1);
+ ticket.setTransportDocument(ds);
+
+ SequenceOfExtensionData ed = new SequenceOfExtensionData();
+ populateExtensionSequence(ed);
+ ticket.setExtension(ed);
+
+ }
+
+
+ private static void addCounterMark(DocumentData dd) {
+
+ TicketDetailData tdd = new TicketDetailData();
+ CountermarkData otd = new CountermarkData();
+ otd.setInfoText("counterMark");
+ otd.setClassCode(TravelClassType.first);
+ otd.setReturnIncluded(false);
+
+ otd.setNumberOfCountermark(12L);
+ otd.setTotalOfCountermarks(24L);
+ otd.setGroupName("groupName");
+
+ otd.setValidRegion(getValidRegion());
+
+ tdd.setCounterMark(otd);
+ dd.setTicket(tdd);
+
+ }
+
+ private static SequenceOfRegionalValidityType getValidRegion() {
+ SequenceOfRegionalValidityType sr = new SequenceOfRegionalValidityType();
+ sr.add(getRegionalValidity());
+ sr.add(getZone());
+ return sr;
+ }
+
+ private static RegionalValidityType getRegionalValidity() {
+ RegionalValidityType r = new RegionalValidityType();
+ r.setViaStations(getRoute());
+ return r;
+ }
+
+ private static ViaStationType getRoute() {
+ ViaStationType m = new ViaStationType();
+ m.setRoute(getMainRoute());
+ m.setSeriesId(999L);
+ return m;
+ }
+
+
+
+ private static ViaStationType getAlternativeRoute() {
+ ViaStationType s = new ViaStationType();
+ s.setAlternativeRoutes(new SequenceOfViaStationType());
+ s.getAlternativeRoutes().add(getAltRoute1());
+ s.getAlternativeRoutes().add(getAltRoute2());
+ return s;
+ }
+
+ /*
+ * { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE }
+ */
+ private static ViaStationType getAltRoute1() {
+ ViaStationType m = new ViaStationType();
+ m.setRoute(new SequenceOfViaStationType());
+ m.getRoute().add(getViaStation(23455L));
+ m.getRoute().add(getViaStation(23456L));
+ return m;
+ }
+
+ /*
+ * { route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE }
+ */
+
+
+ private static ViaStationType getAltRoute2() {
+ ViaStationType m = new ViaStationType();
+ m.setRoute(new SequenceOfViaStationType());
+ m.getRoute().add(getViaStation(3455L));
+ m.getRoute().add(getViaStation(3456L));
+ return m;
+ }
+
+ private static ViaStationType getViaStation(long i) {
+ ViaStationType s = new ViaStationType();
+ s.setStationNum(i);
+ return s;
+ }
+
+ private static SequenceOfViaStationType getMainRoute() {
+ SequenceOfViaStationType s = new SequenceOfViaStationType();
+ s.add(getViaStation(123455L));
+ s.add(getViaStation(123456L));
+ s.add(getAlternativeRoute());
+ s.add(getViaStation(123457L));
+ return s;
+ }
+
+ private static RegionalValidityType getZone() {
+ RegionalValidityType r = new RegionalValidityType();
+ ZoneType z = new ZoneType();
+ z.setZoneId(new SequenceOfUnrestrictedLong());
+ z.getZoneId().add(100L);
+ z.getZoneId().add(200L);
+ r.setZones(z);
+ return r;
+ }
+
+ private static void populateTravelerData(TravelerData td) {
+ td.setGroupName("myGroup");
+ SequenceOfTravelerType trs = new SequenceOfTravelerType();
+ TravelerType tr = new TravelerType();
+ tr.setIdCard("12345");
+ tr.setFirstName("John");
+ tr.setSecondName("Dow");
+ tr.setTicketHolder(true);
+ SequenceOfCustomerStatusType ts = new SequenceOfCustomerStatusType();
+ CustomerStatusType cst = new CustomerStatusType();
+ cst.setCustomerStatusDescr("senior");
+ ts.add(cst);
+ tr.setStatus(ts);
+ trs.add(tr);
+ td.setTraveler(trs);
+ }
+
+ /*
+ * issuingDetail {
+ issuingYear 2018
+ issuingDay 1
+ issuingTime 600
+ specimen TRUE,
+ securePaperTicket FALSE,
+ activated TRUE,
+ issuerPNR "issuerTestPNR",
+ issuedOnLine 12
+ */
+ private static void populateIssuingData(IssuingData issuingDetail) {
+ issuingDetail.setIssuingYear(2018L);
+ issuingDetail.setIssuingDay(1L);
+ issuingDetail.setIssuingTime(600L);
+ issuingDetail.setIssuerPNR("issuerTestPNR");
+ issuingDetail.setSpecimen(true);
+ issuingDetail.setSecurePaperTicket(false);
+ issuingDetail.setActivated(true);
+ issuingDetail.setIssuedOnLine(12L);
+ }
+
+ /*
+ *extension {
+ { extensionId "1", extensionData '82DA'H }
+ ,{ extensionId "2", extensionData '83DA'H }
+ }
+ */
+ private static void populateExtensionSequence(SequenceOfExtensionData ed) {
+ ExtensionData ed1 = new ExtensionData();
+ ed1.setExtensionId("1");
+ byte[] ba1 = { (byte) 0x82, (byte) 0xDA };
+ ed1.setExtensionData(ba1);
+ ExtensionData ed2 = new ExtensionData();
+ ed2.setExtensionId("2");
+ byte[] ba2 = { (byte) 0x83, (byte) 0xDA };
+ ed2.setExtensionData(ba2);
+ ed.add(ed1);
+ ed.add(ed2);
+ }
+
+
+ /*
+ *controlDetail {
+ identificationByCardReference {{ trailingCardIdNum 100 } }
+ ,identificationByIdCard FALSE
+ ,identificationByPassportId FALSE
+ ,passportValidationRequired FALSE
+ ,onlineValidationRequired FALSE
+ ,ageCheckRequired FALSE
+ ,reductionCardCheckRequired FALSE
+ ,infoText "cd"
+ }
+ }
+ */
+ private static void populate(ControlData controlDetail) {
+ controlDetail.infoText = "cd";
+ controlDetail.setAgeCheckRequired(false);
+ controlDetail.setIdentificationByIdCard(false);
+ controlDetail.setIdentificationByPassportId(false);
+ controlDetail.setOnlineValidationRequired(false);
+ controlDetail.setPassportValidationRequired(false);
+ controlDetail.setReductionCardCheckRequired(false);
+ controlDetail.setIdentificationByCardReference(new SequenceOfCardReferenceType());
+ controlDetail.getIdentificationByCardReference().add(populateCardRefrence());
+ SequenceOfTicketLinkType sit = new SequenceOfTicketLinkType();
+ populateLinkedTickets(sit);
+ controlDetail.setIncludedTickets(sit);
+ }
+
+
+ /*
+ * includedTickets {
+ { referenceIA5 "UED12435867"
+ ,issuerName "OEBB"
+ ,issuerPNR "PNR"
+ ,productOwnerIA5 "test"
+ ,ticketType pass
+ ,linkMode onlyValidInCombination
+ }
+ */
+ private static void populateLinkedTickets(SequenceOfTicketLinkType sequenceOfTicketLinkType) {
+ TicketLinkType tlt = new TicketLinkType();
+ tlt.setProductOwnerIA5("test");
+ tlt.setTicketType(TicketType.pass);
+ tlt.setIssuerPNR("PNR");
+ tlt.setReferenceIA5("UED12435867");
+ tlt.setLinkMode(LinkMode.onlyValidInCombination);
+ tlt.setIssuerName("OEBB");
+ sequenceOfTicketLinkType.add(tlt);
+ }
+
+ private static CardReferenceType populateCardRefrence() {
+ CardReferenceType cr = new CardReferenceType();
+ cr.setTrailingCardIdNum(100L);
+ return cr;
+ }
+
+ }