From 86e84ca6333709905f36a197be312cd683e7fa82 Mon Sep 17 00:00:00 2001
From: StarryScythe <tim6542@aol.com>
Date: Wed, 25 Dec 2024 00:59:11 +0100
Subject: [PATCH] issue #4 added nodePage; saving after adding currently not
 working - looking into it - see last error in TaskAndTimeTimJahn

---
 TaskAndTimeTimJahn.txt                        | 102 ++++++++++++++++++
 glsp-client/tasklist-glsp/css/diagram.css     |   4 +
 glsp-client/tasklist-glsp/src/model.ts        |  15 +++
 .../src/tasklist-diagram-module.ts            |   6 +-
 glsp-client/workspace/test.pnml               |  43 --------
 .../org/pnml/emf/ptnet/PtnetPackage.java      |  17 ++-
 .../org/pnml/emf/ptnet/ToolInfoPage.java      |   4 +
 .../pnml/emf/ptnet/impl/PtnetPackageImpl.java |  12 ++-
 .../pnml/emf/ptnet/impl/ToolInfoPageImpl.java |  46 +++++++-
 .../glsp/example/javaemf/PNMLModelTypes.java  |   5 +
 .../javaemf/TaskListDiagramModule.java        |   1 +
 .../CreateNodePageHandler.java                |  70 ++++++++++++
 .../handler/LabelEditOperationHandler.java    |   7 ++
 .../NodeCreation/CreatePageHandler.java       |  40 +++++--
 .../javaemf/model/ModelAccessUtil.java        |   8 ++
 .../javaemf/model/TaskListGModelFactory.java  |  13 ++-
 .../TaskListToolPaletteItemProvider.java      |   2 +
 17 files changed, 340 insertions(+), 55 deletions(-)
 create mode 100644 glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/DiNeROS/ElementCreation/CreateNodePageHandler.java

diff --git a/TaskAndTimeTimJahn.txt b/TaskAndTimeTimJahn.txt
index 2b6424f..f067e48 100644
--- a/TaskAndTimeTimJahn.txt
+++ b/TaskAndTimeTimJahn.txt
@@ -526,3 +526,105 @@ Caused by: org.xml.sax.SAXParseExceptionpublicId: file:/mnt/c/Users/tim65/SHK-Pr
 	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoadHelper(ResourceSetImpl.java:274)
 	... 15 more
 
+
+
+pageNode implementation
+
+NaseModel.pnml
+
+java.lang.ExceptionInInitializerError
+	at org.eclipse.glsp.example.javaemf.model.TaskListSourceModelStorage.setupResourceSet(TaskListSourceModelStorage.java:58)
+	at org.eclipse.glsp.server.emf.EMFSourceModelStorage.getOrCreateEditingDomain(EMFSourceModelStorage.java:68)
+	at org.eclipse.glsp.example.javaemf.model.TaskListSourceModelStorage.loadSourceModel(TaskListSourceModelStorage.java:85)
+	at org.eclipse.glsp.server.features.core.model.RequestModelActionHandler.executeAction(RequestModelActionHandler.java:75)
+	at org.eclipse.glsp.server.features.core.model.RequestModelActionHandler.executeAction(RequestModelActionHandler.java:45)
+	at org.eclipse.glsp.server.actions.AbstractActionHandler.execute(AbstractActionHandler.java:53)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.runAction(DefaultActionDispatcher.java:198)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.handleAction(DefaultActionDispatcher.java:176)
+	at org.eclipse.glsp.example.javaemf.handler.MyActionDispatcher.handleAction(MyActionDispatcher.java:24)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.handleNextAction(DefaultActionDispatcher.java:163)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.runThread(DefaultActionDispatcher.java:149)
+	at java.base/java.lang.Thread.run(Thread.java:1583)
+Caused by: java.lang.ClassCastException: class org.eclipse.emf.ecore.impl.EAttributeImpl cannot be cast to class org.eclipse.emf.ecore.EReference (org.eclipse.emf.ecore.impl.EAttributeImpl and org.eclipse.emf.ecore.EReference are in unnamed module of loader 'app')
+	at org.pnml.emf.ptnet.impl.PtnetPackageImpl.getToolInfoPage_Page(PtnetPackageImpl.java:2024)
+	at org.pnml.emf.ptnet.impl.PtnetPackageImpl.initializePackageContents(PtnetPackageImpl.java:2971)
+	at org.pnml.emf.ptnet.impl.PtnetPackageImpl.init(PtnetPackageImpl.java:597)
+	at org.pnml.emf.ptnet.PtnetPackage.<clinit>(PtnetPackage.java:59)
+	... 12 more
+
+test.pnml
+
+Could not initialize class org.pnml.emf.ptnet.PtnetPackage
+java.lang.NoClassDefFoundError: Could not initialize class org.pnml.emf.ptnet.PtnetPackage
+	at org.eclipse.glsp.example.javaemf.model.TaskListSourceModelStorage.setupResourceSet(TaskListSourceModelStorage.java:58)
+	at org.eclipse.glsp.server.emf.EMFSourceModelStorage.getOrCreateEditingDomain(EMFSourceModelStorage.java:68)
+	at org.eclipse.glsp.example.javaemf.model.TaskListSourceModelStorage.loadSourceModel(TaskListSourceModelStorage.java:85)
+	at org.eclipse.glsp.server.features.core.model.RequestModelActionHandler.executeAction(RequestModelActionHandler.java:75)
+	at org.eclipse.glsp.server.features.core.model.RequestModelActionHandler.executeAction(RequestModelActionHandler.java:45)
+	at org.eclipse.glsp.server.actions.AbstractActionHandler.execute(AbstractActionHandler.java:53)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.runAction(DefaultActionDispatcher.java:198)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.handleAction(DefaultActionDispatcher.java:176)
+	at org.eclipse.glsp.example.javaemf.handler.MyActionDispatcher.handleAction(MyActionDispatcher.java:24)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.handleNextAction(DefaultActionDispatcher.java:163)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.runThread(DefaultActionDispatcher.java:149)
+	at java.base/java.lang.Thread.run(Thread.java:1583)
+Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ClassCastException: class org.eclipse.emf.ecore.impl.EAttributeImpl cannot be cast to class org.eclipse.emf.ecore.EReference (org.eclipse.emf.ecore.impl.EAttributeImpl and org.eclipse.emf.ecore.EReference are in unnamed module of loader 'app') [in thread "MyActionDispatcher 3"]
+	at org.pnml.emf.ptnet.impl.PtnetPackageImpl.getToolInfoPage_Page(PtnetPackageImpl.java:2024)
+	at org.pnml.emf.ptnet.impl.PtnetPackageImpl.initializePackageContents(PtnetPackageImpl.java:2971)
+	at org.pnml.emf.ptnet.impl.PtnetPackageImpl.init(PtnetPackageImpl.java:597)
+	at org.pnml.emf.ptnet.PtnetPackage.<clinit>(PtnetPackage.java:59)
+	... 12 more
+
+
+error trying to save after adding nodePage
+
+class org.pnml.emf.ptnet.impl.PageImpl cannot be cast to class java.lang.String (org.pnml.emf.ptnet.impl.PageImpl is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
+java.lang.ClassCastException: class org.pnml.emf.ptnet.impl.PageImpl cannot be cast to class java.lang.String (org.pnml.emf.ptnet.impl.PageImpl is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
+	at org.eclipse.emf.ecore.impl.EcoreFactoryImpl.convertEStringToString(EcoreFactoryImpl.java:661)
+	at org.eclipse.emf.ecore.impl.EcoreFactoryImpl.convertToString(EcoreFactoryImpl.java:219)
+	at org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl.convertToString(XMLHelperImpl.java:1610)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.getDatatypeValue(XMLSaveImpl.java:3108)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveDataTypeSingle(XMLSaveImpl.java:1698)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1280)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1224)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElementID(XMLSaveImpl.java:2716)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1181)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1042)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveContainedMany(XMLSaveImpl.java:2417)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1553)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1224)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElementID(XMLSaveImpl.java:2716)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1181)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1042)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveContainedMany(XMLSaveImpl.java:2417)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1553)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1224)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElementID(XMLSaveImpl.java:2716)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1181)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1042)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveContainedMany(XMLSaveImpl.java:2417)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1553)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1224)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElementID(XMLSaveImpl.java:2716)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1181)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElement(XMLSaveImpl.java:1042)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveContainedMany(XMLSaveImpl.java:2417)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1553)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveFeatures(XMLSaveImpl.java:1224)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.saveElementID(XMLSaveImpl.java:2716)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.writeTopObject(XMLSaveImpl.java:683)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.traverse(XMLSaveImpl.java:591)
+	at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.save(XMLSaveImpl.java:251)
+	at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doSave(XMLResourceImpl.java:389)
+	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.save(ResourceImpl.java:1475)
+	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.save(ResourceImpl.java:1044)
+	at org.eclipse.glsp.example.javaemf.model.TaskListSourceModelStorage.saveSourceModel(TaskListSourceModelStorage.java:165)
+	at org.eclipse.glsp.server.actions.SaveModelActionHandler.executeAction(SaveModelActionHandler.java:47)
+	at org.eclipse.glsp.server.actions.SaveModelActionHandler.executeAction(SaveModelActionHandler.java:32)
+	at org.eclipse.glsp.server.actions.AbstractActionHandler.execute(AbstractActionHandler.java:53)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.runAction(DefaultActionDispatcher.java:198)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.handleAction(DefaultActionDispatcher.java:176)
+	at org.eclipse.glsp.example.javaemf.handler.MyActionDispatcher.handleAction(MyActionDispatcher.java:24)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.handleNextAction(DefaultActionDispatcher.java:163)
+	at org.eclipse.glsp.server.internal.actions.DefaultActionDispatcher.runThread(DefaultActionDispatcher.java:149)
+	at java.base/java.lang.Thread.run(Thread.java:1583)
diff --git a/glsp-client/tasklist-glsp/css/diagram.css b/glsp-client/tasklist-glsp/css/diagram.css
index 42befd8..c1b729e 100644
--- a/glsp-client/tasklist-glsp/css/diagram.css
+++ b/glsp-client/tasklist-glsp/css/diagram.css
@@ -112,6 +112,10 @@ svg {
     fill: #89d681;
 }
 
+.node-page {
+    fill: #157dcd;
+}
+
 .service-channel {
     fill: #58cb47;
 }
diff --git a/glsp-client/tasklist-glsp/src/model.ts b/glsp-client/tasklist-glsp/src/model.ts
index 0def81f..158332d 100644
--- a/glsp-client/tasklist-glsp/src/model.ts
+++ b/glsp-client/tasklist-glsp/src/model.ts
@@ -156,6 +156,21 @@ export class ServerPageNode extends CategoryNode {
     }
 }
 
+export class NodePageNode extends CategoryNode {
+    override isContainableElement(input: GModelElement | GModelElementSchema | string): boolean {
+        const type: string = getTypeString(input);
+        if (
+            type === PNMLModelTypes.PLACE ||
+            type === PNMLModelTypes.TRANSITION ||
+            type === PNMLModelTypes.REF_PLACE ||
+            type === PNMLModelTypes.REF_TRANSITION
+        ) {
+            return true;
+        }
+        return false;
+    }
+}
+
 export class ServiceNode extends CategoryNode {
     override isContainableElement(input: GModelElement | GModelElementSchema | string): boolean {
         const type: string = getTypeString(input);
diff --git a/glsp-client/tasklist-glsp/src/tasklist-diagram-module.ts b/glsp-client/tasklist-glsp/src/tasklist-diagram-module.ts
index 847488c..a2fb366 100644
--- a/glsp-client/tasklist-glsp/src/tasklist-diagram-module.ts
+++ b/glsp-client/tasklist-glsp/src/tasklist-diagram-module.ts
@@ -57,7 +57,7 @@ import { CopyToClipboardAction } from './Actions/CopyToClipboardAction';
 import { CopyToClipboardHandler } from './Handlers/CopyToClipboardHandler';
 
 import { ModelUpdateListener } from './Handlers/ModelUpdateListener';
-import { PageNode, PNMLGraph, ServerPageNode, ServiceNode } from './model';
+import { PageNode, PNMLGraph, ServerPageNode, NodePageNode, ServiceNode } from './model';
 import { ActivePagesOverlay } from './ui-extensions/active-pages-overlay';
 import { EditInputSignalMenu } from './ui-extensions/edit-input-signals';
 import { EditTokensMenu } from './ui-extensions/edit-tokens';
@@ -124,6 +124,10 @@ const taskListDiagramModule = new ContainerModule((bind, unbind, isBound, rebind
         enable: [resizeFeature],
         disable: [hoverFeedbackFeature]
     });
+    configureModelElement(context, 'nodeAsPage', NodePageNode, PageNodeView, {
+        enable: [resizeFeature],
+        disable: [hoverFeedbackFeature]
+    });
     configureModelElement(context, 'signalClauseLabel', GLabel, GLabelView);
     configureModelElement(context, 'edgeTextLabel', GLabel, GLabelView);
     configureModelElement(context, 'topicLinkLimitLabel', GLabel, GLabelView, { enable: [editLabelFeature] });
diff --git a/glsp-client/workspace/test.pnml b/glsp-client/workspace/test.pnml
index 6fab4f3..e69de29 100644
--- a/glsp-client/workspace/test.pnml
+++ b/glsp-client/workspace/test.pnml
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<pnml xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-  <net id="test">
-    <page id="264f2fbc-b832-48a7-8222-0541aa4707ee">
-      <name text="NewPage5"/>
-      <nodegraphics>
-        <position x="224" y="27"/>
-        <dimension x="500" y="500"/>
-      </nodegraphics>
-      <arc id="89e0d428-4f7a-463a-80d9-6d33f0541d22" source="2d062086-da61-4f6e-a247-635f8c6af7e9" target="c896e5ab-19e9-44b5-94f0-111700b7cd5f">
-        <name text="NewArc0"/>
-      </arc>
-      <place id="c896e5ab-19e9-44b5-94f0-111700b7cd5f" InArcs="89e0d428-4f7a-463a-80d9-6d33f0541d22">
-        <name text="NewPlace14"/>
-        <nodegraphics>
-          <position x="268" y="122"/>
-          <dimension x="70" y="70"/>
-        </nodegraphics>
-        <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1" node="264f2fbc-b832-48a7-8222-0541aa4707ee" subnet=""/>
-      </place>
-      <transition id="2d062086-da61-4f6e-a247-635f8c6af7e9" OutArcs="89e0d428-4f7a-463a-80d9-6d33f0541d22">
-        <name text="NewTransition11"/>
-        <nodegraphics>
-          <position x="111" y="126"/>
-          <dimension x="30" y="70"/>
-        </nodegraphics>
-        <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1" type="discreteTransitionType" node="264f2fbc-b832-48a7-8222-0541aa4707ee" subnet=""/>
-      </transition>
-      <transition id="d5f3a600-7f20-42bf-9bc8-c011e11ab22e">
-        <name text="NewTopic7"/>
-        <nodegraphics>
-          <position x="246" y="312"/>
-          <dimension x="100" y="150"/>
-        </nodegraphics>
-        <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1" type="topicTransitionType" topicName="NewTopic7">
-          <subscribers>
-            <subscriber id="c896e5ab-19e9-44b5-94f0-111700b7cd5f" limit="10"/>
-          </subscribers>
-        </toolspecific>
-      </transition>
-    </page>
-  </net>
-</pnml>
diff --git a/glsp-server/src-gen/org/pnml/emf/ptnet/PtnetPackage.java b/glsp-server/src-gen/org/pnml/emf/ptnet/PtnetPackage.java
index a40cab3..a9c15f1 100644
--- a/glsp-server/src-gen/org/pnml/emf/ptnet/PtnetPackage.java
+++ b/glsp-server/src-gen/org/pnml/emf/ptnet/PtnetPackage.java
@@ -3362,7 +3362,17 @@ public interface PtnetPackage extends EPackage {
     * @generated
     * @ordered
     */
-   int TOOL_INFO_PAGE_FEATURE_COUNT = TOOL_INFO_FEATURE_COUNT + 2;
+   int TOOL_INFO_PAGE_FEATURE_COUNT = TOOL_INFO_FEATURE_COUNT + 3;
+
+/**
+    * The feature id for the '<em><b>Node Name</b></em>' attribute.
+    * <!-- begin-user-doc -->
+   	 * <!-- end-user-doc -->
+    * @generated
+    * @ordered
+    */
+    int TOOL_INFO_PAGE__NODE_NAME = TOOL_INFO_FEATURE_COUNT + 2;
+
 
    /**
     * The number of operations of the '<em>Tool Info Page</em>' class.
@@ -5890,6 +5900,8 @@ public interface PtnetPackage extends EPackage {
     */
    EAttribute getToolInfoPage_ServiceName();
 
+   EAttribute getToolInfoPage_NodePageName();
+
    /**
     * Returns the meta object for the container reference '{@link org.pnml.emf.ptnet.ToolInfoPage#getPage <em>Page</em>}'.
     * <!-- begin-user-doc -->
@@ -7911,6 +7923,9 @@ public interface PtnetPackage extends EPackage {
        */
       EAttribute TOOL_INFO_PAGE__SERVICE_NAME = eINSTANCE.getToolInfoPage_ServiceName();
 
+
+      EAttribute TOOL_INFO_PAGE__NODE_NAME = eINSTANCE.getToolInfoPage_NodePageName();
+
       /**
        * The meta object literal for the '<em><b>Page</b></em>' container reference feature.
        * <!-- begin-user-doc -->
diff --git a/glsp-server/src-gen/org/pnml/emf/ptnet/ToolInfoPage.java b/glsp-server/src-gen/org/pnml/emf/ptnet/ToolInfoPage.java
index d2efdc9..c3cc932 100644
--- a/glsp-server/src-gen/org/pnml/emf/ptnet/ToolInfoPage.java
+++ b/glsp-server/src-gen/org/pnml/emf/ptnet/ToolInfoPage.java
@@ -32,6 +32,8 @@ public interface ToolInfoPage extends ToolInfo {
     */
    String getServiceName();
 
+   String getNodePageName();
+
    /**
     * Sets the value of the '{@link org.pnml.emf.ptnet.ToolInfoPage#getServiceName <em>Service Name</em>}' attribute.
     * <!-- begin-user-doc -->
@@ -42,6 +44,8 @@ public interface ToolInfoPage extends ToolInfo {
     */
    void setServiceName(String value);
 
+   void setNodePageName(String value);
+
    /**
     * Returns the value of the '<em><b>Page</b></em>' container reference.
     * It is bidirectional and its opposite is '{@link org.pnml.emf.ptnet.Page#getToolspecific <em>Toolspecific</em>}'.
diff --git a/glsp-server/src-gen/org/pnml/emf/ptnet/impl/PtnetPackageImpl.java b/glsp-server/src-gen/org/pnml/emf/ptnet/impl/PtnetPackageImpl.java
index 1c7ef08..f8dcf06 100644
--- a/glsp-server/src-gen/org/pnml/emf/ptnet/impl/PtnetPackageImpl.java
+++ b/glsp-server/src-gen/org/pnml/emf/ptnet/impl/PtnetPackageImpl.java
@@ -2021,7 +2021,12 @@ public class PtnetPackageImpl extends EPackageImpl implements PtnetPackage {
     * @generated
     */
    @Override
-   public EReference getToolInfoPage_Page() { return (EReference) toolInfoPageEClass.getEStructuralFeatures().get(1); }
+   public EReference getToolInfoPage_Page() { return (EReference) toolInfoPageEClass.getEStructuralFeatures().get(2); }
+
+   @Override
+   public EAttribute getToolInfoPage_NodePageName() {
+      return (EAttribute) toolInfoPageEClass.getEStructuralFeatures().get(1);
+   }
 
    /**
     * <!-- begin-user-doc -->
@@ -2752,6 +2757,7 @@ public class PtnetPackageImpl extends EPackageImpl implements PtnetPackage {
 
       toolInfoPageEClass = createEClass(TOOL_INFO_PAGE);
       createEAttribute(toolInfoPageEClass, TOOL_INFO_PAGE__SERVICE_NAME);
+      createEAttribute(toolInfoPageEClass, TOOL_INFO_PAGE__NODE_NAME);
       createEReference(toolInfoPageEClass, TOOL_INFO_PAGE__PAGE);
 
       toolInfoNetEClass = createEClass(TOOL_INFO_NET);
@@ -3343,6 +3349,10 @@ public class PtnetPackageImpl extends EPackageImpl implements PtnetPackage {
          ToolInfoPage.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, !IS_RESOLVE_PROXIES,
          !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 
+      initEAttribute(getToolInfoPage_NodePageName(), ecorePackage.getEString(), "nodePageName", null, 0, 1,
+         ToolInfoPage.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED,
+         IS_ORDERED);
+
       initEClass(toolInfoNetEClass, ToolInfoNet.class, "ToolInfoNet", !IS_ABSTRACT, !IS_INTERFACE,
          IS_GENERATED_INSTANCE_CLASS);
       initEReference(getToolInfoNet_Inputsignals(), this.getInputSignals(), this.getInputSignals_ToolInfoNet(),
diff --git a/glsp-server/src-gen/org/pnml/emf/ptnet/impl/ToolInfoPageImpl.java b/glsp-server/src-gen/org/pnml/emf/ptnet/impl/ToolInfoPageImpl.java
index 8269f06..2fb904e 100644
--- a/glsp-server/src-gen/org/pnml/emf/ptnet/impl/ToolInfoPageImpl.java
+++ b/glsp-server/src-gen/org/pnml/emf/ptnet/impl/ToolInfoPageImpl.java
@@ -2,6 +2,7 @@
  */
 package org.pnml.emf.ptnet.impl;
 
+import org.checkerframework.common.reflection.qual.NewInstance;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 
@@ -40,6 +41,7 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
     * @ordered
     */
    protected static final String SERVICE_NAME_EDEFAULT = null;
+   protected static final String NODE_NAME_EDEFAULT = null;
 
    /**
     * The cached value of the '{@link #getServiceName() <em>Service Name</em>}' attribute.
@@ -50,6 +52,7 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
     * @ordered
     */
    protected String serviceName = SERVICE_NAME_EDEFAULT;
+   protected String nodePageName = NODE_NAME_EDEFAULT;
 
    /**
     * <!-- begin-user-doc -->
@@ -78,6 +81,9 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
    @Override
    public String getServiceName() { return serviceName; }
 
+   @Override
+   public String getNodePageName(){ return nodePageName; }
+
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
@@ -92,6 +98,16 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
             oldServiceName, serviceName));
    }
 
+   @Override
+   public void setNodePageName(String newNodePageName) {
+      String oldNodePageName = nodePageName;
+      nodePageName = newNodePageName;
+      if (eNotificationRequired())
+         eNotify(new ENotificationImpl(this, Notification.SET, PtnetPackage.TOOL_INFO_PAGE__NODE_NAME,
+            oldNodePageName, nodePageName));
+   }
+
+
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
@@ -191,6 +207,10 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
       switch (featureID) {
          case PtnetPackage.TOOL_INFO_PAGE__SERVICE_NAME:
             return getServiceName();
+
+         case PtnetPackage.TOOL_INFO_PAGE__NODE_NAME:
+            return getNodePageName();
+
          case PtnetPackage.TOOL_INFO_PAGE__PAGE:
             return getPage();
       }
@@ -208,6 +228,11 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
          case PtnetPackage.TOOL_INFO_PAGE__SERVICE_NAME:
             setServiceName((String) newValue);
             return;
+         
+         case PtnetPackage.TOOL_INFO_PAGE__NODE_NAME:
+            setNodePageName((String) newValue);
+            return;
+
          case PtnetPackage.TOOL_INFO_PAGE__PAGE:
             setPage((Page) newValue);
             return;
@@ -226,6 +251,11 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
          case PtnetPackage.TOOL_INFO_PAGE__SERVICE_NAME:
             setServiceName(SERVICE_NAME_EDEFAULT);
             return;
+
+         case PtnetPackage.TOOL_INFO_PAGE__NODE_NAME:
+            setNodePageName(NODE_NAME_EDEFAULT);
+            return;
+
          case PtnetPackage.TOOL_INFO_PAGE__PAGE:
             setPage((Page) null);
             return;
@@ -243,6 +273,10 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
       switch (featureID) {
          case PtnetPackage.TOOL_INFO_PAGE__SERVICE_NAME:
             return SERVICE_NAME_EDEFAULT == null ? serviceName != null : !SERVICE_NAME_EDEFAULT.equals(serviceName);
+            
+         case PtnetPackage.TOOL_INFO_PAGE__NODE_NAME:
+            return NODE_NAME_EDEFAULT == null ? nodePageName != null : !NODE_NAME_EDEFAULT.equals(nodePageName);
+
          case PtnetPackage.TOOL_INFO_PAGE__PAGE:
             return getPage() != null;
       }
@@ -260,8 +294,16 @@ public class ToolInfoPageImpl extends ToolInfoImpl implements ToolInfoPage {
          return super.toString();
 
       StringBuilder result = new StringBuilder(super.toString());
-      result.append(" (serviceName: ");
-      result.append(serviceName);
+      if(eIsSet(PtnetPackage.TOOL_INFO_PAGE__SERVICE_NAME))
+      {
+         result.append(" (serviceName: ");
+         result.append(serviceName);
+      }
+      else
+      {
+         result.append(" (pageNodeName: ");
+         result.append(serviceName);
+      }
       result.append(')');
       return result.toString();
    }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/PNMLModelTypes.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/PNMLModelTypes.java
index cb94adc..3fa44bd 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/PNMLModelTypes.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/PNMLModelTypes.java
@@ -37,6 +37,8 @@ public final class PNMLModelTypes {
     public static final String SERVER_PAGE = "serverPrototype";
     public static final String SERVICE_SERVER_LINK = "serviceServerLink";
 
+    public static final String NODE_PAGE = "nodeAsPage";
+
     public static final String DISCRETE_TRANSITION = "discreteTransitionType";
     public static final String SIGNAL_CLAUSE_LABEL = "signalClauseLabel";
     public static final String DINEROS_TOOL_NAME = "de.tudresden.inf.st.pnml.distributedPN";
@@ -67,6 +69,9 @@ public final class PNMLModelTypes {
 
         public static final int ServerPageWidth = 250;
         public static final int ServerPageHeight = 250;
+
+        public static final int NodePageWidth = 250;
+        public static final int NodePageHeight = 250;
     }
 
 }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java
index 2aa5041..108aebb 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java
@@ -116,6 +116,7 @@ public class TaskListDiagramModule extends EMFNotationDiagramModule {
       binding.add(DeleteDiNeROSTokenHandler.class);
       binding.add(SetDiNeROSTokenHandler.class);
 
+      binding.add(CreateNodePageHandler.class);
    }
 
 
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/DiNeROS/ElementCreation/CreateNodePageHandler.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/DiNeROS/ElementCreation/CreateNodePageHandler.java
new file mode 100644
index 0000000..e9d255c
--- /dev/null
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/DiNeROS/ElementCreation/CreateNodePageHandler.java
@@ -0,0 +1,70 @@
+package org.eclipse.glsp.example.javaemf.handler.DiNeROS.ElementCreation;
+
+import java.util.Optional;
+
+import org.eclipse.glsp.example.javaemf.PNMLModelTypes;
+import org.eclipse.glsp.example.javaemf.handler.NodeCreation.CreatePageHandler;
+import org.eclipse.glsp.server.operations.CreateNodeOperation;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.edit.command.AddCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.glsp.graph.GModelElement;
+import org.eclipse.glsp.graph.GPoint;
+import org.eclipse.glsp.graph.util.GraphUtil;
+import org.pnml.emf.ptnet.*;
+
+import java.util.Optional;
+
+public class CreateNodePageHandler extends CreatePageHandler
+{
+    public CreateNodePageHandler(){super(PNMLModelTypes.NODE_PAGE);}
+ 
+    @Override
+    public String getLabel(){return "NodePage";}
+
+    @Override
+    public Optional<Command> createCommand(final CreateNodeOperation operation)
+    {
+        GModelElement container = 
+            modelState.getIndex().get(operation.getContainerId())
+                        .orElseGet(modelState::getRoot);
+
+        EObject parentElement = getParentElement(container);
+        EReference relationshipLiteral = getRelationshipLiteral(container);
+
+        Page newPage = PtnetFactory.eINSTANCE.createPage();;
+        setElementId(newPage);
+        setInitialName(newPage, "NodePage");
+        newPage.getToolspecific().add(createNodePageToolInfo(newPage));
+
+        NodeGraphics shape = 
+            createShape(idGenerator.getOrCreateId(newPage),
+            getRelativeLocation(operation), 
+            GraphUtil.dimension(
+                PNMLModelTypes.DefaultSizes.NodePageWidth, 
+                PNMLModelTypes.DefaultSizes.NodePageHeight));
+
+        newPage.setNodegraphics(shape);
+
+        Command pageCommand = 
+            AddCommand.create(
+                modelState.getEditingDomain(), 
+                parentElement,
+                relationshipLiteral, 
+                newPage);
+
+        return Optional.of(pageCommand);
+    }
+
+    protected ToolInfoPage createNodePageToolInfo (Page newPage)
+    {
+        ToolInfoPage toolSpecifics = PtnetFactory.eINSTANCE.createToolInfoPage();
+        toolSpecifics.setTool(PNMLModelTypes.DINEROS_TOOL_NAME);
+        toolSpecifics.setVersion(PNMLModelTypes.DINEROS_VERSION);
+        toolSpecifics.setType(PNMLModelTypes.NODE_PAGE);
+        toolSpecifics.setServiceName(newPage.getName().getText());
+        return toolSpecifics;
+    }
+}
\ No newline at end of file
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/LabelEditOperationHandler.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/LabelEditOperationHandler.java
index 7e07c24..337008d 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/LabelEditOperationHandler.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/LabelEditOperationHandler.java
@@ -111,6 +111,13 @@ public class LabelEditOperationHandler extends EMFOperationHandler<ApplyLabelEdi
                 command.append(SetCommand.create(modelState.getEditingDomain(), toolSpecifics,
                     PtnetPackage.Literals.TOOL_INFO_PAGE__SERVICE_NAME, labelText));
             }
+
+            if(modelAccessUtil.isNodePage(page))
+            {
+                ToolInfoPage toolSpecifics = modelAccessUtil.getDiNeROSPageToolSpecific(page).orElseThrow();
+                command.append(SetCommand.create(modelState.getEditingDomain(), toolSpecifics,
+                    PtnetPackage.Literals.TOOL_INFO_PAGE__NODE_NAME, labelText));
+            }
         }
 
 
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/NodeCreation/CreatePageHandler.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/NodeCreation/CreatePageHandler.java
index 3547e6b..87514af 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/NodeCreation/CreatePageHandler.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/NodeCreation/CreatePageHandler.java
@@ -29,7 +29,12 @@ public class CreatePageHandler extends AbstractCreateNodeHandler<CreateNodeOpera
 
     @Override
     public Optional<Command> createCommand(final CreateNodeOperation operation) {
-        GModelElement container = modelState.getIndex().get(operation.getContainerId()).orElseGet(modelState::getRoot);
+
+        GModelElement container = 
+            modelState.getIndex().get(operation.getContainerId())
+                .orElseGet(modelState::getRoot);
+
+        denySecondRootPage(container);
 
         EObject parentElement = getParentElement(container);
         EReference relationshipLiteral = getRelationshipLiteral(container);
@@ -37,13 +42,23 @@ public class CreatePageHandler extends AbstractCreateNodeHandler<CreateNodeOpera
         Page newPage = PtnetFactory.eINSTANCE.createPage();
         initializeElement(newPage);
 
-        NodeGraphics shape = createShape(idGenerator.getOrCreateId(newPage),
-            getRelativeLocation(operation), GraphUtil.dimension(PNMLModelTypes.DefaultSizes.PageWidth, PNMLModelTypes.DefaultSizes.PageHeight));
-        newPage.setNodegraphics(shape);
+        NodeGraphics shape = 
+            createShape(
+                idGenerator.getOrCreateId(newPage),
+                getRelativeLocation(operation), 
+                GraphUtil.dimension(
+                    PNMLModelTypes.DefaultSizes.PageWidth, 
+                    PNMLModelTypes.DefaultSizes.PageHeight)
+                );
 
-        Command pageCommand = AddCommand.create( modelState.getEditingDomain(), parentElement,
-            relationshipLiteral, newPage);
+        newPage.setNodegraphics(shape);
 
+        Command pageCommand = 
+            AddCommand.create( 
+                modelState.getEditingDomain(), 
+                parentElement,
+                relationshipLiteral, 
+                newPage);
 
         return Optional.of(pageCommand);
     }
@@ -69,4 +84,17 @@ public class CreatePageHandler extends AbstractCreateNodeHandler<CreateNodeOpera
         }
     }
 
+    protected void denySecondRootPage(final GModelElement container)
+    {
+        /* 
+         * assuming all other elements ensure there is an enclosing page,
+         * an empty model implies that no such page exists
+         */
+        if(!modelState.getRoot().eContents().isEmpty() && 
+            container.getType().equals(PNMLModelTypes.GRAPH))
+
+            throw new IllegalArgumentException(
+                "One page has to encapsulate the model"+
+                " - only one such page may exist at any time.");
+    }
 }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java
index 1a51793..e7a1a27 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java
@@ -123,6 +123,14 @@ public class ModelAccessUtil {
             .anyMatch(toolInfo -> Objects.equals(toolInfo.getType(), PNMLModelTypes.SERVER_PAGE));
     }
 
+    public boolean isNodePage(Page page) {
+        if(page.getToolspecific() == null || page.getToolspecific().isEmpty()){
+            return false;
+        }
+        return page.getToolspecific().stream()
+            .anyMatch(toolInfo -> Objects.equals(toolInfo.getType(), PNMLModelTypes.NODE_PAGE));
+    }
+
     public Optional<ToolInfoTransition> getDiNeROSTransitionToolSpecific(Transition transition, String type){
         return transition.getToolspecific().stream().filter(toolInfo -> Objects.equals(toolInfo.getType(), type))
             .findFirst();
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java
index b432e55..996cf1e 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java
@@ -229,7 +229,18 @@ public class TaskListGModelFactory extends EMFNotationGModelFactory {
                  .text((modelAccessUtil.getName(page)))
                  .id(idGenerator.getOrCreateId(page) + "_label")
                  .build());
-      } else {
+      } 
+      else if(modelAccessUtil.isNodePage(page)) 
+      {
+        pageNodeBuilder
+        .type(PNMLModelTypes.NODE_PAGE)
+        .addCssClass("node-page")
+        .add(new GLabelBuilder(DefaultTypes.LABEL)
+            .text((modelAccessUtil.getName(page)))
+            .id(idGenerator.getOrCreateId(page) + "_label")
+            .build());
+      } 
+      else {
          pageNodeBuilder
              .type(PNMLModelTypes.PAGE_NODE)
              .addCssClass("page-node")
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/palette/TaskListToolPaletteItemProvider.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/palette/TaskListToolPaletteItemProvider.java
index fe0ea0b..2fe6952 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/palette/TaskListToolPaletteItemProvider.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/palette/TaskListToolPaletteItemProvider.java
@@ -75,6 +75,7 @@ public class TaskListToolPaletteItemProvider implements ToolPaletteItemProvider
         PaletteItem createServiceChannelLink = edge(PNMLModelTypes.SERVICE_CHANNEL_LINK, "Service Link");
         PaletteItem createServiceServerlLink = edge(PNMLModelTypes.SERVICE_SERVER_LINK, "Server Link");
 
+        PaletteItem createNodePage = node(PNMLModelTypes.NODE_PAGE, "Node Page");
 
         List<PaletteItem> nodes = Lists.newArrayList(
             createTopic,
@@ -82,6 +83,7 @@ public class TaskListToolPaletteItemProvider implements ToolPaletteItemProvider
             createTopicLink,
             createServiceChannel,
             createServerPage,
+            createNodePage,
             createServiceChannelLink,
             createServiceServerlLink
         );
-- 
GitLab