]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d.jme/src/org/simantics/g3d/jme/common/AbstractJMENodeMap.java
Remove dependencies on log4j
[simantics/3d.git] / org.simantics.g3d.jme / src / org / simantics / g3d / jme / common / AbstractJMENodeMap.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g3d.jme.common;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.HashMap;\r
17 import java.util.HashSet;\r
18 import java.util.List;\r
19 import java.util.Map;\r
20 import java.util.Set;\r
21 import java.util.Stack;\r
22 \r
23 import org.simantics.db.ReadGraph;\r
24 import org.simantics.db.Session;\r
25 import org.simantics.db.WriteGraph;\r
26 import org.simantics.db.common.request.ReadRequest;\r
27 import org.simantics.db.common.request.WriteRequest;\r
28 import org.simantics.db.exception.DatabaseException;\r
29 import org.simantics.g3d.ontology.G3D;\r
30 import org.simantics.g3d.scenegraph.IG3DNode;\r
31 import org.simantics.g3d.scenegraph.RenderListener;\r
32 import org.simantics.g3d.scenegraph.base.INode;\r
33 import org.simantics.g3d.scenegraph.base.NodeListener;\r
34 import org.simantics.g3d.scenegraph.base.ParentNode;\r
35 import org.simantics.objmap.graph.IMapping;\r
36 import org.simantics.objmap.graph.IMappingListener;\r
37 import org.simantics.utils.datastructures.MapList;\r
38 import org.simantics.utils.datastructures.MapSet;\r
39 import org.simantics.utils.datastructures.Pair;\r
40 \r
41 import com.jme3.app.Application;\r
42 import com.jme3.scene.Spatial;\r
43 \r
44 public abstract class AbstractJMENodeMap<E extends IG3DNode> implements JMENodeMap, IMappingListener, NodeListener, RenderListener {\r
45 \r
46         protected Session session;\r
47         protected IMapping mapping;\r
48         protected Application app;\r
49 //      protected InteractiveVtkPanel panel;\r
50         \r
51         protected MapList<E, Spatial> nodeToActor = new MapList<E, Spatial>();\r
52         protected Map<Spatial,E> actorToNode = new HashMap<Spatial, E>();\r
53 \r
54         protected ParentNode<E> rootNode;\r
55         \r
56         public AbstractJMENodeMap(Session session, IMapping mapping, Application app, ParentNode<E> rootNode) {\r
57                 this.session = session;\r
58                 this.mapping = mapping;\r
59                 this.rootNode = rootNode;\r
60                 this.app = app;\r
61 //              this.panel = panel;\r
62 //              panel.addListener(this);\r
63                 mapping.addMappingListener(this);\r
64                 rootNode.addListener(this);\r
65         }\r
66         \r
67         protected abstract void addActor(E node);\r
68         protected abstract void removeActor(E node);\r
69         protected abstract void updateActor(E node,Set<String> ids);\r
70         \r
71         \r
72         public void repaint() {\r
73                 \r
74         }\r
75         \r
76         public void populate() {\r
77                 for (E node : rootNode.getNodes()) {\r
78                         receiveAdd(node, node.getParentRel(),true);\r
79                 }\r
80                 repaint();\r
81         }\r
82         \r
83         @Override\r
84         public IG3DNode getNode(Spatial prop) {\r
85                 return actorToNode.get(prop);\r
86         }\r
87         \r
88         @SuppressWarnings("unchecked")\r
89         @Override\r
90         public Collection<Spatial> getRenderObjects(IG3DNode node) {\r
91                 return nodeToActor.getValues((E)node);\r
92         }\r
93         \r
94         @SuppressWarnings("unchecked")\r
95         @Override\r
96         public ParentNode<IG3DNode> getRootNode() {\r
97                 return (ParentNode<IG3DNode>)rootNode;\r
98         }\r
99         \r
100         @Override\r
101         public void commit() {\r
102                 session.asyncRequest(new WriteRequest() {\r
103                         \r
104                         @Override\r
105                         public void perform(WriteGraph graph) throws DatabaseException {\r
106                                 synchronized(syncMutex) {\r
107                                         graphUpdates = true;\r
108                                         mapping.updateDomain(graph);\r
109                                         graphUpdates = false;\r
110                                 }\r
111                         }\r
112                 });\r
113         }\r
114         \r
115         @Override\r
116         public boolean isChangeTracking() {\r
117                 return changeTracking;\r
118         }\r
119         \r
120         @Override\r
121         public void setChangeTracking(boolean enabled) {\r
122                 changeTracking = enabled;\r
123         }\r
124         \r
125         private boolean changeTracking = true;\r
126         \r
127         private Object syncMutex = new Object(); \r
128         \r
129 \r
130         private List<Pair<E,String>> added = new ArrayList<Pair<E,String>>();\r
131         private List<Pair<E,String>> removed = new ArrayList<Pair<E,String>>();\r
132         //private List<Pair<E,String>> updated = new ArrayList<Pair<E,String>>();\r
133         private MapSet<E, String> updated = new MapSet<E, String>();//new MapSet.Hash<E, String>();\r
134 \r
135         \r
136         @SuppressWarnings("unchecked")\r
137         @Override\r
138         public void updateRenderObjectsFor(IG3DNode node) {\r
139                 List<Spatial> toDelete = new ArrayList<Spatial>();\r
140                 for (Spatial prop : nodeToActor.getValues((E)node)) {\r
141 //                      if (prop.GetVTKId() != 0) {\r
142 //                              panel.GetRenderer().RemoveActor(prop);\r
143 //                              //prop.Delete();\r
144 //                              toDelete.add(prop);\r
145 //                      }\r
146                         prop.removeFromParent();\r
147                         actorToNode.remove(prop);\r
148                 }\r
149                 nodeToActor.remove((E)node);\r
150                 Collection<Spatial> coll = getActors((E)node);\r
151                 if (coll == null)\r
152                         return;\r
153                 for (Spatial prop : coll) {\r
154                         nodeToActor.add((E)node,prop);\r
155                         actorToNode.put(prop, (E)node);\r
156                         toDelete.remove(prop);\r
157                 }\r
158                 for (Spatial p : toDelete) {\r
159                         //p.Delete();\r
160                 }\r
161         }\r
162         \r
163         protected abstract  Collection<Spatial> getActors(E node);\r
164         \r
165         @SuppressWarnings("unchecked")\r
166         private void receiveAdd(E node, String id, boolean db) {\r
167                 synchronized (syncMutex) {\r
168                         for (Pair<E, String> n : added) {\r
169                                 if (n.first.equals(node))\r
170                                         return;\r
171                         }\r
172                         if (changeTracking) {\r
173                                 mapping.rangeModified(node.getParent());\r
174                         }\r
175                         added.add(new Pair<E, String>(node, id));       \r
176                 }\r
177                 repaint();\r
178         }\r
179         \r
180         @SuppressWarnings("unchecked")\r
181         private void receiveRemove(E node, String id, boolean db) {\r
182                 synchronized (syncMutex) {\r
183                         for (Pair<E, String> n : removed) {\r
184                                 if (n.first.equals(node))\r
185                                         return;\r
186                         }\r
187                         if (changeTracking && !db)\r
188                                 mapping.rangeModified(node.getParent());\r
189                         removed.add(new Pair<E, String>(node, id));\r
190                 }\r
191                 repaint();\r
192         }\r
193         \r
194         @SuppressWarnings("unchecked")\r
195         private void receiveUpdate(E node, String id, boolean db) {\r
196                 synchronized (syncMutex) {\r
197 //                      for (Pair<E, String> n : updated) {\r
198 //                              if (n.first.equals(node))\r
199 //                                      return;\r
200 //                      }\r
201                         if (changeTracking && !db)\r
202                                 mapping.rangeModified(node);\r
203                         //updated.add(new Pair<E, String>(node, id));\r
204                         updated.add(node, id);\r
205                 }\r
206                 repaint();\r
207         }\r
208         \r
209         private boolean graphUpdates = false;\r
210         private Set<Object> graphModified = new HashSet<Object>();\r
211         \r
212         @Override\r
213         public void domainModified() {\r
214                 if (graphUpdates)\r
215                         return;\r
216                 //System.out.println("domainModified");\r
217                 session.asyncRequest(new ReadRequest() {\r
218                         \r
219                         @SuppressWarnings("unchecked")\r
220                         @Override\r
221                         public void run(ReadGraph graph) throws DatabaseException {\r
222                                 graphUpdates = true;\r
223                                 for (Object domainObject : mapping.getDomainModified()) {\r
224                                         Object rangeObject = mapping.get(domainObject);\r
225                                         if (rangeObject != null)\r
226                                                 graphModified.add(rangeObject);\r
227                                 }\r
228                                 mapping.updateRange(graph);\r
229                                 graphModified.clear();\r
230                                 graphUpdates = false;\r
231                                 if (mapping.isRangeModified())\r
232                                         commit();\r
233                         }\r
234                 });\r
235                 \r
236         }\r
237         \r
238         @Override\r
239         public void rangeModified() {\r
240                 //System.out.println("rangeModified");\r
241 \r
242         }\r
243         \r
244         @Override\r
245         public void postRender() {\r
246                 \r
247         }\r
248         \r
249         List<Pair<E, String>> rem = new ArrayList<Pair<E,String>>();\r
250         List<Pair<E, String>> add = new ArrayList<Pair<E,String>>();\r
251         MapSet<E, String> mod = new MapSet<E, String>();//new MapSet.Hash<E, String>();\r
252         Set<E> propagation = new HashSet<E>();\r
253         Stack<E> stack = new Stack<E>();\r
254         \r
255         @SuppressWarnings("unchecked")\r
256         @Override\r
257         public synchronized void preRender() {\r
258                 rem.clear();\r
259                 add.clear();\r
260                 mod.clear();\r
261                 propagation.clear();\r
262                 \r
263                 synchronized (syncMutex) {\r
264                         rem.addAll(removed);\r
265                         add.addAll(added);\r
266                         //mod.addAll(updated);\r
267                         for (E e : updated.getKeys()) {\r
268                                 for (String s : updated.getValues(e))\r
269                                         mod.add(e, s);\r
270                         }\r
271                         \r
272                         removed.clear();\r
273                         added.clear();\r
274                         updated.clear();\r
275                 }\r
276                 \r
277                 for (Pair<E, String> n : rem) {\r
278                         stopListening(n.first);\r
279                         removeActor(n.first);\r
280                 \r
281                 }\r
282                 \r
283                 for (Pair<E, String> n : add) {\r
284                         addActor(n.first);\r
285                         listen(n.first);\r
286                 }\r
287                 \r
288                 for (E e : mod.getKeys()) {\r
289                         Set<String> ids = mod.getValues(e);\r
290                         if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation)) {\r
291                                 if (!propagation.contains(e))\r
292                                         propagation.add(e);\r
293                         }\r
294                 }\r
295                 \r
296                 if (propagation.size() > 0) {\r
297                         stack.clear();\r
298                         stack.addAll(propagation);\r
299                         propagation.clear();\r
300                         while (!stack.isEmpty()) {\r
301                                 E node = stack.pop();\r
302                                 if (propagation.contains(node))\r
303                                         continue;\r
304                                 propagation.add(node);\r
305                                 for (NodeListener l : node.getListeners()) {\r
306                                         if (l == this) {\r
307                                                 //changeTracking = false;\r
308                                                 //l.propertyChanged(node, G3D.URIs.hasPosition);\r
309                                                 //changeTracking = true;\r
310                                         } else {\r
311                                                 l.propertyChanged(node, G3D.URIs.hasPosition);\r
312                                         }\r
313                                 }\r
314                                 if (node instanceof ParentNode) {\r
315                                         stack.addAll(((ParentNode<E>)node).getNodes());\r
316                                 }\r
317                         }\r
318                 }\r
319                 \r
320                 for (E e : mod.getKeys()) {\r
321                         Set<String> ids = mod.getValues(e);\r
322                         updateActor(e,ids);\r
323                 }\r
324                 \r
325                 for (Pair<E, String> n : rem) {\r
326                         for (NodeListener l : nodeListeners)\r
327                                 l.nodeRemoved(null, n.first, n.second);\r
328                 }\r
329                 for (Pair<E, String> n : add) {\r
330                         for (NodeListener l : nodeListeners)\r
331                                 l.nodeAdded(n.first.getParent(), n.first, n.second);\r
332                 }\r
333 //              for (Pair<E, String> n : mod) {\r
334 //                      for (NodeListener l : nodeListeners)\r
335 //                              l.propertyChanged(n.first, n.second);\r
336 //              }\r
337                 for (E e : mod.getKeys()) {\r
338                         for (NodeListener l : nodeListeners)\r
339                                 for (String s : mod.getValues(e))\r
340                                         l.propertyChanged(e, s);\r
341                 }\r
342         }\r
343         \r
344         @SuppressWarnings("unchecked")\r
345         private void listen(INode node) {\r
346                 node.addListener(this);\r
347                 if (node instanceof ParentNode<?>) {\r
348                         ParentNode<INode> parentNode = (ParentNode<INode>)node;\r
349                         for (INode n : parentNode.getNodes())\r
350                                 listen(n);\r
351                 }\r
352         }\r
353         \r
354         private void stopListening(INode node) {\r
355                 node.removeListener(this);\r
356                 if (node instanceof ParentNode<?>) {\r
357                         @SuppressWarnings("unchecked")\r
358                         ParentNode<INode> parentNode = (ParentNode<INode>)node;\r
359                         for (INode n : parentNode.getNodes())\r
360                                 stopListening(n);\r
361                 }\r
362         }\r
363         \r
364         @SuppressWarnings("unchecked")\r
365         @Override\r
366         public void propertyChanged(INode node, String id) {\r
367                 //receiveUpdate((E)node, id, graphUpdates);\r
368                 receiveUpdate((E)node, id, graphModified.contains(node));\r
369                 \r
370         }\r
371         \r
372         @SuppressWarnings("unchecked")\r
373         @Override\r
374         public <T extends INode> void nodeAdded(ParentNode<T> node, INode child,\r
375                         String rel) {\r
376                 //receiveAdd((E)child, rel ,graphUpdates);\r
377                 receiveAdd((E)child, rel ,graphModified.contains(node));\r
378                 \r
379         }\r
380         \r
381         @SuppressWarnings("unchecked")\r
382         @Override\r
383         public <T extends INode> void nodeRemoved(ParentNode<T> node, INode child,\r
384                         String rel) {\r
385                 //receiveRemove((E)child, rel, graphUpdates);\r
386                 receiveRemove((E)child, rel, graphModified.contains(node));\r
387         }\r
388         \r
389         @Override\r
390         public void delete() {\r
391                 changeTracking = false;\r
392                 //panel.removeListener(this);\r
393                 mapping.removeMappingListener(this);\r
394 \r
395                 List<E> nodes = new ArrayList<E>(nodeToActor.getKeySize());\r
396                 nodes.addAll(nodeToActor.getKeys());\r
397                 for (E node : nodes) {\r
398                         node.removeListener(this);\r
399                         removeActor(node);\r
400                         node.cleanup();\r
401                 }\r
402                 for (Spatial prop : actorToNode.keySet()) {\r
403                         prop.removeFromParent();\r
404                         //if (prop.GetVTKId() != 0) \r
405                         //      prop.Delete();\r
406                 }\r
407                 actorToNode.clear();\r
408                 nodeToActor.clear();\r
409                 \r
410         }\r
411         \r
412         \r
413         private List<NodeListener> nodeListeners = new ArrayList<NodeListener>();\r
414         @Override\r
415         public void addListener(NodeListener listener) {\r
416                 nodeListeners.add(listener);\r
417                 \r
418         }\r
419         \r
420         @Override\r
421         public void removeListener(NodeListener listener) {\r
422                 nodeListeners.remove(listener);\r
423                 \r
424         }\r
425 \r
426 }\r