Package com.eviware.soapui.impl.wsdl.teststeps

Source Code of com.eviware.soapui.impl.wsdl.teststeps.PropertyTransfer

/*
* Copyright 2004-2014 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/

package com.eviware.soapui.impl.wsdl.teststeps;

import com.eviware.soapui.config.PropertyTransferConfig;
import com.eviware.soapui.config.PropertyTransferTypesConfig;
import com.eviware.soapui.impl.support.http.HttpRequestTestStep;
import com.eviware.soapui.model.TestPropertyHolder;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.support.JsonPathFacade;
import com.eviware.soapui.support.PropertyChangeNotifier;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.resolver.ChooseAnotherPropertySourceResolver;
import com.eviware.soapui.support.resolver.ChooseAnotherPropertyTargetResolver;
import com.eviware.soapui.support.resolver.CreateMissingPropertyResolver;
import com.eviware.soapui.support.resolver.DisablePropertyTransferResolver;
import com.eviware.soapui.support.resolver.ResolveContext;
import com.eviware.soapui.support.resolver.ResolveContext.PathToResolve;
import com.eviware.soapui.support.xml.XmlUtils;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlCursor.TokenType;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import static com.eviware.soapui.tools.PropertyExpansionRemover.removeExpansions;

/**
* Class for transferring a property value between 2 test steps. This class is
* relatively complex due to backwards compatibility issues and to graceful
* handling of references test steps and properties.
*
* @author Ole.Matzura
*/

public class PropertyTransfer implements PropertyChangeNotifier {


    private final static Logger log = Logger.getLogger(PropertyTransfer.class);

    public final static String SOURCE_PATH_PROPERTY = PropertyTransfer.class.getName() + "@sourcePath";
    public final static String SOURCE_TYPE_PROPERTY = PropertyTransfer.class.getName() + "@sourceProperty";
    public final static String SOURCE_STEP_PROPERTY = PropertyTransfer.class.getName() + "@sourceStep";
    public final static String TARGET_PATH_PROPERTY = PropertyTransfer.class.getName() + "@targetPath";
    public final static String TARGET_TYPE_PROPERTY = PropertyTransfer.class.getName() + "@targetProperty";
    public final static String TARGET_STEP_PROPERTY = PropertyTransfer.class.getName() + "@targetStep";
    public final static String NAME_PROPERTY = PropertyTransfer.class.getName() + "@name";
    public final static String DISABLED_PROPERTY = PropertyTransfer.class.getName() + "@disabled";
    public final static String CONFIG_PROPERTY = PropertyTransfer.class.getName() + "@config";

    private TestStep testStep;

    // create local copies since a deleted/changed property transfer can be referenced from a result
    private PropertyTransferConfig config;
    private String sourcePath;
    private String sourceType;
    private String targetPath;
    private String name;
    private String targetType;
    private String sourceStep;
    private String targetStep;

    private TestPropertyHolder currentTargetStep;
    private TestPropertyHolder currentSourceStep;
    private TestProperty currentTargetProperty;
    private TestProperty currentSourceProperty;

    private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
    private StepNameChangeListener stepNameChangeListener = new StepNameChangeListener();
    private InternalTestPropertyListener propertyNameChangeListener = new InternalTestPropertyListener();
    private TestCase testCase;

    private InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();

    public PropertyTransfer(TestStep testStep) {
        this(testStep, PropertyTransferConfig.Factory.newInstance());
    }

    public PropertyTransfer(TestStep testStep, PropertyTransferConfig config) {
        this.testStep = testStep;

        if (testStep != null) {
            this.testCase = testStep.getTestCase();
            testCase.getTestSuite().addTestSuiteListener(testSuiteListener);
        }

        setConfig(config);
    }

    void setConfigOnMove(PropertyTransferConfig config) {
        this.config = config;
    }

    void setConfig(PropertyTransferConfig config) {
        releaseListeners();

        this.config = config;

        if (!config.isSetSetNullOnMissingSource()) {
            config.setSetNullOnMissingSource(true);
        }

        if (!config.isSetTransferTextContent()) {
            config.setTransferTextContent(true);
        }
        sourceStep = config.getSourceStep();
        if (sourceStep == null) {
            sourceStep = getSourceStepName();
            if (sourceStep != null) {
                config.setSourceStep(sourceStep);
            }
        } else {
            sourceStep = sourceStep.trim();
        }

        currentSourceStep = getPropertyHolder(sourceStep);

        sourceType = config.getSourceType();
        currentSourceProperty = currentSourceStep == null || sourceType == null ? null : currentSourceStep
                .getProperty(sourceType);

        sourcePath = config.getSourcePath();

        targetStep = config.getTargetStep();
        if (targetStep == null) {
            targetStep = getTargetStepName();
            if (targetStep != null) {
                config.setTargetStep(targetStep);
            }
        } else {
            targetStep = targetStep.trim();
        }

        currentTargetStep = getPropertyHolder(targetStep);

        targetType = config.getTargetType();
        currentTargetProperty = currentTargetStep == null || targetType == null ? null : currentTargetStep
                .getProperty(targetType);

        targetPath = config.getTargetPath();
        if (!config.getUpgraded()) {
            if (shouldConvertSourceProperty()) {
                setSourcePropertyName(WsdlTestStepWithProperties.RESPONSE_AS_XML);
            }
            config.setUpgraded(true);
        }

        name = config.getName();
        initListeners();

        propertyChangeSupport.firePropertyChange(CONFIG_PROPERTY, null, null);
    }

    private boolean shouldConvertSourceProperty() {
        return config.getSourcePath() != null && getSourcePathLanguage() != PathLanguage.JSONPATH &&
                sourcePropertyIsResponse();
    }

    private boolean sourcePropertyIsResponse() {
        TestProperty property = getSourceProperty();
        return property != null && property.getName() != null &&
                property.getName().equals(WsdlTestStepWithProperties.RESPONSE);
    }

    public void setSourcePathLanguage(PathLanguage language) {
        PropertyTransferTypesConfig.Enum languageEnum = language == null ? null : PropertyTransferTypesConfig.Enum.forInt(language.ordinal() + 1);
        getConfig().setType(languageEnum);
    }

    public PathLanguage getSourcePathLanguage() {
        return transferLanguageFromPropertyTransferType(getConfig().getType());
    }

    private PathLanguage transferLanguageFromPropertyTransferType(PropertyTransferTypesConfig.Enum savedLanguage) {
        if (savedLanguage == null) {
            return getUseXQuery() ? PathLanguage.XQUERY : PathLanguage.XPATH;
        }
        return PathLanguage.valueOf(savedLanguage.toString());
    }

    public void setTargetPathLanguage(PathLanguage language) {
        getConfig().setTargetTransferType(PropertyTransferTypesConfig.Enum.forInt(language.ordinal() + 1));
    }

    public PathLanguage getTargetPathLanguage() {
        return transferLanguageFromPropertyTransferType(getConfig().getTargetTransferType());
    }

    private void initListeners() {
        if (currentSourceStep != null) {
            if (currentSourceStep instanceof TestStep) {
                ((TestStep) currentSourceStep)
                        .addPropertyChangeListener(TestStep.NAME_PROPERTY, stepNameChangeListener);
            }

            currentSourceStep.addTestPropertyListener(propertyNameChangeListener);
        }

        if (currentTargetStep != null) {
            if (currentTargetStep instanceof TestStep) {
                ((TestStep) currentTargetStep)
                        .addPropertyChangeListener(TestStep.NAME_PROPERTY, stepNameChangeListener);
            }

            currentTargetStep.addTestPropertyListener(propertyNameChangeListener);
        }
    }

    public void releaseListeners() {
        if (currentSourceStep != null) {
            if (currentSourceStep instanceof TestStep) {
                ((TestStep) currentSourceStep).removePropertyChangeListener(TestStep.NAME_PROPERTY,
                        stepNameChangeListener);
            }

            currentSourceStep.removeTestPropertyListener(propertyNameChangeListener);
        }

        if (currentTargetStep != null) {
            if (currentTargetStep instanceof TestStep) {
                ((TestStep) currentTargetStep).removePropertyChangeListener(TestStep.NAME_PROPERTY,
                        stepNameChangeListener);
            }

            currentTargetStep.removeTestPropertyListener(propertyNameChangeListener);
        }

        PropertyChangeListener[] listeners = propertyChangeSupport.getPropertyChangeListeners();
        for (PropertyChangeListener listener : listeners) {
            propertyChangeSupport.removePropertyChangeListener(listener);
        }
    }

    public void release() {
        releaseListeners();
        testCase.getTestSuite().removeTestSuiteListener(testSuiteListener);
    }

    public PropertyTransferConfig getConfig() {
        return config;
    }

    public String getSourcePath() {
        return sourcePath;
    }

    public String getTargetPath() {
        return targetPath;
    }

    public TestProperty getSourceProperty() {
        if (sourceType == null) {
            return null;
        }

        if (currentSourceProperty != null) {
            return currentSourceProperty;
        }

        TestPropertyHolder actualSourceStep = getSourceStep();
        return actualSourceStep == null ? null : actualSourceStep.getProperty(sourceType);
    }

    public String[] transferProperties(SubmitContext context) throws PropertyTransferException {
        TestProperty sourceProperty = getSourceProperty();
        TestProperty targetProperty = getTargetProperty();

        try {
            if (sourceProperty == null) {
                throw new Exception("Missing source property");
            }
            if (targetProperty == null) {
                throw new Exception("Missing target property");
            }
            if (sourceProperty.getValue() == null && !getSetNullOnMissingSource() && !getIgnoreEmpty()) {
                throw new Exception("Source property is null");
            }

            if (bothPathsAreXmlBased()) {
                return transferXPathToXml(getSourceProperty(), getTargetProperty(), context);
            } else {
                Object sourceValue = readSourceValue(context);
                sourceValue = entitizeIfApplicable(sourceValue);
                if (isResponseProperty(sourceProperty) && sourceValue instanceof String) {
                    sourceValue = removeExpansions((String) sourceValue);
                }
                return writeTargetValue(sourceValue, context);
            }
        } catch (Exception e) {
            throw new PropertyTransferException(e.getMessage(), getSourceStepName(), sourceProperty, getTargetStepName(),
                    targetProperty);
        }
    }

    private boolean isResponseProperty(TestProperty sourceProperty) {
        String propertyName = sourceProperty.getName();
        return propertyName.equals("Response") || propertyName.equals("RawResponse") || propertyName.equals("ResponseAsXml");
    }

    private Object entitizeIfApplicable(Object sourceValue) {
        if (sourceValue instanceof String && StringUtils.hasContent((String) sourceValue) && getEntitize()) {
            return XmlUtils.entitize((String) sourceValue);
        }
        return sourceValue;
    }

    private Object readSourceValue(PropertyExpansionContext context) throws Exception {
        String sourceValue = getSourceProperty().getValue();
        if (!hasSourcePath()) {
            return sourceValue;
        } else if (getSourcePathLanguage() == PathLanguage.JSONPATH) {
            return new JsonPathFacade(sourceValue).readObjectValue(getSourcePath());
        } else {
            XmlObject sourceXml = XmlUtils.createXmlObject(sourceValue);
            XmlCursor sourceCursor = sourceXml.newCursor();

            try {
                String value = null;

                String pathExpression = PropertyExpander.expandProperties(context, getSourcePath());
                boolean usingXQuery = getSourcePathLanguage() == PathLanguage.XQUERY;
                if (usingXQuery) {
                    XmlCursor resultCursor = sourceCursor.execQuery(pathExpression);
                    sourceCursor.dispose();
                    sourceCursor = resultCursor;
                    if (sourceCursor.toNextToken() != TokenType.START && !getSetNullOnMissingSource() && !getIgnoreEmpty()) {
                        throw new Exception("Missing match for Source XQuery [" + pathExpression + "]");
                    }
                } else {
                    sourceCursor.selectPath(pathExpression);
                }

                if (!usingXQuery && !sourceCursor.toNextSelection()) {
                    if (!getSetNullOnMissingSource() && !getIgnoreEmpty()) {
                        throw new Exception("Missing match for Source XPath [" + pathExpression + "]");
                    }
                }

                Node sourceNode = sourceCursor.getDomNode();
                short sourceNodeType = sourceNode.getNodeType();

                if (sourceNodeType == Node.DOCUMENT_FRAGMENT_NODE) {
                    sourceNode = sourceNode.getFirstChild();
                    if (sourceNode != null) {
                        sourceNodeType = sourceNode.getNodeType();
                    } else {
                        throw new Exception("Missing source value for " + getSourcePropertyName());
                    }
                }

                if (sourceNodeType == Node.TEXT_NODE || sourceNodeType == Node.ATTRIBUTE_NODE) {
                    value = sourceNode.getNodeValue();
                } else if (sourceNodeType == Node.ELEMENT_NODE) {
                    if (getTransferTextContent()) {
                        value = XmlUtils.getElementText((Element) sourceNode);
                    }

                    if (value == null || !getTransferTextContent()) {
                        value = sourceCursor.getObject().xmlText(
                                new XmlOptions().setSaveOuter().setSaveAggressiveNamespaces());
                    }
                }
                return value;
            } finally {
                if (sourceCursor != null) {
                    sourceCursor.dispose();
                }
            }
        }
    }

    private String[] writeTargetValue(Object value, SubmitContext context) throws Exception {
        String stringValue = value == null ? null : String.valueOf(value);
        if (!hasTargetPath()) {
            getTargetProperty().setValue(stringValue);
        } else {
            String targetPath = PropertyExpander.expandProperties(context, getTargetPath());
            if (getTargetPathLanguage() == PathLanguage.JSONPATH) {
                JsonPathFacade jsonPathFacade = new JsonPathFacade(getTargetProperty().getValue());
                jsonPathFacade.writeValue(targetPath, value);
                getTargetProperty().setValue(jsonPathFacade.getCurrentJson());
            } else {
                XmlObject targetXml = XmlObject.Factory.parse(getTargetProperty().getValue());
                XmlCursor targetCursor = targetXml.newCursor();

                try {
                    List<String> result = new ArrayList<String>();

                    targetCursor.selectPath(targetPath);

                    if (!targetCursor.toNextSelection()) {
                        throw new Exception("Missing match for Target XPath [" + targetPath + "]");
                    }

                    Node targetNode = targetCursor.getDomNode();
                    setNodeValue(stringValue, targetNode);

                    result.add(stringValue);

                    if (getTransferToAll()) {
                        while (targetCursor.toNextSelection()) {
                            targetNode = targetCursor.getDomNode();
                            setNodeValue(stringValue, targetNode);

                            result.add(stringValue);
                        }
                    }

                    getTargetProperty().setValue(targetXml.xmlText(new XmlOptions().setSaveAggressiveNamespaces()));

                    return result.toArray(new String[result.size()]);
                } finally {
                    targetCursor.dispose();
                }
            }

        }
        return new String[]{stringValue};
    }

    private boolean bothPathsAreXmlBased() {
        return hasSourcePath() && hasTargetPath() && getSourcePathLanguage() != PathLanguage.JSONPATH &&
                getTargetPathLanguage() != PathLanguage.JSONPATH;
    }

    private boolean hasTargetPath() {
        String path = getTargetPath();
        return path != null && path.trim().length() > 0;
    }

    private boolean hasSourcePath() {
        String path = getSourcePath();
        return path != null && path.trim().length() > 0;
    }

    protected String[] transferXPathToXml(TestProperty sourceProperty, TestProperty targetProperty,
                                          SubmitContext context) throws Exception {
        XmlCursor sourceXml;
        try {
            String sourcePropertyValue = sourceProperty.getValue();
            if (isResponseProperty(sourceProperty)) {
                sourcePropertyValue = removeExpansions(sourceProperty.getValue());
            }
            XmlObject sourceXmlObject = sourcePropertyValue == null ? null : XmlUtils
                    .createXmlObject(sourcePropertyValue);
            sourceXml = sourceXmlObject == null ? null : sourceXmlObject.newCursor();
        } catch (XmlException e) {
            throw new Exception("Error parsing source property [" + e.getMessage() + "]");
        }

        XmlObject targetXmlObject;
        XmlCursor targetXml;
        try {
            String targetPropertyValue = targetProperty.getValue();
            targetXmlObject = XmlUtils.createXmlObject(targetPropertyValue);
            targetXml = targetXmlObject.newCursor();
        } catch (XmlException e) {
            throw new Exception("Error parsing target property [" + e.getMessage() + "]");
        }

        XmlCursor lastSource = null;

        try {
            List<String> result = new ArrayList<String>();

            String tp = PropertyExpander.expandProperties(context, getTargetPath());
            targetXml.selectPath(tp);

            if (!targetXml.hasNextSelection()) {
                throw new Exception("Missing match for Target XPath [" + tp + "]");
            }

            if (sourceXml == null) {
                if (getSetNullOnMissingSource()) {
                    while (targetXml.toNextSelection()) {
                        result.add(setNodeValue(null, targetXml.getDomNode()));
                        if (!getTransferToAll()) {
                            break;
                        }
                    }
                }
            } else if (getSourcePathLanguage() == PathLanguage.XQUERY) {
                String sp = PropertyExpander.expandProperties(context, getSourcePath());
                XmlCursor resultCursor = sourceXml.execQuery(sp);
                sourceXml.dispose();
                sourceXml = resultCursor;

                if (sourceXml.toNextToken() != TokenType.START) {
                    if (getSetNullOnMissingSource()) {
                        while (targetXml.toNextSelection()) {
                            result.add(setNodeValue(null, targetXml.getDomNode()));
                            if (!getTransferToAll()) {
                                break;
                            }
                        }
                    } else if (!getIgnoreEmpty()) {
                        throw new Exception("Missing match for Source XQuery [" + sp + "]");
                    }
                }

                boolean hasTarget = targetXml.toNextSelection();

                if (hasTarget) {
                    lastSource = sourceXml.newCursor();
                    result.add(transferXmlValue(sourceXml, targetXml));
                }
            } else {
                String sp = PropertyExpander.expandProperties(context, getSourcePath());
                sourceXml.selectPath(sp);

                if (!sourceXml.hasNextSelection()) {
                    if (getSetNullOnMissingSource()) {
                        while (targetXml.toNextSelection()) {
                            result.add(setNodeValue(null, targetXml.getDomNode()));
                            if (!getTransferToAll()) {
                                break;
                            }
                        }
                    } else if (!getIgnoreEmpty()) {
                        throw new Exception("Missing match for Source XPath [" + sp + "]");
                    }
                } else {
                    boolean hasSource = sourceXml.toNextSelection();
                    boolean hasTarget = targetXml.toNextSelection();

                    while (hasSource && hasTarget) {
                        if (lastSource != null) {
                            lastSource.dispose();
                        }

                        lastSource = sourceXml.newCursor();
                        result.add(transferXmlValue(sourceXml, targetXml));

                        hasSource = sourceXml.toNextSelection();
                        hasTarget = targetXml.toNextSelection();
                    }

                    if (getTransferToAll() && !hasSource && hasTarget && lastSource != null) {
                        while (hasTarget) {
                            result.add(transferXmlValue(lastSource, targetXml));
                            hasTarget = targetXml.toNextSelection();
                        }
                    }
                }
            }

            if (result.size() > 0) {
                String value = targetXmlObject.xmlText(new XmlOptions().setSaveAggressiveNamespaces());
                // if( getEntitize() )
                // value = XmlUtils.entitize( value );

                targetProperty.setValue(value);
            }

            return result.toArray(new String[result.size()]);
        } finally {
            if (sourceXml != null) {
                sourceXml.dispose();
            }
            if (targetXml != null) {
                targetXml.dispose();
            }
            if (lastSource != null) {
                lastSource.dispose();
            }
        }
    }

    private String setNodeValue(String value, Node node) throws Exception {
        short targetNodeType = node.getNodeType();

        if (targetNodeType == Node.DOCUMENT_FRAGMENT_NODE) {
            node = node.getFirstChild();
            if (node != null) {
                targetNodeType = node.getNodeType();
            } else {
                throw new Exception("Missing source value for " + getSourcePropertyName());
            }
        }

        if (!XmlUtils.setNodeValue(node, value)) {
            throw new Exception("Failed to set value to node [" + node.toString() + "] of type [" + targetNodeType + "]");
        }

        return value;
    }

    /**
     * Method called for transferring between 2 xml properties..
     */

    private String transferXmlValue(XmlCursor source, XmlCursor dest) throws Exception {
        // just copy if nodes are of same type
        Node destNode = dest.getDomNode();
        Node sourceNode = source.getDomNode();
        short destNodeType = destNode.getNodeType();
        short sourceNodeType = sourceNode.getNodeType();
        String value = null;

        if (getTransferChildNodes()) {
            while (destNode.hasChildNodes()) {
                destNode.removeChild(destNode.getFirstChild());
            }

            NodeList childNodes = sourceNode.getChildNodes();
            for (int c = 0; c < childNodes.getLength(); c++) {
                destNode.appendChild(destNode.getOwnerDocument().importNode(childNodes.item(c), true));
            }

            return XmlUtils.serialize(destNode, false);
        }

        if (sourceNodeType == Node.DOCUMENT_FRAGMENT_NODE) {
            sourceNode = sourceNode.getFirstChild();
            if (sourceNode != null) {
                sourceNodeType = sourceNode.getNodeType();
            } else {
                throw new Exception("Missing source value for " + source);
            }
        }

        // same type of node?
        if (destNodeType == sourceNodeType) {
            if (destNodeType == Node.TEXT_NODE || destNodeType == Node.ATTRIBUTE_NODE) {
                value = sourceNode.getNodeValue();
                if (!getIgnoreEmpty() || (value != null && value.length() > 0)) {
                    if (getEntitize()) {
                        value = XmlUtils.entitize(value);
                    }

                    destNode.setNodeValue(value);
                }
            } else if (config.getTransferTextContent() && destNodeType == Node.ELEMENT_NODE) {
                value = XmlUtils.getElementText((Element) sourceNode);
                if (value == null && sourceNode.getFirstChild() != null) {
                    value = source.getObject().xmlText(new XmlOptions().setSaveOuter().setSaveAggressiveNamespaces());

                    if (getEntitize()) {
                        value = XmlUtils.entitize(value);
                    }

                    destNode.getParentNode().replaceChild(destNode.getOwnerDocument().importNode(sourceNode, true),
                            destNode);
                } else if (!getIgnoreEmpty() || (value != null && value.length() > 0)) {
                    if (getEntitize()) {
                        value = XmlUtils.entitize(value);
                    }

                    XmlUtils.setElementText((Element) destNode, value);
                }
            } else {
                destNode.getParentNode().replaceChild(
                        destNode.getOwnerDocument().importNode(sourceNode, true), destNode);

                value = dest.xmlText();
            }
        }
        // text to attribute?
        else if ((sourceNodeType == Node.TEXT_NODE && destNodeType == Node.ATTRIBUTE_NODE)
                || (sourceNodeType == Node.ATTRIBUTE_NODE && destNodeType == Node.TEXT_NODE)) {
            value = sourceNode.getNodeValue();
            if (!getIgnoreEmpty() || (value != null && value.length() > 0)) {
                if (getEntitize()) {
                    value = XmlUtils.entitize(value);
                }

                destNode.setNodeValue(value);
            }
        } else if (sourceNodeType == Node.ELEMENT_NODE && destNodeType == Node.ATTRIBUTE_NODE
                || destNodeType == Node.TEXT_NODE) {
            value = XmlUtils.getElementText((Element) sourceNode);
            if (!getIgnoreEmpty() || (value != null && value.length() > 0)) {
                if (getEntitize()) {
                    value = XmlUtils.entitize(value);
                }

                destNode.setNodeValue(value);
            }
        } else if (destNodeType == Node.ELEMENT_NODE && sourceNodeType == Node.ATTRIBUTE_NODE
                || sourceNodeType == Node.TEXT_NODE) {
            // hmm.. not sure xmlbeans handles this ok
            value = sourceNode.getNodeValue();
            if (!getIgnoreEmpty() || (value != null && value.length() > 0)) {
                if (getEntitize()) {
                    value = XmlUtils.entitize(value);
                }

                XmlUtils.setElementText((Element) destNode, value);
            }
        }

        return value;
    }

    /**
     * Returns the name of the source property.
     */

    public String getSourcePropertyName() {
        if (sourceType == null) {
            return null;
        }

        if (currentSourceProperty != null) {
            return currentSourceProperty.getName();
        }

        TestPropertyHolder actualSourceStep = getSourceStep();
        if (actualSourceStep == null) {
            return sourceType;
        }

        TestProperty property = actualSourceStep.getProperty(sourceType);
        return property == null ? sourceType : property.getName();
    }

    public void setSourcePropertyName(String name) {
        String old = getSourcePropertyName();

        // check for change
        if ((name == null && old == null) || (name != null && old != null && name.equals(old))) {
            return;
        }

        // update
        sourceType = name;
        config.setSourceType(name);

        // update actual property
        TestPropertyHolder sourceStep2 = getSourceStep();
        currentSourceProperty = sourceStep2 != null && sourceType != null ? sourceStep2.getProperty(sourceType) : null;

        // notify!
        propertyChangeSupport.firePropertyChange(SOURCE_TYPE_PROPERTY, old, name);
    }

    public TestProperty getTargetProperty() {
        if (targetType == null) {
            return null;
        }

        if (currentTargetProperty != null) {
            return currentTargetProperty;
        }

        TestPropertyHolder actualTargetStep = getTargetStep();
        return actualTargetStep == null ? null : actualTargetStep.getProperty(targetType);
    }

    public String getTargetPropertyName() {
        if (targetType == null) {
            return null;
        }

        if (currentTargetProperty != null) {
            return currentTargetProperty.getName();
        }

        TestPropertyHolder actualTargetStep = getTargetStep();
        TestProperty property = actualTargetStep == null ? null : actualTargetStep.getProperty(targetType);
        return actualTargetStep == null || property == null ? targetType : property.getName();
    }

    public void setTargetPropertyName(String name) {
        String old = getTargetPropertyName();

        // check for change
        if ((name == null && old == null) || (name != null && old != null && name.equals(old))) {
            return;
        }

        // update
        targetType = name;
        config.setTargetType(name);

        // update actual property
        TestPropertyHolder targetStep2 = getTargetStep();

        currentTargetProperty = targetStep2 != null && targetType != null ? targetStep2.getProperty(targetType) : null;

        // notify!
        propertyChangeSupport.firePropertyChange(TARGET_TYPE_PROPERTY, old, name);
    }

    public String getName() {
        return config.getName();
    }

    public void setSourcePath(String path) {
        String old = sourcePath;
        sourcePath = path;
        config.setSourcePath(path);
        propertyChangeSupport.firePropertyChange(SOURCE_PATH_PROPERTY, old, path);
    }

    public void setTargetPath(String path) {
        String old = targetPath;
        targetPath = path;
        config.setTargetPath(path);
        propertyChangeSupport.firePropertyChange(TARGET_PATH_PROPERTY, old, path);
    }

    public void setName(String name) {
        String old = this.name;
        this.name = name;
        config.setName(name);
        propertyChangeSupport.firePropertyChange(NAME_PROPERTY, old, name);
    }

    public TestPropertyHolder getSourceStep() {
        return getPropertyHolder(getSourceStepName());
    }

    public String getSourceStepName() {
        if (sourceStep != null) {
            return sourceStep;
        }

        if (testCase == null) {
            return null;
        }

        HttpRequestTestStep step = testCase.findPreviousStepOfType(this.testStep, HttpRequestTestStep.class);
        return step == null ? null : step.getName();
    }

    public void setSourceStepName(String sourceStep) {
        String old = getSourceStepName();

        // check for change
        if ((sourceStep == null && old == null) || (sourceStep != null && old != null && sourceStep.equals(old))) {
            return;
        }

        if (sourceStep == null) {
            log.debug("Setting sourceStep for transfer [" + getName() + "] to null");
        }

        this.sourceStep = sourceStep;
        config.setSourceStep(sourceStep);

        if (currentSourceStep != null) {
            if (currentSourceStep instanceof TestStep) {
                ((TestStep) currentSourceStep).removePropertyChangeListener(TestStep.NAME_PROPERTY,
                        stepNameChangeListener);
            }

            currentSourceStep.removeTestPropertyListener(propertyNameChangeListener);
        }

        currentSourceStep = getPropertyHolder(sourceStep);
        if (currentSourceStep != null) {
            if (currentSourceStep instanceof TestStep) {
                ((TestStep) currentSourceStep)
                        .addPropertyChangeListener(TestStep.NAME_PROPERTY, stepNameChangeListener);
            }

            currentSourceStep.addTestPropertyListener(propertyNameChangeListener);
        } else {
            log.warn("Failed to get sourceStep [" + sourceStep + "]");
        }

        propertyChangeSupport.firePropertyChange(SOURCE_STEP_PROPERTY, old, sourceStep);
        setSourcePropertyName(null);
    }

    public TestPropertyHolder getTargetStep() {
        return getPropertyHolder(getTargetStepName());
    }

    public String getTargetStepName() {
        if (targetStep != null) {
            return targetStep;
        }

        if (testCase == null) {
            return null;
        }

        HttpRequestTestStep step = testCase.findNextStepOfType(this.testStep, HttpRequestTestStep.class);
        return step == null ? null : step.getName();
    }

    public void setTargetStepName(String targetStep) {
        String old = getTargetStepName();

        // check for change
        if ((targetStep == null && old == null) || (targetStep != null && old != null && targetStep.equals(old))) {
            return;
        }

        if (targetStep == null) {
            log.debug("Setting targetStep for transfer [" + getName() + "] to null");
        }

        this.targetStep = targetStep;
        config.setTargetStep(targetStep);

        if (currentTargetStep != null) {
            if (currentTargetStep instanceof TestStep) {
                ((TestStep) currentTargetStep).removePropertyChangeListener(TestStep.NAME_PROPERTY,
                        stepNameChangeListener);
            }

            currentTargetStep.removeTestPropertyListener(propertyNameChangeListener);
        }

        currentTargetStep = getPropertyHolder(targetStep);
        if (currentTargetStep != null) {
            if (currentTargetStep instanceof TestStep) {
                ((TestStep) currentTargetStep)
                        .addPropertyChangeListener(TestStep.NAME_PROPERTY, stepNameChangeListener);
            }

            currentTargetStep.addTestPropertyListener(propertyNameChangeListener);
        } else {
            log.warn("Failed to get targetStep [" + targetStep + "]");
        }

        propertyChangeSupport.firePropertyChange(TARGET_STEP_PROPERTY, old, targetStep);
        setTargetPropertyName(null);
    }

    private TestPropertyHolder getPropertyHolder(String name) {
        if (!StringUtils.hasContent(name) || testCase == null) {
            return null;
        }

        if (name.charAt(0) == PropertyExpansion.SCOPE_PREFIX) {
            if (name.equals(PropertyExpansion.GLOBAL_REFERENCE)) {
                return PropertyExpansionUtils.getGlobalProperties();
            }

            if (name.equals(PropertyExpansion.PROJECT_REFERENCE)) {
                return testCase.getTestSuite().getProject();
            }

            if (name.equals(PropertyExpansion.TESTSUITE_REFERENCE)) {
                return testCase.getTestSuite();
            }

            if (name.equals(PropertyExpansion.TESTCASE_REFERENCE)) {
                return testCase;
            }
        }

        return testStep.getTestCase().getTestStepByName(name);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
    }

    public boolean getFailOnError() {
        return config.getFailOnError();
    }

    public void setFailOnError(boolean failOnError) {
        config.setFailOnError(failOnError);
    }

    public boolean getTransferToAll() {
        return config.getTransferToAll();
    }

    public void setTransferToAll(boolean transferToAll) {
        config.setTransferToAll(transferToAll);
    }

    public boolean getUseXQuery() {
        return config.getUseXQuery();
    }

    public void setUseXQuery(boolean useXQuery) {
        config.setUseXQuery(useXQuery);
    }

    public boolean getEntitize() {
        return config.getEntitize();
    }

    public void setEntitize(boolean entitize) {
        config.setEntitize(entitize);
    }

    public boolean getIgnoreEmpty() {
        return config.getIgnoreEmpty();
    }

    public void setIgnoreEmpty(boolean ignoreEmpty) {
        config.setIgnoreEmpty(ignoreEmpty);
    }

    public boolean getSetNullOnMissingSource() {
        return config.getSetNullOnMissingSource();
    }

    public void setSetNullOnMissingSource(boolean setNullOnMissingSource) {
        config.setSetNullOnMissingSource(setNullOnMissingSource);
    }

    public boolean getTransferTextContent() {
        return config.getTransferTextContent();
    }

    public void setTransferTextContent(boolean transferTextContent) {
        config.setTransferTextContent(transferTextContent);
    }

    public boolean isDisabled() {
        return config.getDisabled();
    }

    public void setDisabled(boolean disabled) {
        config.setDisabled(disabled);
    }

    public boolean getTransferChildNodes() {
        return config.getTransferChildNodes();
    }

    public void setTransferChildNodes(boolean b) {
        config.setTransferChildNodes(b);
    }

    private final class InternalTestSuiteListener extends TestSuiteListenerAdapter {
        public void testStepRemoved(TestStep testStep, int index) {
            if (testStep.getTestCase() == testCase) {
                String stepName = testStep.getName();
                if (stepName.equals(sourceStep)) {
                    setSourceStepName(null);
                }

                if (stepName.equals(targetStep)) {
                    setTargetStepName(null);
                }
            }
        }
    }

    /**
     * Handle changes to source/target testStep names
     *
     * @author Ole.Matzura
     */

    private class StepNameChangeListener implements PropertyChangeListener {
        public void propertyChange(PropertyChangeEvent evt) {
            String oldName = (String) evt.getOldValue();
            String newValue = (String) evt.getNewValue();

            if (newValue == null) {
                log.error("Tried to change stepname to null!");
                Thread.dumpStack();
                return;
            }

            if (oldName.equals(sourceStep) && currentSourceStep instanceof TestStep) {
                sourceStep = newValue;
                config.setSourceStep(sourceStep);
                propertyChangeSupport.firePropertyChange(SOURCE_STEP_PROPERTY, oldName, sourceStep);
            }

            if (oldName.equals(targetStep) && currentTargetStep instanceof TestStep) {
                targetStep = newValue;
                config.setTargetStep(targetStep);
                propertyChangeSupport.firePropertyChange(TARGET_STEP_PROPERTY, oldName, targetStep);
            }
        }
    }

    /**
     * Handle changes to source/target property names
     *
     * @author Ole.Matzura
     */

    private class InternalTestPropertyListener extends TestPropertyListenerAdapter {
        public void propertyRenamed(String oldName, String newName) {
            if (oldName.equals(sourceType)) {
                sourceType = newName;
                config.setSourceType(sourceType);
                propertyChangeSupport.firePropertyChange(SOURCE_TYPE_PROPERTY, oldName, sourceType);
            }

            if (oldName.equals(targetType)) {
                targetType = newName;
                config.setTargetType(targetType);
                propertyChangeSupport.firePropertyChange(TARGET_TYPE_PROPERTY, oldName, targetType);
            }
        }

        public void propertyRemoved(String name) {
            if (name.equals(sourceType)) {
                log.warn("source property for transfer [" + getName() + "] in teststep [" + testStep.getName() + "/"
                        + testStep.getTestCase().getName() + "/" + testStep.getTestCase().getTestSuite().getName()
                        + "] set to null, was [" + name + "]");

                currentSourceProperty = null;
                setSourcePropertyName(null);
            }

            if (name.equals(targetType)) {
                log.warn("target property for transfer [" + getName() + "] in teststep [" + testStep.getName() + "/"
                        + testStep.getTestCase().getName() + "/" + testStep.getTestCase().getTestSuite().getName()
                        + "] set to null, was [" + name + "]");

                currentTargetProperty = null;
                setTargetPropertyName(null);
            }
        }
    }

    @SuppressWarnings("unchecked")
    public void resolve(ResolveContext<?> context, PropertyTransfersTestStep parent) {
        if (isDisabled()) {
            return;
        }

        if (getSourceProperty() == null) {
            if (context.hasThisModelItem(parent, "Resolve source property", getConfig().getSourceStep())) {
                return;
            }
            context.addPathToResolve(parent, "Resolve source property", getConfig().getSourceStep()).addResolvers(
                    new DisablePropertyTransferResolver(this), new CreateMissingPropertyResolver(this, parent),
                    new ChooseAnotherPropertySourceResolver(this, parent));
        } else {
            if (context.hasThisModelItem(parent, "Resolve source property", getConfig().getSourceStep())) {
                PathToResolve path = context.getPath(parent, "Resolve source property", getConfig().getSourceStep());
                path.setSolved(true);
            }
        }

        if (getTargetProperty() == null) {
            if (context.hasThisModelItem(parent, "Resolve target property", getConfig().getTargetStep())) {
                return;
            }
            context.addPathToResolve(parent, "Resolve target property", getConfig().getTargetStep()).addResolvers(
                    new DisablePropertyTransferResolver(this), new CreateMissingPropertyResolver(this, parent),
                    new ChooseAnotherPropertyTargetResolver(this, parent));
        } else {
            if (context.hasThisModelItem(parent, "Resolve target property", getConfig().getTargetStep())) {
                PathToResolve path = context.getPath(parent, "Resolve target property", getConfig().getTargetStep());
                path.setSolved(true);
            }
        }

    }
}
TOP

Related Classes of com.eviware.soapui.impl.wsdl.teststeps.PropertyTransfer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.