]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop.mapping/src/org/simantics/interop/mapping/Mapper.java
refs #3483
[simantics/interop.git] / org.simantics.interop.mapping / src / org / simantics / interop / mapping / Mapper.java
1 package org.simantics.interop.mapping;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.Iterator;\r
6 import java.util.List;\r
7 \r
8 import org.eclipse.core.runtime.IProgressMonitor;\r
9 import org.eclipse.core.runtime.NullProgressMonitor;\r
10 import org.simantics.db.ReadGraph;\r
11 import org.simantics.db.Resource;\r
12 import org.simantics.db.Session;\r
13 import org.simantics.db.VirtualGraph;\r
14 import org.simantics.db.WriteGraph;\r
15 import org.simantics.db.common.request.ReadRequest;\r
16 import org.simantics.db.common.request.WriteRequest;\r
17 import org.simantics.db.common.request.WriteResultRequest;\r
18 import org.simantics.db.common.utils.NameUtils;\r
19 import org.simantics.db.exception.DatabaseException;\r
20 import org.simantics.db.exception.ServiceException;\r
21 import org.simantics.db.layer0.util.SessionGarbageCollection;\r
22 import org.simantics.db.request.Read;\r
23 import org.simantics.interop.mapping.data.GraphNode;\r
24 import org.simantics.interop.mapping.data.Identifiable;\r
25 import org.simantics.interop.mapping.data.Link;\r
26 import org.simantics.interop.mapping.data.ResourceIdentifiable;\r
27 import org.simantics.ui.jobs.SessionGarbageCollectorJob;\r
28 import org.simantics.utils.datastructures.MapList;\r
29 import org.simantics.utils.datastructures.Pair;\r
30 \r
31 /**\r
32  * \r
33  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
34  *\r
35  */\r
36 public class Mapper {\r
37         \r
38         public static final boolean USE_SPLIT_TRANSACTIONS = false; // Split transactions\r
39         public static int OBJECTS_PER_TRANSACTION = 5000;           // number of objects handled per transaction (split mode) \r
40         private static boolean SLEEP_BETWEEN_WRITES = false;        // sleep between transactions (split mode)     \r
41         private static int SLEEP_TIME = 10;                         // time to sleep (ms)\r
42         private static boolean COLLECT_BETWEEN_WRITES = false;      // Run SessionGC between split transactions\r
43         private static boolean COLLECT_WITHIN_TRANSACTIONS = true;  // Run Collect within transactions (both modes)\r
44         public static int OBJECTS_BEFORE_COLLECT = 5000;            // number of objects that are handled before collect (non-split mode)\r
45         \r
46         private List<InitializedRule> initializedRules = new ArrayList<InitializedRule>();\r
47         private List<Pair<IdentificationRule, Pair<Integer,GenerationRule>>> generationRules;\r
48         private List<List<ModificationRule>> globalModificationRules;\r
49         private List<List<Pair<IdentificationRule, ModificationRule>>> modificationRules;\r
50         private List<Pair<ConnectionIdentificationRule, ConnectionGenerationRule>> connectionRules;\r
51 \r
52         int maxGenPass = 0;\r
53         \r
54         public Mapper() {\r
55                 long maxMemory = Runtime.getRuntime().maxMemory();\r
56                 maxMemory /= (1024*1024);                            // Convert to MB;\r
57                 int use = 290;                                       // Estimated memory usage of the system\r
58                 int freeMem = (int)maxMemory-use;                                        // Free memory for mappings    \r
59                 OBJECTS_BEFORE_COLLECT = (freeMem * freeMem) / 1000; //600M heap -> 84, 3000M heap -> 5645\r
60                 if (OBJECTS_BEFORE_COLLECT < 2)\r
61                         OBJECTS_BEFORE_COLLECT = 2;\r
62                 OBJECTS_PER_TRANSACTION = OBJECTS_BEFORE_COLLECT;\r
63                 \r
64                 \r
65                 generationRules = new ArrayList<Pair<IdentificationRule,Pair<Integer,GenerationRule>>>();\r
66                 modificationRules = new ArrayList<List<Pair<IdentificationRule,ModificationRule>>>();\r
67                 globalModificationRules = new ArrayList<List<ModificationRule>>();\r
68                 connectionRules = new ArrayList<Pair<ConnectionIdentificationRule, ConnectionGenerationRule>>();\r
69         }\r
70         \r
71         public void addRule(int pass, IdentificationRule idRule, GenerationRule genRule) {\r
72                 if (idRule == null || genRule == null) throw new NullPointerException();\r
73                 generationRules.add(new Pair<IdentificationRule, Pair<Integer,GenerationRule>>(idRule, new Pair<Integer,GenerationRule>(pass,genRule)));\r
74                 maxGenPass = Math.max(maxGenPass, pass);\r
75                 if (genRule instanceof InitializedRule)\r
76                         initializedRules.add((InitializedRule)genRule);\r
77         }\r
78         \r
79         public void addRule(IdentificationRule idRule, MappingRule mappingRule) {\r
80                 addRule(0,idRule,mappingRule);\r
81         }\r
82         \r
83         public void addRule(int pass, IdentificationRule idRule, MappingRule mappingRule) {\r
84                 if (idRule == null || mappingRule == null) throw new NullPointerException();\r
85                 if (mappingRule instanceof ModificationRule) {\r
86                         while (pass >= modificationRules.size()) {\r
87                                 modificationRules.add(new ArrayList<Pair<IdentificationRule,ModificationRule>>());\r
88                         }\r
89                         List<Pair<IdentificationRule,ModificationRule>> priList = modificationRules.get(pass);\r
90                         priList.add(new Pair<IdentificationRule, ModificationRule>(idRule, (ModificationRule)mappingRule));\r
91                 }\r
92                 if (mappingRule instanceof GenerationRule)\r
93                         generationRules.add(new Pair<IdentificationRule, Pair<Integer,GenerationRule>>(idRule, new Pair<Integer,GenerationRule>(pass,(GenerationRule)mappingRule)));\r
94                 if (mappingRule instanceof InitializedRule)\r
95                         initializedRules.add((InitializedRule)mappingRule);\r
96         }\r
97         \r
98         public void addRule(IdentificationRule idRule, ModificationRule... modRules) {\r
99                 addRule(0, idRule, modRules);\r
100         }\r
101 \r
102         public void addRule(int pass, IdentificationRule idRule, ModificationRule... modRules) {\r
103                 if (idRule == null) throw new NullPointerException();\r
104                 \r
105                 while (pass >= modificationRules.size()) {\r
106                         modificationRules.add(new ArrayList<Pair<IdentificationRule,ModificationRule>>());\r
107                 }\r
108                 List<Pair<IdentificationRule,ModificationRule>> priList = modificationRules.get(pass);\r
109                 \r
110                 for (ModificationRule modRule : modRules){\r
111                         if (modRule == null) throw new NullPointerException();  \r
112                         priList.add(new Pair<IdentificationRule, ModificationRule>(idRule, modRule));\r
113                         if (modRule instanceof InitializedRule)\r
114                                 initializedRules.add((InitializedRule)modRule);\r
115                 }\r
116         }\r
117         public void addRule(ModificationRule modRule) {\r
118                 addRule(0, modRule);\r
119         }\r
120         \r
121         public void addRule(int pass, ModificationRule modRule) {\r
122                 if (modRule == null) throw new NullPointerException();\r
123                 while (pass >= globalModificationRules.size()) {\r
124                         globalModificationRules.add(new ArrayList<ModificationRule>());\r
125                 }\r
126                 List<ModificationRule> priList = globalModificationRules.get(pass);\r
127                 priList.add(modRule);\r
128                 if (modRule instanceof InitializedRule)\r
129                         initializedRules.add((InitializedRule)modRule);\r
130         }\r
131         \r
132         public void addRule(ConnectionIdentificationRule idRule, ConnectionGenerationRule genRule) {\r
133                 if (idRule == null || genRule == null) throw new NullPointerException();\r
134                 connectionRules.add(new Pair<ConnectionIdentificationRule, ConnectionGenerationRule>(idRule, genRule));\r
135                 if (genRule instanceof InitializedRule)\r
136                         initializedRules.add((InitializedRule)genRule);\r
137         }\r
138         \r
139         /**\r
140          * Runs the mapping procedure. Disposes nodes after mapping is done.\r
141          * @param g\r
142          * @param model\r
143          * @param nodes\r
144          * @param monitor\r
145          * @throws Exception\r
146          */\r
147         public void map(WriteGraph g, Resource model, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
148                 startMapping(null);\r
149                 try {\r
150                         if (monitor == null)\r
151                                 monitor = new NullProgressMonitor();\r
152                         \r
153                         for (InitializedRule rule : initializedRules)\r
154                                 rule.initialize(g, model);\r
155                         \r
156                         applyModifications(g, nodes, monitor);\r
157                         monitor.worked(1);\r
158                         applyGenerations(g,nodes,monitor);\r
159                         monitor.worked(1);\r
160                         applyConnections(g,nodes,monitor);\r
161                         monitor.worked(1);\r
162                 } finally {\r
163                         MappingTools.disposeNodes(nodes);\r
164                         endMapping();\r
165                 }\r
166                 \r
167         }\r
168         \r
169         /**\r
170          * Runs the mapping procedure. Disposes nodes after mapping is done.\r
171          * @param session\r
172          * @param model\r
173          * @param nodes\r
174          * @param monitor\r
175          * @throws Exception\r
176          */\r
177         public void map(Session session, Resource model, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
178                 map(session, model, null, nodes, monitor);\r
179         }\r
180         \r
181         /**\r
182          * Runs the mapping procedure. Disposes nodes after mapping is done.\r
183          * @param session\r
184          * @param model\r
185          * @param vg\r
186          * @param nodes\r
187          * @param monitor\r
188          * @throws Exception\r
189          */\r
190         public void map(Session session, Resource model, VirtualGraph vg, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
191                 startMapping(vg);\r
192                 try {\r
193                         long time = System.currentTimeMillis();\r
194                         if (monitor == null)\r
195                                 monitor = new NullProgressMonitor();\r
196                         \r
197                         initializeRules(session, vg, model);\r
198                         if (USE_SPLIT_TRANSACTIONS) {\r
199                                 applyModifications(session, nodes, monitor);\r
200                                 monitor.worked(1);\r
201                                 applyGenerations(session, vg, nodes, monitor);\r
202                                 monitor.worked(1);\r
203                                 applyConnections(session, vg, nodes, monitor);\r
204                                 monitor.worked(1);\r
205                         } else {\r
206                                 applyModifications2(session, nodes, monitor);\r
207                                 monitor.worked(1);\r
208                                 applyGenerations2(session, vg, nodes, monitor);\r
209                                 monitor.worked(1);\r
210                                 applyConnections2(session, vg, nodes, monitor);\r
211                                 monitor.worked(1);\r
212                         }\r
213                         long time2 = System.currentTimeMillis();\r
214                         System.out.println("Mapping took " + ((time2-time)/1000) + " seconds");\r
215                 } finally {\r
216                         MappingTools.disposeNodes(nodes);\r
217                         if (COLLECT_BETWEEN_WRITES) {\r
218 \r
219                                 SessionGarbageCollection.gc(null, session, true, null);\r
220                         }\r
221                         endMapping();\r
222                 }\r
223                 \r
224         }\r
225         \r
226         \r
227         //private boolean autosaveEndabled = false;\r
228         private VirtualGraph vg;\r
229         \r
230         protected void startMapping(VirtualGraph vg) {\r
231                  SessionGarbageCollectorJob.getInstance().setEnabled(false);\r
232                  //autosaveEndabled = AutosaveCommands.getInstance().isEnabled();\r
233                  //AutosaveCommands.getInstance().setEnabled(false);\r
234                  this.vg = vg;\r
235         }\r
236         \r
237         protected void endMapping() {\r
238                  SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();\r
239                 // AutosaveCommands.getInstance().setEnabled(autosaveEndabled);\r
240                  vg = null;\r
241         }\r
242         \r
243         private void applyModifications(ReadGraph g, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
244                 \r
245                 // Apply global modification rules first\r
246                 \r
247                 int passCount = Math.max(globalModificationRules.size(),modificationRules.size());\r
248 \r
249                 for (int pass = 0; pass < passCount; pass++) {\r
250                         if (globalModificationRules.size() > pass) {\r
251                                 int count = 0;\r
252                                 List<ModificationRule> modRules = globalModificationRules.get(pass);\r
253                                 int size = modRules.size();\r
254                                 monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
255                                 for (ModificationRule r : modRules) {\r
256                                         Collection<GraphNode<Identifiable>> ruleModified = r.modify(g, nodes);\r
257                                         if (ruleModified == null)\r
258                                                 continue;\r
259                                         for (GraphNode<Identifiable> m : ruleModified) {\r
260                                                 if (m.isDisposed()) {\r
261                                                         nodes.remove(m);\r
262                                                 }\r
263                                                 else if (!nodes.contains(m)) {\r
264                                                         nodes.add(m);\r
265                                                 }\r
266                                         }\r
267                                         monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
268                                         if(monitor.isCanceled()) {\r
269                                                 throw new CancelException("Cancel requested.");\r
270                                         }\r
271                                         if (COLLECT_WITHIN_TRANSACTIONS)\r
272                                                 collect(g);\r
273                                 }\r
274                         } if (modificationRules.size() > pass) {\r
275                                 int count = 0;\r
276                                 List<Pair<IdentificationRule, ModificationRule>> modRules = modificationRules.get(pass);\r
277                                 int size = modRules.size();\r
278                                 monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
279                                 // Apply per object modification rules \r
280                                 for (Pair<IdentificationRule, ModificationRule> modRule : modRules) {\r
281                                         Collection<GraphNode<Identifiable>> ruleModified = new ArrayList<GraphNode<Identifiable>>();\r
282                                         for (GraphNode<Identifiable> n : nodes) {\r
283                                                 applyModifications(g, n, modRule, ruleModified);\r
284                                                 if (COLLECT_WITHIN_TRANSACTIONS)\r
285                                                         collect2(g);\r
286                                         }\r
287                                         \r
288                                         for (GraphNode<Identifiable> m : ruleModified) {\r
289                                                 if (m.isDisposed()) {\r
290                                                         nodes.remove(m);\r
291                                                 }\r
292                                                 else if (!nodes.contains(m)) {\r
293                                                         nodes.add(m);\r
294                                                 }\r
295                                         }\r
296                                         monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
297                                         if(monitor.isCanceled()) {\r
298                                                 throw new CancelException("Cancel requested.");\r
299                                         }\r
300                                         \r
301                                 }\r
302                         }\r
303                 }\r
304                 \r
305         }\r
306         \r
307         \r
308         \r
309         private void applyGenerations(WriteGraph graph, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
310                 \r
311                 int size = nodes.size();\r
312                 int count = 0;\r
313                 monitor.subTask("Assigning generation rules ("+ count + "/" + size + ")");\r
314                 // populate generation rules\r
315                 for (GraphNode<Identifiable> n : nodes) {\r
316                         \r
317                         for (Pair<IdentificationRule,Pair<Integer,GenerationRule>> r : generationRules) {\r
318                                 if (r.first.matches(graph, n)) {\r
319                                         MappingTools.assignGenerationRule(n, r.second.first,r.second.second);\r
320                                 }\r
321                         }\r
322                         monitor.subTask("Assigning generation rules ("+ (++count) + "/" + size + ")");\r
323                         if(monitor.isCanceled()) {\r
324                                 throw new CancelException("Cancel requested.");\r
325                         }\r
326                         if (COLLECT_WITHIN_TRANSACTIONS)\r
327                                 collect2(graph);\r
328                 }\r
329                 \r
330                 count = 0;\r
331                 monitor.subTask("Generating objects ("+ count + "/" + size + ")");\r
332                 \r
333                 // apply generation rules.\r
334                 //WriteWrapper g  = new WriteWrapper(graph);\r
335                 \r
336                 //Collection<GenerationRule> usedRules = new ArrayList<GenerationRule>();\r
337                 for (int stage = 0; stage <= maxGenPass; stage++) {\r
338                         count = 0;\r
339                         for (GraphNode<Identifiable> n : nodes) {\r
340 \r
341                                 MapList<Integer,GenerationRule> priRules = n.getHint(MappingHints.KEY_GENERATION_RULES);\r
342                                 List<GenerationRule> rules = priRules.getValues(stage);\r
343                                 for (GenerationRule r : rules) {\r
344                                         r.generate(graph, n);\r
345                                 }\r
346 \r
347                                 monitor.subTask("Generating objects, stage " + stage + " :  ("+ (++count) + "/" + size + ")");\r
348                                 if(monitor.isCanceled()) {\r
349                                         throw new CancelException("Cancel requested.");\r
350                                 }\r
351                                 if (COLLECT_WITHIN_TRANSACTIONS)\r
352                                         collect2(graph);\r
353                         }\r
354                 }\r
355         }\r
356         \r
357         private void applyConnections(WriteGraph g, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
358                 int size = nodes.size();\r
359                 int count = 0;\r
360                 \r
361                 monitor.subTask("Generating connections ("+ count + "/" + size + ")");\r
362                 \r
363                 for (GraphNode<Identifiable> node : nodes) {\r
364                         applyConnections(g, node);\r
365                         monitor.subTask("Generating connections ("+ (++count) + "/" + size + ")");\r
366                         if(monitor.isCanceled()) {\r
367                                 throw new CancelException("Cancel requested.");\r
368                         }\r
369                         if (COLLECT_WITHIN_TRANSACTIONS)\r
370                                 collect2(g);\r
371                 }\r
372         }\r
373         \r
374         \r
375         \r
376         protected String getName(ReadGraph g, Identifiable res) throws DatabaseException {\r
377                 if (res instanceof ResourceIdentifiable)\r
378                         return NameUtils.getSafeName(g, ((ResourceIdentifiable)res).getResource());\r
379                 else\r
380                         return res.toString();\r
381         }\r
382         \r
383         public class WriteWrapper extends WriteGraphProxy {\r
384                 \r
385                 \r
386                 private Collection<Resource> createdResources = new ArrayList<Resource>();\r
387                 \r
388                 public WriteWrapper(WriteGraph graph) {\r
389                         super(graph);\r
390                 }\r
391                 \r
392                 public Collection<Resource> getCreatedResources() {\r
393                         return createdResources;\r
394                 }\r
395                 \r
396                 public void clearCreated() {\r
397                         createdResources = new ArrayList<Resource>();\r
398                 }\r
399                 \r
400                 @Override\r
401                 public Resource newResource() throws ServiceException {\r
402                         Resource res = graph.newResource();\r
403                         createdResources.add(res);\r
404                         return res;\r
405                 }\r
406                 \r
407                 @Override\r
408                 public Resource newResource(long clusterId) throws ServiceException {\r
409                         Resource res = graph.newResource(clusterId);\r
410                         createdResources.add(res);\r
411                         return res;\r
412                 }\r
413                 \r
414                 \r
415         }\r
416         \r
417         private void initializeRules(Session session, VirtualGraph vg, final Resource model ) throws DatabaseException{\r
418                 session.syncRequest(new WriteRequest(vg) {\r
419                         @Override\r
420                         public void perform(WriteGraph g) throws DatabaseException {\r
421                                 for (InitializedRule rule : initializedRules)\r
422                                         rule.initialize(g, model);\r
423                                 \r
424                         }\r
425                 });\r
426                 \r
427         }\r
428                 \r
429         private void collect(ReadGraph g) throws DatabaseException {\r
430                 if (vg != null)\r
431                         return;\r
432                 SessionGarbageCollection.gc(g, 0, -1);\r
433         }\r
434         \r
435         int collect = 0;\r
436         \r
437         private void collect2(ReadGraph g) throws DatabaseException {\r
438                 if (vg != null)\r
439                         return;\r
440                 \r
441                 if (collect == OBJECTS_BEFORE_COLLECT) {\r
442                         SessionGarbageCollection.gc(g, 0, -1);\r
443                         collect = 0;\r
444                 } else {\r
445                         collect++;\r
446                 }\r
447         }\r
448         \r
449         private void applyModifications(Session session, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
450                 \r
451                 \r
452                 \r
453                 int passCount = Math.max(globalModificationRules.size(),modificationRules.size());\r
454                 \r
455                 for (int pass = 0; pass <passCount; pass++) {\r
456                         // Apply global modification rules first\r
457                         if (globalModificationRules.size() > pass) {\r
458                                 int count = 0;\r
459                                 List<ModificationRule> modRules = globalModificationRules.get(pass);\r
460                                 int size = modRules.size();\r
461                                 monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
462                                 for (final ModificationRule r : modRules) {\r
463                                         session.syncRequest(new ReadRequest() {\r
464                                                 \r
465                                                 @Override\r
466                                                 public void run(ReadGraph g) throws DatabaseException {\r
467                                                         try {\r
468                                                                 Collection<GraphNode<Identifiable>> ruleModified = r.modify(g, nodes);\r
469                                                                 \r
470                                                                 if (ruleModified == null)\r
471                                                                         return;\r
472                                                                 for (GraphNode<Identifiable> m : ruleModified) {\r
473                                                                         if (m.isDisposed()) {\r
474                                                                                 nodes.remove(m);\r
475                                                                         }\r
476                                                                         else if (!nodes.contains(m)) {\r
477                                                                                 nodes.add(m);\r
478                                                                         }\r
479                                                                 }\r
480                                                                 if (COLLECT_WITHIN_TRANSACTIONS)\r
481                                                                         collect(g);\r
482                                                         } catch (Exception e) {\r
483                                                                 throw new DatabaseException(e);\r
484                                                         }\r
485                                                         \r
486                                                 }\r
487                                         });\r
488                                         //SessionGarbageCollection.gc(null, session, true, null);\r
489                                         monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
490                                         if(monitor.isCanceled()) {\r
491                                                 throw new CancelException("Cancel requested.");\r
492                                         }\r
493                                 }\r
494                         }\r
495                         if (modificationRules.size() > pass) {\r
496                                 int count = 0;\r
497                                 List<Pair<IdentificationRule, ModificationRule>> modRules = modificationRules.get(pass);\r
498                                 int size = modRules.size();\r
499                                 monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
500                                 \r
501                                 // Apply per object modification rules \r
502                                 for (final Pair<IdentificationRule, ModificationRule> modRule : modRules) {\r
503                                         final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
504                                         final Collection<GraphNode<Identifiable>> ruleModified = new ArrayList<GraphNode<Identifiable>>();\r
505                                         while (iter.hasNext()) {\r
506                                                 session.syncRequest(new ReadRequest() {\r
507                                                         \r
508                                                         @Override\r
509                                                         public void run(ReadGraph g) throws DatabaseException {\r
510                                                                 try {\r
511                                                                         \r
512                                                                         int j = 0; \r
513                                                                         //for (GraphNode<Identifiable> n : nodes) {\r
514                                                                         while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
515                                                                                 GraphNode<Identifiable> n = iter.next();\r
516                                                                                 applyModifications(g, n, modRule, ruleModified);\r
517                                                                                 j++;\r
518                                                                         }\r
519                                                                         if (COLLECT_WITHIN_TRANSACTIONS)\r
520                                                                                 collect(g);\r
521                                                                         \r
522                                                                 } catch (Exception e) {\r
523                                                                         throw new DatabaseException(e);\r
524                                                                 }\r
525                                                                 \r
526                                                         }\r
527                                                 });\r
528                                         }\r
529                                         for (GraphNode<Identifiable> m : ruleModified) {\r
530                                                 if (m.isDisposed()) {\r
531                                                         nodes.remove(m);\r
532                                                 }\r
533                                                 else if (!nodes.contains(m)) {\r
534                                                         nodes.add(m);\r
535                                                 }\r
536                                         }\r
537                                         ruleModified.clear();\r
538                                         \r
539                                         //SessionGarbageCollection.gc(null, session, true, null);\r
540                                         monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
541                                         if(monitor.isCanceled()) {\r
542                                                 throw new CancelException("Cancel requested.");\r
543                                         }\r
544                                 }\r
545                         }       \r
546                 }\r
547                 \r
548         }\r
549         \r
550         private void applyModifications2(Session session, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
551                 session.syncRequest(new ReadRequest() {\r
552                         \r
553                         @Override\r
554                         public void run(ReadGraph g) throws DatabaseException {\r
555                                 try {\r
556                                         applyModifications(g, nodes, monitor);\r
557                                 } catch (Exception e) {\r
558                                         throw new DatabaseException(e);\r
559                                 }\r
560                                 \r
561                         }\r
562                 });\r
563         }\r
564         \r
565         private void applyGenerations(Session session, VirtualGraph vg, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
566                 \r
567                 int size = nodes.size();\r
568                 int count = 0;\r
569                 monitor.subTask("Assigning generation rules ("+ count + "/" + size + ")");\r
570                 // populate generation rules\r
571 \r
572                 {\r
573                         final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
574                         while (iter.hasNext()) {\r
575                                 int c = session.syncRequest(new Read<Integer>() {\r
576                                         \r
577                                         @Override\r
578                                         public Integer perform(ReadGraph graph)\r
579                                                         throws DatabaseException {\r
580                                                 int j = 0;\r
581                                                 while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
582                                                         GraphNode<Identifiable> n = iter.next();\r
583                                                         for (Pair<IdentificationRule,Pair<Integer,GenerationRule>> r : generationRules) {\r
584                                                                 if (r.first.matches(graph, n)) {\r
585                                                                         MapList<Integer,GenerationRule> rules = n.getHint(MappingHints.KEY_GENERATION_RULES);\r
586                                                                         if (rules == null) {\r
587                                                                                 rules = new MapList<Integer,GenerationRule>();  \r
588                                                                         }\r
589                                                                         rules.add(r.second.first,r.second.second);\r
590                                                                         n.setHint(MappingHints.KEY_GENERATION_RULES, rules);\r
591                                                                 }\r
592                                                         }\r
593                                                         j++;\r
594                                                 }\r
595                                                 if (COLLECT_WITHIN_TRANSACTIONS)\r
596                                                         collect(graph);\r
597                                                 return j;\r
598                                                 \r
599                                         }\r
600                                 });\r
601                                 collect(session);\r
602                                 monitor.subTask("Assigning generation rules ("+ (count+=c) + "/" + size + ")");\r
603                                 if(monitor.isCanceled()) {\r
604                                         throw new CancelException("Cancel requested.");\r
605                                 }\r
606                                 sleep();\r
607                         }\r
608                 }\r
609                 \r
610                 count = 0;\r
611                 monitor.subTask("Generating objects ("+ (count) + "/" + size + ")");\r
612                 \r
613                 // apply generation rules.\r
614                 \r
615                 {\r
616                         for (int stage = 0; stage <= maxGenPass; stage++) {\r
617                                 final int fStage = stage;\r
618                                 count = 0;\r
619                                 final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
620                                 while (iter.hasNext()) {\r
621                                         int c = session.syncRequest(new WriteResultRequest<Integer>(vg) {\r
622                                                 \r
623                                                 @Override\r
624                                                 public Integer perform(WriteGraph graph) throws DatabaseException {\r
625                                                         int j = 0;\r
626                                                         try {\r
627                                                                 while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
628                                                                         GraphNode<Identifiable> n = iter.next();\r
629                                                                         \r
630                                                                         MapList<Integer,GenerationRule> priRules = n.getHint(MappingHints.KEY_GENERATION_RULES);\r
631                                                                         if (priRules == null) {\r
632                                                                                 j++;\r
633                                                                                 continue;\r
634                                                                         }\r
635                                                                         final List<GenerationRule> rules = priRules.getValues(fStage);\r
636                                                                         \r
637                                                                         if (fStage == 0 && rules.size() == 0)\r
638                                                                                 System.out.println();\r
639                                                                         for (GenerationRule r : rules) {\r
640                                                                                 r.generate(graph, n);\r
641 \r
642                                                                         }\r
643 \r
644                                                                                 \r
645                                                                         j++;\r
646                                                                         \r
647                                                                 }\r
648                                                                 if (COLLECT_WITHIN_TRANSACTIONS)\r
649                                                                         collect(graph);\r
650                                                                 return j;\r
651                                                         \r
652                                                 } catch (Exception e) {\r
653                                                         throw new DatabaseException(e);\r
654                                                 }\r
655                                         }});\r
656                                         collect(session);\r
657                                         monitor.subTask("Generating objects, stage " + stage + " :  ("+ (count+=c) + "/" + size + ")");\r
658                                         if(monitor.isCanceled()) {\r
659                                                 throw new CancelException("Cancel requested.");\r
660                                         }\r
661                                         sleep();\r
662                                 }\r
663                         }\r
664                 }\r
665         }\r
666         \r
667         private void applyGenerations2(Session session, VirtualGraph vg, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
668                 session.syncRequest(new WriteRequest(vg) {\r
669                         \r
670                         @Override\r
671                         public void perform(WriteGraph graph) throws DatabaseException {\r
672                                 try {\r
673                                         applyGenerations(graph, nodes, monitor);\r
674                                 } catch (Exception e) {\r
675                                         throw new DatabaseException(e);\r
676                                 }\r
677                                 \r
678                         }\r
679                 });\r
680         }\r
681         \r
682         private void collect(Session session) {\r
683                 if (COLLECT_BETWEEN_WRITES)\r
684                         SessionGarbageCollection.gc(null, session, true, null);\r
685         }\r
686         \r
687         \r
688         private void sleep() {\r
689                 if (SLEEP_BETWEEN_WRITES) {\r
690                         try {\r
691                                 Thread.sleep(SLEEP_TIME);\r
692                         } catch (InterruptedException e) {\r
693                                 \r
694                         }\r
695                 }\r
696         }\r
697         \r
698         private void applyConnections(Session session, VirtualGraph vg, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
699                 int size = nodes.size();\r
700                 int count = 0;\r
701                 \r
702                 monitor.subTask("Generating connections ("+ count + "/" + size + ")");\r
703                 \r
704                 final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
705                 while (iter.hasNext()) {\r
706                         int c = session.syncRequest(new WriteResultRequest<Integer>(vg) {\r
707                                 \r
708                                 @Override\r
709                                 public Integer perform(WriteGraph g) throws DatabaseException {\r
710                                         int j = 0;\r
711                                         try {\r
712                                                 while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
713                                                         GraphNode<Identifiable> node = iter.next();\r
714                                                         applyConnections(g, node);\r
715                                                         j++;\r
716                                                 }\r
717                                                 if (COLLECT_WITHIN_TRANSACTIONS)\r
718                                                         collect(g);\r
719                                                 return j;\r
720                                                 \r
721                                         } catch (Exception e) {\r
722                                                 throw new DatabaseException(e);\r
723                                         }       \r
724                                 }       \r
725                         });\r
726                         collect(session);\r
727                         monitor.subTask("Generating connections ("+ (count+=c) + "/" + size + ")");\r
728                         if(monitor.isCanceled()) {\r
729                                 throw new CancelException("Cancel requested.");\r
730                         }\r
731                         sleep();\r
732                 }\r
733         }\r
734         \r
735         private void applyConnections2(Session session, VirtualGraph vg, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
736                 session.syncRequest(new WriteRequest(vg) {\r
737                         \r
738                         @Override\r
739                         public void perform(WriteGraph graph) throws DatabaseException {\r
740                                 try {\r
741                                         applyConnections(graph, nodes, monitor);\r
742                                 } catch (Exception e) {\r
743                                         throw new DatabaseException(e);\r
744                                 }\r
745                                 \r
746                         }\r
747                 });\r
748         }\r
749 \r
750         private void applyModifications(ReadGraph g, GraphNode<Identifiable> n, Pair<IdentificationRule, ModificationRule> modRule, Collection<GraphNode<Identifiable>> ruleModified) throws Exception {\r
751                 if (!n.isDisposed() && modRule.first.matches(g, n)) { // we have to check \r
752                         Collection<GraphNode<Identifiable>> perRule = new ArrayList<GraphNode<Identifiable>>();\r
753                         perRule.add(n);\r
754                         ruleModified.addAll(modRule.second.modify(g, perRule));\r
755                 }\r
756         }\r
757         \r
758         private void applyConnections(WriteGraph g, GraphNode<Identifiable> node) throws Exception {\r
759                 for (Link<Identifiable> link : node.getLinks()) {\r
760                         if (link.isMain()) {\r
761                                 \r
762                                 for (Pair<ConnectionIdentificationRule, ConnectionGenerationRule> r : connectionRules) {\r
763                                         if (r.first.mathces(g, node, link.to(), link)) {\r
764                                                 Logger.defaultLogInfo("Connecting " +  getName(g, node.getData()) + " to " + getName(g, link.to().getData()) + " " + link.getName() + "/"+link.getInverseName());\r
765                                                 r.second.generate(g, node, link.to(), link);\r
766                                                 break;\r
767                                         }\r
768                                 }\r
769                         }\r
770                 }\r
771         }\r
772 }\r