
com.effektif.workflow.impl.WorkflowParser Maven / Gradle / Ivy
/*
* Copyright 2014 Effektif GmbH.
*
* 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 com.effektif.workflow.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.effektif.workflow.api.Configuration;
import com.effektif.workflow.api.condition.Condition;
import com.effektif.workflow.api.model.RelativeTime;
import com.effektif.workflow.api.model.WorkflowId;
import com.effektif.workflow.api.types.DataType;
import com.effektif.workflow.api.workflow.AbstractWorkflow;
import com.effektif.workflow.api.workflow.Activity;
import com.effektif.workflow.api.workflow.Binding;
import com.effektif.workflow.api.workflow.Element;
import com.effektif.workflow.api.workflow.ExecutableWorkflow;
import com.effektif.workflow.api.workflow.MultiInstance;
import com.effektif.workflow.api.workflow.ParseIssue.IssueType;
import com.effektif.workflow.api.workflow.ParseIssues;
import com.effektif.workflow.api.workflow.Transition;
import com.effektif.workflow.api.workflow.Variable;
import com.effektif.workflow.impl.conditions.ConditionImpl;
import com.effektif.workflow.impl.conditions.ConditionService;
import com.effektif.workflow.impl.configuration.Brewery;
import com.effektif.workflow.impl.data.DataTypeService;
import com.effektif.workflow.impl.job.RelativeTimeImpl;
import com.effektif.workflow.impl.template.Hint;
import com.effektif.workflow.impl.template.TextTemplate;
import com.effektif.workflow.impl.workflow.ActivityImpl;
import com.effektif.workflow.impl.workflow.BindingImpl;
import com.effektif.workflow.impl.workflow.ExpressionImpl;
import com.effektif.workflow.impl.workflow.MultiInstanceImpl;
import com.effektif.workflow.impl.workflow.ScopeImpl;
import com.effektif.workflow.impl.workflow.TransitionImpl;
import com.effektif.workflow.impl.workflow.WorkflowImpl;
/** Validates and wires process definition after it's been built by either the builder api or json deserialization. */
public class WorkflowParser {
public static final String PROPERTY_LINE = "line";
public static final String PROPERTY_COLUMN = "column";
public static final Logger log = LoggerFactory.getLogger(WorkflowParser.class);
public Configuration configuration;
public WorkflowImpl workflow;
public LinkedList path;
public ParseIssues issues;
public Stack contextStack;
public Set activityIds = new HashSet<>();
public Set variableIds = new HashSet<>();
public Set transitionIds = new HashSet<>();
public WorkflowParseListener workflowParseListener;
public class ParseContext {
ParseContext(String property, Object element, Object elementImpl, Integer index) {
this.property = property;
this.element = element;
this.elementImpl = elementImpl;
String indexText = null;
if (element instanceof Element) {
indexText = getIdText(element);
}
if (indexText==null && index!=null) {
indexText = Integer.toString(index);
}
}
public Object element;
public String property;
public String index;
public Object elementImpl;
public String toString() {
if (index!=null) {
return property+"["+index+"]";
} else {
return property;
}
}
public Long getLine() {
if (element instanceof Element) {
Number line = (Number) ((Element)element).getProperty(PROPERTY_LINE);
return line!=null ? line.longValue() : null;
}
return null;
}
public Long getColumn() {
if (element instanceof Element) {
Number column = (Number) ((Element)element).getProperty(PROPERTY_COLUMN);
return column!=null ? column.longValue() : null;
}
return null;
}
}
public static String getIdText(Object object) {
if (object instanceof Activity) {
return ((Activity)object).getId();
} else if (object instanceof Transition) {
return ((Transition)object).getId();
} else if (object instanceof Variable) {
return ((Variable)object).getId();
} else if (object instanceof ExecutableWorkflow) {
WorkflowId workflowId = ((ExecutableWorkflow)object).getId();
return workflowId!=null ? workflowId.getInternal() : null;
}
return null;
}
public WorkflowParser(Configuration configuration) {
this.configuration = configuration;
this.path = new LinkedList<>();
this.contextStack = new Stack<>();
this.issues = new ParseIssues();
// this cast is necessary to get the workflow parse listener optional
// because the brewery.getOpt method is not available on the configuration itself
if (configuration instanceof DefaultConfiguration) {
DefaultConfiguration defaultConfiguration = (DefaultConfiguration)configuration;
Brewery brewery = defaultConfiguration.getBrewery();
this.workflowParseListener = brewery.getOpt(WorkflowParseListener.class);
}
}
/**
* Parses the content of workflowApi
into workflowImpl
and
* adds any parse issues to workflowApi
.
* Use one parser for each parse.
*/
public WorkflowImpl parse(AbstractWorkflow workflowApi) {
workflow = new WorkflowImpl();
workflow.id = workflowApi.getId();
pushContext("workflow", workflowApi, workflow, null);
workflow.parse(workflowApi, this);
popContext();
if (this.workflowParseListener!=null) {
this.workflowParseListener.workflowParsed(workflowApi, workflow, this);
}
return workflow;
}
public void pushContext(String property, Object element, Object elementImpl, Integer index) {
this.contextStack.push(new ParseContext(property, element, elementImpl, index));
}
public void popContext() {
this.contextStack.pop();
}
protected String getPathText() {
StringBuilder pathText = new StringBuilder();
String dot = null;
for (ParseContext validationContext: contextStack) {
if (dot==null) {
dot = ".";
} else {
pathText.append(dot);
}
pathText.append(validationContext.toString());
}
return pathText.toString();
}
public String getExistingActivityIdsText(ScopeImpl scope) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy