org.orbeon.oxf.processor.tamino.dom4j.TDOM4JInputStreamInterpreter.java Source code

Java tutorial

Introduction

Here is the source code for org.orbeon.oxf.processor.tamino.dom4j.TDOM4JInputStreamInterpreter.java

Source

/**
 *  Copyright (C) 2004 Orbeon, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version
 *  2.1 of the License, or (at your option) any later version.
 *
 *  This program 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 Lesser General Public License for more details.
 *
 *  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
package org.orbeon.oxf.processor.tamino.dom4j;

import com.softwareag.tamino.db.api.io.TInputStream;
import com.softwareag.tamino.db.api.io.TStreamHeader;
import com.softwareag.tamino.db.api.namespace.TInoNamespace;
import com.softwareag.tamino.db.api.namespace.TXQLNamespace;
import com.softwareag.tamino.db.api.namespace.TXQNamespace;
import com.softwareag.tamino.db.api.objectModel.TXMLObject;
import com.softwareag.tamino.db.api.response.*;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultText;
import org.orbeon.oxf.xml.dom4j.NonLazyUserDataDocumentFactory;
import org.xml.sax.SAXException;

import java.util.Iterator;
import java.util.List;

/**
 ** TDOM4JInputStreamInterpreter is the implemenation for the interpreting as it is needed
 ** for DOM4J needs. This means that instantiated objects for query results are concrete
 ** TXMLObject instances with an underlying DOM4J object model.
 **/
public class TDOM4JInputStreamInterpreter extends TInputStreamInterpreter {

    /**
     **
     **/
    public TDOM4JInputStreamInterpreter(String parserName) {
        super();
        initialize(parserName);
    }

    /**
     **
     **/
    public TDOM4JInputStreamInterpreter() {
        super();
        initialize(null);
    }

    /**
     ** Sets a generic property on the concrete interpreter instance. The properties that can actually be set
     ** depend on the TXMLObjectModel that is related to the concrete interpreter. Each interpreter that might
     ** be instantiated is related to a TXMLObjectModel. Here the user can set specific properties that might
     ** be relevant as additional parameters to the interpreter.
     ** This method does nothing for the DOM4J specific interpreter.
     **/
    public void setProperty(String key, Object value) {
    }

    /**
     ** Interprets the a general inputStream in a generic fashion. As a consequence only the
     ** result state will be obtained.
     **
     ** @param inputStream is the InputStream for a response to a previous operation on Tamino.
     ** @exception TStreamInterpretException when interpreting errors occur.
     **/
    protected void doInterpret(TInputStream inputStream) throws TStreamInterpretException {
        // please have a look at comment in the initialize method.
        try {
            // Create the DOM4J SAXReader with the DOM4J specific underlying SAX parser. This is a JAXP parser!
            SAXReader saxReader = (parserName == null || parserName.equals("")) ? new SAXReader()
                    : new SAXReader(parserName);

            // Make sure the document and its children are thread safe by using our
            // document factory.
            final DocumentFactory factory = NonLazyUserDataDocumentFactory.getInstance();
            saxReader.setDocumentFactory(factory);

            // Invoke the parsing and obtain the Document instance
            document = saxReader.read(inputStream);
            TStreamHeader header = inputStream.getHeader();
            // Set the result state
            setResponseInfoContent(document);
            // Set the result set of querried XML objects only if result relates to a query
            if (document.getRootElement().element(new QName(TXQLNamespace.QUERY.getName(), xqlNamespace)) != null
                    || document.getRootElement()
                            .element(new QName(TXQNamespace.XQUERY.getName(), xqNamespace)) != null) {
                setResponseQueryContent(document, (String) header.getValue(TStreamHeader.COLLECTION),
                        (String) header.getValue(TStreamHeader.DOCTYPE));
            }
        } catch (SAXException saxException) {
            throw new TStreamInterpretException("Interpreting the input stream for DOM4J failed!", saxException);
        } catch (Exception exception) {
            throw new TStreamInterpretException("Interpreting the input stream failed!", exception);
        }
    }

    // Initializes this object.
    private void initialize(String parserName) {
        // The method to retrieve the SAX XMLReader (parser) is delegated to DOM4J in the method doInterpret().
        // This method is not the preferred one, but due to a bug in WebLogic 6.1 this work around has been
        // implemented. The "good" version can be retrieved from revision 1.10
        this.parserName = parserName;
        // Create the internal ino namespace instance.
        this.inoNamespace = Namespace.get(TInoNamespace.getInstance().getPrefix(),
                TInoNamespace.getInstance().getUri());
        // Create the internal xql namespace instance. Hardcoding will be replaced later :-)
        this.xqlNamespace = Namespace.get(TXQLNamespace.getInstance().getPrefix(),
                TXQLNamespace.getInstance().getUri());
        // Create the internal xq namespace instance. Hardcoding will be replaced later :-)
        this.xqNamespace = Namespace.get(TXQNamespace.getInstance().getPrefix(),
                TXQNamespace.getInstance().getUri());
        // Obtain the response content item factory singleton.
        this.responseContentItemFactory = TResponseContentItemFactory.getInstance();
    }

    // Sets the result state due to the XML parsing.
    private void setResponseInfoContent(Document document) {
        // Obtain the response info content first.
        TResponseInfoContent responseInfoContent = getResponseInfoContent();
        // First set the message content item
        setMessageContentItem(responseInfoContent, document);
        // Set the query content item if given
        setQueryContentItem(responseInfoContent, document);
        // Set the session content item if given
        setSessionContentItem(responseInfoContent, document);
        // Set the object content item if given
        setObjectContentItem(responseInfoContent, document);
        // Set the cursor content item if given
        setCursorContentItem(responseInfoContent, document);
    }

    // Sets the message state due to the XML parsing.
    private void setMessageContentItem(TResponseInfoContent responseInfoContent, Document document) {
        // Analyze the message state
        Element re = document.getRootElement();
        // Obtain the list of message elements.
        List messageList = re.elements(new QName(TInoNamespace.MESSAGE.getName(), inoNamespace));
        Iterator messageIter = messageList.iterator();
        // Iterate thru the list of messages.
        while (messageIter.hasNext()) {
            Element message = (Element) messageIter.next();
            // Obtain the messages returnValue.
            QName qname = new QName(TInoNamespace.RETURN_VALUE.getName(), inoNamespace);
            String returnValue = message.attributeValue(qname);
            TMessageLineContentItem[] messageLineContentArray = null;
            // Obtain the list of message lists within the message.
            qname = new QName(TInoNamespace.MESSAGE_LINE.getName(), inoNamespace);
            List messageLineList = message.elements(qname);
            // Go thru the list of message lines and retrieve for each the subject and text content.
            if (messageLineList.size() > 0) {
                messageLineContentArray = new TMessageLineContentItem[messageLineList.size()];
                int index = 0;
                Iterator messageLineIter = messageLineList.iterator();
                while (messageLineIter.hasNext()) {
                    Element messageLine = (Element) messageLineIter.next();
                    qname = new QName(TInoNamespace.SUBJECT.getName(), inoNamespace);
                    String subject = messageLine.attributeValue(qname);
                    qname = new QName(TInoNamespace.UNIT.getName(), inoNamespace);
                    String unit = messageLine.attributeValue(qname);
                    String text = messageLine.getText();
                    // Instantiate the message line content item.
                    TMessageLineContentItem messageLineContentItem = responseContentItemFactory
                            .newMessageLineContentItem(subject, text);
                    if (unit != null && !unit.equals("")) {
                        messageLineContentItem.addAttribute(TInoNamespace.UNIT.getQualifiedName(), unit);
                    }
                    messageLineContentArray[index++] = messageLineContentItem;

                }
            }
            TMessageTextContentItem messageTextContent = null;
            // Obtain the message text if given.
            qname = new QName(TInoNamespace.MESSAGE_TEXT.getName(), inoNamespace);
            Element messageText = message.element(qname);
            if (messageText != null) {
                qname = new QName(TInoNamespace.CODE.getName(), inoNamespace);
                String code = messageText.attributeValue(qname);
                String text = messageText.getText();
                // Instantiate the message text content item for code and text content.
                messageTextContent = responseContentItemFactory.newMessageTextContentItem(code, text);
            }
            // Finally instantiate the message content with returnValue, message lines and message text.
            TMessageContentItem messageContent = responseContentItemFactory.newMessageContentItem(returnValue,
                    messageLineContentArray, messageTextContent);
            // Put the message content into the info content.
            responseInfoContent.putItem(TMessageContentItem.SPECIFIER, messageContent);
        }
    }

    // Set the (x)query content item due to the XML parsing.
    private void setQueryContentItem(TResponseInfoContent responseInfoContent, Document document) {
        Element re = document.getRootElement();
        QName qnameXQuery = new QName(TXQNamespace.XQUERY.getName(), xqNamespace);
        Element xqueryElement = re.element(qnameXQuery);
        if (xqueryElement != null) {
            TXQueryContentItem xqueryContentItem = responseContentItemFactory
                    .newXQueryContentItem(xqueryElement.getText());
            responseInfoContent.putItem(TQueryContentItem.SPECIFIER, xqueryContentItem);
        } else {
            QName qnameQuery = new QName(TXQLNamespace.QUERY.getName(), xqlNamespace);
            Element queryElement = re.element(qnameQuery);
            if (queryElement != null) {
                TQueryContentItem queryContentItem = responseContentItemFactory
                        .newQueryContentItem(queryElement.getText());
                responseInfoContent.putItem(TQueryContentItem.SPECIFIER, queryContentItem);
            }
        }
    }

    // Sets the session state due to the XML parsing.
    private void setSessionContentItem(TResponseInfoContent responseInfoContent, Document document) {
        // Set the session state if one is given within the ino:response root tag
        Element re = document.getRootElement();
        QName qname = new QName(TInoNamespace.SESSION_ID.getName(), inoNamespace);
        String sessionId = re.attributeValue(qname);
        qname = new QName(TInoNamespace.SESSION_KEY.getName(), inoNamespace);
        String sessionKey = re.attributeValue(qname);
        if (sessionId != null && sessionKey != null) {
            TSessionContentItem sessionContentItem = responseContentItemFactory.newSessionContentItem(sessionId,
                    sessionKey);
            responseInfoContent.putItem(TSessionContentItem.SPECIFIER, sessionContentItem);
            // This is the place where the mode listener has to be called!!
            //transactionModeListener.sessionStateChanged( sessionId, sessionKey );
        }
    }

    // Sets the object state due to the XML parsing.
    private void setObjectContentItem(TResponseInfoContent responseInfoContent, Document document) {
        // Set the object state (only relevant for insert or update) if one is given within ino:object child element beneath root element
        Element re = document.getRootElement();
        QName qname = new QName(TInoNamespace.OBJECT.getName(), inoNamespace);
        Element obj = re.element(qname);
        if (obj != null) {
            qname = new QName(TInoNamespace.COLLECTION.getName(), inoNamespace);
            String collection = obj.attributeValue(qname);
            qname = new QName(TInoNamespace.DOCTYPE.getName(), inoNamespace);
            String doctype = obj.attributeValue(qname);
            qname = new QName(TInoNamespace.ID.getName(), inoNamespace);
            String id = obj.attributeValue(qname);
            TObjectContentItem objectContentItem = responseContentItemFactory.newObjectContentItem(collection,
                    doctype, id);
            responseInfoContent.putItem(TObjectContentItem.SPECIFIER, objectContentItem);
        }
    }

    // Sets the cursor state due to the XML parsing.
    private void setCursorContentItem(TResponseInfoContent responseInfoContent, Document document) {
        QName qname = new QName(TInoNamespace.CURSOR.getName(), inoNamespace);
        // Set the cursor state if one is given within ino:cursor element beneath root element
        Element re = document.getRootElement();
        Element ce = re.element(qname);
        if (ce != null) {
            // Get the cursor handle attribute of the cursor element
            qname = new QName(TInoNamespace.HANDLE.getName(), inoNamespace);
            String handleValue = ce.attributeValue(qname);
            // Get the count attribute of the cursor element if available
            qname = new QName(TInoNamespace.COUNT.getName(), inoNamespace);
            String countValue = ce.attributeValue(qname);
            // Get the current, next and previous attribute values of cursor structure
            qname = new QName(TInoNamespace.CURRENT.getName(), inoNamespace);
            Element current = ce.element(qname);
            qname = new QName(TInoNamespace.NEXT.getName(), inoNamespace);
            Element next = ce.element(qname);
            qname = new QName(TInoNamespace.PREVIOUS.getName(), inoNamespace);
            Element prev = ce.element(qname);
            // Get the concrete attribute values
            qname = new QName(TInoNamespace.POSITION.getName(), inoNamespace);
            String currentValue = (current != null) ? current.attributeValue(qname) : null;
            qname = new QName(TInoNamespace.QUANTITY.getName(), inoNamespace);
            String quantityValue = (current != null) ? current.attributeValue(qname) : null;
            qname = new QName(TInoNamespace.POSITION.getName(), inoNamespace);
            String nextValue = (next != null) ? next.attributeValue(qname) : null;
            String prevValue = (prev != null) ? prev.attributeValue(qname) : null;
            // Instantiate the cursor instance
            TCursorContentItem cursorContentItem = responseContentItemFactory.newCursorContentItem(handleValue,
                    currentValue, quantityValue, nextValue, prevValue, countValue);
            responseInfoContent.putItem(TCursorContentItem.SPECIFIER, cursorContentItem);
        }
    }

    // Sets the result set enumeration due to the XML parsing.
    private void setResponseQueryContent(Document document, String collection, String doctype) {
        // Get all the Elements returned from Tamino
        Element re = document.getRootElement();
        // Get the xql/xq:result element as the container for the querried XML instances.
        QName qname = new QName(TXQNamespace.RESULT.getName(), xqNamespace);
        Element qc = re.element(qname);
        if (qc == null) {
            qname = new QName(TXQLNamespace.RESULT.getName(), xqlNamespace);
            qc = re.element(qname);
        }

        if (qc != null) {
            // Get the list of all result DOM4J element instances referring to the XML instances. Currently getMixedContent is used, will be changed later.
            //List list  = qc.elements();
            List list = qc.content();
            if (list.size() != 0) {
                // Obtain the response query content.
                TResponseQueryContent responseQueryContent = getResponseQueryContent();
                Iterator iter = list.iterator();
                while (iter.hasNext()) {
                    Object item = iter.next();
                    // Well, if the item happens to be a string then there is either mixed content or only text content.
                    if (item instanceof String) {
                        responseQueryContent.setText(item.toString());
                    } else if (item instanceof DefaultText) {
                        responseQueryContent.setText(((DefaultText) item).getText());
                    } else if (item instanceof Element) {
                        Element element = (Element) item;
                        // Create the appropiate Tamino XML object with the given ino:id, collection and schema information.
                        TXMLObject xmlObject = TXMLObject.newInstance(element);
                        xmlObject.setCollection(collection);
                        xmlObject.setDoctype(doctype);
                        // Add the obtained TXMLObject to the result set.
                        responseQueryContent.add(xmlObject);
                    }
                }
            }
        }
    }

    // The DOM4J ino Namespace attribute.
    private Namespace inoNamespace = null;

    // The DOM4J xql Namespace attribute.
    private Namespace xqlNamespace = null;

    // The DOM4J xq Namespace attribute.
    private Namespace xqNamespace = null;

    // The SAX parser class type.
    private String parserName = "";

    // The DOM4J document obtained from the parsing
    private Document document = null;

    // Factory for the instantiation of response content item instances.
    private TResponseContentItemFactory responseContentItemFactory = null;

}