]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.document.server/src/org/simantics/document/server/client/DocumentClient.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / client / DocumentClient.java
diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/client/DocumentClient.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/client/DocumentClient.java
new file mode 100644 (file)
index 0000000..be4e44b
--- /dev/null
@@ -0,0 +1,213 @@
+package org.simantics.document.server.client;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+\r
+import org.simantics.db.common.procedure.adapter.ListenerAdapter;\r
+import org.simantics.db.common.procedure.adapter.ListenerSupport;\r
+import org.simantics.db.layer0.variable.ProxyChildVariable;\r
+import org.simantics.document.server.DocumentHistoryCollector;\r
+import org.simantics.document.server.JSONObject;\r
+import org.simantics.utils.datastructures.Pair;\r
+import org.simantics.utils.threads.IThreadWorkQueue;\r
+\r
+abstract public class DocumentClient implements Document {\r
+\r
+       protected HashMap<String, WidgetData> widgetData = new HashMap<String, WidgetData>();\r
+       private WidgetMapping mapping;\r
+    private CommandMapping commandMapping;\r
+       \r
+       public DocumentClient(WidgetMapping mapping, CommandMapping commandMapping) {\r
+               this.mapping = mapping;\r
+               this.commandMapping = commandMapping;\r
+       }\r
+\r
+       @Override\r
+       public WidgetManager<?, ?> getManager(JSONObject object) {\r
+               return mapping.getWidget(object.getType());\r
+       }\r
+       \r
+       @Override\r
+       public WidgetData getWidget(String id) {\r
+               return widgetData.get(id);\r
+       }\r
+       \r
+       abstract public IThreadWorkQueue thread();\r
+       \r
+       protected void updateDocument(Collection<JSONObject> objects) {\r
+\r
+               ArrayList<WidgetData> updatedData = new ArrayList<WidgetData>();\r
+               // Cache data\r
+               for (JSONObject object : objects) {\r
+                       WidgetData datum = widgetData.get(object.getId());\r
+                       if(datum == null) {\r
+                               datum = new WidgetData(this, null, object);\r
+                               widgetData.put(object.getId(), datum);\r
+                       } else {\r
+                               // This could replace changed information instead of replacing the whole object\r
+                               datum.object = object;\r
+                       }\r
+                       updatedData.add(datum);\r
+               }\r
+\r
+               // Create widgets\r
+               for(WidgetData datum : updatedData) {\r
+                       createElementIfNecessary(datum);\r
+               }\r
+               \r
+               HashSet<WidgetData> updatedParents = new HashSet<WidgetData>(); \r
+               \r
+               // Update parent hierarchy\r
+               for(WidgetData datum : updatedData) {\r
+                       updateChildmaps(datum, updatedParents);\r
+               }\r
+               \r
+               updateTree(updatedParents);\r
+               \r
+               // Set values\r
+               for(WidgetData datum : updatedData) {\r
+                       datum.updateProperties();\r
+                       datum.updateCommands();\r
+               }\r
+\r
+       }\r
+       \r
+       private void createElementIfNecessary(WidgetData data) {\r
+               if(data.widget == null) { \r
+                       data.widget = data.createElement();\r
+               }\r
+       }\r
+\r
+       private void updateChildmaps(WidgetData data, HashSet<WidgetData> updates) {\r
+\r
+               // Root\r
+               if(data.object == null) return;\r
+               \r
+//             System.err.println("p:" + data.object);\r
+//             Object o = data.object.getParent();\r
+               \r
+               WidgetData parent = widgetData.get(data.object.getParent()); \r
+\r
+//             System.out.println("parent:" + parent);\r
+\r
+               if(parent == null) return;\r
+               \r
+               String parentOrd = data.object.getParentOrd();\r
+               \r
+               WidgetData existing = parent.childmap.get(parentOrd);\r
+               if(!data.equals(existing)) {\r
+                       updates.add(parent);\r
+                       parent.childmap.put(parentOrd, data);\r
+               }\r
+               \r
+       }\r
+\r
+       protected void updateTree(HashSet<WidgetData> updates) {\r
+               \r
+               if(updates.isEmpty()) return;\r
+               \r
+               ArrayList<WidgetData> updateList = new ArrayList<WidgetData>(updates);\r
+               Collections.sort(updateList, new Comparator<WidgetData>() {\r
+\r
+                       private boolean isParent(WidgetData data, WidgetData possibleParent) {\r
+                               WidgetData parent = widgetData.get(data.object.getParent());\r
+                               if(parent == null) return false;\r
+                               else if(parent == possibleParent) return true;\r
+                               else return isParent(parent, possibleParent);\r
+                       }\r
+                       \r
+                       @Override\r
+                       public int compare(WidgetData arg0, WidgetData arg1) {\r
+                               if(arg0 == arg1) return 0;\r
+                               else if( isParent(arg0, arg1) ) return 1;\r
+                               else if( isParent(arg1, arg0) ) return -1;\r
+                               else return 0;\r
+                       }\r
+                       \r
+               });\r
+                       \r
+               for(WidgetData d : updateList) d.updateChildren();\r
+               \r
+       }\r
+       \r
+       public class DocumentListener extends ListenerAdapter<Integer> {\r
+\r
+               int revision = -1;\r
+               \r
+               final private ListenerSupport support;\r
+               final private String document;\r
+               final private String input;\r
+               private boolean performing = false;\r
+               \r
+               public DocumentListener(ListenerSupport support, String document, String input) {\r
+                       this.support = support;\r
+                       this.document = document;\r
+                       this.input = input;\r
+               }\r
+               \r
+               public synchronized void perform() {\r
+                   if(performing) return;\r
+                   performing = true;\r
+                   try {\r
+                       Pair<Integer, Collection<JSONObject>> content = DocumentHistoryCollector.getContent(DocumentListener.this, document + "/" + ProxyChildVariable.CONTEXT_BEGIN  + input + "/" + ProxyChildVariable.CONTEXT_END, revision);\r
+                       revision = content.first;\r
+                       updateDocument(content.second);\r
+                   } finally {\r
+                       performing = false;\r
+                   }\r
+               }\r
+               \r
+               Runnable updater = new Runnable() {\r
+\r
+                       @Override\r
+                       public void run() {\r
+                               perform();\r
+//                             Pair<Integer, Collection<JSONObject>> content = DocumentHistoryCollector.getContent(DocumentListener.this, document + "/???" + input + "/???", revision);\r
+//                             revision = content.first;\r
+//                             updateDocument(content.second);\r
+                       }\r
+                       \r
+               };\r
+               \r
+               @Override\r
+               public void execute(Integer result) {\r
+                       IThreadWorkQueue thread = thread();\r
+                       if(thread.currentThreadAccess()) thread.syncExec(updater);\r
+                       else thread.asyncExec(updater);\r
+               }\r
+               \r
+               @Override\r
+               public boolean isDisposed() {\r
+                       return support.isDisposed();\r
+               }\r
+\r
+       };\r
+       \r
+       public void track(ListenerSupport support, String document, String input) {\r
+               \r
+               new DocumentListener(support, document, input).perform();\r
+               \r
+//             DocumentHistoryCollector.register(location, listener);\r
+//             listener.execute(-1);\r
+               \r
+       }\r
+       \r
+       WidgetData getRoot() {\r
+               return widgetData.get("root");\r
+       }\r
+       \r
+       @SuppressWarnings("unchecked")\r
+       <T> T getRootWidget() {\r
+               return (T)getRoot().widget;\r
+       }\r
+       \r
+       @Override\r
+       public CommandManager<?, ?> getCommandManager(JSONObject object) {\r
+           return commandMapping.getCommandManager(object.getType());\r
+       }\r
+       \r
+}\r