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