com.devoteam.srit.xmlloader.ucp.data.UcpMessage.java Source code

Java tutorial

Introduction

Here is the source code for com.devoteam.srit.xmlloader.ucp.data.UcpMessage.java

Source

/* 
 * Copyright 2012 Devoteam http://www.devoteam.com
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * 
 * This file is part of Multi-Protocol Test Suite (MTS).
 * 
 * Multi-Protocol Test Suite (MTS) is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, either version 3 of the
 * License.
 * 
 * Multi-Protocol Test Suite (MTS) is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Multi-Protocol Test Suite (MTS).
 * If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.devoteam.srit.xmlloader.ucp.data;

import com.devoteam.srit.xmlloader.core.Runner;
import com.devoteam.srit.xmlloader.core.log.GlobalLogger;
import com.devoteam.srit.xmlloader.core.log.TextEvent;
import com.devoteam.srit.xmlloader.core.protocol.StackFactory;
import com.devoteam.srit.xmlloader.core.utils.Utils;
import com.devoteam.srit.xmlloader.core.utils.dictionaryElement.Attribute;
import com.devoteam.srit.xmlloader.ucp.StackUcp;

import gp.utils.arrays.*;

import java.util.List;
import java.util.Vector;

import org.dom4j.Element;

/**
 *
 * @author Benjamin Bouvier
 */
public class UcpMessage {
    static public Array STX = new ConstantArray((byte) 2, 1);
    static public Array ETX = new ConstantArray((byte) 3, 1);
    static public Array SEP = new ConstantArray((byte) 47, 1);//47 is 2f in hexa

    private String name;
    private String transactionNumber; //2 char num
    private String length; //5 char num
    private String messageType; //O or R char
    private String operationType; //2 char num
    private Vector<Attribute> listAttributes;
    private String checksum;
    private String dataRaw;

    private String logError = "";

    public UcpMessage() {
        listAttributes = new Vector<Attribute>();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setLength(String value) {
        this.length = value;
        if (length != null) {
            while (length.length() < 5) {
                length = "0" + length;//padding with zero
            }
        }
    }

    public String getLength() {
        return this.length;
    }

    public void calculLength() {
        //calcul the message's length
        //useful before sending message from an xml
        //10 header + 2 checksum + 4 SEP no yet set at this time
        //=> STX TRN/LN/OR/OT/.../CHECKSUM ETX
        int lg = 0;
        for (int i = 0; i < listAttributes.size(); i++) {
            if (listAttributes.get(i).getValue() instanceof Vector) {
                Vector<UcpAttribute> vec = (Vector<UcpAttribute>) listAttributes.get(i).getValue();
                for (int j = 0; j < vec.size(); j++) {
                    lg += ((String) vec.get(j).getValue()).length() + 1;//+1 for separator
                }
            } else {
                lg += ((String) listAttributes.get(i).getValue()).length() + 1;//+1 for separator
            }
        }
        length = Integer.toString(lg + 16);
    }

    public void setTransactionNumber(String value) {
        this.transactionNumber = value;
        if ((transactionNumber != null) && (transactionNumber.length() < 2)) {
            transactionNumber = "0" + transactionNumber;//padding with zero 
        }
    }

    public String getTransactionNumber() {
        return this.transactionNumber;
    }

    public void setMessageType(String value) {
        this.messageType = value;
    }

    public String getMessageType() {
        return this.messageType;
    }

    public void setOperationType(String status) {
        this.operationType = status;
    }

    public String getOperationType() {
        return this.operationType;
    }

    public void calculChecksum(Array array) {
        //check calcul on int is good
        byte sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum += array.get(i);
        }
        this.checksum = Integer.toHexString(sum & 0xFF);
        if (checksum.length() < 2) {
            checksum = "0" + checksum;
        }
        checksum = checksum.toUpperCase();
    }

    public String getChecksum() {
        return this.checksum;
    }

    public void addAttribute(Attribute att) {
        listAttributes.add(att);
    }

    public String getDataRaw() {
        return dataRaw;
    }

    public void setDataRaw(String dataRaw) {
        this.dataRaw = dataRaw;
    }

    public String getLogError() {
        return logError;
    }

    public void setLogError(String logError) {
        this.logError += logError;
    }

    public UcpAttribute getAttribute(String name) {
        Attribute att = null;
        boolean result = false;

        for (int i = 0; (i < listAttributes.size()) && !result; i++) {
            att = listAttributes.get(i);

            if ((att != null)) {
                if (att instanceof UcpChoice) {
                    Vector<UcpAttribute> groupList = (Vector<UcpAttribute>) att.getValue();//get list of group in value
                    String choiceValue = ((String) listAttributes.get(i - 1).getValue());//because choiceValue is attribute just before
                    UcpAttribute att2 = null;

                    for (int j = 0; (j < groupList.size()) && !result; j++) {
                        att = groupList.get(j);
                        if (((UcpGroup) att).getChoiceValue().equals(choiceValue)) {
                            for (int k = 0; !result && (k < ((Vector<UcpAttribute>) att.getValue()).size()); k++) {
                                att2 = ((Vector<UcpAttribute>) att.getValue()).get(k);
                                if (att2.getName().equalsIgnoreCase(name)) {
                                    att = att2;
                                    result = true;
                                }
                            }
                        }
                    }
                } else if (att.getName().equalsIgnoreCase(name)) {
                    result = true;
                }
            }
        }

        if (!result) {
            att = null;
        }
        return (UcpAttribute) att;
    }

    public Vector<Attribute> getData() {
        return listAttributes;
    }

    public Array getArray() throws Exception {
        SupArray array = new SupArray();

        for (Attribute att : listAttributes) {
            array.addLast(att.getArray());
        }

        //calcul the message's length
        //10 header + 2 checksum + 4 SEP no yet set at this time
        //=> STX TRN/LN/OR/OT/.../CHECKSUM ETX
        setLength(Integer.toString(array.length + 16));

        array.addFirst(SEP);
        array.addFirst(new DefaultArray(operationType.getBytes()));
        array.addFirst(SEP);
        array.addFirst(new DefaultArray(messageType.getBytes()));
        array.addFirst(SEP);
        array.addFirst(new DefaultArray(length.getBytes()));
        array.addFirst(SEP);
        array.addFirst(new DefaultArray(transactionNumber.getBytes()));

        calculChecksum(array);
        array.addLast(new DefaultArray(checksum.getBytes()));
        array.addFirst(STX);
        array.addLast(ETX);

        return array;
    }

    public void parseArray(Array array) throws Exception {
        String[] splittedMsg = Utils.splitNoRegex(new String(array.getBytes()), "/");
        int index = 0;
        UcpAttribute attribute = null;

        //check the message checksum
        calculChecksum(array.subArray(0, array.length - 2));//length - 2 to not include checksum
        if (!checksum.equals(splittedMsg[splittedMsg.length - 1])) {
            GlobalLogger.instance().getApplicationLogger().warn(TextEvent.Topic.PROTOCOL,
                    "Bad checksum of the message");
        }

        if (splittedMsg.length < 4) {
            throw new Exception("Cannot decode message " + array.toString() + " cause it is to short");
        }

        //the index take account of the separator
        setTransactionNumber(splittedMsg[index++]);
        setLength(splittedMsg[index++]);
        setMessageType(splittedMsg[index++]);
        setOperationType(splittedMsg[index++]);

        Attribute att = null;
        int i = 0;

        dataRaw = new String(array.getBytes());

        for (i = 0; (i < listAttributes.size()) && (index < splittedMsg.length); i++) {
            att = listAttributes.get(i);

            if (!att.getNotApplicable()) {
                if (att instanceof UcpChoice) {
                    UcpChoice choice = (UcpChoice) att;
                    //get choice parameter
                    String choiceName = choice.getChoiceAttribute().getName();
                    Attribute att2 = null;
                    String value = null;
                    boolean result = false;
                    //search this choice parameter in the attribute list
                    for (int j = 0; !result && (j < listAttributes.size()); j++) {
                        att2 = listAttributes.get(j);
                        if (choiceName.equals(att2.getName())) {
                            //get its value
                            value = (String) att2.getValue();
                            result = true;
                        }
                    }
                    result = false;

                    if ((value != null) && (value.length() != 0)) {
                        //search value of the choice parameter in the choice attribute group list
                        for (int j = 0; !result && (j < ((Vector<UcpGroup>) choice.getValue()).size()); j++) {
                            att2 = ((Vector<UcpGroup>) choice.getValue()).get(j);
                            if (((UcpGroup) att2).getChoiceValue().equals(value)) {
                                //set value of the group
                                for (int k = 0; (k < ((Vector<UcpAttribute>) att2.getValue()).size())
                                        && (index < splittedMsg.length); k++) {
                                    checkAttribute(((Vector<UcpAttribute>) att2.getValue()).get(k),
                                            splittedMsg[index++]);
                                }
                                result = true;
                            }
                        }
                    } else {
                        //skip the next attribute which could have been useful if choiceParameter was set
                        index += ((Vector) ((Vector<UcpGroup>) choice.getValue()).get(0).getValue()).size();
                    }
                } else if (att.getName().equals("XSer")) {
                    //decode xser
                    String xser = splittedMsg[index++];
                    att.setValue(new Vector<UcpXser>());
                    UcpXser ser = null;

                    while (xser.length() > 0) {
                        ser = new UcpXser();
                        ser.setType(xser.substring(0, 2));
                        ser.setLength(Integer.parseInt(xser.substring(2, 4), 16));//check store of value hexa in string
                        ser.setValue(xser.substring(4, ser.getLength() * 2 + 4));//*2 because data is in hexa
                        ((Vector<UcpXser>) att.getValue()).add(ser);
                        xser = xser.substring(ser.getLength() * 2 + 4);
                    }

                } else if (att.getValue() instanceof Vector)//for imbricate attribute
                {
                    Vector<UcpAttribute> vec = (Vector<UcpAttribute>) att.getValue();

                    for (int j = 0; (j < vec.size()) && (index < splittedMsg.length); j++) {
                        checkAttribute(((UcpAttribute) vec.get(j)), splittedMsg[index++]);
                    }
                } else {
                    if (att.getOccurenceAttribute() != null) {
                        //copy information of the attribute
                        UcpAttribute att2 = (UcpAttribute) att.clone();
                        att.setValue(new Vector<UcpAttribute>());
                        String value = (String) listAttributes.get(i - 1).getValue();
                        int cpt = 0;

                        if ((value != null) && (value.length() != 0)) {
                            //search occurence value (normally value of precedent attribute)
                            cpt = Integer.parseInt(value);
                        }

                        //get value for each value count in occurence
                        while (cpt != 0) {
                            att2.setValue(splittedMsg[index++]);
                            ((Vector<UcpAttribute>) att.getValue()).add(att2);
                            att2 = att2.clone();//not not erase precedent value
                            cpt--;
                        }
                    } else {
                        checkAttribute((UcpAttribute) att, splittedMsg[index++]);
                    }
                }
            } else {
                //skip this parameter which should be empty
                //if not empty
                if (splittedMsg[index++].length() != 0) {
                    setLogError("Attribute " + att.getName()
                            + " is not applicable to this message, it must have empty value\r\n");
                }
            }
        }

        if (index < (splittedMsg.length - 1))//all parameters were not set, (splittedMsg.length - 1) to not include checksum
        {
            setLogError("Incorrect parsing, some attributes are plus in message\r\n");
        } else if (index > (splittedMsg.length - 1)) {
            setLogError("Incorrect parsing, some attributes are missing in message\r\n");
        }

        i = 0;//reset i to count unknown attributes
        while (index < (splittedMsg.length - 1)) {
            //register last parameters as unknown attributes
            attribute = new UcpAttribute();
            attribute.setValue(splittedMsg[index++]);
            attribute.setName("Unknown" + i);
            i++;
            addAttribute(attribute);
        }
    }

    private void checkAttribute(UcpAttribute att, String value) throws Exception {
        int lg = att.getLength();

        if ((value.length() == 0) && att.isMandatory())//check if mandatory
        {
            setLogError("Malformed message: attribute " + att.getName() + " must not be empty\r\n");
        } else if ((value.length() != 0) && (lg != -1) && (value.length() != lg))//check size
        {
            setLogError("Size of attribute " + att.getName() + " should be " + lg + " instead of " + value.length()
                    + "\r\n");
        } else if (att.getFormat().equalsIgnoreCase("numericString"))//check format numericString
        {
            for (int i = 0; i < value.length(); i++) {
                if ((value.charAt(i) < 0x30) || (value.charAt(i) > 0x39)) {
                    setLogError("Attribute " + att.getName() + " should be a numeric string\r\n");
                    break;
                }
            }
        } else if (att.getFormat().equalsIgnoreCase("encodedString"))//check format string encoding
        {
            //Nothing to do usually
        }
        att.setValue(value);
    }

    @Override
    public UcpMessage clone() {
        UcpMessage clone = new UcpMessage();

        clone.setName(getName());
        clone.setMessageType(getMessageType());
        clone.setOperationType(getOperationType());
        for (int i = 0; i < listAttributes.size(); i++)
            clone.listAttributes.add(listAttributes.get(i).clone());

        return clone;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        if (getLogError().length() != 0) {
            str.append(getLogError());
        }

        str.append(name).append(", operationType ").append(operationType);
        str.append(", transactionNumber ").append(transactionNumber).append(", length ");
        str.append(length).append(", O/R ").append(messageType).append("\r\n");

        for (int i = 0; i < listAttributes.size(); i++)
            str.append(listAttributes.get(i).toString());

        return str.toString();
    }

    /** 
     * Parse the message from XML element 
     */
    public void parseMsgFromXml(Element root) throws Exception {
        // header
        Element header = root.element("header");
        String msgName = header.attributeValue("name");
        String msgOT = header.attributeValue("OT");

        if ((msgOT != null) && (msgName != null))
            throw new Exception("OT and name of the message " + msgName + " must not be set both");

        if ((msgOT == null) && (msgName == null))
            throw new Exception("One of the parameter OT and name of the message header must be set");

        StackUcp stack = (StackUcp) StackFactory.getStack(StackFactory.PROTOCOL_UCP);

        if (msgName != null) {
            this.name = msgName;
            this.operationType = stack.ucpDictionary.getMessageOperationTypeFromName(msgName);
            if (this.operationType == null)
                throw new Exception("Message <" + msgName + "> is unknown in the dictionary");
        }

        if (msgOT != null) {
            this.name = stack.ucpDictionary.getMessageNameFromOperationType(msgOT);
            if (this.name == null)
                throw new Exception("Message with OperationType <" + msgOT + "> is unknown in the dictionary");
            this.operationType = msgOT;
        }

        this.messageType = header.attributeValue("MT");
        this.transactionNumber = header.attributeValue("TRN");

        this.parseAttributes(root);
        this.calculLength();//calcul the length with attribute from the attribute       
    }

    public void parseAttributes(Element root) throws Exception {
        List<Element> attributes = root.elements("attribute");
        List<Element> imbricateAttributes = null;
        List<Element> xserAttributes = null;
        UcpAttribute att = null;
        UcpAttribute att2 = null;

        for (Element element : attributes) {
            att = new UcpAttribute();
            att.setName(element.attributeValue("name"));

            //check imbricate attribute + extra service(xser) to send
            imbricateAttributes = element.selectNodes("attribute");
            xserAttributes = element.selectNodes("xser");

            if (imbricateAttributes.size() != 0) {
                att.setValue(new Vector<UcpAttribute>());
                for (Element element2 : imbricateAttributes) {
                    att2 = new UcpAttribute();
                    att2.setName(element2.attributeValue("name"));
                    att2.setValue(element2.attributeValue("value"));
                    ((Vector<UcpAttribute>) att.getValue()).add(att2);
                }
            } else if (xserAttributes.size() != 0) {
                parseXser(xserAttributes, att);
            } else {
                String encoding = element.attributeValue("encoding");
                if ((encoding != null) && (encoding.equalsIgnoreCase("true"))) {
                    att.setFormat("encodedString");
                }
                att.setValue(element.attributeValue("value"));
            }
            this.addAttribute(att);
        }
    }

    public void parseXser(List<Element> list, UcpAttribute att) throws Exception {
        UcpXser ser = null;
        att.setValue(new Vector<UcpXser>());
        for (Element element : list) {
            ser = new UcpXser();
            ser.setType(element.attributeValue("type"));
            ser.setLength(Integer.parseInt(element.attributeValue("length")));
            ser.setValue(element.attributeValue("value").toUpperCase());
            ((Vector<UcpXser>) att.getValue()).add(ser);
        }
    }

}