diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNFilterValue.java b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNFilterValue.java new file mode 100644 index 0000000..d0c8b55 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNFilterValue.java @@ -0,0 +1,38 @@ +package org.epctagcoder.option.GSRN; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum GSRNFilterValue { + ALL_OTHERS_0(0), + RESERVED_1(1), + RESERVED_2(2), + RESERVED_3(3), + RESERVED_4(4), + RESERVED_5(5), + RESERVED_6(6), + RESERVED_7(7); + + private int value; + + private GSRNFilterValue(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (GSRNFilterValue rae : GSRNFilterValue.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static GSRNFilterValue forCode(int code) { + return BY_CODE_MAP.get(code); + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNHeader.java b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNHeader.java new file mode 100644 index 0000000..deb1e37 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNHeader.java @@ -0,0 +1,37 @@ +package org.epctagcoder.option.GSRN; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum GSRNHeader { + HEADER_00101101("00101101") { + public Integer getTagSize() { + return 96; + } + }; + + private String value; + public abstract Integer getTagSize(); + + + private GSRNHeader(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (GSRNHeader rae : GSRNHeader.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static GSRNHeader forCode(String code) { + return BY_CODE_MAP.get(code); + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNTagSize.java b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNTagSize.java new file mode 100644 index 0000000..2339fed --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/GSRNTagSize.java @@ -0,0 +1,36 @@ +package org.epctagcoder.option.GSRN; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum GSRNTagSize { + BITS_96(96) { + public Integer getHeader() { + return 45; + } + }; + + private int value; + public abstract Integer getHeader(); + + private GSRNTagSize(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (GSRNTagSize rae : GSRNTagSize.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static GSRNTagSize forCode(int code) { + return BY_CODE_MAP.get(code); + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/partitionTable/GSRNPartitionTableList.java b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/partitionTable/GSRNPartitionTableList.java new file mode 100644 index 0000000..1ce0d73 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/GSRN/partitionTable/GSRNPartitionTableList.java @@ -0,0 +1,49 @@ +package org.epctagcoder.option.GSRN.partitionTable; + +import java.util.ArrayList; +import java.util.List; + +import org.epctagcoder.option.TableItem; + + +public class GSRNPartitionTableList { + static final private List list = new ArrayList(); + + static { + list.add( new TableItem(0, 40, 12, 18, 5) ); + list.add( new TableItem(1, 37, 11, 21, 6) ); + list.add( new TableItem(2, 34, 10, 24, 7) ); + list.add( new TableItem(3, 30, 9, 28, 8) ); + list.add( new TableItem(4, 27, 8, 31, 9) ); + list.add( new TableItem(5, 24, 7, 34, 10) ); + list.add( new TableItem(6, 20, 6, 38, 11) ); + } + + public GSRNPartitionTableList() { + + } + + public TableItem getPartitionByL(Integer index) { + TableItem tableItem = null; + for (TableItem item : list) { + if (item.getL()==index) { + tableItem = item; + break; + } + } + return tableItem; + } + + public TableItem getPartitionByValue(Integer index) { + TableItem tableItem = null; + for (TableItem item : list) { + if (item.getPartitionValue()==index) { + tableItem = item; + break; + } + } + return tableItem; + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCExtensionDigit.java b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCExtensionDigit.java new file mode 100644 index 0000000..f4c953e --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCExtensionDigit.java @@ -0,0 +1,42 @@ +package org.epctagcoder.option.SSCC; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum SSCCExtensionDigit { + EXTENSION_0(0), + EXTENSION_1(1), + EXTENSION_2(2), + EXTENSION_3(3), + EXTENSION_4(4), + EXTENSION_5(5), + EXTENSION_6(6), + EXTENSION_7(7), + EXTENSION_8(8), + EXTENSION_9(9); + + private int value; + + private SSCCExtensionDigit(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (SSCCExtensionDigit rae : SSCCExtensionDigit.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static SSCCExtensionDigit forCode(int code) { + return BY_CODE_MAP.get(code); + } + + + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCFilterValue.java b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCFilterValue.java new file mode 100644 index 0000000..a0305a5 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCFilterValue.java @@ -0,0 +1,38 @@ +package org.epctagcoder.option.SSCC; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum SSCCFilterValue { + ALL_OTHERS_0(0), + RESERVED_1(1), + CASE_2(2), + RESERVED_3(3), + RESERVED_4(4), + RESERVED_5(5), + UNIT_LOAD_6(6), + RESERVED_7(7); + + private int value; + + private SSCCFilterValue(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (SSCCFilterValue rae : SSCCFilterValue.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static SSCCFilterValue forCode(int code) { + return BY_CODE_MAP.get(code); + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCHeader.java b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCHeader.java new file mode 100644 index 0000000..c1f9837 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCHeader.java @@ -0,0 +1,37 @@ +package org.epctagcoder.option.SSCC; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum SSCCHeader { + HEADER_00110001("00110001") { + public Integer getTagSize() { + return 96; + } + }; + + private String value; + public abstract Integer getTagSize(); + + + private SSCCHeader(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (SSCCHeader rae : SSCCHeader.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static SSCCHeader forCode(String code) { + return BY_CODE_MAP.get(code); + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCTagSize.java b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCTagSize.java new file mode 100644 index 0000000..f87b18d --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/SSCCTagSize.java @@ -0,0 +1,36 @@ +package org.epctagcoder.option.SSCC; + +import java.util.LinkedHashMap; +import java.util.Map; + +public enum SSCCTagSize { + BITS_96(96) { + public Integer getHeader() { + return 49; + } + }; + + private int value; + public abstract Integer getHeader(); + + private SSCCTagSize(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static final Map BY_CODE_MAP = new LinkedHashMap<>(); + static { + for (SSCCTagSize rae : SSCCTagSize.values()) { + BY_CODE_MAP.put(rae.value, rae); + } + } + + public static SSCCTagSize forCode(int code) { + return BY_CODE_MAP.get(code); + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/partitionTable/SSCCPartitionTableList.java b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/partitionTable/SSCCPartitionTableList.java new file mode 100644 index 0000000..f63d399 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/option/SSCC/partitionTable/SSCCPartitionTableList.java @@ -0,0 +1,49 @@ +package org.epctagcoder.option.SSCC.partitionTable; + +import java.util.ArrayList; +import java.util.List; + +import org.epctagcoder.option.TableItem; + + +public class SSCCPartitionTableList { + static final private List list = new ArrayList(); + + static { + list.add( new TableItem(0, 40, 12, 18, 5) ); + list.add( new TableItem(1, 37, 11, 21, 6) ); + list.add( new TableItem(2, 34, 10, 24, 7) ); + list.add( new TableItem(3, 30, 9, 28, 8) ); + list.add( new TableItem(4, 27, 8, 31, 9) ); + list.add( new TableItem(5, 24, 7, 34, 10) ); + list.add( new TableItem(6, 20, 6, 38, 11) ); + } + + public SSCCPartitionTableList() { + + } + + public TableItem getPartitionByL(Integer index) { + TableItem tableItem = null; + for (TableItem item : list) { + if (item.getL()==index) { + tableItem = item; + break; + } + } + return tableItem; + } + + public TableItem getPartitionByValue(Integer index) { + TableItem tableItem = null; + for (TableItem item : list) { + if (item.getPartitionValue()==index) { + tableItem = item; + break; + } + } + return tableItem; + } + + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/parse/GSRN/ParseGSRN.java b/epctagcoder/src/main/java/org/epctagcoder/parse/GSRN/ParseGSRN.java new file mode 100644 index 0000000..ab9612e --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/parse/GSRN/ParseGSRN.java @@ -0,0 +1,304 @@ +package org.epctagcoder.parse.GSRN; + +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.epctagcoder.option.PrefixLength; +import org.epctagcoder.option.TableItem; +import org.epctagcoder.option.GSRN.GSRNFilterValue; +import org.epctagcoder.option.GSRN.GSRNHeader; +import org.epctagcoder.option.GSRN.GSRNTagSize; +import org.epctagcoder.option.GSRN.partitionTable.GSRNPartitionTableList; +import org.epctagcoder.result.GSRN; +import org.epctagcoder.util.Converter; + +public class ParseGSRN { + private static final Integer RESERVED = 0; // 24 zero bits + private GSRN gsrn = new GSRN(); + private String companyPrefix; + private PrefixLength prefixLength; + private GSRNTagSize tagSize; + private GSRNFilterValue filterValue; + private String serviceReference; + private String rfidTag; + private String epcTagURI; + private String epcPureIdentityURI; + private TableItem tableItem; + + public static ChoiceStep Builder() { + return new Steps(); + } + + private ParseGSRN(Steps steps) { + this.companyPrefix = steps.companyPrefix; + this.tagSize = steps.tagSize; + this.filterValue = steps.filterValue; + this.serviceReference = steps.serviceReference; + this.rfidTag = steps.rfidTag; + this.epcTagURI = steps.epcTagURI; + this.epcPureIdentityURI = steps.epcPureIdentityURI; + parse(); + } + + + private void parse() { + Optional optionalCompanyPrefix = Optional.ofNullable(companyPrefix); + Optional optionalRfidTag = Optional.ofNullable(rfidTag); + Optional optionalEpcTagURI = Optional.ofNullable(epcTagURI); + Optional optionalEpcPureIdentityURI = Optional.ofNullable(epcPureIdentityURI); + + if ( optionalRfidTag.isPresent() ) { + String inputBin = Converter.hexToBin(rfidTag); + String headerBin = inputBin.substring(0, 8); + String filterBin = inputBin.substring(8,11); + String partitionBin = inputBin.substring(11,14); + GSRNPartitionTableList GSRNPartitionTableList = new GSRNPartitionTableList(); + + tableItem = GSRNPartitionTableList.getPartitionByValue( Integer.parseInt(partitionBin, 2) ); + + String companyPrefixBin = inputBin.substring(14,14+tableItem.getM()); + String serialWithExtensionBin = inputBin.substring(14+tableItem.getM(),14+tableItem.getM()+tableItem.getN()); + String filterDec = Long.toString( Long.parseLong(filterBin, 2) ); + String companyPrefixDec = Converter.binToDec(companyPrefixBin); //Long.toString( Long.parseLong(companyPrefixBin, 2) ); + + serviceReference = Converter.strZero(Converter.binToDec(serialWithExtensionBin), tableItem.getDigits() ); + companyPrefix = Converter.strZero(companyPrefixDec, tableItem.getL()); + filterValue = GSRNFilterValue.forCode( Integer.parseInt(filterDec) ); + tagSize = GSRNTagSize.forCode( GSRNHeader.forCode(headerBin).getTagSize() ); + prefixLength = PrefixLength.forCode(tableItem.getL()); + + } else { + + if ( optionalCompanyPrefix.isPresent() ) { + GSRNPartitionTableList GSRNPartitionTableList = new GSRNPartitionTableList(); + + prefixLength = PrefixLength.forCode( companyPrefix.length() ); + + validateCompanyPrefix(); + + tableItem = GSRNPartitionTableList.getPartitionByL( prefixLength.getValue() ); + + validateServiceReference(); + + } else { + + if ( optionalEpcTagURI.isPresent() ) { + Pattern pattern = Pattern.compile("(urn:epc:tag:gsrn-)(96)\\:([0-7])\\.(\\d+)\\.(\\d+)"); + Matcher matcher = pattern.matcher(epcTagURI); + + if ( matcher.matches() ) { + tagSize = GSRNTagSize.forCode( Integer.parseInt(matcher.group(2)) ); + filterValue = GSRNFilterValue.forCode( Integer.parseInt(matcher.group(3)) ); + companyPrefix = matcher.group(4); + prefixLength = PrefixLength.forCode( matcher.group(4).length() ); + serviceReference = matcher.group(5); + } else { + throw new IllegalArgumentException("EPC Tag URI is invalid"); + } + + } else if ( optionalEpcPureIdentityURI.isPresent() ) { + Pattern pattern = Pattern.compile("(urn:epc:id:gsrn)\\:(\\d+)\\.(\\d+)"); + Matcher matcher = pattern.matcher(epcPureIdentityURI); + + if ( matcher.matches() ) { + companyPrefix = matcher.group(2); + prefixLength = PrefixLength.forCode( matcher.group(2).length() ); + serviceReference = matcher.group(3); + } else { + throw new IllegalArgumentException("EPC Pure Identity is invalid"); + } + + + } + + GSRNPartitionTableList GSRNPartitionTableList = new GSRNPartitionTableList(); + tableItem = GSRNPartitionTableList.getPartitionByL( prefixLength.getValue() ); + + } + + } + + + String outputBin = getBinary(); + String outputHex = Converter.binToHex( outputBin ); + + gsrn.setEpcScheme("gsrn"); + gsrn.setApplicationIdentifier("AI 8018"); + gsrn.setTagSize(Integer.toString(tagSize.getValue())); + gsrn.setFilterValue(Integer.toString(filterValue.getValue()) ); + gsrn.setPartitionValue(Integer.toString(tableItem.getPartitionValue())); + gsrn.setPrefixLength(Integer.toString(prefixLength.getValue())); + gsrn.setCompanyPrefix(companyPrefix); + gsrn.setServiceReference(serviceReference); + gsrn.setCheckDigit(Integer.toString(getCheckDigit())); + gsrn.setEpcPureIdentityURI(String.format("urn:epc:id:gsrn:%s.%s", companyPrefix, serviceReference)); + gsrn.setEpcTagURI(String.format("urn:epc:tag:gsrn-%s:%s.%s.%s", tagSize.getValue(), + filterValue.getValue(), companyPrefix, serviceReference)); + gsrn.setEpcRawURI(String.format("urn:epc:raw:%s.x%s", tagSize.getValue(), outputHex )); + gsrn.setBinary(outputBin); + gsrn.setRfidTag(outputHex); + + } + + private Integer getCheckDigit() { + String value = new StringBuilder() + .append(companyPrefix) + .append(serviceReference) + .toString(); + + Integer d18 = (10 - ((3 + * (Character.getNumericValue(value.charAt(0)) + Character.getNumericValue(value.charAt(2)) + + Character.getNumericValue(value.charAt(4)) + Character.getNumericValue(value.charAt(6)) + + Character.getNumericValue(value.charAt(8)) + + Character.getNumericValue(value.charAt(10)) + Character.getNumericValue(value.charAt(12)) + + Character.getNumericValue(value.charAt(14)) + Character.getNumericValue(value.charAt(16))) + + (Character.getNumericValue(value.charAt(1)) + Character.getNumericValue(value.charAt(3)) + + Character.getNumericValue(value.charAt(5)) + Character.getNumericValue(value.charAt(7)) + + Character.getNumericValue(value.charAt(9)) + Character.getNumericValue(value.charAt(11)) + + Character.getNumericValue(value.charAt(13)) + Character.getNumericValue(value.charAt(15)))) + % 10)) % 10; + return d18; + } + + + private String getBinary() { + StringBuilder bin = new StringBuilder(); + + bin.append( Converter.decToBin(tagSize.getHeader(), 8) ); + bin.append( Converter.decToBin(filterValue.getValue(), 3) ); + bin.append( Converter.decToBin(tableItem.getPartitionValue(), 3) ); + bin.append( Converter.decToBin(Integer.parseInt(companyPrefix), tableItem.getM()) ); + bin.append( Converter.decToBin(Integer.parseInt(serviceReference), tableItem.getN()) ); + bin.append( Converter.decToBin(RESERVED, 24) ); + + return bin.toString(); + } + + + public GSRN getGSRN() { + return gsrn; + } + + public String getRfidTag() { + return Converter.binToHex( getBinary() ); + } + + + + private void validateServiceReference() { + StringBuilder value = new StringBuilder() + .append(serviceReference); + + if ( value.length()!=tableItem.getDigits() ) { + throw new IllegalArgumentException(String.format("Service Reference \"%s\" has %d length and should have %d length", + serviceReference, value.length(), tableItem.getDigits())); + } + } + + + private void validateCompanyPrefix() { + Optional optionalpPefixLenght = Optional.ofNullable(prefixLength); + if ( !optionalpPefixLenght.isPresent() ) { + throw new IllegalArgumentException("Company Prefix is invalid. Length not found in the partition table"); + } + + } + + + + + public static interface ChoiceStep { + ServiceReferenceStep withCompanyPrefix(String companyPrefix); + BuildStep withRFIDTag(String rfidTag); + BuildStep withEPCTagURI(String epcTagURI); + TagSizeStep withEPCPureIdentityURI(String epcPureIdentityURI); + } + + + public static interface ServiceReferenceStep { + TagSizeStep withServiceReference(String serviceReference); + } + + public static interface TagSizeStep { + FilterValueStep withTagSize( GSRNTagSize tagSize ); + } + + public static interface FilterValueStep { + BuildStep withFilterValue( GSRNFilterValue filterValue ); + } + + public static interface BuildStep { + ParseGSRN build(); + } + + + + private static class Steps implements ChoiceStep, ServiceReferenceStep, TagSizeStep, FilterValueStep, BuildStep { + private String companyPrefix; + private GSRNTagSize tagSize; + private GSRNFilterValue filterValue; + private String serviceReference; + private String rfidTag; + private String epcTagURI; + private String epcPureIdentityURI; + + @Override + public ParseGSRN build() { + return new ParseGSRN(this); + } + +// @Override +// public SerialStep withExtensionDigit(SSCCExtensionDigit extensionDigit) { +// this.extensionDigit = extensionDigit; +// return this; +// } + + + @Override + public BuildStep withFilterValue(GSRNFilterValue filterValue) { + this.filterValue = filterValue; + return this; + } + + @Override + public FilterValueStep withTagSize(GSRNTagSize tagSize) { + this.tagSize = tagSize; + return this; + } + + @Override + public TagSizeStep withServiceReference(String serviceReference) { + this.serviceReference = serviceReference; + return this; + } + + @Override + public ServiceReferenceStep withCompanyPrefix(String companyPrefix) { + this.companyPrefix = companyPrefix; + return this; + } + + @Override + public BuildStep withRFIDTag(String rfidTag) { + this.rfidTag = rfidTag; + return this; + } + + @Override + public BuildStep withEPCTagURI(String epcTagURI) { + this.epcTagURI = epcTagURI; + return this; + } + + @Override + public TagSizeStep withEPCPureIdentityURI(String epcPureIdentityURI) { + this.epcPureIdentityURI = epcPureIdentityURI; + return this; + } + + + + + } + +} diff --git a/epctagcoder/src/main/java/org/epctagcoder/parse/SSCC/ParseSSCC.java b/epctagcoder/src/main/java/org/epctagcoder/parse/SSCC/ParseSSCC.java new file mode 100644 index 0000000..9db8467 --- /dev/null +++ b/epctagcoder/src/main/java/org/epctagcoder/parse/SSCC/ParseSSCC.java @@ -0,0 +1,326 @@ +package org.epctagcoder.parse.SSCC; + +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +import org.epctagcoder.option.PrefixLength; +import org.epctagcoder.option.TableItem; +import org.epctagcoder.option.SSCC.SSCCExtensionDigit; +import org.epctagcoder.option.SSCC.SSCCFilterValue; +import org.epctagcoder.option.SSCC.SSCCHeader; +import org.epctagcoder.option.SSCC.SSCCTagSize; +import org.epctagcoder.option.SSCC.partitionTable.SSCCPartitionTableList; +import org.epctagcoder.result.SSCC; +//import org.epctagcoder.util.BigDec2Bin; +import org.epctagcoder.util.Converter; + +public class ParseSSCC { + private static final Integer RESERVED = 0; // 24 zero bits + private SSCC sscc = new SSCC(); + private SSCCExtensionDigit extensionDigit; + private String companyPrefix; + private PrefixLength prefixLength; + private SSCCTagSize tagSize; + private SSCCFilterValue filterValue; + private String serial; + private String rfidTag; + private String epcTagURI; + private String epcPureIdentityURI; + private TableItem tableItem; + + public static ChoiceStep Builder() { + return new Steps(); + } + + private ParseSSCC(Steps steps) { + this.extensionDigit = steps.extensionDigit; + this.companyPrefix = steps.companyPrefix; + this.tagSize = steps.tagSize; + this.filterValue = steps.filterValue; + this.serial = steps.serial; + this.rfidTag = steps.rfidTag; + this.epcTagURI = steps.epcTagURI; + this.epcPureIdentityURI = steps.epcPureIdentityURI; + parse(); + } + + + private void parse() { + Optional optionalCompanyPrefix = Optional.ofNullable(extensionDigit); + Optional optionalRfidTag = Optional.ofNullable(rfidTag); + Optional optionalEpcTagURI = Optional.ofNullable(epcTagURI); + Optional optionalEpcPureIdentityURI = Optional.ofNullable(epcPureIdentityURI); + + if ( optionalRfidTag.isPresent() ) { + String inputBin = Converter.hexToBin(rfidTag); + String headerBin = inputBin.substring(0, 8); + String filterBin = inputBin.substring(8,11); + String partitionBin = inputBin.substring(11,14); + SSCCPartitionTableList ssccPartitionTableList = new SSCCPartitionTableList(); + + tableItem = ssccPartitionTableList.getPartitionByValue( Integer.parseInt(partitionBin, 2) ); + + String companyPrefixBin = inputBin.substring(14,14+tableItem.getM()); + String serialWithExtensionBin = inputBin.substring(14+tableItem.getM(),14+tableItem.getM()+tableItem.getN()); + String filterDec = Long.toString( Long.parseLong(filterBin, 2) ); + String companyPrefixDec = Converter.binToDec(companyPrefixBin); //Long.toString( Long.parseLong(companyPrefixBin, 2) ); + String serialWithExtension = Converter.strZero(Converter.binToDec(serialWithExtensionBin), tableItem.getDigits() ); + String extensionDec = serialWithExtension.substring(0,1); + + serial = serialWithExtension.substring(1); + companyPrefix = Converter.strZero(companyPrefixDec, tableItem.getL()); + extensionDigit = SSCCExtensionDigit.forCode( Integer.parseInt(extensionDec) ); + filterValue = SSCCFilterValue.forCode( Integer.parseInt(filterDec) ); + tagSize = SSCCTagSize.forCode( SSCCHeader.forCode(headerBin).getTagSize() ); + prefixLength = PrefixLength.forCode(tableItem.getL()); + + } else { + + if ( optionalCompanyPrefix.isPresent() ) { + SSCCPartitionTableList ssccPartitionTableList = new SSCCPartitionTableList(); + prefixLength = PrefixLength.forCode( companyPrefix.length() ); + + validateCompanyPrefix(); + + tableItem = ssccPartitionTableList.getPartitionByL( prefixLength.getValue() ); + + validateExtensionDigitAndSerial(); + + } else { + + if ( optionalEpcTagURI.isPresent() ) { + Pattern pattern = Pattern.compile("(urn:epc:tag:sscc-)(96)\\:([0-7])\\.(\\d+)\\.([0-8])(\\d+)"); + Matcher matcher = pattern.matcher(epcTagURI); + + if ( matcher.matches() ) { + tagSize = SSCCTagSize.forCode( Integer.parseInt(matcher.group(2)) ); + filterValue = SSCCFilterValue.forCode( Integer.parseInt(matcher.group(3)) ); + companyPrefix = matcher.group(4); + prefixLength = PrefixLength.forCode( matcher.group(4).length() ); + extensionDigit = SSCCExtensionDigit.forCode( Integer.parseInt(matcher.group(5)) ); + serial = matcher.group(6); + } else { + throw new IllegalArgumentException("EPC Tag URI is invalid"); + } + + } else if ( optionalEpcPureIdentityURI.isPresent() ) { + Pattern pattern = Pattern.compile("(urn:epc:id:sscc)\\:(\\d+)\\.([0-8])(\\d+)"); + Matcher matcher = pattern.matcher(epcPureIdentityURI); + + if ( matcher.matches() ) { + companyPrefix = matcher.group(2); + prefixLength = PrefixLength.forCode( matcher.group(2).length() ); + extensionDigit = SSCCExtensionDigit.forCode( Integer.parseInt(matcher.group(3)) ); + serial = matcher.group(4); + } else { + throw new IllegalArgumentException("EPC Pure Identity is invalid"); + } + + + } + + SSCCPartitionTableList ssccPartitionTableList = new SSCCPartitionTableList(); + tableItem = ssccPartitionTableList.getPartitionByL( prefixLength.getValue() ); + + } + + } + + + String outputBin = getBinary(); + String outputHex = Converter.binToHex( outputBin ); + + sscc.setEpcScheme("sscc"); + sscc.setApplicationIdentifier("AI 00"); + sscc.setTagSize(Integer.toString(tagSize.getValue())); + sscc.setFilterValue(Integer.toString(filterValue.getValue()) ); + sscc.setPartitionValue(Integer.toString(tableItem.getPartitionValue())); + sscc.setPrefixLength(Integer.toString(prefixLength.getValue())); + sscc.setCompanyPrefix(companyPrefix); + sscc.setExtensionDigit(Integer.toString(extensionDigit.getValue())); + sscc.setSerial(serial); + sscc.setCheckDigit(Integer.toString(getCheckDigit())); + sscc.setEpcPureIdentityURI(String.format("urn:epc:id:sscc:%s.%s%s", companyPrefix, extensionDigit.getValue(), serial)); + sscc.setEpcTagURI(String.format("urn:epc:tag:sscc-%s:%s.%s.%s%s", tagSize.getValue(), + filterValue.getValue(), companyPrefix, extensionDigit.getValue(), serial)); + sscc.setEpcRawURI(String.format("urn:epc:raw:%s.x%s", tagSize.getValue(), outputHex )); + sscc.setBinary(outputBin); + sscc.setRfidTag(outputHex); + + } + + + private Integer getCheckDigit() { + String value = new StringBuilder() + .append(extensionDigit.getValue()) + .append(companyPrefix) + .append(serial) + .toString(); + + Integer d18 = (10 - ((3 + * (Character.getNumericValue(value.charAt(0)) + Character.getNumericValue(value.charAt(2)) + + Character.getNumericValue(value.charAt(4)) + Character.getNumericValue(value.charAt(6)) + + Character.getNumericValue(value.charAt(8)) + + Character.getNumericValue(value.charAt(10)) + Character.getNumericValue(value.charAt(12)) + + Character.getNumericValue(value.charAt(14)) + Character.getNumericValue(value.charAt(16))) + + (Character.getNumericValue(value.charAt(1)) + Character.getNumericValue(value.charAt(3)) + + Character.getNumericValue(value.charAt(5)) + Character.getNumericValue(value.charAt(7)) + + Character.getNumericValue(value.charAt(9)) + Character.getNumericValue(value.charAt(11)) + + Character.getNumericValue(value.charAt(13)) + Character.getNumericValue(value.charAt(15)))) + % 10)) % 10; + return d18; + } + + + private String getBinary() { + StringBuilder bin = new StringBuilder(); + + bin.append( Converter.decToBin(tagSize.getHeader(), 8) ); + bin.append( Converter.decToBin(filterValue.getValue(), 3) ); + bin.append( Converter.decToBin(tableItem.getPartitionValue(), 3) ); + bin.append( Converter.decToBin(Integer.parseInt(companyPrefix), tableItem.getM()) ); + +// jlc +// bin.append( Converter.strZero(BigDec2Bin.dec2bin(extensionDigit.getValue()+serial), tableItem.getN()) ); + + bin.append( Converter.decToBin(extensionDigit.getValue()+serial, tableItem.getN()) ); + + bin.append( Converter.decToBin(RESERVED, 24) ); + + return bin.toString(); + } + + + public SSCC getSSCC() { + return sscc; + } + + public String getRfidTag() { + return Converter.binToHex( getBinary() ); + } + + + + private void validateExtensionDigitAndSerial() { + StringBuilder value = new StringBuilder() + .append(extensionDigit.getValue()) + .append(serial); + + if ( value.length()!=tableItem.getDigits() ) { + throw new IllegalArgumentException(String.format("Concatenation between Extension Digit \"%d\" and Serial \"%s\" has %d length and should have %d length", + extensionDigit.getValue(), serial, value.length(), tableItem.getDigits())); + } + } + + + private void validateCompanyPrefix() { + Optional optionalpPefixLenght = Optional.ofNullable(prefixLength); + if ( !optionalpPefixLenght.isPresent() ) { + throw new IllegalArgumentException("Company Prefix is invalid. Length not found in the partition table"); + } + + } + + + + + public static interface ChoiceStep { + ExtensionDigiStep withCompanyPrefix(String companyPrefix); + BuildStep withRFIDTag(String rfidTag); + BuildStep withEPCTagURI(String epcTagURI); + TagSizeStep withEPCPureIdentityURI(String epcPureIdentityURI); + } + + public static interface ExtensionDigiStep { + SerialStep withExtensionDigit(SSCCExtensionDigit extensionDigit); + } + + public static interface SerialStep { + TagSizeStep withSerial(String serial); + } + + public static interface TagSizeStep { + FilterValueStep withTagSize( SSCCTagSize tagSize ); + } + + public static interface FilterValueStep { + BuildStep withFilterValue( SSCCFilterValue filterValue ); + } + + public static interface BuildStep { + ParseSSCC build(); + } + + + + private static class Steps implements ChoiceStep, ExtensionDigiStep, SerialStep, TagSizeStep, FilterValueStep, BuildStep { + private SSCCExtensionDigit extensionDigit; + private String companyPrefix; + private SSCCTagSize tagSize; + private SSCCFilterValue filterValue; + private String serial; + private String rfidTag; + private String epcTagURI; + private String epcPureIdentityURI; + + @Override + public ParseSSCC build() { + return new ParseSSCC(this); + } + + + @Override + public SerialStep withExtensionDigit(SSCCExtensionDigit extensionDigit) { + this.extensionDigit = extensionDigit; + return this; + } + + @Override + public ExtensionDigiStep withCompanyPrefix(String companyPrefix) { + this.companyPrefix = companyPrefix; + return this; + } + + @Override + public TagSizeStep withSerial(String serial) { + this.serial = serial; + return this; + } + + @Override + public FilterValueStep withTagSize(SSCCTagSize tagSize) { + this.tagSize = tagSize; + return this; + } + + @Override + public BuildStep withFilterValue(SSCCFilterValue filterValue) { + this.filterValue = filterValue; + return this; + } + + @Override + public BuildStep withRFIDTag(String rfidTag) { + this.rfidTag = rfidTag; + return this; + } + + + @Override + public BuildStep withEPCTagURI(String epcTagURI) { + this.epcTagURI = epcTagURI; + return this; + } + + + @Override + public TagSizeStep withEPCPureIdentityURI(String epcPureIdentityURI) { + this.epcPureIdentityURI = epcPureIdentityURI; + return this; + } + + } + +}