From 4a55cbeb2c4bd65644d61a99ad041a5435cb713f Mon Sep 17 00:00:00 2001 From: Andreas Hell Date: Fri, 5 Apr 2024 14:13:03 +0200 Subject: [PATCH 1/2] Extended workflow example by injecting non-default state --- .../workflow/WorkflowDiagramModule.java | 15 +++- .../workflow/WorkflowModelFactory.java | 51 ++++++++++++ .../example/workflow/WorkflowModelState.java | 49 +++++++++++ .../workflow/WorkflowModelStorage.java | 81 +++++++++++++++++++ 4 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelFactory.java create mode 100644 examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelState.java create mode 100644 examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelStorage.java diff --git a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowDiagramModule.java b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowDiagramModule.java index f9f8bc5e..372afa96 100644 --- a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowDiagramModule.java +++ b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowDiagramModule.java @@ -47,6 +47,7 @@ import org.eclipse.glsp.server.features.contextactions.ContextActionsProvider; import org.eclipse.glsp.server.features.contextactions.RequestContextActionsHandler; import org.eclipse.glsp.server.features.contextmenu.ContextMenuItemProvider; +import org.eclipse.glsp.server.features.core.model.GModelFactory; import org.eclipse.glsp.server.features.core.model.SourceModelStorage; import org.eclipse.glsp.server.features.directediting.ContextEditValidator; import org.eclipse.glsp.server.features.directediting.LabelEditValidator; @@ -58,8 +59,8 @@ import org.eclipse.glsp.server.features.typehints.EdgeCreationChecker; import org.eclipse.glsp.server.features.validation.ModelValidator; import org.eclipse.glsp.server.gmodel.GModelDiagramModule; -import org.eclipse.glsp.server.gmodel.GModelStorage; import org.eclipse.glsp.server.layout.LayoutEngine; +import org.eclipse.glsp.server.model.GModelState; import org.eclipse.glsp.server.operations.OperationHandler; public class WorkflowDiagramModule extends GModelDiagramModule { @@ -71,7 +72,17 @@ protected Class bindDiagramConfiguration() { @Override protected Class bindSourceModelStorage() { - return GModelStorage.class; + return WorkflowModelStorage.class; + } + + @Override + protected Class bindGModelState() { + return WorkflowModelState.class; + } + + @Override + protected Class bindGModelFactory() { + return WorkflowModelFactory.class; } @Override diff --git a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelFactory.java b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelFactory.java new file mode 100644 index 00000000..92b9fdb8 --- /dev/null +++ b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelFactory.java @@ -0,0 +1,51 @@ +/******************************************************************************** + * 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 + * 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; + +import com.google.inject.Inject; +import org.eclipse.glsp.graph.GModelRoot; +import org.eclipse.glsp.server.features.core.model.GModelFactory; + +/** + * This class provides the method to transform a source model into a GModel, updating the {@link GModelRoot}. + * + * This is, however, only relevant in cases where the source model is not already a valid GModel. + * + * Here, this custom implementation only serves to provide an entrypoint, but for a more extensive example + * look to + * https://eclipse.dev/glsp/documentation/gmodel/#graphical-model-factory. + */ +public class WorkflowModelFactory implements GModelFactory { + + @Inject + protected WorkflowModelState modelState; + + /** + * Since this is an example using Workflow, which inherently already uses a GModel format, no difference + * exists between the underlying source model and `root`. Therefore all handlers directly update the + * root, making this method detrimental after first model creation. + * + * If other handlers are instead written to update `modelState.model`, then the root has to be updated + * after every change. + */ + @Override + public void createGModel() { + if (modelState.getRoot() == null) { + modelState.updateRoot(modelState.getModel()); + modelState.getRoot().setRevision(-1); + } + } +} diff --git a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelState.java b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelState.java new file mode 100644 index 00000000..45ab7582 --- /dev/null +++ b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelState.java @@ -0,0 +1,49 @@ +/******************************************************************************** + * 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 + * 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; + +import org.eclipse.glsp.graph.GGraph; +import org.eclipse.glsp.graph.GModelRoot; +import org.eclipse.glsp.server.model.DefaultGModelState; +import org.eclipse.glsp.server.model.GModelState; +import org.eclipse.glsp.server.features.core.model.GModelFactory; + +/** + * This model state serves to demonstrate how to extend or create a custom model state. + * + * While this may not be necessary when handling JSON formatted graphs that already + * correspond to a GModel (as the Workflow example does), since {@link DefaultGModelState} + * is sufficient, it nonetheless provides an adequte example for custom formats. + */ +public class WorkflowModelState extends DefaultGModelState { + + /** + * The source model that needs to be transformed into a GModel and its {@link GModelRoot}. + * It is saved in the {@link GModelState} in order to later be available in the + * corresponding {@link GModelFactory}. + * + * Its type solely depends on the used source model. + */ + private GGraph model; + + public GGraph getModel() { + return model; + } + + public void setModel(GGraph model) { + this.model = model; + } +} diff --git a/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelStorage.java b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelStorage.java new file mode 100644 index 00000000..98647706 --- /dev/null +++ b/examples/org.eclipse.glsp.example.workflow/src/org/eclipse/glsp/example/workflow/WorkflowModelStorage.java @@ -0,0 +1,81 @@ +/******************************************************************************** + * 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 + * 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; + +import com.google.gson.Gson; +import com.google.inject.Inject; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import org.eclipse.glsp.graph.GGraph; +import org.eclipse.glsp.server.actions.SaveModelAction; +import org.eclipse.glsp.server.features.core.model.RequestModelAction; +import org.eclipse.glsp.server.features.core.model.SourceModelStorage; +import org.eclipse.glsp.server.gson.GraphGsonConfigurationFactory; +import org.eclipse.glsp.server.types.GLSPServerException; +import org.eclipse.glsp.server.utils.ClientOptionsUtil; +import org.eclipse.glsp.server.gmodel.GModelStorage; + +/** + * This {@link SourceModelStorage} serves as a naive implementation similar to the default {@link GModelStorage}. + * The main difference being that the source model is not directly instantiated as GModel, which works + * in the Workflow example (since its data format is already a valid GModel), but not generally. Therefore, + * this example is more easily applicable to custom model formats. + * + * The model saved here is later on transformed in {@link WorkflowModelFactory} and has to be updated in the handlers, + * if source model and GModel are different. + */ +public class WorkflowModelStorage implements SourceModelStorage { + + @Inject + protected WorkflowModelState modelState; + + protected Gson gson; + + @Inject + public void configureGson(final GraphGsonConfigurationFactory gsonConfigurator) { + gson = gsonConfigurator.configureGson().setPrettyPrinting().create(); + } + + @Override + public void loadSourceModel(final RequestModelAction action) { + final File file = ClientOptionsUtil.getSourceUriAsFile(action.getOptions()).orElseThrow(); + try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { + var model = gson.fromJson(reader, GGraph.class); + modelState.setModel(model); + modelState.setProperty(ClientOptionsUtil.SOURCE_URI, action.getOptions().get(ClientOptionsUtil.SOURCE_URI)); + } catch (IOException e) { + throw new GLSPServerException("Could not load model from file: " + file.toURI().toString(), e); + } + } + + @Override + public void saveSourceModel(final SaveModelAction action) { + File file = ClientOptionsUtil.getAsFile(modelState.getProperty(ClientOptionsUtil.SOURCE_URI, String.class).orElseThrow()); + try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { + gson.toJson(modelState.getRoot(), GGraph.class, writer); + } catch (IOException e) { + throw new GLSPServerException("An error occured during save process.", e); + } + } + +} From 2240da1d3d01879f7326774ac4f3e48930aa62d3 Mon Sep 17 00:00:00 2001 From: Andreas Hell Date: Fri, 5 Apr 2024 15:03:25 +0200 Subject: [PATCH 2/2] Allow Gson for workflow --- .../org.eclipse.glsp.example.workflow/META-INF/MANIFEST.MF | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/org.eclipse.glsp.example.workflow/META-INF/MANIFEST.MF b/examples/org.eclipse.glsp.example.workflow/META-INF/MANIFEST.MF index 5bfa67f5..c8a160ee 100644 --- a/examples/org.eclipse.glsp.example.workflow/META-INF/MANIFEST.MF +++ b/examples/org.eclipse.glsp.example.workflow/META-INF/MANIFEST.MF @@ -27,5 +27,6 @@ Require-Bundle: org.eclipse.glsp.layout;bundle-version="[2.0.0,3.0.0)", org.eclipse.glsp.server.websocket;bundle-version="[2.0.0,3.0.0)", org.eclipse.elk.core;bundle-version="0.8.1", org.eclipse.elk.alg.layered;bundle-version="0.8.1", - org.eclipse.elk.graph;bundle-version="0.8.1" + org.eclipse.elk.graph;bundle-version="0.8.1", + com.google.gson;bundle-version="2.8.7" Import-Package: org.apache.logging.log4j;version="2.17.1"