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