OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.erp.gs1;

public class GS1Util {

    // ISO/IEC 15424 symbology identifiers
    // ]E0 : EAN-13, UPC-A, or UPC-E : 13 digits
    // ]E1 : Two-digit add-on symbol : 2 digits
    // ]E2 : Five-digit add-on symbol : 5 digits
    // ]E3 : EAN-13, UPC-A, or UPC-E with add-on symbol : 15 or 18 digits
    // ]E4 : EAN-8 : 8 digits
    // ]I1 : ITF-14 : 14 digits
    // ]C1 : GS1-128 : Standard AI element strings
    private static final String GS1_128_SCANNER_PREFIX = "]C1";
    // ]e0 : GS1 DataBar : Standard AI element strings
    private static final String GS1_DATABAR_SCANNER_PREFIX = "]e0";
    // ]e1 : GS1 Composite : Data packet containing the data + an encoded symbol separator
    // character.
    // ]e2 : GS1 Composite : Data packet containing the data following an escape mechanism
    // character.
    // ]d2 : GS1 DataMatrix : Standard AI element strings
    private static final String GS1_DATAMATRIX_SCANNER_PREFIX = "]d2";
    private static final String GS1_DATAMATRIX_SCANNER_PREFIX_2 = "]D2";
    // ]Q3 : GS1 QR Code : Standard AI element strings
    private static final String GS1_QRCODE_SCANNER_PREFIX = "]Q3";
    // ]J1 : GS1 DotCode : Standard AI element strings

    static final int ERROR_CODE_INVALID_GS1_SCAN = 0;
    static final int ERROR_CODE_UNKNOWN_AI = 1;
    static final int ERROR_CODE_INCOMPLETE_AI = 2;
    static final int ERROR_CODE_NOT_FOUND_SEPARATOR = 3;
    static final int ERROR_CODE_INSUFFICIENT_VALUE_LENGTH = 4;
    static final int ERROR_CODE_EXCEEDED_VALUE_LENGTH = 5;
    static final int ERROR_CODE_CONVERT_DECIMAL_POINT = 5;
    static final int ERROR_CODE_WRONG_DECIMAL_POINT = 6;
    static final int ERROR_CODE_CONVERT_DECIMAL_VALUE = 7;

    public static final char GS_SEPARATOR = '\u001D';

    static final int SPACE_SEPARATOR = ' ';

    int separator;

    public GS1Util() {
        this(GS_SEPARATOR);
    }

    public GS1Util(int separator) {
        this.separator = separator;
    }

    public GS1AIElements parseFromScanner(String scan) throws GS1ParseException {
        if (scan.startsWith(GS1_DATAMATRIX_SCANNER_PREFIX) || scan.startsWith(GS1_DATAMATRIX_SCANNER_PREFIX_2) || scan.startsWith(GS1_128_SCANNER_PREFIX) || scan.startsWith(GS1_DATABAR_SCANNER_PREFIX)
                || scan.startsWith(GS1_QRCODE_SCANNER_PREFIX)) {
            return parse(scan.substring(3));
        }
        return parse(scan);
    }

    public GS1AIElements parse(String barcode) throws GS1ParseException {
        if (barcode.length() < 3) {
            throw new GS1ParseException("", ERROR_CODE_INVALID_GS1_SCAN, "code too short");
        }

        GS1AIElements attr = new GS1AIElements();
        StringBuilder ai = new StringBuilder();

        int length = barcode.length();
        for (int i = 0; i < length; ++i) {
            int aiLength = ai.length();
            if (aiLength > 1) {
                GS1ApplicationIdentifier aii = GS1AIElements.getApplicationIdentifier(ai.toString());
                if (aii == null) {
                    if (aiLength < 4)
                        ai.append(barcode.charAt(i));
                    else
                        throw new GS1ParseException(ai.toString(), ERROR_CODE_UNKNOWN_AI, "Unknown AI");
                } else {
                    int decimalPoint = 0;
                    if (aii.decimalPoint) {
                        try {
                            decimalPoint = Integer.valueOf(String.valueOf(barcode.charAt(i)));
                        } catch (NumberFormatException e) {
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_CONVERT_DECIMAL_POINT, "Errow convert to decimal point");
                        }

                        if (++i >= length)
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_INSUFFICIENT_VALUE_LENGTH, "Insufficient value length");
                    }

                    String value;

                    if (aii.variableLength) {
                        int separatorIndex = barcode.indexOf(this.separator, i);

                        if (separatorIndex < 0) {
                            if (length - i > aii.length)
                                throw new GS1ParseException(ai.toString(), ERROR_CODE_NOT_FOUND_SEPARATOR, "Not found separator");
                            else if (length - i < aii.minLength)
                                throw new GS1ParseException(ai.toString(), ERROR_CODE_INSUFFICIENT_VALUE_LENGTH, "Insufficient value length");
                            else {
                                value = barcode.substring(i);
                                i = length;
                            }
                        } else if (separatorIndex - i > aii.length)
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_EXCEEDED_VALUE_LENGTH, "Exceeded value length");
                        else if (separatorIndex - i < aii.minLength)
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_INSUFFICIENT_VALUE_LENGTH, "Insufficient value length");
                        else {
                            value = barcode.substring(i, separatorIndex);
                            i = separatorIndex;
                        }
                    } else {
                        if (i + aii.length > length) {
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_INSUFFICIENT_VALUE_LENGTH, "Insufficient value length");
                        }
                        value = barcode.substring(i, i + aii.length);
                        i += aii.length - 1;
                    }

                    if (aii.decimalPoint && decimalPoint > 0) {
                        if (decimalPoint >= value.length())
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_WRONG_DECIMAL_POINT, "Decimal point more then value length");

                        try {
                            value = String.valueOf(Double.valueOf(value.substring(0, value.length() - decimalPoint) + "." + value.substring(value.length() - decimalPoint)));
                        } catch (NumberFormatException e) {
                            throw new GS1ParseException(ai.toString(), ERROR_CODE_CONVERT_DECIMAL_VALUE, "Error convert decimal point value");
                        }
                    }

                    attr.put(ai.toString(), value);

                    ai.setLength(0);
                }
            } else
                ai.append(barcode.charAt(i));
        }

        if (ai.length() > 0)
            throw new GS1ParseException(ai.toString(), ERROR_CODE_INCOMPLETE_AI, "Incomplete AI");

        return attr;
    }

    public String format(GS1AIElements values) {

        StringBuilder b = new StringBuilder();
        int size = values.size();
        for (int i = 0; i < size; i++) {
            String k = values.getKey(i);
            GS1ApplicationIdentifier ai = GS1AIElements.getApplicationIdentifier(k);
            final String value = values.getValue(i);
            b.append(k);
            b.append(value);
            if (ai.variableLength && i < size - 1) {
                b.append((char) this.separator);
            }
        }
        return b.toString();
    }

    public String formatZPL(GS1AIElements values) {

        StringBuilder b = new StringBuilder();
        int size = values.size();
        b.append("@1");
        for (int i = 0; i < size; i++) {
            String k = values.getKey(i);
            GS1ApplicationIdentifier ai = GS1AIElements.getApplicationIdentifier(k);
            final String value = values.getValue(i);
            b.append(k);
            b.append(value);
            if (ai.variableLength && i < size - 1) {
                b.append("@d029");
            }
        }
        return b.toString();
    }

    public String formatDataMatrix(GS1AIElements values) {

        StringBuilder b = new StringBuilder();
        int size = values.size();
        // b.append(FNC1_SEPARATOR);
        for (int i = 0; i < size; i++) {
            String k = values.getKey(i);
            GS1ApplicationIdentifier ai = GS1AIElements.getApplicationIdentifier(k);
            final String value = values.getValue(i);
            b.append('[');
            b.append(k);
            b.append(']');
            b.append(value);
            if (ai.variableLength && i < size - 1) {
                // b.append(GS_SEPARATOR);
            }
        }
        return b.toString();
    }

    public static void main(String[] args) throws GS1ParseException {
        GS1Util p = new GS1Util('_');
        System.out.println("GS1Util.main()" + (char) p.separator);
        String barcode = "0104607018700852111806051718062910180605_211";
        // barcode = "01088888931021461712031510W1040190";
        GS1AIElements values = p.parse(barcode);
        values.dump(System.out);

        values.put("391", "kookkk");
        System.out.println(p.format(values));
        System.out.println(values.formatHumanReadable());

        GS1AIElements valuesMax = new GS1AIElements();
        valuesMax.put("02", "01234567891234");
        valuesMax.put("15", "201202");
        valuesMax.put("37", "12345678");
        valuesMax.put("10", "12345678901234567890");
        GS1Util pStd = new GS1Util();
        System.out.println(p.format(valuesMax));
        System.out.println(p.format(valuesMax).length());
        System.out.println(pStd.format(valuesMax));
        System.out.println(pStd.format(valuesMax).length());
        System.err.println("GS1Util.main() GS128 from barcode reader");
        String gs1128 = "]C10207612345678900152012153745646578";
        GS1Util p2 = new GS1Util();
        values = p2.parseFromScanner(gs1128);
        values.dump(System.out);
    }

    public static String showAllChars(String s) {
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (ISO646.isValid(s.charAt(i))) {
                b.append(s.charAt(i));
            } else {
                b.append("[" + (int) s.charAt(i) + "]");
            }
        }
        return b.toString();
    }

}