/******************************************************************************* * Copyright (C) 2013, 2014, International Business Machines Corporation * All Rights Reserved *******************************************************************************/ package com.ibm.streamsx.messaging.jms; import java.util.List; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.Session; import javax.jms.TextMessage; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.ibm.streams.operator.Tuple; import com.ibm.streams.operator.metrics.Metric; //This class handles the wbe22 message type class WBE22TextMessageHandler extends BaseXMLMessageHandler { // the document builder private DocumentBuilder documentBuilder; // constructor public WBE22TextMessageHandler(List<NativeSchema> nativeSchemaObjects, String eventName) throws TransformerConfigurationException, ParserConfigurationException { // call the base class constructor to initialize the native schema // attributes and event name super(nativeSchemaObjects, eventName); documentBuilder = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); } // constructor public WBE22TextMessageHandler(List<NativeSchema> nativeSchemaObjects, String eventName, Metric nTruncatedInserts) throws TransformerConfigurationException, ParserConfigurationException { // call the base class constructor to initialize the native schema // attributes,nTruncatedInserts and event name super(nativeSchemaObjects, eventName, nTruncatedInserts); documentBuilder = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); } // For JMSSink operator, convert the incoming tuple to a JMS TextMessage public Message convertTupleToMessage(Tuple tuple, Session session) throws JMSException, ParserConfigurationException, TransformerException { // create a new TextMessage TextMessage message; synchronized (session) { message = (TextMessage) session.createTextMessage(); } // create document element Document document; synchronized (documentBuilder) { document = documentBuilder.newDocument(); } // create elements for constructing the xml document // with wbe22 mesage format Element field; // creates an element for root tuple Element rootElement = document.createElement("connector"); //$NON-NLS-1$ rootElement.setAttribute("name", "System S"); //$NON-NLS-1$ //$NON-NLS-2$ rootElement.setAttribute("version", "2.2"); //$NON-NLS-1$ //$NON-NLS-2$ Element rootEle1 = document.createElement("connector-object"); //$NON-NLS-1$ rootEle1.setAttribute("name", eventName); //$NON-NLS-1$ rootElement.appendChild(rootEle1); String stringdata = new String(); // variable to specify if any of the attributes in the message is // truncated boolean isTruncated = false; for (NativeSchema currentObject : nativeSchemaObjects) { // iterate through the native schema elements // extract the name, type and length final String name = currentObject.getName(); final int length = currentObject.getLength(); field = document.createElement("field"); // create another element //$NON-NLS-1$ field.setAttribute("name", name); //$NON-NLS-1$ // handle based on data type switch (tuple.getStreamSchema().getAttribute(name).getType() .getMetaType()) { // BLOB is not supported for wbe22 message class case RSTRING: case USTRING: // extract the String // get its length String rdata = tuple.getString(name); int size = rdata.length(); // If no length was specified in native schema or // if the length of the String rdata is less than the length // specified in native schema if (length == LENGTH_ABSENT_IN_NATIVE_SCHEMA || size <= length) { stringdata = rdata; } // if the length of rdate is greater than the length specified // in native schema // set the isTruncated to true // truncate the String else if (size > length) { isTruncated = true; stringdata = rdata.substring(0, length); } break; // spl types decimal32, decimal64,decimal128, timestamp are mapped // to String. case TIMESTAMP: stringdata = (tuple.getTimestamp(name).getTimeAsSeconds()) .toString(); break; case DECIMAL32: case DECIMAL64: case DECIMAL128: // for decimal stringdata = tuple.getBigDecimal(name).toString(); break; default: stringdata = tuple.getString(name); break; } field.appendChild(document.createTextNode(stringdata)); // append to root element rootEle1.appendChild(field); } // append rootElement to the document document.appendChild(rootElement); // set the message message.setText(createFinalDocument(document)); // if the isTruncated boolean is set, increment the metric // nTruncatedInserts if (isTruncated) { nTruncatedInserts.incrementValue(1); } // return the message return message; } }