public void endElement()

in ch-sxmp/src/main/java/com/cloudhopper/sxmp/SxmpParser.java [502:768]


        public void endElement(String uri, String localName, String qName) throws SAXException {
            //
            // get the tag stripped of any namespace
            //
            String tag = (StringUtil.isEmpty(uri)) ? qName : localName;

//            logger.trace("endElement: uri=" + uri + ", localName=" + localName + ", qName=" + qName);

            if (depth == 1) {
                if (tag.equals("application")) {
                    // parse the character data, check for duplicates
                    String applicationNameText = parseCharacterData(tag, true);
                    this.application = new Application(applicationNameText);
                }
            } else if (depth == 2) {
                if (tag.equals("operatorId")) {
                    // parse the character data, check for duplicates
                    String operatorIdText = parseCharacterData(tag, true);

                    // convert to an integer
                    Integer operatorId = parseIntegerValue(tag, operatorIdText);

                    try {
                        if (operation instanceof MessageRequest) {
                            ((MessageRequest)operation).setOperatorId(operatorId);
                        } else {
                            throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [operatorId] element is not supported for this operation type", this.operation);
                        }
                    } catch (SxmpErrorException e) {
                        throw new SxmpParsingException(e.getErrorCode(), e.getErrorMessage(), this.operation);
                    }
		} else if (tag.equals("priority")) {
                    // parse the character data, check for duplicates
                    String priorityText = parseCharacterData(tag, true);

                    // convert to an integer
                    Integer priorityFlag = parseIntegerValue(tag, priorityText);

                    try {
                        if (operation instanceof MessageRequest) {
                            ((MessageRequest)operation).setPriority(Priority.fromPriorityFlag(priorityFlag));
                        } else {
                            throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [priority] element is not supported for this operation type", this.operation);
                        }
                    } catch (IllegalArgumentException e) {
                        throw new SxmpParsingException(SxmpErrorCode.INVALID_VALUE, e.getMessage(), this.operation);
                    }
                } else if (tag.equals("error")) {
                    // parse the error element
                    ErrorCodeMessage ecm = parseErrorElement(tag, currentAttrs);

                    if (operation instanceof Response) {
                        ((Response)operation).setErrorCode(ecm.code);
                        ((Response)operation).setErrorMessage(ecm.message);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [" + tag + "] element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("ticketId")) {
                    // parse the character data, check for duplicates
                    String ticketId = parseCharacterData(tag, true);

                    // we basically support a ticket element on anything (request or response)
                    operation.setTicketId(ticketId);
                } else if (tag.equals("status")) {
                    // should only occur once
                    if (elements.contains(tag)) {
                        throw new SxmpParsingException(SxmpErrorCode.MULTIPLE_ELEMENTS_NOT_SUPPORTED, "Multiple [status] elements are not supported", this.operation);
                    }

                    // add the element tag to something we visisted
                    elements.add(tag);

                    String statusCodeString = this.getRequiredAttributeValue("status", currentAttrs, "code");
                    String statusMessage = this.getRequiredAttributeValue("status", currentAttrs, "message");
                    Integer statusCode = this.parseIntegerValue("code", statusCodeString);

                    DeliveryStatus status = new DeliveryStatus(statusCode, statusMessage);

                    if (operation instanceof DeliveryReportRequest) {
                        ((DeliveryReportRequest)operation).setStatus(status);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The status element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("messageError")) {
                    // should only occur once
                    if (elements.contains(tag)) {
                        throw new SxmpParsingException(SxmpErrorCode.MULTIPLE_ELEMENTS_NOT_SUPPORTED, "Multiple [messageError] elements are not supported", this.operation);
                    }

                    // add the element tag to something we visisted
                    elements.add(tag);

                    String messageErrorCodeString = this.getRequiredAttributeValue("messageError", currentAttrs, "code");
                    Integer messageErrorCode = this.parseIntegerValue("code", messageErrorCodeString);

                    if (operation instanceof DeliveryReportRequest) {
                        ((DeliveryReportRequest)operation).setMessageErrorCode(messageErrorCode);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The messageError element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("createDate")) {
                    // should only occur once
                    if (elements.contains(tag)) {
                        throw new SxmpParsingException(SxmpErrorCode.MULTIPLE_ELEMENTS_NOT_SUPPORTED, "Multiple [createDate] elements are not supported", this.operation);
                    }

                    String createDateText = parseCharacterData(tag, true);

                    DateTime createDate = null;
                    try {
                        createDate = dateTimeFormat.parseDateTime(createDateText);
                    } catch (Exception e) {
                        throw new SxmpParsingException(SxmpErrorCode.INVALID_VALUE, "Unable to convert createDate [" + createDateText + "] into a DateTime", this.operation);
                    }

                    if (operation instanceof DeliveryReportRequest) {
                        ((DeliveryReportRequest)operation).setCreateDate(createDate);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The createDate element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("finalDate")) {
                    // should only occur once
                    if (elements.contains(tag)) {
                        throw new SxmpParsingException(SxmpErrorCode.MULTIPLE_ELEMENTS_NOT_SUPPORTED, "Multiple [finalDate] elements are not supported", this.operation);
                    }

                    String finalDateText = parseCharacterData(tag, true);

                    DateTime finalDate = null;
                    try {
                        finalDate = dateTimeFormat.parseDateTime(finalDateText);
                    } catch (Exception e) {
                        throw new SxmpParsingException(SxmpErrorCode.INVALID_VALUE, "Unable to convert finalDate [" + finalDateText + "] into a DateTime", this.operation);
                    }

                    if (operation instanceof DeliveryReportRequest) {
                        ((DeliveryReportRequest)operation).setFinalDate(finalDate);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The finalDate element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("deliveryReport")) {
                    // parse the character data, check for duplicates
                    String deliveryReportText = parseCharacterData(tag, true);

                    Boolean deliveryReport = parseBooleanValue(tag, deliveryReportText);

                    if (operation instanceof SubmitRequest) {
                        ((SubmitRequest)operation).setDeliveryReport(deliveryReport);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [deliveryReport] element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("sourceAddress")) {
                    // parse the character data, check for duplicates
                    String addrString = parseCharacterData(tag, true);

                    // a type attribute is required
                    String addrTypeString = getRequiredAttributeValue(tag, currentAttrs, "type");

                    try {
                        // parse and create address
                        MobileAddress srcAddr = MobileAddressUtil.parseAddress(addrTypeString, addrString);

                        if (operation instanceof MessageRequest) {
                            ((MessageRequest)operation).setSourceAddress(srcAddr);
                        } else {
                            throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [sourceAddress] element is not supported for this operation type", this.operation);
                        }
                    } catch (SxmpErrorException e) {
                        throw new SxmpParsingException(e.getErrorCode(), e.getErrorMessage(), this.operation);
                    }
                } else if (tag.equals("destinationAddress")) {
                    // parse the character data, check for duplicates
                    String addrString = parseCharacterData(tag, true);

                    // a type attribute is required
                    String addrTypeString = getRequiredAttributeValue(tag, currentAttrs, "type");

                    try {
                        // dest address is XML-escaped for push
                        if (MobileAddressUtil.parseType(addrTypeString) == MobileAddress.Type.PUSH_DESTINATION) {
       // TODO: CHANGE TO STRINGUTIL.UNESCAPE MAKE FCN
                            addrString = StringEscapeUtils.unescapeXml(addrString);
                        }
                        // parse and create address
                        MobileAddress destAddr = MobileAddressUtil.parseAddress(addrTypeString, addrString);

                        if (operation instanceof MessageRequest) {
                            ((MessageRequest)operation).setDestinationAddress(destAddr);
                        } else {
                            throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [destinationAddress] element is not supported for this operation type", this.operation);
                        }
                    } catch (SxmpErrorException e) {
                        throw new SxmpParsingException(e.getErrorCode(), e.getErrorMessage(), this.operation);
                    }
                } else if (tag.equals("text")) {
                    // parse the character data, check for duplicates
                    // NOTE: the text element can contain no chars (empty message)
                    String encodedText = parseCharacterData(tag, false);

                    // an encoding MUST be included
                    String encoding = getRequiredAttributeValue(tag, currentAttrs, "encoding");

                    TextEncoding te = TextEncoding.valueOfCharset(encoding);

                    // if no encoding was found, then this is not supported
                    if (te == null) {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_TEXT_ENCODING, "Unsupported text encoding [" + encoding + "] found", this.operation);
                    }

                    // try to convert hex encoding
                    String text = null;
                    try {
                        if (logger.isTraceEnabled()) {
                            logger.trace("textBeforeDecoding: [" + encodedText + "]");
                        }

                        byte[] bytes = HexUtil.toByteArray(encodedText);

                        // convert these bytes into a string using the provided charset
                        text = new String(bytes, te.getCharset());

                        if (logger.isTraceEnabled()) {
                            logger.debug("textAfterDecoding: [" + text + "]");
                        }
                    } catch (Exception e) {
                        throw new SxmpParsingException(SxmpErrorCode.TEXT_HEX_DECODING_FAILED, "Unable to decode hex data into text", this.operation);
                    }

                    if (operation instanceof MessageRequest) {
                        ((MessageRequest)operation).setText(text, te);
                    } else {
                        throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "The [text] element is not supported for this operation type", this.operation);
                    }
                } else if (tag.equals("optionalParams") && version.equals(VERSION_1_1)) {
                    String encodedText = parseCharacterData(tag, false);

                    // optionalParams are XML-escaped
                    encodedText = StringEscapeUtils.unescapeXml(encodedText);

                    if (!StringUtils.isBlank(encodedText)) {
                        //logger.debug("*** Encoded text: '"+encodedText+"'");
                        try {
                            JSONObject jsonObj = new JSONObject(encodedText);
                            OptionalParamMap optionalParams = new OptionalParamMap(OptionalParamMap.HASH_MAP);
                            Iterator<String> nameItr = jsonObj.keys();
                            while(nameItr.hasNext()) {
                                String name = nameItr.next();
                                Object o = jsonObj.get(name);
                                optionalParams.put(name, o);
                            }
                            ((MessageRequest)operation).setOptionalParams(optionalParams);

                        } catch (JSONException e) {
                            logger.warn("", e);
                            throw new SxmpParsingException(SxmpErrorCode.UNABLE_TO_CONVERT_VALUE, "Unable to decode json data", this.operation);
                        } catch (IllegalArgumentException e) {
                            throw new SxmpParsingException(SxmpErrorCode.INVALID_VALUE, "Invalid optional parameters", this.operation);
                        }
                    }
                } else {
                    throw new SxmpParsingException(SxmpErrorCode.UNSUPPORTED_ELEMENT, "Unsupported [" + tag + "] element found at depth [" + depth + "]", this.operation);
                }
            }

            // always decrement our depth
            depth--;
        }