Package org.drools.ruleflow.core.impl

Source Code of org.drools.ruleflow.core.impl.RuleFlowProcessValidatorImpl

package org.drools.ruleflow.core.impl;

/*
* Copyright 2005 JBoss Inc
*
* 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.
*/

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.drools.ruleflow.core.ActionNode;
import org.drools.ruleflow.core.Connection;
import org.drools.ruleflow.core.EndNode;
import org.drools.ruleflow.core.Join;
import org.drools.ruleflow.core.MilestoneNode;
import org.drools.ruleflow.core.Node;
import org.drools.ruleflow.core.RuleFlowProcess;
import org.drools.ruleflow.core.RuleFlowProcessValidationError;
import org.drools.ruleflow.core.RuleFlowProcessValidator;
import org.drools.ruleflow.core.RuleSetNode;
import org.drools.ruleflow.core.Split;
import org.drools.ruleflow.core.StartNode;
import org.drools.ruleflow.core.SubFlowNode;
import org.drools.ruleflow.core.Variable;
import org.mvel.ExpressionCompiler;
import org.mvel.ParserContext;

/**
* Default implementation of a RuleFlow validator.
*
* @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
*/
public class RuleFlowProcessValidatorImpl
    implements
    RuleFlowProcessValidator {

    private static RuleFlowProcessValidatorImpl instance;

    private RuleFlowProcessValidatorImpl() {
    }

    public static RuleFlowProcessValidatorImpl getInstance() {
        if ( instance == null ) {
            instance = new RuleFlowProcessValidatorImpl();
        }
        return instance;
    }

    public RuleFlowProcessValidationError[] validateProcess(final RuleFlowProcess process) {
        final List errors = new ArrayList();

        if ( process.getName() == null ) {
            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.NO_PROCESS_NAME ) );
        }

        if ( process.getId() == null || "".equals( process.getId() ) ) {
            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.NO_PROCESS_ID ) );
        }

        if ( process.getPackageName() == null || "".equals( process.getPackageName() ) ) {
            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.NO_PACKAGE_NAME ) );
        }

        // check start node of process
        if ( process.getStart() == null ) {
            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.NO_START_NODE ) );
        }

        boolean startNodeFound = false;
        boolean endNodeFound = false;
        final Node[] nodes = process.getNodes();
        for ( int i = 0; i < nodes.length; i++ ) {
            final Node node = nodes[i];
            if ( node instanceof StartNode ) {
                final StartNode startNode = (StartNode) node;
                startNodeFound = true;
                if ( startNode.getTo() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.START_NODE_WITHOUT_OUTGOING_NODES ) );
                }
            } else if ( node instanceof EndNode ) {
                final EndNode endNode = (EndNode) node;
                endNodeFound = true;
                if ( endNode.getFrom() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.END_NODE_HAS_NO_INCOMING_CONNECTIONS ) );
                }
            } else if ( node instanceof RuleSetNode ) {
                final RuleSetNode ruleSetNode = (RuleSetNode) node;
                if ( ruleSetNode.getFrom() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.RULE_SET_NODE_WITHOUT_INCOMING_CONNECTIONS, "name = " + ruleSetNode.getName() ) );
                }

                if ( ruleSetNode.getTo() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.RULE_SET_NODE_WITHOUT_OUTGOING_CONNECTIONS, "name = " + ruleSetNode.getName() ) );
                }
                final String ruleFlowGroup = ruleSetNode.getRuleFlowGroup();
                if ( ruleFlowGroup == null || "".equals( ruleFlowGroup ) ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.RULE_SET_NODE_WITHOUT_RULE_SET_GROUP, "name = " + ruleSetNode.getName() ) );
                }
            } else if ( node instanceof Split ) {
                final Split split = (Split) node;
                if ( split.getType() == Split.TYPE_UNDEFINED ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SPLIT_WITHOUT_TYPE, "name = " + split.getName() ) );
                }
                if ( split.getFrom() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SPLIT_WITHOUT_INCOMING_CONNECTION, "name = " + split.getName() ) );
                }
                if ( split.getOutgoingConnections().size() < 2 ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SPLIT_NOT_ENOUGH_OUTGOING_CONNECTIONS, "name = " + split.getName() ) );
                }
                if ( split.getType() == Split.TYPE_XOR || split.getType() == Split.TYPE_OR ) {
                    for ( final Iterator it = split.getOutgoingConnections().iterator(); it.hasNext(); ) {
                        final Connection connection = (Connection) it.next();
                        if ( split.getConstraint( connection ) == null ) {
                            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SPLIT_OUTGOING_CONNECTION_WITHOUT_CONSTRAINT, "name = " + split.getName() ) );
                        }
                    }
                }
            } else if ( node instanceof Join ) {
                final Join join = (Join) node;
                if ( join.getType() == Join.TYPE_UNDEFINED ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.JOIN_WITHOUT_TYPE, "name = " + join.getName() ) );
                }
                if ( join.getIncomingConnections().size() < 2 ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.JOIN_NOT_ENOUGH_INCOMING_CONNECTIONS, "name = " + join.getName() ) );
                }
                if ( join.getTo() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.JOIN_WITHOUT_OUTGOING_CONNECTION, "name = " + join.getName() ) );
                }
            } else if ( node instanceof MilestoneNode ) {
                final MilestoneNode milestone = (MilestoneNode) node;
                if ( milestone.getFrom() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.MILESTONE_NODE_WITHOUT_INCOMING_CONNECTIONS, "name = " + milestone.getName() ) );
                }

                if ( milestone.getTo() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.MILESTONE_NODE_WITHOUT_OUTGOING_CONNECTIONS, "name = " + milestone.getName() ) );
                }
                if ( milestone.getConstraint() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.MILESTONE_WITHOUT_CONSTRAINT, "name = " + milestone.getName() ) );
                }
            } else if ( node instanceof SubFlowNode ) {
                final SubFlowNode subFlow = (SubFlowNode) node;
                if ( subFlow.getFrom() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SUBFLOW_NODE_WITHOUT_INCOMING_CONNECTIONS, "name = " + subFlow.getName() ) );
                }

                if ( subFlow.getTo() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SUBFLOW_NODE_WITHOUT_OUTGOING_CONNECTIONS, "name = " + subFlow.getName() ) );
                }
                if ( subFlow.getProcessId() == null ) {
                   errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.SUBFLOW_WITHOUT_PROCESS_ID, "name = " + subFlow.getName() ) );
                }
            } else if ( node instanceof ActionNode ) {
                final ActionNode actionNode = (ActionNode) node;
                if ( actionNode.getFrom() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ACTION_NODE_WITHOUT_INCOMING_CONNECTIONS, "name = " + actionNode.getName() ) );
                }

                if ( actionNode.getTo() == null ) {
                    errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ACTION_NODE_WITHOUT_OUTGOING_CONNECTIONS, "name = " + actionNode.getName() ) );
                }
                if ( actionNode.getAction() == null ) {
                   errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ACTION_NODE_WITHOUT_ACTION, "name = " + actionNode.getName() ) );
                } else {
                  if (actionNode.getAction() instanceof DroolsConsequenceAction) {
                    DroolsConsequenceAction droolsAction = (DroolsConsequenceAction) actionNode.getAction();
                    String actionString = droolsAction.getConsequence();
                    if (actionString == null) {
                      errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ACTION_NODE_WITHOUT_ACTION, "name = " + actionNode.getName() ) );
                    } else {
                        try {
                          ExpressionCompiler compiler = new ExpressionCompiler(actionString);
                          compiler.setVerifying(true);
                        ParserContext parserContext = new ParserContext();
                        //parserContext.setStrictTypeEnforcement(true);
                        compiler.compile(parserContext);
                        List mvelErrors = parserContext.getErrorList();
                        if (mvelErrors != null) {
                          for (Iterator iterator = mvelErrors.iterator(); iterator.hasNext(); ) {
                            Object error = iterator.next();
                            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ACTION_NODE_WITH_INVALID_ACTION, "name = " + actionNode.getName() + " " + error ) );
                          }
                        }
                        } catch (Throwable t) {
                          errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ACTION_NODE_WITH_INVALID_ACTION, "name = " + actionNode.getName() + " " + t.getMessage() ) );
                        }
                    }
                  }
                }
            }
        }
        if ( !startNodeFound ) {
            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.NO_START_NODE ) );
        }
        if ( !endNodeFound ) {
            errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.NO_END_NODE ) );
        }
        for ( final Iterator it = process.getVariables().iterator(); it.hasNext(); ) {
            final Variable variable = (Variable) it.next();
            if ( variable.getType() == null ) {
                errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.VARIABLE_WITHOUT_TYPE, "name = " + variable.getName() ) );
            }
        }

        checkAllNodesConnectedToStart( process,
                                       errors );

        return (RuleFlowProcessValidationError[]) errors.toArray( new RuleFlowProcessValidationError[errors.size()] );
    }

    private void checkAllNodesConnectedToStart(final RuleFlowProcess process,
                                               final List errors) {
        final Map processNodes = new HashMap();
        final Node[] nodes = process.getNodes();
        for ( int i = 0; i < nodes.length; i++ ) {
            final Node node = nodes[i];
            processNodes.put( node,
                              Boolean.FALSE );
        }

        final Node start = process.getStart();
        if ( start != null ) {
            processNode( start,
                         processNodes );
        }

        for ( final Iterator it = processNodes.keySet().iterator(); it.hasNext(); ) {
            final Node node = (Node) it.next();
            if ( Boolean.FALSE.equals( processNodes.get( node ) ) ) {
                errors.add( new RuleFlowProcessValidationErrorImpl( RuleFlowProcessValidationError.ALL_NODES_CONNECTED_TO_START, "name = " + node.getName() ) );
            }
        }
    }

    private void processNode(final Node node,
                             final Map nodes) {
        if ( !nodes.containsKey( node ) ) {
            throw new IllegalStateException( "A process node is connected with a node that does not belong to the process." );
        }
        final Boolean prevValue = (Boolean) nodes.put( node,
                                                       Boolean.TRUE );
        if ( prevValue == Boolean.FALSE ) {
            for ( final Iterator it = node.getOutgoingConnections().iterator(); it.hasNext(); ) {
                final Connection connection = (Connection) it.next();
                processNode( connection.getTo(),
                             nodes );
            }
        }
    }

}
TOP

Related Classes of org.drools.ruleflow.core.impl.RuleFlowProcessValidatorImpl

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.