Package org.jbpm.designer.bpmn2.validation

Source Code of org.jbpm.designer.bpmn2.validation.BPMN2SyntaxChecker

package org.jbpm.designer.bpmn2.validation;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import bpsim.*;
import bpsim.impl.BpsimFactoryImpl;
import org.drools.core.xml.SemanticModules;
import org.eclipse.bpmn2.*;
import org.eclipse.bpmn2.Process;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.jboss.drools.impl.DroolsFactoryImpl;
import org.jbpm.bpmn2.xml.BPMNDISemanticModule;
import org.jbpm.bpmn2.xml.BPMNSemanticModule;
import org.jbpm.compiler.xml.XmlProcessReader;
import org.jbpm.designer.repository.Repository;
import org.jbpm.designer.web.profile.IDiagramProfile;
import org.jbpm.process.core.validation.ProcessValidationError;
import org.jbpm.ruleflow.core.validation.RuleFlowProcessValidator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class BPMN2SyntaxChecker implements SyntaxChecker {
    public static final String BPMN2_TYPE = "BPMN2";
    public static final String SIMULATION_TYPE = "Simulation";
    public static final String PROCESS_TYPE = "Process";
    private static final Logger _logger = LoggerFactory.getLogger(BPMN2SyntaxChecker.class);

  protected Map<String, List<ValidationSyntaxError>> errors = new HashMap<String, List<ValidationSyntaxError>>();
  private String json;
  private String preprocessingData;
  private IDiagramProfile profile;
  private String defaultResourceId = "processerrors";
  private String uuid;
    private Repository repository;
 
  public BPMN2SyntaxChecker(String json, String preprocessingData, IDiagramProfile profile, String uuid) {
    this.json = json;
    this.preprocessingData = preprocessingData;
    this.profile = profile;
    this.uuid = uuid;
        this.repository = profile.getRepository();
  }
 
  public void checkSyntax() {
    DroolsFactoryImpl.init();
        BpsimFactoryImpl.init();

        try {
            Definitions def = profile.createMarshaller().getDefinitions(json, preprocessingData);
            List<RootElement> rootElements =  def.getRootElements();
            Scenario defaultScenario = getDefaultScenario(def);

            for(RootElement root : rootElements) {
                if(root instanceof Process) {
                    Process process = (Process) root;
                    if(process.getFlowElements() != null && process.getFlowElements().size() > 0) {
                        defaultResourceId = process.getFlowElements().get(0).getId();
                    }

                    if(isEmpty(process.getId())) {
                        addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE, "Process has no id."));
                    } else {
                        if(!SyntaxCheckerUtils.isNCName(process.getId())) {
                            addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Invalid process id. See http://www.w3.org/TR/REC-xml-names/#NT-NCName for more info."));
                        }
                    }

                    String pname;
                    Iterator<FeatureMap.Entry> iter = process.getAnyAttribute().iterator();
                    boolean foundPackageName = false;
                    while(iter.hasNext()) {
                        FeatureMap.Entry entry = iter.next();
                        if(entry.getEStructuralFeature().getName().equals("packageName")) {
                            foundPackageName = true;
                            pname = (String) entry.getValue();
                            if(isEmpty(pname)) {
                                addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Process has no package name."));
                            }
                            if(!isValidPackageName(pname)) {
                                addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Package name contains invalid characters."));
                            }
                        }
                    }
                    if(!foundPackageName) {
                        addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Process has no package name."));
                    }

                    if(isEmpty(process.getName())) {
                        addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Process has no name."));
                    }

                    List<Property> processProperties = process.getProperties();
                    if(processProperties != null && processProperties.size() > 0) {
                        for(Property prop : processProperties) {
                            String propId = prop.getId();
                            Pattern pattern = Pattern.compile("\\s");
                            Matcher matcher = pattern.matcher(propId);
                            if(matcher.find()) {
                                addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Process variable \"" + propId + "\" contains white spaces."));
                            }
                        }
                    }

                    boolean foundStartEvent = false;
                    boolean foundEndEvent = false;
                    List<FlowElement> flowElements =  process.getFlowElements();
                    for(FlowElement fe : flowElements) {
                        if(fe instanceof StartEvent) {
                            foundStartEvent = true;
                        }
                        if(fe instanceof EndEvent) {
                            foundEndEvent = true;
                        }
                    }
                    if(!foundStartEvent && !isAdHocProcess(process)) {
                        addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE,  "Process has no start node."));
                    }
                    if(!foundEndEvent && !isAdHocProcess(process)) {
                        addError(defaultResourceId, new ValidationSyntaxError(process, BPMN2_TYPE, "Process has no end node."));
                    }

                    checkFlowElements(process, process, defaultScenario);
                }
            }
        } catch(Exception e) {
            addError(defaultResourceId, new ValidationSyntaxError(null, PROCESS_TYPE, "Could not parse BPMN2 process."));
        }

        // if there are no suggestions add RuleFlowProcessValidator process errors
        if(this.errors.size() < 1) {
            try {
                SemanticModules modules = new SemanticModules();
                modules.addSemanticModule(new BPMNSemanticModule());
                modules.addSemanticModule(new BPMNDISemanticModule());
                XmlProcessReader xmlReader = new XmlProcessReader(modules, getClass().getClassLoader());
                List<org.kie.api.definition.process.Process> processes = xmlReader.read(new StringReader(profile.createMarshaller().parseModel(json, preprocessingData)));
                if(processes != null) {
                    ProcessValidationError[] errors = RuleFlowProcessValidator.getInstance().validateProcess((org.jbpm.ruleflow.core.RuleFlowProcess) processes.get(0));
                    for(ProcessValidationError er : errors) {
                        addError(defaultResourceId, new ValidationSyntaxError(null, PROCESS_TYPE, er.getMessage()));
                    }
                }
            } catch(Exception e) {
                _logger.warn("Could not parse to RuleFlowProcess.");
                addError(defaultResourceId, new ValidationSyntaxError(null, PROCESS_TYPE, "Could not parse BPMN2 to RuleFlowProcess."));
            }
        }

    }
 
  private void checkFlowElements(FlowElementsContainer container, Process process, Scenario defaultScenario) {
   
    for(FlowElement fe : container.getFlowElements()) {
      if(fe instanceof StartEvent) {
        StartEvent se = (StartEvent) fe;
        if(se.getOutgoing() == null || se.getOutgoing().size() < 1) {
                    if(container instanceof Process) {
                        if(!isAdHocProcess(process)) {
                            addError(se, new ValidationSyntaxError(se, BPMN2_TYPE,  "Start node has no outgoing connections"));
                        }
                    } else if(container instanceof SubProcess) {
                        if(!(container instanceof AdHocSubProcess)) {
                            addError(se, new ValidationSyntaxError(se, BPMN2_TYPE,  "Start node has no outgoing connections"));
                        }
                    } else {
                        addError(se, new ValidationSyntaxError(se, BPMN2_TYPE,  "Start node has no outgoing connections"));
                    }
        }
      } else if (fe instanceof EndEvent) {
        EndEvent ee = (EndEvent) fe;
        if(ee.getIncoming() == null || ee.getIncoming().size() < 1) {
                    if(container instanceof Process) {
                        if(!isAdHocProcess(process)) {
                            addError(ee, new ValidationSyntaxError(ee, BPMN2_TYPE,  "End node has no incoming connections"));
                        }
                    } else if(container instanceof SubProcess) {
                        if(!(container instanceof AdHocSubProcess)) {
                            addError(ee, new ValidationSyntaxError(ee, BPMN2_TYPE,  "End node has no incoming connections"));
                        }
                    } else {
                        addError(ee, new ValidationSyntaxError(ee, BPMN2_TYPE,  "End node has no incoming connections"));
                    }
        }
      } else {
        if(fe instanceof FlowNode) {
          FlowNode fn = (FlowNode) fe;
          if((fn.getOutgoing() == null || fn.getOutgoing().size() < 1) && !isAdHocProcess(process) && !(fn instanceof BoundaryEvent) && !(fn instanceof EventSubprocess)) {
                        if(container instanceof Process) {
                            if(!isAdHocProcess(process)) {
                                if(!isCompensatingFlowNodeInProcess(fn, (Process) container)) {
                                    addError(fn, new ValidationSyntaxError(fn, BPMN2_TYPE, "Node has no outgoing connections"));
                                }
                            }
                        } else if(container instanceof SubProcess) {
                            if(!(container instanceof AdHocSubProcess)) {
                                if(!isCompensatingFlowNodeInSubprocess(fn, (SubProcess) container)) {
                                    addError(fn, new ValidationSyntaxError(fn, BPMN2_TYPE, "Node has no outgoing connections"));
                                }
                            }
                        } else {
                            addError(fn, new ValidationSyntaxError(fn, BPMN2_TYPE, "Node has no outgoing connections"));
                        }
            }
                    if(!(fn instanceof BoundaryEvent)) {
                        if((fn.getIncoming() == null || fn.getIncoming().size() < 1) && !isAdHocProcess(process)) {
                            if(container instanceof Process) {
                                if(!isAdHocProcess(process) && !(fn instanceof EventSubprocess)) {
                                    if(!isCompensatingFlowNodeInProcess(fn, (Process) container)) {
                                        addError(fn, new ValidationSyntaxError(fn, BPMN2_TYPE, "Node has no incoming connections"));
                                    }
                                }
                            } else if(container instanceof SubProcess) {
                                if(!(container instanceof AdHocSubProcess)) {
                                    if(!isCompensatingFlowNodeInSubprocess(fn, (SubProcess) container)) {
                                        addError(fn, new ValidationSyntaxError(fn, BPMN2_TYPE, "Node has no incoming connections"));
                                    }
                                }
                            } else {
                                addError(fn, new ValidationSyntaxError(fn, BPMN2_TYPE, "Node has no incoming connections"));
                            }
                        }
                    }
        }
      }
     
      if(fe instanceof BusinessRuleTask) {
        BusinessRuleTask bt = (BusinessRuleTask) fe;
        Iterator<FeatureMap.Entry> biter = bt.getAnyAttribute().iterator();
        boolean foundRuleflowGroup = false;
              while(biter.hasNext()) {
                  FeatureMap.Entry entry = biter.next();
                  if(entry.getEStructuralFeature().getName().equals("ruleFlowGroup")) {
                    foundRuleflowGroup = true;
                    String ruleflowGroup = (String) entry.getValue();
                    if(isEmpty(ruleflowGroup)) {
                      addError(bt, new ValidationSyntaxError(bt, BPMN2_TYPE, "Business Rule Task has no ruleflow-group."));
                    }
                  }
              }
              if(!foundRuleflowGroup) {
                addError(bt, new ValidationSyntaxError(bt, BPMN2_TYPE, "Business Rule Task has no ruleflow-group."));
              }
      }
     
      if(fe instanceof ScriptTask) {
        ScriptTask st = (ScriptTask) fe;
        if(isEmpty(st.getScript())) {
          addError(st, new ValidationSyntaxError(st, BPMN2_TYPE, "Script Task has no script."));
        }
        if(isEmpty(st.getScriptFormat())) {
          addError(st, new ValidationSyntaxError(st, BPMN2_TYPE, "Script Task has no script format."));
        }
      }
     
      if(fe instanceof SendTask) {
        SendTask st = (SendTask) fe;
        if(st.getMessageRef() == null) {
          addError(st, new ValidationSyntaxError(st, BPMN2_TYPE, "Send Task has no message."));
        }
      }

            if(fe instanceof ServiceTask) {
                ServiceTask st = (ServiceTask) fe;
                if(st.getOperationRef() == null) {
                    addError(st, new ValidationSyntaxError(st, BPMN2_TYPE, "Service Task has no operation."));
                }
            }
     
      if(fe instanceof UserTask) {
        UserTask ut = (UserTask) fe;
        String taskName = null;
        Iterator<FeatureMap.Entry> utiter = ut.getAnyAttribute().iterator();
        boolean foundTaskName = false;


                if(ut.getIoSpecification() != null && ut.getIoSpecification().getDataInputs() != null) {
                    List<DataInput> taskDataInputs = ut.getIoSpecification().getDataInputs();
                    for(DataInput din : taskDataInputs) {
                        if(din.getName() != null && din.getName().equals("TaskName")) {
                            List<DataInputAssociation> taskDataInputAssociations = ut.getDataInputAssociations();
                            for(DataInputAssociation dia : taskDataInputAssociations) {
                                if(dia.getTargetRef().getId().equals(din.getId())) {
                                    foundTaskName = true;
                                    taskName = ((FormalExpression) dia.getAssignment().get(0).getFrom()).getBody();
                                    if(isEmpty(taskName)) {
                                        addError(ut, new ValidationSyntaxError(ut, BPMN2_TYPE, "User Task has no task name."));
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            if(!foundTaskName) {
              addError(ut, new ValidationSyntaxError(ut, BPMN2_TYPE, "User Task has no task name."));
            }
           
            // simulation validation
            if(defaultScenario != null && defaultScenario.getElementParameters() != null) {
              for(ElementParameters eleType : defaultScenario.getElementParameters()) {
                if(eleType.getElementRef().equals(ut.getId())) {
                  if(eleType.getResourceParameters() != null) {
                    ResourceParameters resourceParams = eleType.getResourceParameters();
                    if(resourceParams.getQuantity() != null) {
                      FloatingParameterType quantityVal = (FloatingParameterType) resourceParams.getQuantity().getParameterValue().get(0);
                      double val = quantityVal.getValue();
                      if(val < 0) {
                        addError(ut, new ValidationSyntaxError(ut, SIMULATION_TYPE, "Staff Availability value must be positive."));
                      }
                    }
                  }
                }
              }
            }
        }
     
      if(fe instanceof Task) {
        Task ta = (Task) fe;
       
        // simulation validation
        if(defaultScenario != null && defaultScenario.getElementParameters() != null) {
          for(ElementParameters eleType : defaultScenario.getElementParameters()) {
            if(eleType.getElementRef().equals(ta.getId())) {
                  if(eleType.getCostParameters() != null) {
                    CostParameters costParams = eleType.getCostParameters();
                    if(costParams.getUnitCost() != null) {
                      FloatingParameterType unitCostVal = (FloatingParameterType) costParams.getUnitCost().getParameterValue().get(0);
                      Double val = unitCostVal.getValue();
                      if(val.doubleValue() < 0) {
                        addError(ta, new ValidationSyntaxError(ta, SIMULATION_TYPE, "Cost per Time Unit value must be positive."));
                      }
                    }
                  }
                  if(eleType.getResourceParameters() != null) {
                    ResourceParameters resourceParams = eleType.getResourceParameters();
                    if(resourceParams.getQuantity() != null) {
                      FloatingParameterType workingHoursVal = (FloatingParameterType) resourceParams.getQuantity().getParameterValue().get(0);
                      if(workingHoursVal.getValue() < 0) {
                        addError(ta, new ValidationSyntaxError(ta, SIMULATION_TYPE, "Working Hours value must be positive."));
                      }
                    }
                  }
                }
          }
        }
      }
     
      if(fe instanceof CatchEvent) {
        CatchEvent event = (CatchEvent) fe;
        List<EventDefinition> eventdefs = event.getEventDefinitions();
        for(EventDefinition ed : eventdefs) {
            if(ed instanceof TimerEventDefinition) {
                      TimerEventDefinition ted = (TimerEventDefinition) ed;
                        if(ted.getTimeDate() != null && ted.getTimeDuration() != null && ted.getTimeCycle() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has timeDate and timeDuration and timeCycle defined."));
                        } else if(ted.getTimeDate() != null && ted.getTimeDuration() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has both timeDate and timeDuration defined."));
                        } else if(ted.getTimeDate() != null && ted.getTimeCycle() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has both timeDate and timeCycle defined."));
                        } else if(ted.getTimeDuration() != null && ted.getTimeCycle() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has both timeduration and timecycle defined."));
                        }

                        if(ted.getTimeDate() == null && ted.getTimeDuration() == null && ted.getTimeCycle() == null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has no timeDate or timeDuration or timeCycle defined."));
                        }
                  } else if( ed instanceof SignalEventDefinition) {
                      if(((SignalEventDefinition) ed).getSignalRef() == null) {
                        addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Event has no signalref."));
                      }
                  } else if( ed instanceof ErrorEventDefinition) {
                      if(((ErrorEventDefinition) ed).getErrorRef() == null || ((ErrorEventDefinition) ed).getErrorRef().getErrorCode() == null) {
                        addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Event has no errorref."));
                      }
                  } else if( ed instanceof ConditionalEventDefinition ) {
                      FormalExpression conditionalExp = (FormalExpression) ((ConditionalEventDefinition) ed).getCondition();
                      if(conditionalExp.getBody() == null) {
                        addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Event has no conditionexpression."));
                      }
                  } else if( ed instanceof EscalationEventDefinition ) {
                      if(((EscalationEventDefinition) ed).getEscalationRef() == null) {
                        addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Event has no escalationref."));
                      }
                  } else if( ed instanceof MessageEventDefinition) {
                      if(((MessageEventDefinition) ed).getMessageRef() == null) {
                          addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Event has no messageref."));
                      }
                  }
        }
      }
     
      if(fe instanceof ThrowEvent) {
        ThrowEvent event = (ThrowEvent) fe;
        List<EventDefinition> eventdefs = event.getEventDefinitions();
            for(EventDefinition ed : eventdefs) {
                if(ed instanceof TimerEventDefinition) {
                        TimerEventDefinition ted = (TimerEventDefinition) ed;
                        if(ted.getTimeDate() != null && ted.getTimeDuration() != null && ted.getTimeCycle() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has timeDate and timeDuration and timeCycle defined."));
                        } else if(ted.getTimeDate() != null && ted.getTimeDuration() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has both timeDate and timeDuration defined."));
                        } else if(ted.getTimeDate() != null && ted.getTimeCycle() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has both timeDate and timeCycle defined."));
                        } else if(ted.getTimeDuration() != null && ted.getTimeCycle() != null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has both timeduration and timecycle defined."));
                        }

                        if(ted.getTimeDate() == null && ted.getTimeDuration() == null && ted.getTimeCycle() == null) {
                            addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Catch Even has no timeDate or timeDuration or timeCycle defined."));
                        }
                } else if( ed instanceof SignalEventDefinition) {
                    if(((SignalEventDefinition) ed).getSignalRef() == null) {
                      addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Throw Event has no signalref."));
                    }
                } else if( ed instanceof ErrorEventDefinition) {
                    if(((ErrorEventDefinition) ed).getErrorRef() == null || ((ErrorEventDefinition) ed).getErrorRef().getErrorCode() == null) {
                      addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Throw Event has no errorref."));
                    }
                } else if( ed instanceof ConditionalEventDefinition ) {
                    FormalExpression conditionalExp = (FormalExpression) ((ConditionalEventDefinition) ed).getCondition();
                    if(conditionalExp.getBody() == null) {
                      addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Throw Event has no conditional expression."));
                    }
                } else if( ed instanceof EscalationEventDefinition ) {
                    if(((EscalationEventDefinition) ed).getEscalationRef() == null) {
                      addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Throw Event has no conditional escalationref."));
                    }
                } else if( ed instanceof MessageEventDefinition) {
                    if(((MessageEventDefinition) ed).getMessageRef() == null) {
                      addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Throw Event has no conditional messageref."));
                    }
                }  else if( ed instanceof CompensateEventDefinition) {
                    if(((CompensateEventDefinition) ed).getActivityRef() == null) {
                      addError(event, new ValidationSyntaxError(event, BPMN2_TYPE, "Throw Event has no conditional activityref."));
                    }
                } 
            }
      }
     
      if(fe instanceof SequenceFlow) {
        SequenceFlow sf = (SequenceFlow) fe;
        if(sf.getSourceRef() == null) {
          addError((SequenceFlow) fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "An Edge must have a source node."));
        }
        if(sf.getTargetRef() == null) {
          addError((SequenceFlow) fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "An Edge must have a target node."));
        }
      }
     
      if(fe instanceof Gateway) {
        Gateway gw = (Gateway) fe;
        if(gw.getGatewayDirection() == null || gw.getGatewayDirection().getValue() == GatewayDirection.UNSPECIFIED.getValue()) {
          addError((Gateway) fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Gateway does not specify a valid direction."));
        }
        if(gw instanceof ExclusiveGateway) {
          if(gw.getGatewayDirection().getValue() != GatewayDirection.DIVERGING.getValue() && gw.getGatewayDirection().getValue() != GatewayDirection.CONVERGING.getValue()) {
            addError(fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Invalid Gateway direction for Exclusing Gateway. It should be 'Converging' or 'Diverging'."));
          }
        }
        if(gw instanceof EventBasedGateway) {
          if(gw.getGatewayDirection().getValue() != GatewayDirection.DIVERGING.getValue()) {
            addError(fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Invalid Gateway direction for EventBased Gateway. It should be 'Diverging'."));
          }
        }
        if(gw instanceof ParallelGateway) {
          if(gw.getGatewayDirection().getValue() != GatewayDirection.DIVERGING.getValue() && gw.getGatewayDirection().getValue() != GatewayDirection.CONVERGING.getValue()) {
            addError(fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Invalid Gateway direction for Parallel Gateway. It should be 'Converging' or 'Diverging'."));
          }
        }
//        if(gw instanceof InclusiveGateway) {
//          if(gw.getGatewayDirection().getValue() != GatewayDirection.DIVERGING.getValue()) {
//            addError(fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Invalid Gateway direction for Inclusive Gateway. It should be 'Diverging'."));
//          }
//        }
        if(gw instanceof ComplexGateway) {
          if(gw.getGatewayDirection().getValue() != GatewayDirection.DIVERGING.getValue() && gw.getGatewayDirection().getValue() != GatewayDirection.CONVERGING.getValue()) {
            addError(fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Invalid Gateway direction for Complex Gateway. It should be 'Converging' or 'Diverging'."));
          }
        }

                if( (gw instanceof ExclusiveGateway || gw instanceof InclusiveGateway) && (gw.getGatewayDirection().getValue() == GatewayDirection.DIVERGING.getValue())) {
                    List<SequenceFlow> outgoingFlows = gw.getOutgoing();
                    if(outgoingFlows != null && outgoingFlows.size() > 0) {
                        for(SequenceFlow flow : outgoingFlows) {
                            if(flow.getConditionExpression() == null) {
                                addError(flow, new ValidationSyntaxError(flow, BPMN2_TYPE, "Sequence flow has no condition expression defined."));
                            } else {
                                if(flow.getConditionExpression() instanceof FormalExpression) {
                                    FormalExpression formalExp = (FormalExpression) flow.getConditionExpression();
                                    if(formalExp.getBody() == null && formalExp.getBody().length() < 1) {
                                        addError(flow, new ValidationSyntaxError(flow, BPMN2_TYPE, "Sequence flow has no condition expression defined."));
                                    }
                                } else {
                                    addError(flow, new ValidationSyntaxError(flow, BPMN2_TYPE, "Invalid condition expression on sequence flow."));
                                }
                            }
                        }
                    }
                }

        // simulation validation
        if(!(gw instanceof ParallelGateway)) {
          List<SequenceFlow> outgoingGwSequenceFlows = gw.getOutgoing();
          if(outgoingGwSequenceFlows != null && outgoingGwSequenceFlows.size() > 0) {
            double sum = 0;
            for(SequenceFlow sf : outgoingGwSequenceFlows) {
                    if(defaultScenario.getElementParameters() != null) {
                      for(ElementParameters eleType : defaultScenario.getElementParameters()) {
                        if(eleType.getElementRef().equals(sf.getId())) {
                          if(eleType.getControlParameters() != null && eleType.getControlParameters().getProbability() != null) {
                            FloatingParameterType valType = (FloatingParameterType) eleType.getControlParameters().getProbability().getParameterValue().get(0);
                                  if(valType.getValue() < 0) {
                                    addError(sf, new ValidationSyntaxError(sf, SIMULATION_TYPE, "Probability value must be positive."));
                                  } else {
                                    sum += valType.getValue();
                                  }
                          } else {
                            addError(sf, new ValidationSyntaxError(sf, SIMULATION_TYPE, "Sequence Flow has no probability defined."));
                          }
                        }
                      }
                    }
            }
            if(sum != 100) {
              addError(gw, new ValidationSyntaxError(gw, SIMULATION_TYPE, "The sum of probability values of all outgoing Sequence Flows must be equal 100."));
            }
          }
        }
      }
     
      if(fe instanceof CallActivity) {
        CallActivity ca = (CallActivity) fe;
        if(ca.getCalledElement() == null || ca.getCalledElement().length() < 1) {
          addError((CallActivity) fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Reusable Subprocess has no called element specified."));
        }
      }
     
      if(fe instanceof DataObject) {
        DataObject dao = (DataObject) fe;
        if(dao.getName() == null || dao.getName().length() < 1) {
          addError((DataObject) fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Data Object has no name defined."));
        } else {
          if(containsWhiteSpace(dao.getName())) {
            addError((DataObject) fe, new ValidationSyntaxError(fe, BPMN2_TYPE, "Data Object name contains white spaces."));
          }
        }
      }
     
      if(fe instanceof SubProcess) {
        checkFlowElements((SubProcess) fe, process, defaultScenario);
      }
    }
  }

  public Map<String, List<ValidationSyntaxError>> getErrors() {
    return errors;
  }

  public JSONObject getErrorsAsJson() {
    JSONObject jsonObject = new JSONObject();
    for (Entry<String, List<ValidationSyntaxError>> error: this.getErrors().entrySet()) {
      try {
                JSONArray errorsArray = new JSONArray();
                for(ValidationSyntaxError se : error.getValue()) {
                    errorsArray.put(se.toJSON());
                }
        jsonObject.put(error.getKey(), errorsArray);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    return jsonObject;
  }

  public boolean errorsFound() {
    return errors.size() > 0;
  }

  public void clearErrors() {
    errors.clear();
  }
 
  private void addError(BaseElement element, ValidationSyntaxError error) {
    addError(element.getId(), error);
  }
 
  private void addError(String resourceId, ValidationSyntaxError error) {
    if(errors.containsKey(resourceId) && errors.get(resourceId) != null) {
      errors.get(resourceId).add(error);
    } else {
      List<ValidationSyntaxError> value = new ArrayList<ValidationSyntaxError>();
      value.add(error);
      errors.put(resourceId, value);
    }
  }
 
  private static boolean isEmpty(final CharSequence str) {
    if ( str == null || str.length() == 0 ) {
      return true;
      }
      for ( int i = 0, length = str.length(); i < length; i++ ) {
        if ( str.charAt( i ) != ' ' ) {
          return false;
          }
      }
      return true;
  }
 
   
    private boolean isAdHocProcess(Process process) {
        Iterator<FeatureMap.Entry> iter = process.getAnyAttribute().iterator();
        while(iter.hasNext()) {
            FeatureMap.Entry entry = iter.next();
            if(entry.getEStructuralFeature().getName().equals("adHoc")) {
              return Boolean.parseBoolean(((String)entry.getValue()).trim());
            }
        }
        return false;
    }

    private boolean isCompensatingFlowNodeInSubprocess(FlowNode node, SubProcess subProcess ) {
        for(Artifact artifact : subProcess.getArtifacts()) {
            if (artifact instanceof Association){
                Association association = (Association) artifact;
                if (association.getTargetRef().getId().equals(node.getId())) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean isCompensatingFlowNodeInProcess(FlowNode node, Process process ) {
        for(Artifact artifact : process.getArtifacts()) {
            if (artifact instanceof Association){
                Association association = (Association) artifact;
                if (association.getTargetRef().getId().equals(node.getId())) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean containsWhiteSpace(String testString){
        if(testString != null){
            for(int i = 0; i < testString.length(); i++){
                if(Character.isWhitespace(testString.charAt(i))){
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isValidPackageName(String pkg) {
        Pattern p = Pattern.compile("^[a-zA-Z_\\$][\\w\\$]*(?:\\.[a-zA-Z_\\$][\\w\\$]*)*$");
        return p.matcher(pkg).matches();
    }
   
    private Scenario getDefaultScenario(Definitions def) {
      if(def.getRelationships() != null && def.getRelationships().size() > 0) {
          // current support for single relationship
          Relationship relationship = def.getRelationships().get(0);
          for(ExtensionAttributeValue extattrval : relationship.getExtensionValues()) {
                FeatureMap extensionElements = extattrval.getValue();
                @SuppressWarnings("unchecked")
                List<BPSimDataType> bpsimExtensions = (List<BPSimDataType>) extensionElements.get(BpsimPackage.Literals.DOCUMENT_ROOT__BP_SIM_DATA, true);
                if(bpsimExtensions != null && bpsimExtensions.size() > 0) {
                    BPSimDataType processAnalysis = bpsimExtensions.get(0);
                  if(processAnalysis.getScenario() != null && processAnalysis.getScenario().size() > 0) {
                    return processAnalysis.getScenario().get(0);
                  }
                }
          }
        }
      return null;
    }

    public class ValidationSyntaxError {
        private BaseElement element;
        private String error;
        private String type;

        public ValidationSyntaxError(BaseElement element, String type, String error) {
            this.element = element;
            this.error = error;
            this.type = type;
        }

        public JSONObject toJSON() throws JSONException {
            JSONObject errorJSON = new JSONObject();
            errorJSON.put("id", this.element == null ? "" : this.element.getId());
            errorJSON.put("type", type);
            errorJSON.put("error", this.error);

            return errorJSON;
        }

        public BaseElement getElement() {
            return this.element;
        }

        public String getError() {
            return this.error;
        }
    }
}
TOP

Related Classes of org.jbpm.designer.bpmn2.validation.BPMN2SyntaxChecker

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.