]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.document.server.client;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.Collections;\r
6 import java.util.Comparator;\r
7 import java.util.HashMap;\r
8 import java.util.HashSet;\r
9 \r
10 import org.simantics.db.common.procedure.adapter.ListenerAdapter;\r
11 import org.simantics.db.common.procedure.adapter.ListenerSupport;\r
12 import org.simantics.db.layer0.variable.ProxyChildVariable;\r
13 import org.simantics.document.server.DocumentHistoryCollector;\r
14 import org.simantics.document.server.JSONObject;\r
15 import org.simantics.utils.datastructures.Pair;\r
16 import org.simantics.utils.threads.IThreadWorkQueue;\r
17 \r
18 abstract public class DocumentClient implements Document {\r
19 \r
20         protected HashMap<String, WidgetData> widgetData = new HashMap<String, WidgetData>();\r
21         private WidgetMapping mapping;\r
22     private CommandMapping commandMapping;\r
23         \r
24         public DocumentClient(WidgetMapping mapping, CommandMapping commandMapping) {\r
25                 this.mapping = mapping;\r
26                 this.commandMapping = commandMapping;\r
27         }\r
28 \r
29         @Override\r
30         public WidgetManager<?, ?> getManager(JSONObject object) {\r
31                 return mapping.getWidget(object.getType());\r
32         }\r
33         \r
34         @Override\r
35         public WidgetData getWidget(String id) {\r
36                 return widgetData.get(id);\r
37         }\r
38         \r
39         abstract public IThreadWorkQueue thread();\r
40         \r
41         protected void updateDocument(Collection<JSONObject> objects) {\r
42 \r
43                 ArrayList<WidgetData> updatedData = new ArrayList<WidgetData>();\r
44                 // Cache data\r
45                 for (JSONObject object : objects) {\r
46                         WidgetData datum = widgetData.get(object.getId());\r
47                         if(datum == null) {\r
48                                 datum = new WidgetData(this, null, object);\r
49                                 widgetData.put(object.getId(), datum);\r
50                         } else {\r
51                                 // This could replace changed information instead of replacing the whole object\r
52                                 datum.object = object;\r
53                         }\r
54                         updatedData.add(datum);\r
55                 }\r
56 \r
57                 // Create widgets\r
58                 for(WidgetData datum : updatedData) {\r
59                         createElementIfNecessary(datum);\r
60                 }\r
61                 \r
62                 HashSet<WidgetData> updatedParents = new HashSet<WidgetData>(); \r
63                 \r
64                 // Update parent hierarchy\r
65                 for(WidgetData datum : updatedData) {\r
66                         updateChildmaps(datum, updatedParents);\r
67                 }\r
68                 \r
69                 updateTree(updatedParents);\r
70                 \r
71                 // Set values\r
72                 for(WidgetData datum : updatedData) {\r
73                         datum.updateProperties();\r
74                         datum.updateCommands();\r
75                 }\r
76 \r
77         }\r
78         \r
79         private void createElementIfNecessary(WidgetData data) {\r
80                 if(data.widget == null) { \r
81                         data.widget = data.createElement();\r
82                 }\r
83         }\r
84 \r
85         private void updateChildmaps(WidgetData data, HashSet<WidgetData> updates) {\r
86 \r
87                 // Root\r
88                 if(data.object == null) return;\r
89                 \r
90 //              System.err.println("p:" + data.object);\r
91 //              Object o = data.object.getParent();\r
92                 \r
93                 WidgetData parent = widgetData.get(data.object.getParent()); \r
94 \r
95 //              System.out.println("parent:" + parent);\r
96 \r
97                 if(parent == null) return;\r
98                 \r
99                 String parentOrd = data.object.getParentOrd();\r
100                 \r
101                 WidgetData existing = parent.childmap.get(parentOrd);\r
102                 if(!data.equals(existing)) {\r
103                         updates.add(parent);\r
104                         parent.childmap.put(parentOrd, data);\r
105                 }\r
106                 \r
107         }\r
108 \r
109         protected void updateTree(HashSet<WidgetData> updates) {\r
110                 \r
111                 if(updates.isEmpty()) return;\r
112                 \r
113                 ArrayList<WidgetData> updateList = new ArrayList<WidgetData>(updates);\r
114                 Collections.sort(updateList, new Comparator<WidgetData>() {\r
115 \r
116                         private boolean isParent(WidgetData data, WidgetData possibleParent) {\r
117                                 WidgetData parent = widgetData.get(data.object.getParent());\r
118                                 if(parent == null) return false;\r
119                                 else if(parent == possibleParent) return true;\r
120                                 else return isParent(parent, possibleParent);\r
121                         }\r
122                         \r
123                         @Override\r
124                         public int compare(WidgetData arg0, WidgetData arg1) {\r
125                                 if(arg0 == arg1) return 0;\r
126                                 else if( isParent(arg0, arg1) ) return 1;\r
127                                 else if( isParent(arg1, arg0) ) return -1;\r
128                                 else return 0;\r
129                         }\r
130                         \r
131                 });\r
132                         \r
133                 for(WidgetData d : updateList) d.updateChildren();\r
134                 \r
135         }\r
136         \r
137         public class DocumentListener extends ListenerAdapter<Integer> {\r
138 \r
139                 int revision = -1;\r
140                 \r
141                 final private ListenerSupport support;\r
142                 final private String document;\r
143                 final private String input;\r
144                 private boolean performing = false;\r
145                 \r
146                 public DocumentListener(ListenerSupport support, String document, String input) {\r
147                         this.support = support;\r
148                         this.document = document;\r
149                         this.input = input;\r
150                 }\r
151                 \r
152                 public synchronized void perform() {\r
153                     if(performing) return;\r
154                     performing = true;\r
155                     try {\r
156                         Pair<Integer, Collection<JSONObject>> content = DocumentHistoryCollector.getContent(DocumentListener.this, document + "/" + ProxyChildVariable.CONTEXT_BEGIN  + input + "/" + ProxyChildVariable.CONTEXT_END, revision);\r
157                         revision = content.first;\r
158                         updateDocument(content.second);\r
159                     } finally {\r
160                         performing = false;\r
161                     }\r
162                 }\r
163                 \r
164                 Runnable updater = new Runnable() {\r
165 \r
166                         @Override\r
167                         public void run() {\r
168                                 perform();\r
169 //                              Pair<Integer, Collection<JSONObject>> content = DocumentHistoryCollector.getContent(DocumentListener.this, document + "/???" + input + "/???", revision);\r
170 //                              revision = content.first;\r
171 //                              updateDocument(content.second);\r
172                         }\r
173                         \r
174                 };\r
175                 \r
176                 @Override\r
177                 public void execute(Integer result) {\r
178                         IThreadWorkQueue thread = thread();\r
179                         if(thread.currentThreadAccess()) thread.syncExec(updater);\r
180                         else thread.asyncExec(updater);\r
181                 }\r
182                 \r
183                 @Override\r
184                 public boolean isDisposed() {\r
185                         return support.isDisposed();\r
186                 }\r
187 \r
188         };\r
189         \r
190         public void track(ListenerSupport support, String document, String input) {\r
191                 \r
192                 new DocumentListener(support, document, input).perform();\r
193                 \r
194 //              DocumentHistoryCollector.register(location, listener);\r
195 //              listener.execute(-1);\r
196                 \r
197         }\r
198         \r
199         WidgetData getRoot() {\r
200                 return widgetData.get("root");\r
201         }\r
202         \r
203         @SuppressWarnings("unchecked")\r
204         <T> T getRootWidget() {\r
205                 return (T)getRoot().widget;\r
206         }\r
207         \r
208         @Override\r
209         public CommandManager<?, ?> getCommandManager(JSONObject object) {\r
210             return commandMapping.getCommandManager(object.getType());\r
211         }\r
212         \r
213 }\r