eu.artist.postmigration.eubt.executiontrace.abstractor.SOAPTraceAbstractor.java Source code

Java tutorial

Introduction

Here is the source code for eu.artist.postmigration.eubt.executiontrace.abstractor.SOAPTraceAbstractor.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.executiontrace.abstractor;

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.axiom.om.OMElement;
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 org.apache.commons.collections4.map.LinkedMap;
import org.xml.sax.SAXException;

import eu.artist.postmigration.eubt.Debug;
import eu.artist.postmigration.eubt.applications.APPLICATION_TYPE;
import eu.artist.postmigration.eubt.exceptions.EUBTException;
import eu.artist.postmigration.eubt.executiontrace.IndependentSOAPTrace;
import eu.artist.postmigration.eubt.executiontrace.IndependentTrace;
import eu.artist.postmigration.eubt.executiontrace.SOAPTrace;
import eu.artist.postmigration.eubt.executiontrace.Trace;
import eu.artist.postmigration.eubt.helpers.SOAPHelper;
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.Response;
import eu.artist.postmigration.eubt.responses.SOAPResponse;

/**
 * @author pneubaue
 * 
 */
public class SOAPTraceAbstractor implements TraceAbstractor {

    private static final String VALIDATION_VALID = "valid";
    private static final String VALIDATION_INVALID = "invalid";
    private static final String PATH_TO_INDEPENDENT_MIGRATED_RESPONSE_FOLDER = System.getProperty("user.dir")
            + "\\responses\\PIM\\migrated\\";
    private static final String PATH_TO_INDEPENDENT_ORIGINAL_RESPONSE_FOLDER = System.getProperty("user.dir")
            + "\\responses\\PIM\\original\\";
    private String schemaLocation;
    private LinkedMap<SOAPResponse, String> validationResults;
    private WSMigrationTraceHandler wsMigrationTraceHandler;

    /* (non-Javadoc)
     * @see eu.artist.postmigration.eubt.executiontrace.abstractor.TraceAbstractor#abstractTrace(eu.artist.postmigration.eubt.executiontrace.Trace, java.lang.String)
     */
    @Override
    public IndependentTrace abstractTrace(final Trace soapTrace, final String responseMigrationTraceModelLocation) {

        IndependentTrace independentSoapTrace = null;

        try {
            if (schemaLocation == null) {
                throw new EUBTException("No Schema location defined.");
            }
            // validate trace against schema and store result      
            validationResults = validateSoapTrace((SOAPTrace) soapTrace);
            // init migration trace handler
            wsMigrationTraceHandler = new WSMigrationTraceHandler(responseMigrationTraceModelLocation);
            // abstract migrated or original trace to independent soap trace
            independentSoapTrace = abstractSoapTrace((SOAPTrace) soapTrace, responseMigrationTraceModelLocation);

        } catch (final Exception e) {
            Debug.out(this, "Failed to abstract trace. " + e.getMessage());
        }

        return independentSoapTrace;
    }// abstractTrace

    /**
     * @param soapTrace
     * @param responseMigrationTraceModelLocation
     * @return
     * @throws Exception
     */
    private IndependentSOAPTrace abstractSoapTrace(final SOAPTrace soapTrace,
            final String responseMigrationTraceModelLocation) throws Exception {
        IndependentSOAPTrace independentSoapTrace = null;
        if (validationResults.size() == 0) {
            throw new EUBTException("Empty trace cannot be abstracted.");
        }
        // obtain trace application type
        final APPLICATION_TYPE applicationType = validationResults.asList().get(0).getType();

        if (applicationType == APPLICATION_TYPE.ORIGINAL_APPLICATION) {
            independentSoapTrace = abstractOriginalSoapTrace(soapTrace);
        } else if (applicationType == APPLICATION_TYPE.MODERNIZED_APPLICATION) {
            independentSoapTrace = abstractMigratedSoapTrace(soapTrace);
        }
        return independentSoapTrace;
    }// abstractSoapTrace

    /**
     * Migrated Soap Trace ==> Independent Soap Trace
     * 
     * Returns an independent form of the migrated soap trace comparable with
     * the independent original soap trace.
     * It does so by:
     * - removing operations that have been newly introduced and do not originate from the
     * original system
     * - removing parameters that have been newly introduced and do not originate from the
     * original system
     * 
     * @param migratedSoapTrace
     * @param wsMigrationTraceHandler
     * @return
     * @throws EUBTException 
     */
    private IndependentSOAPTrace abstractMigratedSoapTrace(final SOAPTrace migratedSoapTrace) throws EUBTException {
        SOAP11Factory factory = new SOAP11Factory();

        // check newly introduced operations/parameters that cannot be traced back to the original system
        Response migratedResponse = migratedSoapTrace.getResponses().get(0);
        SOAPEnvelope sourceSoapEnvelope = (SOAPEnvelope) migratedResponse.getData();
        SOAPBody sourceSoapBody = sourceSoapEnvelope.getBody();
        OMElement sourceSoapBodyFirstChild = (OMElement) sourceSoapBody.getFirstOMChild(); // level: soap response
        OMElement independentSoapResponse = generateIndependentMigratedResponse(sourceSoapBodyFirstChild);

        // put result in soap envelope and store it in the "targetMigratedSoapResponse"
        SOAPEnvelope targetSoapEnvelope = factory.createSOAPEnvelope();
        SOAPBody targetSoapBody = factory.createSOAPBody(targetSoapEnvelope);
        targetSoapBody.addChild(independentSoapResponse);

        SOAPResponse targetMigratedSoapResponse = null;

        // store independent soap response to file
        final String migratedIndependentResponseFileLocation = SOAPHelper
                .storeSoapEnvelopeToFile(targetSoapEnvelope, PATH_TO_INDEPENDENT_MIGRATED_RESPONSE_FOLDER);
        Debug.out(this, "Successfully stored abstracted SOAP envelope to file at "
                .concat(migratedIndependentResponseFileLocation));
        targetMigratedSoapResponse = SOAPHelper.createSoapResponseFromFile(targetSoapEnvelope,
                migratedIndependentResponseFileLocation, APPLICATION_TYPE.MODERNIZED_APPLICATION);

        LinkedList<Response> targetMigratedSoapResponses = new LinkedList<Response>();
        targetMigratedSoapResponses.add(targetMigratedSoapResponse); // can only be one response as it always starts with one migrated response
        SOAPTrace targetMigratedSoapTrace = new SOAPTrace(targetMigratedSoapResponses);

        return new IndependentSOAPTrace(targetMigratedSoapTrace);
    }

    private OMElement generateIndependentMigratedResponse(OMElement element) {
        SOAP11Factory factory = new SOAP11Factory();

        if (SOAPHelper.hasElementChildren(element)) {
            // has more children --> recursively add each child
            TargetElement targetElement = wsMigrationTraceHandler.getTargetElement(
                    element.getNamespace().getNamespaceURI(), element.getLocalName(),
                    SOAPHelper.obtainImmediateChildNodesAndValues(element));
            List<SourceElement> sourceElements = wsMigrationTraceHandler.getSourceElements(targetElement);
            Iterator<?> elementChildrenIterator = element.getChildElements();
            // has more children --> check if element exists a corresponding target element, if so add children, if not skip
            while (sourceElements.size() > 0 && elementChildrenIterator.hasNext()) {
                QName elementName = new QName(element.getNamespace().getNamespaceURI(), element.getLocalName(),
                        element.getNamespace().getPrefix());
                OMElement independentElement = factory.createOMElement(elementName);
                OMElement matchingChildElement = (OMElement) elementChildrenIterator.next();
                independentElement.addChild(generateIndependentMigratedResponse(matchingChildElement));
                return independentElement;
            }
        } else {
            // no more children (leaf(s) reached) --> add matching parameters
            OMElement parameterContainer = factory.createOMElement(element.getQName());
            Map<String, String> parameterNamesAndValues = SOAPHelper.obtainImmediateChildNodesAndValues(element);
            TargetElement matchingTargetElement = obtainMatchingTargetElement(element, parameterNamesAndValues);

            if (matchingTargetElement != null) {
                for (TargetParameter targetParameter : matchingTargetElement.getParameters()) {
                    // obtain corresponding source parameter(s)
                    MultiMap<SourceElement, SourceParameter> sourceElementParameterMap = wsMigrationTraceHandler
                            .getSourceParameters(matchingTargetElement, targetParameter);
                    for (Object sourceParameterObject : sourceElementParameterMap.values()) {
                        SourceParameter sourceParameter = (SourceParameter) sourceParameterObject;
                        // check if source parameter links to given target parameter (i.e., the source parameter's target parameter list must contain the given target parameter)
                        for (TargetParameter matchingTargetParameter : sourceParameter.getTargetParameter()) {
                            if (matchingTargetParameter.equals(targetParameter)) {
                                // matching target parameter found --> add it
                                String parameterValueString = parameterNamesAndValues
                                        .get(targetParameter.getParameterName());
                                QName parameterName = new QName(targetParameter.getParameterName());
                                OMElement parameter = factory.createOMElement(parameterName);
                                OMText parameterValue = factory.createOMText(parameter, parameterValueString);
                                parameter.addChild(parameterValue);
                                parameterContainer.addChild(parameter);
                            } // if target parameter matches
                        } // for each matching target parameter
                    } // for each source parameter object
                } // for each target parameter
            } else {
                // the target is a parameter (not an element, e.g. in case of <result>boolean</result>)
                QName parameterName = new QName(((OMElement) element.getFirstOMChild()).getLocalName());
                String parameterValueString = parameterNamesAndValues.get(parameterName.toString());
                OMElement parameter = factory.createOMElement(parameterName);
                OMText parameterValue = factory.createOMText(parameter, parameterValueString);
                parameter.addChild(parameterValue);
                parameterContainer.addChild(parameter);
            }

            return parameterContainer;
        } // else

        return null; // unreachable?
    }

    /**
     * @param element soap element to find a match for in the model
     * @param parameterNamesAndValues parameter names and values found in the soap element
     * @return a matching target element
     */
    private TargetElement obtainMatchingTargetElement(OMElement element,
            Map<String, String> parameterNamesAndValues) {
        OMElement parentElement = (OMElement) element.getParent();

        // obtain matching target element
        TargetElement matchingTargetElement = wsMigrationTraceHandler.getTargetElement(
                parentElement.getNamespace().getNamespaceURI(), element.getLocalName(), parameterNamesAndValues);
        return matchingTargetElement;
    }// obtainMatchingTargetElement

    /**
     * Original Soap Trace ==> Independent Soap Trace
     * 
     * Returns an independent form of the original soap trace comparable with the
     * independent migrated soap trace.
     * It does so by:
     * - migrating the original soap responses into migrated soap responses
     * 
     * @param originalSoapTrace
     * @param wsMigrationTraceHandler
     * @return
     * @throws Exception
     */
    private IndependentSOAPTrace abstractOriginalSoapTrace(final SOAPTrace originalSoapTrace) throws Exception {
        final LinkedList<Response> targetSoapResponses = new LinkedList<Response>();
        SOAP11Factory factory = new SOAP11Factory();
        /*
         * - Use the response migration trace model to ... resulting in independent soap traces
         *       - ... map the original response to a migrated response, i.e., 
         *          similarly as done by SOAPUserRequestMapper for the request. 
         */
        for (Response originalResponse : originalSoapTrace.getResponses()) {
            SOAPEnvelope sourceSoapEnvelope = (SOAPEnvelope) originalResponse.getData();
            SOAPBody sourceSoapBody = sourceSoapEnvelope.getBody();
            OMElement sourceSoapBodyFirstChild = (OMElement) sourceSoapBody.getFirstOMChild(); // level: soap response
            String namespaceUri = sourceSoapBodyFirstChild.getNamespace().getNamespaceURI();
            String operationName = sourceSoapBodyFirstChild.getLocalName();
            OMElement sourceSoapBodyFirstChildReturn = (OMElement) sourceSoapBodyFirstChild.getFirstOMChild(); // level: <return>..</return>
            Map<String, String> parameterNameValueMap = SOAPHelper
                    .obtainImmediateChildNodesAndValues(sourceSoapBodyFirstChildReturn);

            if (parameterNameValueMap.size() == 0) {
                // only one child that represents the parameter (e.g. <return>..</return>)
                OMText singleChildText = (OMText) sourceSoapBodyFirstChildReturn.getFirstOMChild();
                parameterNameValueMap.put(sourceSoapBodyFirstChildReturn.getLocalName(), singleChildText.getText());
            }

            // obtain migration trace elements
            SourceElement originalOperation = wsMigrationTraceHandler.getSourceElement(namespaceUri, operationName,
                    parameterNameValueMap);

            // abstract to independent response
            OMElement independentSoapResponse = abstractOriginalSoapResponse((SOAPResponse) originalResponse,
                    originalOperation);

            // put result in soap envelope and store it in the "targetMigratedSoapResponse"
            SOAPEnvelope targetSoapEnvelope = factory.createSOAPEnvelope();
            SOAPBody targetSoapBody = factory.createSOAPBody(targetSoapEnvelope);
            targetSoapBody.addChild(independentSoapResponse);

            // store independent soap trace to file
            final String originalIndependentResponseFileLocation = SOAPHelper
                    .storeSoapEnvelopeToFile(targetSoapEnvelope, PATH_TO_INDEPENDENT_ORIGINAL_RESPONSE_FOLDER);
            Debug.out(this, "Successfully stored abstracted SOAP envelope to file at "
                    .concat(originalIndependentResponseFileLocation));
            SOAPResponse targetOriginalSoapResponse = SOAPHelper.createSoapResponseFromFile(targetSoapEnvelope,
                    originalIndependentResponseFileLocation, APPLICATION_TYPE.ORIGINAL_APPLICATION);

            // add to list of responses         
            targetSoapResponses.add(targetOriginalSoapResponse);
        }

        // init independentSoapTrace and assign resulting soapTrace to it
        SOAPTrace independializedSoapTrace = new SOAPTrace(targetSoapResponses);
        IndependentSOAPTrace independenSoapTrace = new IndependentSOAPTrace(independializedSoapTrace);
        return independenSoapTrace;
    }// abstractOriginalSoapTrace

    /**
     * Original Response ==> Independent Original Response
     * 
     * @param sourceResponse a original response
     * @param originalOperation original operation element in migration trace model
     *            corresponding to the original response
     * @return migrated response (independent)
     * @throws Exception 
     */
    private OMElement abstractOriginalSoapResponse(SOAPResponse sourceResponse, SourceElement originalOperation)
            throws Exception {
        final SOAPEnvelope sourceSoapEnvelope = (SOAPEnvelope) sourceResponse.getData();
        final SOAPBody sourceSoapBody = sourceSoapEnvelope.getBody();
        final Iterator<?> sourceSoapBodyChildrenIterator = sourceSoapBody.getChildElements();
        final OMElement sourceSoapBodyChildElement = (OMElement) sourceSoapBodyChildrenIterator.next(); // operation

        OMElement independentSoapResponse = generateIndependentOriginalResponse(sourceSoapBodyChildElement);
        Debug.out(this, "Successfully abstracted source SOAP response to target SOAP response.");
        return independentSoapResponse;
    }// abstractOriginalSoapResponse

    private OMElement generateIndependentOriginalResponse(OMElement element) throws Exception {
        SOAP11Factory factory = new SOAP11Factory();

        if (SOAPHelper.hasElementChildren(element)) {
            // has more children --> recursively add each child
            SourceElement sourceElement = wsMigrationTraceHandler.getSourceElement(
                    element.getNamespace().getNamespaceURI(), element.getLocalName(),
                    SOAPHelper.obtainImmediateChildNodesAndValues(element));
            List<TargetElement> targetElements = wsMigrationTraceHandler.getTargetElements(sourceElement);
            Iterator<?> elementChildrenIterator = element.getChildElements();
            // has more children --> check if element exists a corresponding source element, if so add children, if not skip
            while (targetElements.size() > 0 && elementChildrenIterator.hasNext()) {
                QName elementName = null;
                if (element.getParent() instanceof SOAPBody) {
                    // operation level element
                    elementName = new QName(element.getNamespace().getNamespaceURI(),
                            targetElements.get(0).getElementName(), element.getNamespace().getPrefix());
                } else {
                    // below operation level element
                    elementName = new QName(element.getNamespace().getNamespaceURI(), element.getLocalName(),
                            element.getNamespace().getPrefix());
                }
                OMElement independentElement = factory.createOMElement(elementName);
                OMElement matchingChildElement = (OMElement) elementChildrenIterator.next();
                independentElement.addChild(generateIndependentOriginalResponse(matchingChildElement));
                return independentElement;
            } // while there are children of element
        } else {
            // no more children (leaf(s) reached) --> add matching parameters
            OMElement parameterContainer = factory.createOMElement(element.getQName());
            Map<String, String> parameterNamesAndValues = SOAPHelper.obtainImmediateChildNodesAndValues(element);
            SourceElement matchingSourceElement = obtainMatchingSourceElement(element, parameterNamesAndValues);

            if (matchingSourceElement != null) {
                for (SourceParameter sourceParameter : matchingSourceElement.getParameters()) {
                    // obtain corresponding target parameter(s)
                    MultiMap<TargetElement, TargetParameter> targetElementParameterMap = wsMigrationTraceHandler
                            .getTargetParameters(matchingSourceElement, sourceParameter);
                    for (Object targetParameterObject : targetElementParameterMap.values()) {
                        TargetParameter targetParameter = (TargetParameter) targetParameterObject;
                        // check if target parameter links to given source parameter (i.e., the source parameter's target parameter list must match with the iterating target parameter)
                        for (TargetParameter matchingTargetParameter : sourceParameter.getTargetParameter()) {
                            if (matchingTargetParameter.equals(targetParameter) && parameterContainer
                                    .getChildrenWithLocalName(sourceParameter.getParameterName())
                                    .hasNext() != true) {
                                // matching target parameter that is not yet there found --> add it
                                String parameterValueString = parameterNamesAndValues
                                        .get(sourceParameter.getParameterName());
                                QName parameterName = new QName(targetParameter.getParameterName());
                                OMElement parameter = factory.createOMElement(parameterName);
                                OMText parameterValue = factory.createOMText(parameter, parameterValueString);
                                parameter.addChild(parameterValue);
                                parameterContainer.addChild(parameter);
                            }
                        }
                    } // for each source parameter object
                } // for each target parameter
            } else {
                // the target is a parameter (not an element, e.g. in case of <result>..</result>)
                QName parameterName = new QName(((OMElement) element.getFirstOMChild()).getLocalName());
                String parameterValueString = parameterNamesAndValues.get(parameterName.toString());
                OMElement parameter = factory.createOMElement(parameterName);
                OMText parameterValue = factory.createOMText(parameter, parameterValueString);
                parameter.addChild(parameterValue);
                parameterContainer.addChild(parameter);
            }

            return parameterContainer;
        } // else

        return null; // unreachable?
    }

    /**
     * @param element soap element to find a match for in the model
     * @param parameterNamesAndValues parameter names and values inside the soap element
     * @return a matching source element
     * @throws Exception
     */
    private SourceElement obtainMatchingSourceElement(OMElement element,
            Map<String, String> parameterNamesAndValues) throws Exception {
        OMElement parentElement = (OMElement) element.getParent();

        // obtain matching source element
        SourceElement matchingSourceElement = null;
        if (parentElement instanceof SOAPBody) {
            matchingSourceElement = wsMigrationTraceHandler.getSourceElement(
                    element.getNamespace().getNamespaceURI(), element.getLocalName(), parameterNamesAndValues);
        } else {
            matchingSourceElement = wsMigrationTraceHandler.getSourceElement(
                    parentElement.getNamespace().getNamespaceURI(), element.getLocalName(),
                    parameterNamesAndValues);
        }
        return matchingSourceElement;
    }

    /**
     * Validates soap trace (i.e., list of soap responses) against schema and
     * stores the result
     * 
     * @param soapResponseTrace trace that contains soap responses
     * @return map of soap responses and their respective validation result
     * @throws EUBTException in case the schema location could not be found
     */
    private LinkedMap<SOAPResponse, String> validateSoapTrace(final SOAPTrace soapResponseTrace)
            throws EUBTException {
        final LinkedMap<SOAPResponse, String> validationResults = new LinkedMap<SOAPResponse, String>();

        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Validator validator;
        try {
            final Schema schema = schemaFactory.newSchema(new URL(schemaLocation));
            validator = schema.newValidator();
        } catch (SAXException | IOException e) {
            throw new EUBTException("Failed to create Schema from Schema location " + schemaLocation
                    + ". Detailed Exception: " + e.getMessage());
        }
        // for each soap response
        for (final Response response : soapResponseTrace.getResponses()) {
            String validationResult = VALIDATION_INVALID;
            final SOAPResponse soapResponse = (SOAPResponse) response;
            final SOAPEnvelope soapEnvelope = (SOAPEnvelope) soapResponse.getData();
            final OMElement bodyContent = soapEnvelope.getBody().getFirstElement();

            // create some invalid content
            //         SOAP12Factory factory = new SOAP12Factory();
            //         OMElement invalidElement = factory.createOMElement(new QName("blah"));
            //         OMNamespace invalidNamespace = factory.createOMNamespace("http://notMyNamespace.com", "invNS");
            //         OMAttribute invalidAttribute = factory.createOMAttribute("someAttribute", invalidNamespace, "attributeValue");
            //         bodyContent.addChild(invalidElement);
            //         bodyContent.addAttribute(invalidAttribute);

            // validate soap body content -> will cause an exception if not valid
            try {
                validator.validate(bodyContent.getSAXSource(true));
                // validation succeeded
                validationResult = VALIDATION_VALID;
                Debug.debug(this, "Successfully validated SOAP body content " + bodyContent);
            } catch (final IOException e) {
                throw new EUBTException("Failed to validate SOAP body content " + bodyContent
                        + ". Detailed Exception: " + e.getMessage());
            } catch (final SAXException e) {
                // validation failed
                Debug.debug(this, "Failed to validate soap SOAP content " + bodyContent + ". Detailed Exception: "
                        + e.getMessage());
            }
            // finished validating, store result
            validationResults.put(soapResponse, validationResult);
            validator.reset();
        } // for each soap response

        return validationResults;
    }// validateSoapTrace

    public void setSchemaLocation(final String schemaLocation) {
        this.schemaLocation = schemaLocation;
    }// setSchemaLocation

    public boolean isValidTrace() throws EUBTException {
        if (validationResults == null) {
            throw new EUBTException("Trace has not been validated yet, call 'abstractTrace' first.");
        } else if (validationResults.size() == 0) {
            throw new EUBTException("Empty trace cannot be validated.");
        }
        for (final Map.Entry<SOAPResponse, String> mapEntry : validationResults.entrySet()) {
            if (mapEntry.getValue().equals(VALIDATION_INVALID)) {
                Debug.out(this, "Failed to validated full " + mapEntry.getKey().getType()
                        + " response trace against its schema. First invalid trace element: " + mapEntry.getKey());
                return false;
            }
        }
        Debug.out(this, "Successfully validated full " + validationResults.asList().get(0).getType()
                + " response trace against its schema.");
        return true;
    }// isValidTrace

}// SOAPTraceAbstractor