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--;
}