diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFEdgeLink.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFEdgeLink.cs
index ee0ae20b184ac1c30465b2648b31a727a4222bb4..1f39c84b149e444f415e87761726a7f06fe368f1 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFEdgeLink.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFEdgeLink.cs	
@@ -22,6 +22,7 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Graph
 
         public void clicked()
         {
+            Debug.Log(worldLink.ToJson());
             NodeEditorWindow.ShowWindow(this);
         }
     }
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFGraphView.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFGraphView.cs
index b85f7c825d3198f6b92821b81c93383f28554d8b..6cd3ad9093b15a5d3633ee6b6c15408012b222b7 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFGraphView.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFGraphView.cs	
@@ -76,7 +76,7 @@ namespace ETSI.ARF.WorldStorage.UI
             {
                 if (SaveInfo.instance.elemsToRemove == null)
                 {
-                    SaveInfo.instance.elemsToRemove = new List<string>();
+                    SaveInfo.instance.elemsToRemove = new Dictionary<string, Type>();
                 }
                 foreach (GraphElement elt in selection.ToArray())
                 {
@@ -86,7 +86,7 @@ namespace ETSI.ARF.WorldStorage.UI
                         nodeAnchor.DisconnectAllPorts(this);
                         if (SaveInfo.instance.nodePositions.ContainsKey(nodeAnchor.GUID))
                         {
-                            SaveInfo.instance.elemsToRemove.Add(nodeAnchor.GUID);
+                            SaveInfo.instance.elemsToRemove.Add(nodeAnchor.GUID, typeof(WorldAnchor));
                         }
                         RemoveElement(elt);
                         continue;
@@ -97,7 +97,7 @@ namespace ETSI.ARF.WorldStorage.UI
                         nodeTrackable.DisconnectAllPorts(this);
                         if (SaveInfo.instance.nodePositions.ContainsKey(nodeTrackable.GUID))
                         {
-                            SaveInfo.instance.elemsToRemove.Add(nodeTrackable.GUID);
+                            SaveInfo.instance.elemsToRemove.Add(nodeTrackable.GUID, typeof(Trackable));
                         }
                         RemoveElement(elt);
                         continue;
@@ -107,7 +107,7 @@ namespace ETSI.ARF.WorldStorage.UI
                     {
                         edgeLink.input.Disconnect(edgeLink);
                         edgeLink.output.Disconnect(edgeLink);
-                        SaveInfo.instance.elemsToRemove.Add(edgeLink.GUID);
+                        SaveInfo.instance.elemsToRemove.Add(edgeLink.GUID, typeof(WorldLink));
                         RemoveElement(elt);
                         continue;
                     }
@@ -123,9 +123,9 @@ namespace ETSI.ARF.WorldStorage.UI
             evt.menu.AppendSeparator();
             evt.menu.AppendAction("Reload graph", delegate
             {
-                if (positionshaveBeenChanged() && EditorUtility.DisplayDialog("Saving node positions", "The nodes positions have been changed, would you like to save them ?", "Yes", "No"))
+                if (ServerAndLocalDifferent() && EditorUtility.DisplayDialog("Saving node positions", "The World Graph has been modified. \nWould you like to push the modifications to the server ?", "Yes", "No"))
                 {
-                    saveElemPositionsInServer();
+                    saveInServer();
                 }
                 reload();
                 SaveInfo.instance.toReFrame = true;
@@ -185,9 +185,10 @@ namespace ETSI.ARF.WorldStorage.UI
             {
             }
         }
-        private bool positionshaveBeenChanged()
+
+        public bool ServerAndLocalDifferent()
         {
-            if (SaveInfo.instance.elemsToRemove.Count != 0)
+            if ((SaveInfo.instance.elemsToRemove.Count != 0) || (SaveInfo.instance.elemsToUpdate.Count != 0))
             {
                 return true;
             }
@@ -195,9 +196,23 @@ namespace ETSI.ARF.WorldStorage.UI
             {
                 float nodeX = node.GetPosition().x;
                 float nodeY = node.GetPosition().y;
-                float dataX = SaveInfo.instance.nodePositions[node.GUID].x;
-                float dataY = SaveInfo.instance.nodePositions[node.GUID].y;
-                if ((nodeX != dataX) || (nodeY != dataY))
+                if (!SaveInfo.instance.nodePositions.ContainsKey(node.GUID))
+                {
+                    return true;
+                }
+                else
+                {
+                    float dataX = SaveInfo.instance.nodePositions[node.GUID].x;
+                    float dataY = SaveInfo.instance.nodePositions[node.GUID].y;
+                    if ((nodeX != dataX) || (nodeY != dataY))
+                    {
+                        return true;
+                    }
+                }
+            }
+            foreach (ARFEdgeLink edge in edges)
+            {
+                if (!SaveInfo.instance.linkIds.Contains(edge.GUID))
                 {
                     return true;
                 }
@@ -225,7 +240,7 @@ namespace ETSI.ARF.WorldStorage.UI
             {
                 var waNode = new ARFNodeWorldAnchor(worldAnchor);
 
-                Rect posTemp = new Rect(26, 93, 160, 77);
+                Rect posTemp = new(26, 93, 160, 77);
                 SaveInfo.instance.nodePositions.TryGetValue(worldAnchor.UUID.ToString(), out posTemp);
                 waNode.SetPosition(posTemp);
 
@@ -236,7 +251,7 @@ namespace ETSI.ARF.WorldStorage.UI
             {
                 var tracknode = new ARFNodeTrackable(trackable);
 
-                Rect posTemp = new Rect(26, 93, 160, 77);
+                Rect posTemp = new(26, 93, 160, 77);
                 SaveInfo.instance.nodePositions.TryGetValue(trackable.UUID.ToString(), out posTemp);
                 tracknode.SetPosition(posTemp);
 
@@ -427,14 +442,64 @@ namespace ETSI.ARF.WorldStorage.UI
             return a = Mathf.Round(a * 2f) * 0.5f;
         }
 
-        public void saveElemPositionsInServer()
+        //Save all modified/deleted/added elements to the server
+        public void saveInServer()
         {
             foreach (ARFNode node in nodes)
             {
                 if (!SaveInfo.instance.nodePositions.ContainsKey(node.GUID))
                 {
-                    //TODO
-                    Debug.Log("need to post " + node.GUID);
+                    //POST TRACKABLE
+                    if (node is ARFNodeTrackable aRFNodeTrackable)
+                    {
+                        var posX = new List<String>();
+                        posX.Add(aRFNodeTrackable.GetPosition().x.ToString());
+                        var posY = new List<String>();
+                        posY.Add(aRFNodeTrackable.GetPosition().y.ToString());
+                        Trackable trackable = aRFNodeTrackable.trackable;
+                        trackable.KeyvalueTags["unityAuthoringPosX"] = posX;
+                        trackable.KeyvalueTags["unityAuthoringPosY"] = posY;
+                        String uuid = TrackableRequest.AddTrackable(worldStorageServer, trackable);
+
+                        //change the uuid in its edges, if there is a new edge to be added in the world storage it needs to have the correct uuid
+                        uuid = uuid.Replace("\"", "");
+                        foreach (ARFEdgeLink edge in aRFNodeTrackable.portIn.connections)
+                        {
+                            edge.worldLink.UUIDTo = Guid.Parse(uuid);
+                        }
+                        foreach (ARFEdgeLink edge in aRFNodeTrackable.portOut.connections)
+                        {
+                            edge.worldLink.UUIDFrom = Guid.Parse(uuid);
+                        }
+                        aRFNodeTrackable.trackable.UUID = Guid.Parse(uuid);
+                        aRFNodeTrackable.GUID = uuid;
+                    }
+                    //POST WORLDANCHOR
+                    if (node is ARFNodeWorldAnchor aRFNodeWorldAnchor)
+                    {
+                        var posX = new List<String>();
+                        posX.Add(aRFNodeWorldAnchor.GetPosition().x.ToString());
+                        var posY = new List<String>();
+                        posY.Add(aRFNodeWorldAnchor.GetPosition().y.ToString());
+                        WorldAnchor worldAnchor = aRFNodeWorldAnchor.worldAnchor;
+                        worldAnchor.KeyvalueTags["unityAuthoringPosX"] = posX;
+                        worldAnchor.KeyvalueTags["unityAuthoringPosY"] = posY;
+
+                        String uuid = WorldAnchorRequest.AddWorldAnchor(worldStorageServer, worldAnchor);
+
+                        //change the uuid in its edges, if there is a new edge to be added in the world storage it needs to have the correct uuid
+                        uuid = uuid.Replace("\"","");
+                        foreach (ARFEdgeLink edge in aRFNodeWorldAnchor.portIn.connections)
+                        {
+                            edge.worldLink.UUIDTo = Guid.Parse(uuid);
+                        }
+                        foreach (ARFEdgeLink edge in aRFNodeWorldAnchor.portOut.connections)
+                        {
+                            edge.worldLink.UUIDFrom = Guid.Parse(uuid);
+                        }
+                        aRFNodeWorldAnchor.worldAnchor.UUID = Guid.Parse(uuid);
+                        aRFNodeWorldAnchor.GUID = uuid;
+                    }
                 }
                 else
                 {
@@ -442,26 +507,74 @@ namespace ETSI.ARF.WorldStorage.UI
                     float yLocal = node.GetPosition().y;
                     float xServer = SaveInfo.instance.nodePositions[node.GUID].x; ;
                     float yServer = SaveInfo.instance.nodePositions[node.GUID].y;
-                    if ((xLocal != xServer) && (yLocal != yServer))
+                    if (((xLocal != xServer) || (yLocal != yServer)) || SaveInfo.instance.elemsToUpdate.Contains(node.GUID))
                     {
-                        //TODO
-                        Debug.Log("need to update " + node.GUID);
+                        if(node is ARFNodeTrackable aRFNodeTrackable)
+                        {
+                            var posX = new List<String>();
+                            posX.Add(aRFNodeTrackable.GetPosition().x.ToString());
+                            var posY = new List<String>();
+                            posY.Add(aRFNodeTrackable.GetPosition().y.ToString());
+                            Trackable trackable = aRFNodeTrackable.trackable;
+                            trackable.KeyvalueTags["unityAuthoringPosX"] = posX;
+                            trackable.KeyvalueTags["unityAuthoringPosY"] = posY;
+                            TrackableRequest.UpdateTrackable(worldStorageServer, trackable);
+                        }
+                        if (node is ARFNodeWorldAnchor aRFNodeWorldAnchor)
+                        {
+                            var posX = new List<String>();
+                            posX.Add(aRFNodeWorldAnchor.GetPosition().x.ToString());
+                            var posY = new List<String>();
+                            posY.Add(aRFNodeWorldAnchor.GetPosition().y.ToString());
+                            WorldAnchor worldAnchor = aRFNodeWorldAnchor.worldAnchor;
+                            worldAnchor.KeyvalueTags["unityAuthoringPosX"] = posX;
+                            worldAnchor.KeyvalueTags["unityAuthoringPosY"] = posY;
+                            WorldAnchorRequest.UpdateWorldAnchor(worldStorageServer, worldAnchor);
+                        }
                     }
                 }
             }
             foreach (ARFEdgeLink edge in edges)
             {
-                if (!SaveInfo.instance.linkIds.Contains(edge.GUID))
+                if (edge is ARFEdgeLink aRFEdgeLink)
                 {
-                    //TODO
-                    Debug.Log("need to post link between " + edge.input);
+                    if (!SaveInfo.instance.linkIds.Contains(aRFEdgeLink.GUID))
+                    {
+                        WorldLink worldLink = aRFEdgeLink.worldLink;
+                        string uuid = WorldLinkRequest.AddWorldLink(worldStorageServer, worldLink);
+                        uuid = uuid.Replace("\"", "");
+
+                        aRFEdgeLink.worldLink.UUID = Guid.Parse(uuid);
+                        aRFEdgeLink.GUID = uuid;
+                    }
+                    else if (SaveInfo.instance.elemsToUpdate.Contains(aRFEdgeLink.GUID))
+                    {
+                        WorldLink worldLink = aRFEdgeLink.worldLink;
+                        WorldLinkRequest.UpdateWorldLink(worldStorageServer, worldLink);
+                    }
                 }
             }
-            foreach (String elemId in SaveInfo.instance.elemsToRemove)
+            //DELETE ELEMENTS FROM THE SERVER
+            foreach (KeyValuePair<String, Type> elemToRemove in SaveInfo.instance.elemsToRemove)
             {
-                //TODO
-                Debug.Log("need to remove " + elemId);
+                string typeName = elemToRemove.Value.Name;
+                switch (typeName)
+                {
+                    case nameof(Trackable):
+                        TrackableRequest.DeleteTrackable(worldStorageServer, elemToRemove.Key);
+                        break;
+                    case nameof(WorldAnchor):
+                        WorldAnchorRequest.DeleteWorldAnchor(worldStorageServer, elemToRemove.Key);
+                        break;
+                    case nameof(WorldLink):
+                        WorldLinkRequest.DeleteWorldLink(worldStorageServer, elemToRemove.Key);
+                        break;
+                    default:
+                        Debug.Log("oops");
+                        break;
+                }
             }
+            SaveInfo.instance.initNodePos(worldStorageServer, worldStorageUser);
         }
     }
 }
\ No newline at end of file
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNode.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNode.cs
index 6c29371aa286dcbe0f9fccb5581906357972b2f8..fb3eb4e9d56ded0e5e164a43be766770573b83cf 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNode.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNode.cs	
@@ -39,27 +39,26 @@ using System;
 
 namespace ETSI.ARF.WorldStorage.UI
 {
-    public class ARFNode : Node
+    public abstract class ARFNode : Node
     {
         public string GUID;
         public bool entryPoint = false;
-        public Port portOut;
-        public Port portIn;
+        public ARFPort portOut;
+        public ARFPort portIn;
         public GUID id;
         public ARFNode()
         {
             
         }
-
         public override Port InstantiatePort(Orientation orientation, Direction direction, Port.Capacity capacity, Type type)
         {
             switch (direction)
             {
                 case Direction.Input:
-                    portIn = Port.Create<ARFEdgeLink>(orientation, direction, capacity, type);
+                    portIn = ARFPort.CreateARF<ARFEdgeLink>(orientation, direction, capacity, type);
                     return portIn;
                 case Direction.Output:
-                    portOut = Port.Create<ARFEdgeLink>(orientation, direction, capacity, type);
+                    portOut = ARFPort.CreateARF<ARFEdgeLink>(orientation, direction, capacity, type);
                     return portOut;
                 default:
                     return null;
@@ -99,5 +98,7 @@ namespace ETSI.ARF.WorldStorage.UI
         {
             return node.InstantiatePort(Orientation.Horizontal, portDirection, capacity, typeof(int)); // dummy
         }
+
+        public abstract ObjectType GetElemType();
     }
 }
\ No newline at end of file
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeTrackable.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeTrackable.cs
index b25b58e73ca7634a46e7f81d957dce74cf21516d..ebc1646a9bcde7ec56711cdb5ad6412e57cecc01 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeTrackable.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeTrackable.cs	
@@ -60,13 +60,13 @@ namespace ETSI.ARF.WorldStorage.UI
             var portIn = GeneratePort(this, Direction.Input, Port.Capacity.Multi);
             portIn.portColor = new Color(0.77f, 0.77f, 0.77f, 0.77f);
             portIn.portName = "Target"; // "Input"
-            portIn.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener()));
+            //portIn.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener()));
             inputContainer.Add(portIn);
 
             var portOut = GeneratePort(this, Direction.Output, Port.Capacity.Multi);
             portOut.portColor = new Color(0.77f, 0.77f, 0.77f, 0.77f);
             portOut.portName = "Source"; // "Output";
-            portOut.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener())); ;
+            //portOut.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener())); ;
             outputContainer.Add(portOut);
 
             RefreshExpandedState();
@@ -84,5 +84,9 @@ namespace ETSI.ARF.WorldStorage.UI
             NodeEditorWindow.ShowWindow(this);
             Debug.Log(trackable.ToString());
         }
+        public override ObjectType GetElemType()
+        {
+            return ObjectType.Trackable;
+        }
     }
 }
\ No newline at end of file
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeWorldAnchor.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeWorldAnchor.cs
index a8c83a337c3360a7aca0de47a04a881c8001e55a..4c272f906ad305c1c2fca99208225bbc6519b8ba 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeWorldAnchor.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFNodeWorldAnchor.cs	
@@ -60,13 +60,13 @@ namespace ETSI.ARF.WorldStorage.UI
             var portIn = GeneratePort(this, Direction.Input, Port.Capacity.Multi);
             portIn.portColor = new Color(0.77f,0.77f,0.77f, 0.77f);
             portIn.portName = "Target"; // "Input";
-            portIn.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener()));
+            //portIn.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener()));
             inputContainer.Add(portIn);
 
             var portOut = GeneratePort(this, Direction.Output, Port.Capacity.Multi);
             portOut.portColor = new Color(0.77f, 0.77f, 0.77f, 0.77f);
             portOut.portName = "Source"; // "Output";
-            portOut.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener()));
+            //portOut.AddManipulator(new EdgeConnector<ARFEdgeLink>(new WorldLinkListener()));
             outputContainer.Add(portOut);
 
             RefreshExpandedState();
@@ -84,5 +84,9 @@ namespace ETSI.ARF.WorldStorage.UI
             Debug.Log(worldAnchor.ToString());
             NodeEditorWindow.ShowWindow(this);
         }
+        public override ObjectType GetElemType()
+        {
+            return ObjectType.WorldAnchor;
+        }
     }
 }
\ No newline at end of file
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFPort.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFPort.cs
new file mode 100644
index 0000000000000000000000000000000000000000..faa80776654773811633e56a7ce197debacc3a16
--- /dev/null
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFPort.cs	
@@ -0,0 +1,49 @@
+using Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows;
+using ETSI.ARF.WorldStorage.UI;
+using Org.OpenAPITools.Model;
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEditor.Experimental.GraphView;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Graph
+{
+    public class ARFPort : Port
+    {
+        protected ARFPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) : base(portOrientation, portDirection, portCapacity, type)
+        {
+        }
+
+        public override void Connect(Edge edge)
+        {
+            base.Connect(edge);
+            ARFNode fromNode = edge.output.node as ARFNode;
+            ARFNode toNode = edge.input.node as ARFNode;
+
+            if (edge is ARFEdgeLink aRFedge)
+            {
+                List<float> transform = new List<float>();
+                for (int i = 0; i < 16; i++)
+                {
+                    transform.Add(0);
+                }
+
+                WorldLink worldLink = new WorldLink(Guid.NewGuid(), Guid.Parse(SaveInfo.instance.worldStorageUser.UUID), Guid.Parse(fromNode.GUID), Guid.Parse(toNode.GUID), fromNode.GetElemType(), toNode.GetElemType(), transform, UnitSystem.CM, new Dictionary<string, List<string>>());
+                aRFedge.worldLink = worldLink;
+            }
+        }
+
+        public static ARFPort CreateARF<TEdge>(Orientation orientation, Direction direction, Capacity capacity, Type type) where TEdge : Edge, new()
+        {
+            WorldLinkListener listener = new WorldLinkListener();
+            ARFPort port = new(orientation, direction, capacity, type)
+            {
+                m_EdgeConnector = new EdgeConnector<TEdge>(listener)
+            };
+            port.AddManipulator(port.m_EdgeConnector);
+            return port;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFPort.cs.meta b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFPort.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..6d043fde500829981fc15944de7d1198cb5e1375
--- /dev/null
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/ARFPort.cs.meta	
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3c67fa4402011954bb65be6215d52512
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/GraphWindow.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/GraphWindow.cs
index 9c496ee89040237b46e84b324ab9267529fc7529..8d70a34a0d72dd8522b941fe4fae238734c13921 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/GraphWindow.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/GraphWindow.cs	
@@ -41,6 +41,8 @@ using IO.Swagger.Model;
 #endif
 
 
+//THIS CLASS IS GOING TO BE DELETED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 namespace ETSI.ARF.WorldStorage.UI
 {
 
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/WorldLinkListener.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/WorldLinkListener.cs
index 36c855f14fcdcc3827aed119132b75f97ead4322..79b691491118da7fa2910789ad10db351a5a79fe 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/WorldLinkListener.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Graph/WorldLinkListener.cs	
@@ -1,22 +1,76 @@
 using Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows;
 using ETSI.ARF.WorldStorage;
 using ETSI.ARF.WorldStorage.UI;
+using Org.OpenAPITools.Model;
+using System;
+using System.Collections.Generic;
 using UnityEditor;
 using UnityEditor.Experimental.GraphView;
 using UnityEngine;
 using UnityEngine.UIElements;
+using static UnityEditor.Experimental.GraphView.Port;
 
 namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Graph
 {
     public class WorldLinkListener : IEdgeConnectorListener
     {
+        private GraphViewChange m_GraphViewChange;
+
+        private List<Edge> m_EdgesToCreate;
+
+        private List<GraphElement> m_EdgesToDelete;
+
+        public WorldLinkListener()
+        {
+            m_EdgesToCreate = new List<Edge>();
+            m_EdgesToDelete = new List<GraphElement>();
+            m_GraphViewChange.edgesToCreate = m_EdgesToCreate;
+        }
         public void OnDrop(GraphView graphView, Edge edge)
         {
-            ARFNode fromNode = edge.output.node as ARFNode;
-            ARFNode toNode = edge.input.node as ARFNode;
+            m_EdgesToCreate.Clear();
+            m_EdgesToCreate.Add(edge);
+            m_EdgesToDelete.Clear();
+            if (edge.input.capacity == Capacity.Single)
+            {
+                foreach (Edge connection in edge.input.connections)
+                {
+                    if (connection != edge)
+                    {
+                        m_EdgesToDelete.Add(connection);
+                    }
+                }
+            }
+
+            if (edge.output.capacity == Capacity.Single)
+            {
+                foreach (Edge connection2 in edge.output.connections)
+                {
+                    if (connection2 != edge)
+                    {
+                        m_EdgesToDelete.Add(connection2);
+                    }
+                }
+            }
+
+            if (m_EdgesToDelete.Count > 0)
+            {
+                graphView.DeleteElements(m_EdgesToDelete);
+            }
+
+            List<Edge> edgesToCreate = m_EdgesToCreate;
+            if (graphView.graphViewChanged != null)
+            {
+                edgesToCreate = graphView.graphViewChanged(m_GraphViewChange).edgesToCreate;
+            }
 
+            foreach (Edge item in edgesToCreate)
+            {
+                graphView.AddElement(item);
+                edge.input.Connect(item);
+                edge.output.Connect(item);
+            }
             NodeEditorWindow.ShowWindow((ARFEdgeLink)edge);
-            //WorldLinkWindow.preFill(fromNode, toNode);
         }
 
         public void OnDropOutsidePort(Edge edge, Vector2 position)
diff --git a/Assets/ETSI.ARF/ARF World Storage API/Editor/Windows/WorldGraphWindow.cs b/Assets/ETSI.ARF/ARF World Storage API/Editor/Windows/WorldGraphWindow.cs
index d20562f0cfcdcd47452acd25aadfeea9e3065e00..f32f961183efe7b4d8954d2168471260aeafcc02 100644
--- a/Assets/ETSI.ARF/ARF World Storage API/Editor/Windows/WorldGraphWindow.cs	
+++ b/Assets/ETSI.ARF/ARF World Storage API/Editor/Windows/WorldGraphWindow.cs	
@@ -19,6 +19,9 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
 
         private ARFGraphView myGraph;
 
+        //to delay the reframe (otherwise it reframes when the graph isn't built yet)
+        int twoFrames = 0;
+
         [MenuItem("ARFWorldStorage/Edit Graph...")]
         public static void ShowWindow()
         {
@@ -27,13 +30,13 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
 
         public void OnEnable()
         {
-            if (SaveInfo.instance.nodePositions == null)
-            {
-                SaveInfo.instance.initNodePos(worldStorageServer);
-            }
 
             rootVisualElement.Add(GenerateToolbar());
 
+            if (SaveInfo.instance.nodePositions == null)
+            {
+                SaveInfo.instance.initNodePos(worldStorageServer, worldStorageUser);
+            }
             ConstructGraphView();
             myGraph.style.top = Length.Percent(11);
             rootVisualElement.Add(myGraph);
@@ -58,6 +61,11 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
 
         void OnGUI()
         {
+            if (SaveInfo.instance.nodePositions == null)
+            {
+                SaveInfo.instance.initNodePos(worldStorageServer, worldStorageUser);
+            }
+
             EditorGUILayout.BeginVertical();
             EditorGUILayout.Space(24);
 
@@ -65,11 +73,13 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
             worldStorageServer = (WorldStorageServer)EditorGUILayout.ObjectField("World Storage Server", worldStorageServer, typeof(WorldStorageServer), false, GUILayout.Width(500));
             if (EditorGUI.EndChangeCheck())
             {
-                myGraph.saveElemPositionsInServer();
+                if (myGraph.ServerAndLocalDifferent() && EditorUtility.DisplayDialog("Saving node positions", "The World Graph has been modified. \nWould you like to push the modifications to the server ?", "Yes", "No"))
+                {
+                    myGraph.saveInServer();
+                }
                 rootVisualElement.Remove(myGraph);
 
-                SaveInfo.instance.initNodePos(worldStorageServer);
-
+                SaveInfo.instance.initNodePos(worldStorageServer, worldStorageUser);
                 ConstructGraphView();
                 myGraph.style.top = Length.Percent(11);
                 rootVisualElement.Add(myGraph);
@@ -77,36 +87,19 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
 
 
             //reframe all elements to see them all
-            if (SaveInfo.instance.toReFrame)
+            if (SaveInfo.instance.toReFrame && (twoFrames == 2))
             {
                 myGraph.FrameAllElements();
                 SaveInfo.instance.toReFrame = false;
+                twoFrames = 0;
             }
-            EditorGUILayout.EndVertical();
-        }
-        private bool localAndServerDifferent()
-        {
-            foreach (ARFNode node in myGraph.nodes)
+            else if (SaveInfo.instance.toReFrame)
             {
-                float nodeX = node.GetPosition().x;
-                float nodeY = node.GetPosition().y;
-                if (SaveInfo.instance.nodePositions.ContainsKey(node.GUID)){ 
-                    float dataX = SaveInfo.instance.nodePositions[node.GUID].x;
-                    float dataY = SaveInfo.instance.nodePositions[node.GUID].y;
-                    if ((nodeX != dataX) || (nodeY != dataY))
-                    {
-                        return true;
-                    }
-                }
-                else
-                {
-                    return true;
-                }
+                twoFrames++;
             }
-            return false;
+            EditorGUILayout.EndVertical();
         }
 
-
         //generate the window's top toolbar
         private Toolbar GenerateToolbar()
         {
@@ -137,7 +130,7 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
 
             var save = new Button(clickEvent: () =>
             {
-                myGraph.saveElemPositionsInServer();
+                myGraph.saveInServer();
             })
             {
                 text = "Save"
@@ -154,16 +147,19 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
         public Dictionary<String, Rect> nodePositions;
         public List<String> linkIds;
 
-        public List<String> elemsToRemove;
+        public Dictionary<String,Type> elemsToRemove;
+        public List<String> elemsToUpdate;
 
         //keep the info of the graph reframe
         public Boolean toReFrame = false;
 
         public WorldStorageServer worldStorageServer;
+        public WorldStorageUser worldStorageUser;
 
-        public void initNodePos(WorldStorageServer server)
+        public void initNodePos(WorldStorageServer server, WorldStorageUser user)
         {
             worldStorageServer = server;
+            worldStorageUser = user;
 
             instance.nodePositions = new Dictionary<string, Rect>();
             foreach (Trackable track in TrackableRequest.GetAllTrackables(worldStorageServer))
@@ -172,12 +168,12 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
                 {
                     var posX = RoundToNearestHalf(float.Parse(track.KeyvalueTags["unityAuthoringPosX"][0]));
                     var posY = RoundToNearestHalf(float.Parse(track.KeyvalueTags["unityAuthoringPosY"][0]));
-                    Rect trackPos = new Rect(posX, posY, 135, 77);
+                    Rect trackPos = new(posX, posY, 135, 77);
                     instance.nodePositions[track.UUID.ToString()] = trackPos;
                 }
                 else
                 {
-                    Rect trackPos = new Rect(0, 0, 135, 77);
+                    Rect trackPos = new(0, 0, 135, 77);
                     instance.nodePositions[track.UUID.ToString()] = trackPos;
                 }
             }
@@ -187,12 +183,12 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
                 {
                     var posX = RoundToNearestHalf(float.Parse(wa.KeyvalueTags["unityAuthoringPosX"][0]));
                     var posY = RoundToNearestHalf(float.Parse(wa.KeyvalueTags["unityAuthoringPosY"][0]));
-                    Rect waPos = new Rect(posX, posY, 135, 77);
+                    Rect waPos = new(posX, posY, 135, 77);
                     instance.nodePositions[wa.UUID.ToString()] = waPos;
                 }
                 else
                 {
-                    Rect trackPos = new Rect(0, 0, 135, 77);
+                    Rect trackPos = new(0, 0, 135, 77);
                     instance.nodePositions[wa.UUID.ToString()] = trackPos;
                 }
             }
@@ -202,9 +198,10 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
             {
                 instance.linkIds.Add(link.UUID.ToString());
             }
-            instance.toReFrame = true;
 
-            instance.elemsToRemove = new List<string>();
+            instance.toReFrame = true;
+            instance.elemsToRemove = new Dictionary<string, Type>();
+            instance.elemsToUpdate = new List<string>();
         }
 
         //method to predict the position of a node (the float that will be saved in the PositionInfo singleton)
@@ -212,7 +209,5 @@ namespace Assets.ETSI.ARF.ARF_World_Storage_API.Editor.Windows
         {
             return a = Mathf.Round(a * 2f) * 0.5f;
         }
-
-
     }
 }
\ No newline at end of file
diff --git a/UserSettings/Layouts/default-2021.dwlt b/UserSettings/Layouts/default-2021.dwlt
index aff4bb35650cf53043c42f28eca027b3561aa8af..ac8618fa07b3acdd61c12f58faec880a2e0e50c4 100644
--- a/UserSettings/Layouts/default-2021.dwlt
+++ b/UserSettings/Layouts/default-2021.dwlt
@@ -48,7 +48,7 @@ MonoBehaviour:
   m_MinSize: {x: 300, y: 200}
   m_MaxSize: {x: 24288, y: 16192}
   vertical: 0
-  controlID: 15
+  controlID: 50
 --- !u!114 &3
 MonoBehaviour:
   m_ObjectHideFlags: 52
@@ -70,10 +70,10 @@ MonoBehaviour:
     height: 768
   m_MinSize: {x: 101, y: 121}
   m_MaxSize: {x: 4001, y: 4021}
-  m_ActualView: {fileID: 12}
+  m_ActualView: {fileID: 13}
   m_Panes:
   - {fileID: 15}
-  - {fileID: 12}
+  - {fileID: 13}
   m_Selected: 1
   m_LastSelected: 1
 --- !u!114 &4
@@ -93,10 +93,10 @@ MonoBehaviour:
     serializedVersion: 2
     x: 0
     y: 0
-    width: 314
+    width: 313
     height: 455
-  m_MinSize: {x: 201, y: 221}
-  m_MaxSize: {x: 4001, y: 4021}
+  m_MinSize: {x: 200, y: 200}
+  m_MaxSize: {x: 4000, y: 4000}
   m_ActualView: {fileID: 16}
   m_Panes:
   - {fileID: 16}
@@ -224,7 +224,7 @@ MonoBehaviour:
   m_MinSize: {x: 200, y: 200}
   m_MaxSize: {x: 16192, y: 16192}
   vertical: 1
-  controlID: 83
+  controlID: 51
 --- !u!114 &10
 MonoBehaviour:
   m_ObjectHideFlags: 52
@@ -249,7 +249,7 @@ MonoBehaviour:
   m_MinSize: {x: 200, y: 100}
   m_MaxSize: {x: 16192, y: 8096}
   vertical: 0
-  controlID: 84
+  controlID: 52
 --- !u!114 &11
 MonoBehaviour:
   m_ObjectHideFlags: 52
@@ -265,19 +265,19 @@ MonoBehaviour:
   m_Children: []
   m_Position:
     serializedVersion: 2
-    x: 314
+    x: 313
     y: 0
-    width: 872
+    width: 873
     height: 455
   m_MinSize: {x: 102, y: 121}
   m_MaxSize: {x: 4002, y: 4021}
-  m_ActualView: {fileID: 13}
+  m_ActualView: {fileID: 12}
   m_Panes:
   - {fileID: 17}
   - {fileID: 18}
-  - {fileID: 13}
+  - {fileID: 12}
   m_Selected: 2
-  m_LastSelected: 2
+  m_LastSelected: 1
 --- !u!114 &12
 MonoBehaviour:
   m_ObjectHideFlags: 52
@@ -287,26 +287,27 @@ MonoBehaviour:
   m_GameObject: {fileID: 0}
   m_Enabled: 1
   m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: e219817d65c8b1f40ad85e6185e89e92, type: 3}
+  m_Script: {fileID: 11500000, guid: 2c1a0c92306453d46897c1af6cb5c2f9, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
   m_MinSize: {x: 100, y: 100}
   m_MaxSize: {x: 4000, y: 4000}
   m_TitleContent:
-    m_Text: Trackable Editor
+    m_Text: Graph Editor
     m_Image: {fileID: 0}
     m_Tooltip: 
   m_Pos:
     serializedVersion: 2
-    x: 1186
+    x: 313
     y: 72
-    width: 413
-    height: 747
+    width: 871
+    height: 434
   m_ViewDataDictionary: {fileID: 0}
   m_OverlayCanvas:
     m_LastAppliedPresetName: Default
     m_SaveData: []
-  type: 2
+  worldStorageServer: {fileID: 11400000, guid: 777684ed8f62c9d408a1813e8382c676, type: 2}
+  worldStorageUser: {fileID: 11400000, guid: c0696089e4a855b46ad490437919b1e8, type: 2}
 --- !u!114 &13
 MonoBehaviour:
   m_ObjectHideFlags: 52
@@ -316,27 +317,26 @@ MonoBehaviour:
   m_GameObject: {fileID: 0}
   m_Enabled: 1
   m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 2c1a0c92306453d46897c1af6cb5c2f9, type: 3}
+  m_Script: {fileID: 11500000, guid: e219817d65c8b1f40ad85e6185e89e92, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
   m_MinSize: {x: 100, y: 100}
   m_MaxSize: {x: 4000, y: 4000}
   m_TitleContent:
-    m_Text: Graph Editor
+    m_Text: Trackable Editor
     m_Image: {fileID: 0}
     m_Tooltip: 
   m_Pos:
     serializedVersion: 2
-    x: 314
+    x: 1186
     y: 72
-    width: 870
-    height: 434
+    width: 413
+    height: 747
   m_ViewDataDictionary: {fileID: 0}
   m_OverlayCanvas:
     m_LastAppliedPresetName: Default
     m_SaveData: []
-  worldStorageServer: {fileID: 11400000, guid: 3a9ba82f4e8dd124ca2b005861c64d01, type: 2}
-  worldStorageUser: {fileID: 11400000, guid: c0696089e4a855b46ad490437919b1e8, type: 2}
+  type: 0
 --- !u!114 &14
 MonoBehaviour:
   m_ObjectHideFlags: 52
@@ -393,7 +393,7 @@ MonoBehaviour:
     scrollPos: {x: 0, y: 0}
     m_SelectedIDs: 644b0000
     m_LastClickedID: 19300
-    m_ExpandedIDs: 00000000504b0000524b0000544b0000564b000000ca9a3bffffff7f
+    m_ExpandedIDs: 00000000524b0000544b0000564b0000584b0000
     m_RenameOverlay:
       m_UserAcceptedRename: 0
       m_Name: 
@@ -421,7 +421,7 @@ MonoBehaviour:
     scrollPos: {x: 0, y: 0}
     m_SelectedIDs: 
     m_LastClickedID: 0
-    m_ExpandedIDs: 00000000504b0000524b0000544b0000564b0000
+    m_ExpandedIDs: 00000000524b0000544b0000564b0000584b0000
     m_RenameOverlay:
       m_UserAcceptedRename: 0
       m_Name: 
@@ -511,7 +511,7 @@ MonoBehaviour:
     m_CachedPref: 160
     m_ControlHash: -371814159
     m_PrefName: Preview_InspectorPreview
-  m_LastInspectedObjectInstanceID: 3288
+  m_LastInspectedObjectInstanceID: 19264
   m_LastVerticalScrollValue: 0
   m_GlobalObjectId: 
   m_InspectorMode: 0
@@ -540,7 +540,7 @@ MonoBehaviour:
     serializedVersion: 2
     x: 0
     y: 72
-    width: 313
+    width: 312
     height: 434
   m_ViewDataDictionary: {fileID: 0}
   m_OverlayCanvas:
@@ -549,7 +549,7 @@ MonoBehaviour:
   m_SceneHierarchy:
     m_TreeViewState:
       scrollPos: {x: 0, y: 0}
-      m_SelectedIDs: d80c0000
+      m_SelectedIDs: 404b0000
       m_LastClickedID: 0
       m_ExpandedIDs: 38fbffff
       m_RenameOverlay:
@@ -900,10 +900,10 @@ MonoBehaviour:
     m_Tooltip: 
   m_Pos:
     serializedVersion: 2
-    x: 507
-    y: 94
-    width: 1532
-    height: 790
+    x: 313
+    y: 72
+    width: 871
+    height: 434
   m_ViewDataDictionary: {fileID: 0}
   m_OverlayCanvas:
     m_LastAppliedPresetName: Default
@@ -914,10 +914,10 @@ MonoBehaviour:
   m_ShowGizmos: 0
   m_TargetDisplay: 0
   m_ClearColor: {r: 0, g: 0, b: 0, a: 0}
-  m_TargetSize: {x: 1532, y: 769}
+  m_TargetSize: {x: 871, y: 413}
   m_TextureFilterMode: 0
   m_TextureHideFlags: 61
-  m_RenderIMGUI: 0
+  m_RenderIMGUI: 1
   m_EnterPlayModeBehavior: 0
   m_UseMipMap: 0
   m_VSyncEnabled: 0
@@ -929,10 +929,10 @@ MonoBehaviour:
     m_VRangeLocked: 0
     hZoomLockedByDefault: 0
     vZoomLockedByDefault: 0
-    m_HBaseRangeMin: -383
-    m_HBaseRangeMax: 383
-    m_VBaseRangeMin: -192.25
-    m_VBaseRangeMax: 192.25
+    m_HBaseRangeMin: -217.75
+    m_HBaseRangeMax: 217.75
+    m_VBaseRangeMin: -103.25
+    m_VBaseRangeMax: 103.25
     m_HAllowExceedBaseRangeMin: 1
     m_HAllowExceedBaseRangeMax: 1
     m_VAllowExceedBaseRangeMin: 1
@@ -950,23 +950,23 @@ MonoBehaviour:
       serializedVersion: 2
       x: 0
       y: 21
-      width: 1532
-      height: 769
+      width: 871
+      height: 413
     m_Scale: {x: 2, y: 2}
-    m_Translation: {x: 766, y: 384.5}
+    m_Translation: {x: 435.5, y: 206.5}
     m_MarginLeft: 0
     m_MarginRight: 0
     m_MarginTop: 0
     m_MarginBottom: 0
     m_LastShownAreaInsideMargins:
       serializedVersion: 2
-      x: -383
-      y: -192.25
-      width: 766
-      height: 384.5
+      x: -217.75
+      y: -103.25
+      width: 435.5
+      height: 206.5
     m_MinimalGUI: 1
   m_defaultScale: 2
-  m_LastWindowPixelSize: {x: 3064, y: 1580}
+  m_LastWindowPixelSize: {x: 1742, y: 868}
   m_ClearInEditMode: 1
   m_NoCameraWarning: 1
   m_LowResolutionForAspectRatios: 01000000000000000000