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