Skip to content

Commit

Permalink
GLSP-211: Revise TypeHints and server side feedback for creation actions
Browse files Browse the repository at this point in the history
- Add a new parameter to EdgeTypeHint, 'dynamic', indicating that new
edges need to check with the server before allowing creation
 -  Make source/target element type ids in `EdgeTypeHint` optional
  If not defined, all potential element types are considered to be valid sources/targets
- Add `RequestEdgeCheckAction` and `EdgeCheckResultAction` response to implement
 the dynamic check
- Add a optional `EdegeCreationchecker` component that can be implemented by adopters to provide dynamic typehints
- Adapt workflow example to use dynamic edge hints for weighted edges
- Move typehints related components into feature subpackage
- Move progress actions into progress feature subpackage

Co-authored-by: Camille Letavernier <[email protected] >
  • Loading branch information
tortmayr and CamilleLetavernier committed Sep 24, 2023
1 parent 7f8495b commit b2cb25f
Show file tree
Hide file tree
Showing 19 changed files with 448 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019-2021 EclipseSource and others.
* Copyright (c) 2019-2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -72,7 +72,7 @@ public List<ShapeTypeHint> getShapeTypeHints() {
nodeHints.add(new ShapeTypeHint(AUTOMATED_TASK, true, true, true, true));
ShapeTypeHint catHint = new ShapeTypeHint(CATEGORY, true, true, true, true);
catHint.setContainableElementTypeIds(
Arrays.asList(DECISION_NODE, MERGE_NODE, FORK_NODE, JOIN_NODE, AUTOMATED_TASK, MANUAL_TASK, CATEGORY));
Arrays.asList(TASK, ACTIVITY_NODE, CATEGORY));
nodeHints.add(catHint);
nodeHints.add(createDefaultShapeTypeHint(FORK_NODE));
nodeHints.add(createDefaultShapeTypeHint(JOIN_NODE));
Expand All @@ -91,24 +91,21 @@ public ShapeTypeHint createDefaultShapeTypeHint(final String elementId) {
@Override
public List<EdgeTypeHint> getEdgeTypeHints() {
List<EdgeTypeHint> edgeHints = new ArrayList<>();
edgeHints.add(createDefaultEdgeTypeHint(EDGE));
EdgeTypeHint weightedEdgeHint = super.createDefaultEdgeTypeHint(WEIGHTED_EDGE);
weightedEdgeHint.setSourceElementTypeIds(Arrays.asList(DECISION_NODE));
weightedEdgeHint.setTargetElementTypeIds(Arrays.asList(MANUAL_TASK, AUTOMATED_TASK, FORK_NODE, JOIN_NODE));

EdgeTypeHint hint = super.createDefaultEdgeTypeHint(EDGE);
hint.addSourceElementTypeId(TASK, ACTIVITY_NODE, CATEGORY);
hint.addTargetElementTypeId(TASK, ACTIVITY_NODE, CATEGORY);
edgeHints.add(hint);

EdgeTypeHint weightedEdgeHint = createDefaultEdgeTypeHint(WEIGHTED_EDGE);
weightedEdgeHint.addSourceElementTypeId(ACTIVITY_NODE);
weightedEdgeHint.addTargetElementTypeId(TASK, ACTIVITY_NODE);
weightedEdgeHint.setDynamic(true);
edgeHints.add(weightedEdgeHint);
return edgeHints;
}

@Override
public EdgeTypeHint createDefaultEdgeTypeHint(final String elementId) {
EdgeTypeHint hint = super.createDefaultEdgeTypeHint(elementId);
hint.setSourceElementTypeIds(
Arrays.asList(MANUAL_TASK, AUTOMATED_TASK, DECISION_NODE, MERGE_NODE, FORK_NODE, JOIN_NODE, CATEGORY));
hint.setTargetElementTypeIds(
Arrays.asList(MANUAL_TASK, AUTOMATED_TASK, DECISION_NODE, MERGE_NODE, FORK_NODE, JOIN_NODE, CATEGORY));
return hint;
}


@Override
public ServerLayoutKind getLayoutKind() { return ServerLayoutKind.MANUAL; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.eclipse.glsp.example.workflow.taskedit.EditTaskOperationHandler;
import org.eclipse.glsp.example.workflow.taskedit.TaskEditContextActionProvider;
import org.eclipse.glsp.example.workflow.taskedit.TaskEditValidator;
import org.eclipse.glsp.example.workflow.typehints.WorkflowEdgeCreationChecker;
import org.eclipse.glsp.graph.GraphExtension;
import org.eclipse.glsp.server.actions.ActionHandler;
import org.eclipse.glsp.server.di.MultiBinding;
Expand All @@ -54,6 +55,7 @@
import org.eclipse.glsp.server.features.popup.PopupModelFactory;
import org.eclipse.glsp.server.features.sourcemodelwatcher.FileWatcher;
import org.eclipse.glsp.server.features.sourcemodelwatcher.SourceModelWatcher;
import org.eclipse.glsp.server.features.typehints.EdegeCreationChecker;
import org.eclipse.glsp.server.features.validation.ModelValidator;
import org.eclipse.glsp.server.gmodel.GModelDiagramModule;
import org.eclipse.glsp.server.gmodel.GModelStorage;
Expand Down Expand Up @@ -159,6 +161,11 @@ protected Class<? extends NavigationTargetResolver> bindNavigationTargetResolver
return WorkflowNavigationTargetResolver.class;
}

@Override
protected Class<? extends EdegeCreationChecker> bindEdgeCreationChecker() {
return WorkflowEdgeCreationChecker.class;
}

@Override
public String getDiagramType() { return "workflow-diagram"; }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/********************************************************************************
* Copyright (c) 2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
package org.eclipse.glsp.example.workflow.typehints;

import static org.eclipse.glsp.example.workflow.utils.ModelTypes.DECISION_NODE;
import static org.eclipse.glsp.example.workflow.utils.ModelTypes.FORK_NODE;
import static org.eclipse.glsp.example.workflow.utils.ModelTypes.JOIN_NODE;
import static org.eclipse.glsp.example.workflow.utils.ModelTypes.WEIGHTED_EDGE;

import org.eclipse.glsp.example.workflow.wfgraph.TaskNode;
import org.eclipse.glsp.graph.GModelElement;
import org.eclipse.glsp.server.features.typehints.EdegeCreationChecker;

public class WorkflowEdgeCreationChecker implements EdegeCreationChecker {

@Override
public boolean isValidSource(final String edgeType, final GModelElement sourceElement) {
return edgeType.equals(WEIGHTED_EDGE) && sourceElement.getType().equals(DECISION_NODE);
}

@Override
public boolean isValidTarget(final String edgeType, final GModelElement sourceElement,
final GModelElement targetElement) {

if (!edgeType.equals(WEIGHTED_EDGE)) {
return false;
}
String targetType = targetElement.getType();
return targetElement instanceof TaskNode || targetType.equals(FORK_NODE)
|| targetType.equals(JOIN_NODE);

}
}
2 changes: 2 additions & 0 deletions plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ Export-Package: org.eclipse.glsp.server.actions,
org.eclipse.glsp.server.features.directediting,
org.eclipse.glsp.server.features.navigation,
org.eclipse.glsp.server.features.popup,
org.eclipse.glsp.server.features.progress,
org.eclipse.glsp.server.features.sourcemodelwatcher,
org.eclipse.glsp.server.features.toolpalette,
org.eclipse.glsp.server.features.typehints,
org.eclipse.glsp.server.features.undoredo,
org.eclipse.glsp.server.features.validation,
org.eclipse.glsp.server.gmodel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.eclipse.glsp.server.di.scope.DiagramGlobalScope;
import org.eclipse.glsp.server.di.scope.DiagramGlobalSingleton;
import org.eclipse.glsp.server.diagram.DiagramConfiguration;
import org.eclipse.glsp.server.diagram.RequestTypeHintsActionHandler;
import org.eclipse.glsp.server.diagram.ServerConfigurationContribution;
import org.eclipse.glsp.server.features.commandpalette.CommandPaletteActionProvider;
import org.eclipse.glsp.server.features.contextactions.ContextActionsProvider;
Expand All @@ -53,6 +52,9 @@
import org.eclipse.glsp.server.features.progress.ProgressService;
import org.eclipse.glsp.server.features.sourcemodelwatcher.SourceModelWatcher;
import org.eclipse.glsp.server.features.toolpalette.ToolPaletteItemProvider;
import org.eclipse.glsp.server.features.typehints.EdegeCreationChecker;
import org.eclipse.glsp.server.features.typehints.RequestCheckEdgeTargetActionHandler;
import org.eclipse.glsp.server.features.typehints.RequestTypeHintsActionHandler;
import org.eclipse.glsp.server.features.undoredo.UndoRedoActionHandler;
import org.eclipse.glsp.server.features.validation.ModelValidator;
import org.eclipse.glsp.server.features.validation.RequestMarkersHandler;
Expand Down Expand Up @@ -127,6 +129,7 @@
* <li>{@link PopupModelFactory} as {@link Optional}
* <li>{@link LayoutEngine} as {@link Optional}
* <li>{@link GraphExtension} as {@link Optional}
* <li>{@link EdegeCreationChecker} as {@link Optional}
* </ul>
*
*
Expand Down Expand Up @@ -185,6 +188,7 @@ protected void configureBase() {
bindOptionally(PopupModelFactory.class, bindPopupModelFactory());
bindOptionally(LayoutEngine.class, bindLayoutEngine());
bindOptionally(GraphExtension.class, bindGraphExtension());
bindOptionally(EdegeCreationChecker.class, bindEdgeCreationChecker());
}

protected void bindDiagramType() {
Expand Down Expand Up @@ -271,6 +275,7 @@ protected void configureActionHandlers(final MultiBinding<ActionHandler> binding
binding.add(ComputedBoundsActionHandler.class);
binding.add(SaveModelActionHandler.class);
binding.add(UndoRedoActionHandler.class);
binding.add(RequestCheckEdgeTargetActionHandler.class);
}

protected Class<? extends ActionHandlerRegistry> bindActionHandlerRegistry() {
Expand Down Expand Up @@ -319,5 +324,9 @@ protected Class<? extends GraphExtension> bindGraphExtension() {
return null;
}

protected Class<? extends EdegeCreationChecker> bindEdgeCreationChecker() {
return null;
}

public abstract String getDiagramType();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019-2021 EclipseSource and others.
* Copyright (c) 2019-2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -71,7 +71,7 @@ public interface DiagramConfiguration {
Optional<GraphExtension> getGraphExtension();

default EdgeTypeHint createDefaultEdgeTypeHint(final String elementId) {
return new EdgeTypeHint(elementId, true, true, true, null, null);
return new EdgeTypeHint(elementId, true, true, true, false, null, null);
}

default ShapeTypeHint createDefaultShapeTypeHint(final String elementId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import java.util.UUID;

import org.eclipse.glsp.server.actions.ActionDispatcher;
import org.eclipse.glsp.server.actions.EndProgressAction;
import org.eclipse.glsp.server.actions.StartProgressAction;
import org.eclipse.glsp.server.actions.UpdateProgressAction;

import com.google.inject.Inject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
package org.eclipse.glsp.server.actions;
package org.eclipse.glsp.server.features.progress;

import java.util.Optional;

import org.eclipse.glsp.server.actions.Action;

/**
* Sent by the server to the client to end the reporting of a progress.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
package org.eclipse.glsp.server.actions;
package org.eclipse.glsp.server.features.progress;

import java.util.Optional;

import org.eclipse.glsp.server.actions.Action;

/**
* Sent by the server to the client to request presenting the progress of a long running process in the UI.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/********************************************************************************
* Copyright (c) 2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
package org.eclipse.glsp.server.features.typehints;

import java.util.Optional;

import org.eclipse.glsp.server.actions.ResponseAction;

/**
* Response Action for a {@link RequestCheckEdgeAction}. It provides
* a boolean indicating whether the requested element is a valid target
* for the edge being created and the context edge context information (type, source, target).
*/
public class CheckEdgeTargetResultAction extends ResponseAction {

public static final String KIND = "checkEdgeResult";

/**
* true if the selected element is a valid target for this edge,
* false otherwise.
*/
private boolean isValid;

/**
* The element type of the Edge that has been checked.
*/
private String edgeType;

/**
* The ID of the source element of the edge that has been checked.
*/
private String sourceElementId;
/**
* The ID of the target element of the edge that has been checked.
*/
private String targetElementId;

public CheckEdgeTargetResultAction() {
super(KIND);
}

public CheckEdgeTargetResultAction(final boolean isValid, final RequestCheckEdgeAction requestAction) {
super(KIND);
this.setValid(isValid);
this.setEdgeType(requestAction.getEdgeType());
this.setSourceElementId(requestAction.getSourceElementId());
this.setTargetElementId(requestAction.getTargetElementId().orElse(null));
}

public String getEdgeType() { return edgeType; }

public void setEdgeType(final String edgeType) { this.edgeType = edgeType; }

public String getSourceElementId() { return sourceElementId; }

public void setSourceElementId(final String sourceElementId) { this.sourceElementId = sourceElementId; }

public Optional<String> getTargetElementId() { return Optional.ofNullable(this.targetElementId); }

public void setTargetElementId(final String targetElementId) { this.targetElementId = targetElementId; }

public boolean isValid() { return isValid; }

public void setValid(final boolean isValid) { this.isValid = isValid; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/********************************************************************************
* Copyright (c) 2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
package org.eclipse.glsp.server.features.typehints;

import org.eclipse.glsp.graph.GModelElement;
import org.eclipse.glsp.server.types.EdgeTypeHint;

/**
* Optional service used to check the validity of an edge being created. Used in combination with `dynamic`
* {@link EdgeTypeHint}s.
* A dynamic edge type hint is used for cases where a plain list of allowed source and target element ids is not enough
* to determine
* wether an edge beeing created is valid. In this cases the client will query the server to determine wether the edge
* is valid.
* The `EdegeCreationChecker` then checks the given edge information and returns wether the edge beeing created is
* valid.
* If no `EdgeTargetChecker` implementation is bound the creation of dynamic edge will always be rejected.
*
*/
public interface EdegeCreationChecker {
/**
* Checks wether the given source element for an edge beeing created is valid i.e. if the
* given source is and allowed source element for the given edge type.
*
* @return `true` if the edge source is valid, `false` otherwise
*/
boolean isValidSource(String edgeType, GModelElement sourceElement);

/**
* Checks wether the given information for an edge beeing created is valid i.e. if the
* given target is an allowed target for the given source and edge type.
*
* @return `true` if the edge target is valid, `false` otherwise
*/
boolean isValidTarget(String edgeType, GModelElement sourceElement, GModelElement targetElement);
}
Loading

0 comments on commit b2cb25f

Please sign in to comment.