eu.artist.postmigration.eubt.helpers.SOAPHelper.java Source code

Java tutorial

Introduction

Here is the source code for eu.artist.postmigration.eubt.helpers.SOAPHelper.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Vienna University of Technology.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Patrick Neubauer (Vienna University of Technology) - initial API and implementation
 *
 * Initially developed in the context of ARTIST EU project www.artist-project.eu
 *******************************************************************************/
package eu.artist.postmigration.eubt.helpers;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMText;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.impl.dom.soap11.SOAP11Factory;
import org.apache.commons.collections4.MultiMap;

import com.sun.xml.txw2.output.IndentingXMLStreamWriter;

import eu.artist.postmigration.eubt.applications.APPLICATION_TYPE;
import eu.artist.postmigration.eubt.exceptions.EUBTException;
import eu.artist.postmigration.eubt.migrationtracemodel.wsmigrationtrace.SourceElement;
import eu.artist.postmigration.eubt.migrationtracemodel.wsmigrationtrace.SourceParameter;
import eu.artist.postmigration.eubt.migrationtracemodel.wsmigrationtrace.TargetElement;
import eu.artist.postmigration.eubt.migrationtracemodel.wsmigrationtrace.TargetParameter;
import eu.artist.postmigration.eubt.migrationtracemodel.wsmigrationtrace.loader.WSMigrationTraceHandler;
import eu.artist.postmigration.eubt.responses.SOAPResponse;

/**
 * @author pneubaue
 * 
 */
public class SOAPHelper {

    /**
     * Obtain the element node and values (= parameter and value) of an element
     * (!) Warning this assumes that you are on the lowest level (leaf) and no more children are available.
     * Hence, value at non-leaf level is skipped (i.e., only element names is returned)
     * 
     * @param element element from which to obtain the nodes  (= node name
     *            and value) from
     * @return the nodes (= attribute and value) of an element
     */
    public static Map<String, String> obtainImmediateChildNodesAndValues(final OMElement element) {
        final Map<String, String> elementAndValues = new LinkedHashMap<String, String>();
        final Iterator<?> childElementIterator = element.getChildElements();
        while (childElementIterator.hasNext()) {
            // collect attribute names and values               
            final OMElement childElement = (OMElement) childElementIterator.next();
            String attributeName = childElement.getLocalName();
            OMNode childOMNode = childElement.getFirstOMChild();
            String attributeValue = null;
            if (childOMNode instanceof OMText) {
                attributeValue = ((OMText) childOMNode).getText();
            }
            elementAndValues.put(attributeName, attributeValue);
        }
        return elementAndValues;
    }// obtainChildElementAndValues

    /**
     * Obtain a list of child elements for a given element
     * 
     * @param element element for which a list of children is established
     * @return a list of children for the given element
     */
    public static List<OMElement> obtainChildElements(final OMElement element) {
        List<OMElement> childElements = new LinkedList<OMElement>();
        final Iterator<?> childElementsIterator = element.getChildElements();
        while (childElementsIterator.hasNext()) {
            // collect child elements in a list
            final OMElement childElement = (OMElement) childElementsIterator.next();
            childElements.add(childElement);
        }
        return childElements;
    }// obtainChildElements

    /**
     * Obtain a list of child element local names for a given element
     * 
     * @param element element for which a list of children local names is established
     * @return a list of children local names for the given element
     */
    public static List<String> obtainChildElementLocalNames(final OMElement element) {
        List<String> childElementNames = new LinkedList<String>();
        List<OMElement> childElements = obtainChildElements(element);
        for (OMElement childElement : childElements) {
            childElementNames.add(childElement.getLocalName());
        }
        return childElementNames;
    }// obtainChildElementLocalNames

    /**
     * Checks if the given element has element (non-parameter) children
     * 
     * @param element element to check for element (non-parameter) children
     * @return true if the element has element (non-parameter) children, false otherwise
     */
    public static boolean hasElementChildren(final OMElement element) {
        final Iterator<?> childElementIterator = element.getChildElements();
        while (childElementIterator.hasNext()) {
            OMElement child = (OMElement) childElementIterator.next();
            final Iterator<?> childChildIterator = child.getChildElements();
            if (childChildIterator.hasNext()) {
                return true;
            }
        }
        return false;
    }// hasElementChildren

    /**
     * @param element 
     * @return
     */
    @SuppressWarnings("unused")
    @Deprecated
    private static String obtainAttributeName(final OMNode element) {
        String attributeName = null;
        // NOTE: The following line is DANGEROUS (!) -> Find a better solution?
        attributeName = element.toString().substring(element.toString().indexOf("<") + 1,
                element.toString().indexOf(">"));
        return attributeName;
    }// obtainAttributeName

    @Deprecated
    public static String obtainAttributeValue(final OMNode element) {
        String attributeValue = null;
        // NOTE: The following line is DANGEROUS (!) -> Find a better solution?
        attributeValue = element.toString().substring(element.toString().indexOf(">") + 1,
                element.toString().indexOf("</"));
        return attributeValue;
    }// obtainAttributeValue

    /**
     * Migrated request operation ==> Original request operation(s)
     * 
     * @param migratedOperationModel migrated operation model
     * @param migratedOperationAttributes operation attributes (= attribute name
     *            and value)
     * @return original soap envelops corresponding to the given migrated
     *         operation
     */
    public static List<SOAPEnvelope> generateOriginalRequestSoapEnvelops(final TargetElement migratedOperationModel,
            final Map<String, String> migratedOperationAttributes,
            final WSMigrationTraceHandler wsMigrationTraceHandler) {
        final Map<SourceElement, OMElement> oparationMap = new LinkedHashMap<SourceElement, OMElement>();
        final SOAP11Factory factory = new SOAP11Factory();

        // For every migrated parameter, create its corresponding original parameter within their original operation(s)
        for (final TargetParameter migratedParameter : migratedOperationModel.getParameters()) {
            // in which original operation does this parameter exist?
            final MultiMap<SourceElement, SourceParameter> originalOperationParameters = wsMigrationTraceHandler
                    .getSourceParameters(migratedOperationModel, migratedParameter);

            // for any original operation in which the migrated parameter exist --> create/extend original operation and parameter
            for (final SourceElement originalOperation : originalOperationParameters.keySet()) {
                OMElement operationElement = null;
                if (!oparationMap.containsKey(originalOperation)) {
                    // new operation encountered --> create new operation
                    final QName operationName = new QName(originalOperation.getElementNamespace().getNamespaceURI(),
                            originalOperation.getElementName(),
                            originalOperation.getElementNamespace().getNamespacePrefix());
                    operationElement = factory.createOMElement(operationName);

                } else {
                    // existing operation encountered --> extend
                    operationElement = oparationMap.get(originalOperation);
                }
                // obtain corresponding original parameter by checking the source parameter's target parameter back-link
                SourceParameter originalParameter = null;
                for (final SourceParameter sourceParameter : originalOperation.getParameters()) {
                    for (final TargetParameter sourcesTargetParameter : sourceParameter.getTargetParameter()) {
                        if (sourcesTargetParameter.equals(migratedParameter)) {
                            originalParameter = sourceParameter;
                        }
                    }
                }

                // if there is a corresponding original attribute in the model --> create attribute
                if (originalParameter != null) {
                    // create operation parameter
                    final QName operationElementAttributeName = new QName(originalParameter.getParameterName());
                    final OMElement operationElementAttribute = factory
                            .createOMElement(operationElementAttributeName);
                    // obtain attribute value
                    final OMText operationElementAttributeValue = factory.createOMText(operationElementAttribute,
                            migratedOperationAttributes.get(migratedParameter.getParameterName()));
                    // add attribute value to attribute
                    operationElementAttribute.addChild(operationElementAttributeValue);
                    // add attribute to operation
                    operationElement.addChild(operationElementAttribute);
                    // add operation to operation map
                    oparationMap.put(originalOperation, operationElement);
                }

            } // for each original operation

        } // for each migrated parameter

        // Obtain corresponding original operation(s)
        final List<SourceElement> originalOperations = wsMigrationTraceHandler
                .getSourceElements(migratedOperationModel);
        // create new soap envelope for each original operation
        final List<SOAPEnvelope> soapEnvelops = new ArrayList<SOAPEnvelope>();
        for (final SourceElement originalOperation : originalOperations) {
            // create operation element
            final OMElement operationElement = oparationMap.get(originalOperation);
            //OMNamespace operationNamespace = factory.createOMNamespace(originalOperation.getElementNamespace().getNamespaceURI(), originalOperation.getElementNamespace().getNamespacePrefix());
            final SOAPEnvelope soapEnvelope = factory.createSOAPEnvelope();
            final SOAPBody soapBody = factory.createSOAPBody(soapEnvelope);
            soapBody.addChild(operationElement);
            // populate list of soap envelops
            soapEnvelops.add(soapEnvelope);
        }

        return soapEnvelops;
    }// generateOriginalSoapEnvelops

    /**
     * Original response operation => Migrated response operation(s)
     * 
     * @param originalOperationModel migrated operation model
     * @param originalOperationAttributes operation attributes (= attribute name
     *            and value)
     * @return migrated soap envelops corresponding to the given original
     *         operation
     */
    @Deprecated
    public static List<SOAPEnvelope> generateMigratedResponseSoapEnvelops(
            final SourceElement originalOperationModel, final OMElement originalOperation,
            final WSMigrationTraceHandler wsMigrationTraceHandler) {
        final Map<TargetElement, OMElement> elementMap = new LinkedHashMap<TargetElement, OMElement>();
        final SOAP11Factory factory = new SOAP11Factory();

        // SourceElement.parameters -> targetParameters (at source element level)
        // SourceElement.childElement(s) -> targetElement (from there match their parameters)      

        // For every original parameter, create its corresponding migrated parameter within their migrated operation(s)
        for (final SourceParameter originalParameter : originalOperationModel.getParameters()) {
            // in which migrated operation does this parameter exist?
            final MultiMap<TargetElement, TargetParameter> migratedOperationParameters = wsMigrationTraceHandler
                    .getTargetParameters(originalOperationModel, originalParameter);

            // for any migrated operation in which the original parameter exist --> create/extend migrated operation and parameter
            for (final TargetElement migratedOperation : migratedOperationParameters.keySet()) {
                OMElement operationElement = null;
                if (!elementMap.containsKey(migratedOperation)) {
                    // new operation encountered --> create new operation
                    final QName operationName = new QName(originalOperation.getNamespace().getNamespaceURI(),
                            originalOperation.getLocalName(), originalOperation.getNamespace().getPrefix());
                    operationElement = factory.createOMElement(operationName);
                    // create <result> element for result operation
                    OMElement resultElement = factory.createOMElement(new QName("result"));
                    operationElement.addChild(resultElement);

                } else {
                    // existing operation encountered --> extend operation
                    operationElement = elementMap.get(migratedOperation);
                }
                // obtain corresponding migrated parameter by checking the target parameter's source parameter back-link
                TargetParameter migratedParameter = null;
                for (final TargetParameter targetParameter : migratedOperation.getParameters()) {
                    MultiMap<SourceElement, SourceParameter> sourceElementParameterMap = wsMigrationTraceHandler
                            .getSourceParameters(migratedOperation, targetParameter);
                    for (Iterator<Object> iterator = sourceElementParameterMap.values().iterator(); iterator
                            .hasNext();) {
                        SourceParameter sourceElementParameter = (SourceParameter) iterator.next();
                        if (sourceElementParameter.equals(originalParameter)) {
                            migratedParameter = targetParameter;
                            break;
                        }
                    }
                }

                // if there is a corresponding migrated attribute in the model --> create attribute
                if (migratedParameter != null) {
                    // create operation parameter
                    final QName operationElementAttributeName = new QName(migratedParameter.getParameterName());
                    final OMElement operationElementAttribute = factory
                            .createOMElement(operationElementAttributeName);
                    // obtain attribute value
                    final OMText operationElementAttributeValue;
                    if (originalOperation.getFirstOMChild() instanceof OMText) {
                        // no child attributes available (only <result>)
                        operationElementAttributeValue = factory.createOMText(operationElementAttribute,
                                obtainAttributeValue((OMNode) originalOperation));
                    } else {
                        // child attributes available
                        final Map<String, String> originalOperationAttributes = SOAPHelper
                                .obtainImmediateChildNodesAndValues(originalOperation);
                        operationElementAttributeValue = factory.createOMText(operationElementAttribute,
                                originalOperationAttributes.get(originalParameter.getParameterName()));
                    }
                    // add attribute value to attribute
                    operationElementAttribute.addChild(operationElementAttributeValue);
                    // add attribute to operation result
                    OMElement resultElement = operationElement.getFirstChildWithName(new QName("result"));
                    resultElement.addChild(operationElementAttribute);
                    // add operation to element map
                    elementMap.put(migratedOperation, operationElement);
                }

            } // for each migrated operation

        } // for each original parameter

        // Obtain corresponding migrated operation(s)
        final List<TargetElement> migratedOperations = wsMigrationTraceHandler
                .getTargetElements(originalOperationModel);
        final List<SOAPEnvelope> soapEnvelops = new ArrayList<SOAPEnvelope>();
        for (final TargetElement migratedOperation : migratedOperations) {
            // create operation element
            final OMElement operationElement = elementMap.get(migratedOperation);
            final SOAPEnvelope soapEnvelope = factory.createSOAPEnvelope();
            final SOAPBody soapBody = factory.createSOAPBody(soapEnvelope);
            soapBody.addChild(operationElement);
            // populate list of soap envelops
            soapEnvelops.add(soapEnvelope);
        }

        return soapEnvelops;
    }// generateMigratedSoapEnvelops

    /**
     * @param migratedSoapEnvelope
     * @return
     * @throws XMLStreamException
     * @throws FactoryConfigurationError
     * @throws IOException
     */
    public static String storeSoapEnvelopeToFile(final SOAPEnvelope migratedSoapEnvelope,
            final String migratedResponseFileFolder) throws EUBTException {
        // store created soap envelope in a file
        final String migratedResponseFileLocation = migratedResponseFileFolder
                + migratedSoapEnvelope.getSOAPBodyFirstElementLocalName() + ".xml";
        XMLStreamWriter writer;
        try {
            writer = new IndentingXMLStreamWriter(XMLOutputFactory.newInstance()
                    .createXMLStreamWriter(new FileWriter(migratedResponseFileLocation)));
            migratedSoapEnvelope.serialize(writer);
            writer.flush();
        } catch (XMLStreamException e) {
            throw new EUBTException(
                    "Failed to create stream writer, or serialize or flush output. Detailed Exception: " + e);
        } catch (FactoryConfigurationError e) {
            throw new EUBTException("Failed to configure xml output factory. Detailed Exception: " + e);
        } catch (IOException e) {
            throw new EUBTException("General I/O Exception (wrong path, file location?). Detailed Exception: " + e);
        }
        return migratedResponseFileLocation;
    }// storeSoapEnvelopeToFile

    /**
     * @param soapEnvelope
     * @param responseFileLocation
     * @return
     * @throws EUBTException
     */
    public static SOAPResponse createSoapResponseFromFile(final SOAPEnvelope soapEnvelope,
            final String responseFileLocation, final APPLICATION_TYPE applicationType) throws EUBTException {
        // create migrated soap request from file
        final String targetSoapAction = soapEnvelope.getSOAPBodyFirstElementNS().getNamespaceURI()
                + Character.toUpperCase(soapEnvelope.getSOAPBodyFirstElementLocalName().charAt(0))
                + soapEnvelope.getSOAPBodyFirstElementLocalName().substring(1);
        final SOAPResponse targetSoapResponse = new SOAPResponse(applicationType, responseFileLocation,
                targetSoapAction);
        return targetSoapResponse;
    }// createSoapResponseFromFile

}// SOAPHelper