Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions plugins/ru.runa.gpd/plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ label.menu.help=Help
label.menu.moreDetails=More details
label.menu.helpContents=Help Contents
label.menu.helpAbout=About
label.menu.cycleDetector=Check for "instantaneous" cycles
label.menu.checkProcess=Check process
label.menu.preferences=Preferences
label.preference.diagram=Diagram settings
label.menu.mapping=Mapping
Expand Down Expand Up @@ -928,7 +930,7 @@ model.validation.startState.formScriptIsNotUsableInSubprocess = Form script will
model.validation.startState.swimlaneIsNotUsableInEmbeddedSubprocess = Swimlane will never used in start state of embedded subprocess
model.validation.multiTask.discriminator.empty = Discriminator variable is not defined
model.validation.multiTask.discriminator.executors.classcasterror = Tasks can be assigned only by List(Executor) variable
model.validation.multiTask.discriminator.unmapped =
model.validation.multiTask.discriminator.unmapped =
model.validation.multiTask.variable.duplicate.name = Variable \"{0}\" defined twice in mapping
model.validation.multiTask.variable.duplicate.mappedName = Variable \"{0}\" defined twice in mapping
model.validation.multiTask.variable.doesNotExist = Variable \"{0}\" does not exist
Expand Down Expand Up @@ -1134,17 +1136,17 @@ mail.smtp.port.help = Mail server port
mail.smtp.auth = Use authentication
mail.smtp.auth.help = Mail server requires authentication
mail.user = User name
mail.user.help =
mail.user.help =
mail.password = Password
mail.password.help =
mail.password.help =
mail.debug = Debug
mail.debug.help = Write protocol communication to log
mail.subject = Subject
mail.subject.help = Message subject
mail.to = To
mail.to.help = Recipient's e-mail
mail.cc = Cc
mail.cc.help =
mail.cc.help =
mail.bodyInlined = Use body from form

pref.notation.defaultNotation = Default notation
Expand Down Expand Up @@ -1359,6 +1361,9 @@ ru.runa.wfe.extension.orgfunction.ExecutorsFromListFunction=Executors from list
CheckingTokensAction.SituationExist.Message=The situation with infinitely increasing tokens can be exist. The problem found in object {0}.
CheckingTokensAction.SituationNotExist.Message=The situation with infinitely increasing tokens can not be exist.

CycleDetectorAction.CycleExist.Message=The cycle can be exist.
CycleDetectorAction.CycleNotExist.Message=The cycle can not be exist.

VariableWizard.create = Create variable
VariableWizard.edit = Edit variable
VariableNamePage.title = Set variable name
Expand Down
16 changes: 15 additions & 1 deletion plugins/ru.runa.gpd/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2689,6 +2689,13 @@
<separator name="common"/>
<separator name="additions"/>
</menu>

<menu
id="checkProcess"
label="%label.menu.checkProcess"
path="file/command">
<separator name="command"/>
</menu>

<action
class="ru.runa.gpd.ui.action.NewProcessAction"
Expand Down Expand Up @@ -3043,7 +3050,14 @@
class="ru.runa.gpd.ui.action.CheckUnlimitedTokenAction"
id="ru.runa.gpd.checkUnlimitedToken"
label="%label.menu.checkingTokens"
menubarPath="file/command"
menubarPath="file/checkProcess/unlimitedToken"
style="push">
</action>
<action
class="ru.runa.gpd.ui.action.CycleDetectorAction"
id="ru.runa.gpd.cycleDetectorAction"
label="%label.menu.cycleDetector"
menubarPath="file/checkProcess/cycle"
style="push">
</action>
<action
Expand Down
5 changes: 5 additions & 0 deletions plugins/ru.runa.gpd/plugin_ru.properties
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ tooltip.menu.export=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u043f\u0440\u043
label.menu.import=\u0418\u043c\u043f\u043e\u0440\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430
label.menu.exit=\u0412\u044b\u0445\u043e\u0434
label.menu.view=\u0412\u0438\u0434
label.menu.cycleDetector=\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C\u0020\u043D\u0430\u043B\u0438\u0447\u0438\u0435\u0020\u0022\u043C\u0433\u043D\u043E\u0432\u0435\u043D\u043D\u044B\u0445\u0022\u0020\u0446\u0438\u043A\u043B\u043E\u0432
label.menu.checkProcess=\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u043F\u0440\u043E\u0446\u0435\u0441\u0441
label.menu.properties=\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430
label.menu.properties.antialiasing=\u0421\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u043d\u0438\u0435
label.menu.properties.enableGrid=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0435\u0442\u043a\u0443
Expand Down Expand Up @@ -1374,6 +1376,9 @@ ru.runa.wfe.extension.orgfunction.ExecutorsFromListFunction=\u0418\u0441\u043f\u
CheckingTokensAction.SituationExist.Message=\u0412 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0441 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u0447\u0435\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0443\u0437\u043b\u0435 \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c {0}.
CheckingTokensAction.SituationNotExist.Message=\u0412 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0441 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u0447\u0435\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.

CycleDetectorAction.CycleExist.Message=\u0412\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0020\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043E\u0432\u0430\u043D\u0438\u0435\u0020\u0446\u0438\u043A\u043B\u0430\u002E
CycleDetectorAction.CycleNotExist.Message=\u0426\u0438\u043A\u043B\u0020\u043D\u0435\u0020\u043C\u043E\u0436\u0435\u0442\u0020\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C\u002E

VariableWizard.create = \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439
VariableWizard.edit = \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439
VariableNamePage.title = \u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439
Expand Down
71 changes: 71 additions & 0 deletions plugins/ru.runa.gpd/src/ru/runa/gpd/algorithms/CycleDetector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package ru.runa.gpd.algorithms;

import java.util.Queue;
import java.util.PriorityQueue;
import java.util.HashSet;
import java.util.Set;
import ru.runa.gpd.lang.model.Node;
import ru.runa.gpd.lang.model.AbstractTransition;
import ru.runa.gpd.lang.model.Decision;
import ru.runa.gpd.lang.model.bpmn.ScriptTask;
import ru.runa.gpd.lang.model.bpmn.ParallelGateway;


public class CycleDetector {

private Set<Node> visited;
private Queue<Node> queue;

public CycleDetector() {
visited = new HashSet<>();
queue = new PriorityQueue<>();
}


public boolean hasCycle(Node startNode) {
visited.add(startNode);
queue.add(startNode);
while (!queue.isEmpty()) {
Node currentNode = queue.poll();
if (currentNode instanceof Decision || currentNode instanceof ScriptTask
|| currentNode instanceof ParallelGateway) {
boolean isCycle = traverseNode(currentNode);
if (isCycle) {
return true;
}
}
for (AbstractTransition outgoingNode : currentNode.getLeavingTransitions()) {
if (!visited.contains(outgoingNode.getTarget())) {
visited.add(outgoingNode.getTarget());
queue.add(outgoingNode.getTarget());
}
}
}
return false;
}

private boolean traverseNode(Node startNode) {
Queue<Node> queue = new PriorityQueue<>();
Set<Node> visited = new HashSet<>();
queue.add(startNode);
while (!queue.isEmpty()) {
Node node = queue.poll();
if (visited.contains(node)) {
return true;
}
visited.add(node);
for (AbstractTransition outgoingNode : node.getLeavingTransitions()) {
if (outgoingNode.getTarget() instanceof Decision
|| outgoingNode.getTarget() instanceof ScriptTask
|| outgoingNode.getTarget() instanceof ParallelGateway) {
queue.add(outgoingNode.getTarget());
} else {
if (node instanceof ParallelGateway) {
return false;
}
}
}
}
return false;
}
}
18 changes: 9 additions & 9 deletions plugins/ru.runa.gpd/src/ru/runa/gpd/lang/model/GraphElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

@SuppressWarnings("unchecked")
public abstract class GraphElement extends EventSupport
implements IPropertySource, PropertyNames, IActionFilter, VariableContainer, ProcessDefinitionAware {
implements IPropertySource, PropertyNames, IActionFilter, VariableContainer, ProcessDefinitionAware {
private PropertyChangeListener delegatedListener;
private GraphElement parent;
private GraphElement uiParentContainer;
Expand Down Expand Up @@ -129,7 +129,7 @@ public void setConstraint(Rectangle newConstraint) {
if (this.constraint != null && this instanceof IBoundaryEventContainer) {
for (GraphElement element : children) {
if (element.getConstraint() != null && element instanceof IBoundaryEventCapable
&& ((IBoundaryEventCapable) element).isBoundaryEvent()) {
&& ((IBoundaryEventCapable) element).isBoundaryEvent()) {
((IBoundaryEventCapable) element).updateBoundaryEventConstraint();
}
}
Expand Down Expand Up @@ -173,14 +173,14 @@ public void validate(List<ValidationError> errors, IFile definitionFile) {
List<String> docxErrors = Lists.newArrayList();
List<Delegable> docxErrorSources = Lists.newArrayList();
DocxDialogEnhancement.checkScriptTaskParametersWithDocxTemplate(delegable,
EmbeddedFileUtils.getProcessFileName(embeddedDocxTemplateFileName), docxErrors, docxErrorSources, null);
EmbeddedFileUtils.getProcessFileName(embeddedDocxTemplateFileName), docxErrors, docxErrorSources, null);
if (docxErrors.size() > 0 && docxErrors.size() == docxErrorSources.size()) {
ListIterator<String> iterator = docxErrors.listIterator();
ListIterator<Delegable> iterator2 = docxErrorSources.listIterator();
while (iterator.hasNext()) {
Delegable delegable2 = iterator2.next();
errors.add(ValidationError.createError(delegable2 instanceof GraphElement ? (GraphElement) delegable2 : this,
iterator.next()));
iterator.next()));
}
}
}
Expand Down Expand Up @@ -260,7 +260,7 @@ public void changeChildIndex(GraphElement child, GraphElement insertBefore) {
firePropertyChange(PROPERTY_CHILDREN_CHANGED, old, before + 1);
}
}

public <T extends GraphElement> List<T> getChildren(Class<T> type) {
return getChildren(type, null);
}
Expand Down Expand Up @@ -411,19 +411,19 @@ public final IPropertyDescriptor[] getPropertyDescriptors() {
}
if (this instanceof Describable) {
descriptors
.add(new DescribablePropertyDescriptor(PROPERTY_DESCRIPTION, Localization.getString("property.description"), (Describable) this));
.add(new DescribablePropertyDescriptor(PROPERTY_DESCRIPTION, Localization.getString("property.description"), (Describable) this));
}
if (isDelegable()) {
Delegable delegable = (Delegable) this;
descriptors.add(new DelegableClassPropertyDescriptor(PROPERTY_CLASS, Localization.getString("property.delegation.class"), delegable));
descriptors.add(new DelegableConfPropertyDescriptor(PROPERTY_CONFIGURATION, (Delegable) this,
Localization.getString("property.delegation.configuration")));
Localization.getString("property.delegation.configuration")));
}
if (this instanceof ITimed && getProcessDefinition().getLanguage() == Language.JPDL) {
Timer timer = ((ITimed) this).getTimer();
if (timer != null) {
descriptors.add(new DurationPropertyDescriptor(PROPERTY_TIMER_DELAY, timer.getProcessDefinition(), timer.getDelay(),
Localization.getString("property.duration")));
Localization.getString("property.duration")));
descriptors.add(new TimerActionPropertyDescriptor(PROPERTY_TIMER_ACTION, Localization.getString("Timer.action"), timer));
}
}
Expand Down Expand Up @@ -539,4 +539,4 @@ public String getLabel() {
return id;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ru.runa.gpd.ui.action;

import java.util.List;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.part.FileEditorInput;

import ru.runa.gpd.Localization;
import ru.runa.gpd.ProcessCache;
import ru.runa.gpd.editor.ProcessEditorBase;
import ru.runa.gpd.lang.model.bpmn.ScriptTask;
import ru.runa.gpd.lang.model.StartState;
import ru.runa.gpd.lang.model.Node;
import ru.runa.gpd.lang.model.ProcessDefinition;
import ru.runa.gpd.lang.model.bpmn.ExclusiveGateway;
import ru.runa.gpd.ui.custom.Dialogs;
import ru.runa.gpd.algorithms.CycleDetector;

public class CycleDetectorAction extends BaseActionDelegate {

@Override
public void run(IAction action) {
IEditorPart editorPart = getActiveEditor();
if (editorPart != null) {
IEditorInput editorInput = editorPart.getEditorInput();
if (editorInput instanceof FileEditorInput) {
ProcessDefinition definition = ProcessCache.getProcessDefinition(
((FileEditorInput) editorInput).getFile());
StartState startNode = definition.getChildren(StartState.class).get(0);

CycleDetector cycleDetector = new CycleDetector();
boolean isCycle = cycleDetector.hasCycle(startNode);

if (isCycle) {
Dialogs.warning(
Localization.getString("CycleDetectorAction.CycleExist.Message"));
} else {
Dialogs.information(
Localization.getString("CycleDetectorAction.CycleNotExist.Message"));
}
}
}
}

@Override
public void selectionChanged(IAction action, ISelection selection) {
action.setEnabled(
hasElements(StartState.class) && (hasElements(ExclusiveGateway.class) || hasElements(
ScriptTask.class)));
}

private IEditorPart[] getDirtyEditors() {
return window.getActivePage().getDirtyEditors();
}

private <T extends Node> boolean hasElements(Class<T> type) {
ProcessEditorBase editor = getActiveDesignerEditor();

List<T> nodes = null;
if (editor != null) {
nodes = editor.getDefinition().getChildren(type);
}

return nodes != null && !nodes.isEmpty();
}
}