org.flowable.cmmn.converter.ExtensionElementsXMLConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.flowable.cmmn.converter.ExtensionElementsXMLConverter.java

Source

/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.flowable.cmmn.converter;

import static org.flowable.cmmn.converter.CmmnXmlConstants.ATTRIBUTE_CLASS;
import static org.flowable.cmmn.converter.CmmnXmlConstants.ATTRIBUTE_DELEGATE_EXPRESSION;
import static org.flowable.cmmn.model.ImplementationType.IMPLEMENTATION_TYPE_CLASS;
import static org.flowable.cmmn.model.ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION;

import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamReader;

import org.apache.commons.lang3.StringUtils;
import org.flowable.cmmn.converter.exception.XMLException;
import org.flowable.cmmn.converter.util.CmmnXmlUtil;
import org.flowable.cmmn.converter.util.ListenerXmlConverterUtil;
import org.flowable.cmmn.model.AbstractFlowableHttpHandler;
import org.flowable.cmmn.model.BaseElement;
import org.flowable.cmmn.model.CmmnElement;
import org.flowable.cmmn.model.CompletionNeutralRule;
import org.flowable.cmmn.model.DecisionTask;
import org.flowable.cmmn.model.ExtensionElement;
import org.flowable.cmmn.model.FieldExtension;
import org.flowable.cmmn.model.FlowableHttpRequestHandler;
import org.flowable.cmmn.model.FlowableHttpResponseHandler;
import org.flowable.cmmn.model.FlowableListener;
import org.flowable.cmmn.model.HttpServiceTask;
import org.flowable.cmmn.model.HumanTask;
import org.flowable.cmmn.model.IOParameter;
import org.flowable.cmmn.model.PlanItemControl;
import org.flowable.cmmn.model.PlanItemDefinition;
import org.flowable.cmmn.model.ProcessTask;
import org.flowable.cmmn.model.ServiceTask;
import org.flowable.common.engine.api.FlowableException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Tijs Rademakers
 * @author Joram Barrez
 */
public class ExtensionElementsXMLConverter extends CaseElementXmlConverter {

    protected static final Logger LOGGER = LoggerFactory.getLogger(ExtensionElementsXMLConverter.class);

    @Override
    public String getXMLElementName() {
        return CmmnXmlConstants.ELEMENT_EXTENSION_ELEMENTS;
    }

    @Override
    public boolean hasChildElements() {
        return false;
    }

    @Override
    protected CmmnElement convert(XMLStreamReader xtr, ConversionHelper conversionHelper) {

        boolean readyWithChildElements = false;
        try {

            while (!readyWithChildElements && xtr.hasNext()) {
                xtr.next();
                if (xtr.isStartElement()) {
                    if (CmmnXmlConstants.ELEMENT_COMPLETION_NEUTRAL_RULE.equals(xtr.getLocalName())) {
                        readCompletionNeutralRule(xtr, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_FIELD.equals(xtr.getLocalName())) {
                        readFieldExtension(xtr, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_HTTP_REQUEST_HANDLER.equals(xtr.getLocalName())) {
                        readHttpRequestHandler(xtr, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_HTTP_RESPONSE_HANDLER.equals(xtr.getLocalName())) {
                        readHttpResponseHandler(xtr, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_PROCESS_TASK_IN_PARAMETERS.equals(xtr.getLocalName())) {
                        readIOParameter(xtr, true, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_PROCESS_TASK_OUT_PARAMETERS.equals(xtr.getLocalName())) {
                        readIOParameter(xtr, false, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_TASK_LISTENER.equals(xtr.getLocalName())) {
                        readTaskListener(xtr, conversionHelper);

                    } else if (CmmnXmlConstants.ELEMENT_PLAN_ITEM_LIFECYCLE_LISTENER.equals(xtr.getLocalName())) {
                        readLifecycleListener(xtr, conversionHelper);

                    } else {
                        ExtensionElement extensionElement = CmmnXmlUtil.parseExtensionElement(xtr);
                        conversionHelper.getCurrentCmmnElement().addExtensionElement(extensionElement);
                    }

                } else if (xtr.isEndElement()) {
                    if (CmmnXmlConstants.ELEMENT_TASK_LISTENER.equalsIgnoreCase(xtr.getLocalName())
                            || CmmnXmlConstants.ELEMENT_PLAN_ITEM_LIFECYCLE_LISTENER
                                    .equalsIgnoreCase(xtr.getLocalName())) {
                        conversionHelper.removeCurrentCmmnElement();
                    } else if (CmmnXmlConstants.ELEMENT_EXTENSION_ELEMENTS.equalsIgnoreCase(xtr.getLocalName())) {
                        readyWithChildElements = true;
                    }
                }

            }
        } catch (Exception ex) {
            LOGGER.error("Error processing CMMN document", ex);
            throw new XMLException("Error processing CMMN document", ex);
        }

        return null;
    }

    protected void readCompletionNeutralRule(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        if (conversionHelper.getCurrentCmmnElement() instanceof PlanItemControl) {
            CompletionNeutralRule completionNeutralRule = new CompletionNeutralRule();
            completionNeutralRule.setName(xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_NAME));

            PlanItemControl planItemControl = (PlanItemControl) conversionHelper.getCurrentCmmnElement();
            planItemControl.setCompletionNeutralRule(completionNeutralRule);

            readCommonXmlInfo(completionNeutralRule, xtr);

            boolean readyWithChildElements = false;
            try {

                while (!readyWithChildElements && xtr.hasNext()) {
                    xtr.next();
                    if (xtr.isStartElement()) {
                        if (CmmnXmlConstants.ELEMENT_CONDITION.equals(xtr.getLocalName())) {
                            xtr.next();
                            if (xtr.isCharacters()) {
                                completionNeutralRule.setCondition(xtr.getText());
                            }
                            break;
                        }

                    } else if (xtr.isEndElement()) {
                        if (CmmnXmlConstants.ELEMENT_COMPLETION_NEUTRAL_RULE.equalsIgnoreCase(xtr.getLocalName())) {
                            readyWithChildElements = true;
                        }
                    }

                }
            } catch (Exception ex) {
                LOGGER.error("Error processing CMMN document", ex);
                throw new XMLException("Error processing CMMN document", ex);
            }
        }
    }

    protected void readFieldExtension(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement cmmnElement = conversionHelper.getCurrentCmmnElement();

        FieldExtension extension = new FieldExtension();
        extension.setFieldName(xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_NAME));

        String stringValueAttribute = xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_FIELD_STRING);
        String expressionAttribute = xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_FIELD_EXPRESSION);
        if (StringUtils.isNotEmpty(stringValueAttribute)) {
            extension.setStringValue(stringValueAttribute);

        } else if (StringUtils.isNotEmpty(expressionAttribute)) {
            extension.setExpression(expressionAttribute);

        } else {
            boolean readyWithFieldExtension = false;
            try {
                while (!readyWithFieldExtension && xtr.hasNext()) {
                    xtr.next();
                    if (xtr.isStartElement()
                            && CmmnXmlConstants.ELEMENT_FIELD_STRING.equalsIgnoreCase(xtr.getLocalName())) {
                        extension.setStringValue(xtr.getElementText().trim());

                    } else if (xtr.isStartElement()
                            && CmmnXmlConstants.ELEMENT_FIELD_EXPRESSION.equalsIgnoreCase(xtr.getLocalName())) {
                        extension.setExpression(xtr.getElementText().trim());

                    } else if (xtr.isEndElement()
                            && CmmnXmlConstants.ELEMENT_FIELD.equalsIgnoreCase(xtr.getLocalName())) {
                        readyWithFieldExtension = true;
                    }
                }
            } catch (Exception e) {
                LOGGER.warn("Error parsing field extension child elements", e);
            }
        }

        CmmnElement currentCmmnElement = conversionHelper.getCurrentCmmnElement();
        if (currentCmmnElement instanceof ServiceTask) {
            ((ServiceTask) currentCmmnElement).getFieldExtensions().add(extension);

        } else if (currentCmmnElement instanceof DecisionTask) {
            ((DecisionTask) currentCmmnElement).getFieldExtensions().add(extension);
        } else if (currentCmmnElement instanceof FlowableListener) {
            ((FlowableListener) currentCmmnElement).getFieldExtensions().add(extension);

        } else {
            throw new FlowableException("Programmatic error: field added to unkown element " + currentCmmnElement);

        }
    }

    protected void readHttpRequestHandler(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement cmmnElement = conversionHelper.getCurrentCmmnElement();
        if (!(cmmnElement instanceof HttpServiceTask)) {
            return;
        }

        FlowableHttpRequestHandler requestHandler = new FlowableHttpRequestHandler();
        setImplementation(xtr, requestHandler);

        ((HttpServiceTask) cmmnElement).setHttpRequestHandler(requestHandler);
    }

    protected void readHttpResponseHandler(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement cmmnElement = conversionHelper.getCurrentCmmnElement();
        if (!(cmmnElement instanceof HttpServiceTask)) {
            return;
        }

        FlowableHttpResponseHandler responseHandler = new FlowableHttpResponseHandler();
        setImplementation(xtr, responseHandler);

        ((HttpServiceTask) cmmnElement).setHttpResponseHandler(responseHandler);
    }

    protected void readIOParameter(XMLStreamReader xtr, boolean isInParameter, ConversionHelper conversionHelper) {
        if (!(conversionHelper.getCurrentCmmnElement() instanceof ProcessTask)) {
            return;
        }

        ProcessTask processTask = (ProcessTask) conversionHelper.getCurrentCmmnElement();
        String source = xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_IOPARAMETER_SOURCE);
        String sourceExpression = xtr.getAttributeValue(null,
                CmmnXmlConstants.ATTRIBUTE_IOPARAMETER_SOURCE_EXPRESSION);
        String target = xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_IOPARAMETER_TARGET);
        String targetExpression = xtr.getAttributeValue(null,
                CmmnXmlConstants.ATTRIBUTE_IOPARAMETER_TARGET_EXPRESSION);

        IOParameter parameter = new IOParameter();

        if (StringUtils.isNotEmpty(sourceExpression)) {
            parameter.setSourceExpression(sourceExpression);
        } else {
            parameter.setSource(source);
        }

        if (StringUtils.isNotEmpty(targetExpression)) {
            parameter.setTargetExpression(targetExpression);
        } else {
            parameter.setTarget(target);
        }

        if (isInParameter) {
            processTask.getInParameters().add(parameter);
        } else {
            processTask.getOutParameters().add(parameter);
        }
    }

    protected void readTaskListener(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement currentCmmnElement = conversionHelper.getCurrentCmmnElement(); // needs to be captured before setting the flowable listeners as this will change the current element

        FlowableListener flowableListener = ListenerXmlConverterUtil.convertToListener(xtr);
        if (flowableListener != null) {
            if (currentCmmnElement instanceof HumanTask) {
                HumanTask humanTask = (HumanTask) currentCmmnElement;
                humanTask.getTaskListeners().add(flowableListener);
            } else {
                throw new FlowableException(
                        "Programmatic error: task listener added to an element that is not a human task, but a "
                                + currentCmmnElement.getClass());
            }
        }

        conversionHelper.setCurrentCmmnElement(flowableListener);
    }

    protected void readLifecycleListener(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement currentCmmnElement = conversionHelper.getCurrentCmmnElement(); // needs to be captured before setting the flowable listeners as this will change the current element

        FlowableListener flowableListener = ListenerXmlConverterUtil.convertToListener(xtr);
        if (flowableListener != null) {
            if (currentCmmnElement instanceof PlanItemDefinition) {
                PlanItemDefinition planItemDefinition = (PlanItemDefinition) currentCmmnElement;
                planItemDefinition.getLifecycleListeners().add(flowableListener);
            } else {
                throw new FlowableException(
                        "Programmatic error: task listener added to an element that is not a plan item definition, but a "
                                + currentCmmnElement.getClass());
            }
        }

        conversionHelper.setCurrentCmmnElement(flowableListener);

    }

    protected void setImplementation(XMLStreamReader xtr, AbstractFlowableHttpHandler handler) {
        if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_CLASS))) {
            handler.setImplementation(xtr.getAttributeValue(null, ATTRIBUTE_CLASS));
            handler.setImplementationType(IMPLEMENTATION_TYPE_CLASS);

        } else if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_DELEGATE_EXPRESSION))) {
            handler.setImplementation(xtr.getAttributeValue(null, ATTRIBUTE_DELEGATE_EXPRESSION));
            handler.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        }
    }

    protected void readCommonXmlInfo(BaseElement baseElement, XMLStreamReader xtr) {
        baseElement.setId(xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_ID));
        Location location = xtr.getLocation();
        baseElement.setXmlRowNumber(location.getLineNumber());
        baseElement.setXmlRowNumber(location.getColumnNumber());
    }

}