--- /dev/null
+package org.simantics.interop.mapping;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.NullProgressMonitor;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.request.WriteResultRequest;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.layer0.util.SessionGarbageCollection;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.interop.mapping.data.GraphNode;\r
+import org.simantics.interop.mapping.data.Identifiable;\r
+import org.simantics.interop.mapping.data.Link;\r
+import org.simantics.interop.mapping.data.ResourceIdentifiable;\r
+import org.simantics.ui.jobs.SessionGarbageCollectorJob;\r
+import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+/**\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class Mapper {\r
+ \r
+ public static final boolean USE_SPLIT_TRANSACTIONS = false; // Split transactions\r
+ public static int OBJECTS_PER_TRANSACTION = 5000; // number of objects handled per transaction (split mode) \r
+ private static boolean SLEEP_BETWEEN_WRITES = false; // sleep between transactions (split mode) \r
+ private static int SLEEP_TIME = 10; // time to sleep (ms)\r
+ private static boolean COLLECT_BETWEEN_WRITES = false; // Run SessionGC between split transactions\r
+ private static boolean COLLECT_WITHIN_TRANSACTIONS = true; // Run Collect within transactions (both modes)\r
+ public static int OBJECTS_BEFORE_COLLECT = 5000; // number of objects that are handled before collect (non-split mode)\r
+ \r
+ private List<InitializedRule> initializedRules = new ArrayList<InitializedRule>();\r
+ private List<Pair<IdentificationRule, Pair<Integer,GenerationRule>>> generationRules;\r
+ private List<List<ModificationRule>> globalModificationRules;\r
+ private List<List<Pair<IdentificationRule, ModificationRule>>> modificationRules;\r
+ private List<Pair<ConnectionIdentificationRule, ConnectionGenerationRule>> connectionRules;\r
+\r
+ int maxGenPass = 0;\r
+ \r
+ public Mapper() {\r
+ long maxMemory = Runtime.getRuntime().maxMemory();\r
+ maxMemory /= (1024*1024); // Convert to MB;\r
+ int use = 290; // Estimated memory usage of the system\r
+ int freeMem = (int)maxMemory-use; // Free memory for mappings \r
+ OBJECTS_BEFORE_COLLECT = (freeMem * freeMem) / 1000; //600M heap -> 84, 3000M heap -> 5645\r
+ if (OBJECTS_BEFORE_COLLECT < 2)\r
+ OBJECTS_BEFORE_COLLECT = 2;\r
+ OBJECTS_PER_TRANSACTION = OBJECTS_BEFORE_COLLECT;\r
+ \r
+ \r
+ generationRules = new ArrayList<Pair<IdentificationRule,Pair<Integer,GenerationRule>>>();\r
+ modificationRules = new ArrayList<List<Pair<IdentificationRule,ModificationRule>>>();\r
+ globalModificationRules = new ArrayList<List<ModificationRule>>();\r
+ connectionRules = new ArrayList<Pair<ConnectionIdentificationRule, ConnectionGenerationRule>>();\r
+ }\r
+ \r
+ public void addRule(int pass, IdentificationRule idRule, GenerationRule genRule) {\r
+ if (idRule == null || genRule == null) throw new NullPointerException();\r
+ generationRules.add(new Pair<IdentificationRule, Pair<Integer,GenerationRule>>(idRule, new Pair<Integer,GenerationRule>(pass,genRule)));\r
+ maxGenPass = Math.max(maxGenPass, pass);\r
+ if (genRule instanceof InitializedRule)\r
+ initializedRules.add((InitializedRule)genRule);\r
+ }\r
+ \r
+ public void addRule(IdentificationRule idRule, MappingRule mappingRule) {\r
+ addRule(0,idRule,mappingRule);\r
+ }\r
+ \r
+ public void addRule(int pass, IdentificationRule idRule, MappingRule mappingRule) {\r
+ if (idRule == null || mappingRule == null) throw new NullPointerException();\r
+ if (mappingRule instanceof ModificationRule) {\r
+ while (pass >= modificationRules.size()) {\r
+ modificationRules.add(new ArrayList<Pair<IdentificationRule,ModificationRule>>());\r
+ }\r
+ List<Pair<IdentificationRule,ModificationRule>> priList = modificationRules.get(pass);\r
+ priList.add(new Pair<IdentificationRule, ModificationRule>(idRule, (ModificationRule)mappingRule));\r
+ }\r
+ if (mappingRule instanceof GenerationRule)\r
+ generationRules.add(new Pair<IdentificationRule, Pair<Integer,GenerationRule>>(idRule, new Pair<Integer,GenerationRule>(pass,(GenerationRule)mappingRule)));\r
+ if (mappingRule instanceof InitializedRule)\r
+ initializedRules.add((InitializedRule)mappingRule);\r
+ }\r
+ \r
+ public void addRule(IdentificationRule idRule, ModificationRule... modRules) {\r
+ addRule(0, idRule, modRules);\r
+ }\r
+\r
+ public void addRule(int pass, IdentificationRule idRule, ModificationRule... modRules) {\r
+ if (idRule == null) throw new NullPointerException();\r
+ \r
+ while (pass >= modificationRules.size()) {\r
+ modificationRules.add(new ArrayList<Pair<IdentificationRule,ModificationRule>>());\r
+ }\r
+ List<Pair<IdentificationRule,ModificationRule>> priList = modificationRules.get(pass);\r
+ \r
+ for (ModificationRule modRule : modRules){\r
+ if (modRule == null) throw new NullPointerException(); \r
+ priList.add(new Pair<IdentificationRule, ModificationRule>(idRule, modRule));\r
+ if (modRule instanceof InitializedRule)\r
+ initializedRules.add((InitializedRule)modRule);\r
+ }\r
+ }\r
+ public void addRule(ModificationRule modRule) {\r
+ addRule(0, modRule);\r
+ }\r
+ \r
+ public void addRule(int pass, ModificationRule modRule) {\r
+ if (modRule == null) throw new NullPointerException();\r
+ while (pass >= globalModificationRules.size()) {\r
+ globalModificationRules.add(new ArrayList<ModificationRule>());\r
+ }\r
+ List<ModificationRule> priList = globalModificationRules.get(pass);\r
+ priList.add(modRule);\r
+ if (modRule instanceof InitializedRule)\r
+ initializedRules.add((InitializedRule)modRule);\r
+ }\r
+ \r
+ public void addRule(ConnectionIdentificationRule idRule, ConnectionGenerationRule genRule) {\r
+ if (idRule == null || genRule == null) throw new NullPointerException();\r
+ connectionRules.add(new Pair<ConnectionIdentificationRule, ConnectionGenerationRule>(idRule, genRule));\r
+ if (genRule instanceof InitializedRule)\r
+ initializedRules.add((InitializedRule)genRule);\r
+ }\r
+ \r
+ /**\r
+ * Runs the mapping procedure. Disposes nodes after mapping is done.\r
+ * @param g\r
+ * @param model\r
+ * @param nodes\r
+ * @param monitor\r
+ * @throws Exception\r
+ */\r
+ public void map(WriteGraph g, Resource model, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ startMapping(null);\r
+ try {\r
+ if (monitor == null)\r
+ monitor = new NullProgressMonitor();\r
+ \r
+ for (InitializedRule rule : initializedRules)\r
+ rule.initialize(g, model);\r
+ \r
+ applyModifications(g, nodes, monitor);\r
+ monitor.worked(1);\r
+ applyGenerations(g,nodes,monitor);\r
+ monitor.worked(1);\r
+ applyConnections(g,nodes,monitor);\r
+ monitor.worked(1);\r
+ } finally {\r
+ MappingTools.disposeNodes(nodes);\r
+ endMapping();\r
+ }\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Runs the mapping procedure. Disposes nodes after mapping is done.\r
+ * @param session\r
+ * @param model\r
+ * @param nodes\r
+ * @param monitor\r
+ * @throws Exception\r
+ */\r
+ public void map(Session session, Resource model, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ map(session, model, null, nodes, monitor);\r
+ }\r
+ \r
+ /**\r
+ * Runs the mapping procedure. Disposes nodes after mapping is done.\r
+ * @param session\r
+ * @param model\r
+ * @param vg\r
+ * @param nodes\r
+ * @param monitor\r
+ * @throws Exception\r
+ */\r
+ public void map(Session session, Resource model, VirtualGraph vg, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ startMapping(vg);\r
+ try {\r
+ long time = System.currentTimeMillis();\r
+ if (monitor == null)\r
+ monitor = new NullProgressMonitor();\r
+ \r
+ initializeRules(session, vg, model);\r
+ if (USE_SPLIT_TRANSACTIONS) {\r
+ applyModifications(session, nodes, monitor);\r
+ monitor.worked(1);\r
+ applyGenerations(session, vg, nodes, monitor);\r
+ monitor.worked(1);\r
+ applyConnections(session, vg, nodes, monitor);\r
+ monitor.worked(1);\r
+ } else {\r
+ applyModifications2(session, nodes, monitor);\r
+ monitor.worked(1);\r
+ applyGenerations2(session, vg, nodes, monitor);\r
+ monitor.worked(1);\r
+ applyConnections2(session, vg, nodes, monitor);\r
+ monitor.worked(1);\r
+ }\r
+ long time2 = System.currentTimeMillis();\r
+ System.out.println("Mapping took " + ((time2-time)/1000) + " seconds");\r
+ } finally {\r
+ MappingTools.disposeNodes(nodes);\r
+ if (COLLECT_BETWEEN_WRITES) {\r
+\r
+ SessionGarbageCollection.gc(null, session, true, null);\r
+ }\r
+ endMapping();\r
+ }\r
+ \r
+ }\r
+ \r
+ \r
+ //private boolean autosaveEndabled = false;\r
+ private VirtualGraph vg;\r
+ \r
+ protected void startMapping(VirtualGraph vg) {\r
+ SessionGarbageCollectorJob.getInstance().setEnabled(false);\r
+ //autosaveEndabled = AutosaveCommands.getInstance().isEnabled();\r
+ //AutosaveCommands.getInstance().setEnabled(false);\r
+ this.vg = vg;\r
+ }\r
+ \r
+ protected void endMapping() {\r
+ SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();\r
+ // AutosaveCommands.getInstance().setEnabled(autosaveEndabled);\r
+ vg = null;\r
+ }\r
+ \r
+ private void applyModifications(ReadGraph g, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ \r
+ // Apply global modification rules first\r
+ \r
+ int passCount = Math.max(globalModificationRules.size(),modificationRules.size());\r
+\r
+ for (int pass = 0; pass < passCount; pass++) {\r
+ if (globalModificationRules.size() > pass) {\r
+ int count = 0;\r
+ List<ModificationRule> modRules = globalModificationRules.get(pass);\r
+ int size = modRules.size();\r
+ monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ for (ModificationRule r : modRules) {\r
+ Collection<GraphNode<Identifiable>> ruleModified = r.modify(g, nodes);\r
+ if (ruleModified == null)\r
+ continue;\r
+ for (GraphNode<Identifiable> m : ruleModified) {\r
+ if (m.isDisposed()) {\r
+ nodes.remove(m);\r
+ }\r
+ else if (!nodes.contains(m)) {\r
+ nodes.add(m);\r
+ }\r
+ }\r
+ monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect(g);\r
+ }\r
+ } if (modificationRules.size() > pass) {\r
+ int count = 0;\r
+ List<Pair<IdentificationRule, ModificationRule>> modRules = modificationRules.get(pass);\r
+ int size = modRules.size();\r
+ monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ // Apply per object modification rules \r
+ for (Pair<IdentificationRule, ModificationRule> modRule : modRules) {\r
+ Collection<GraphNode<Identifiable>> ruleModified = new ArrayList<GraphNode<Identifiable>>();\r
+ for (GraphNode<Identifiable> n : nodes) {\r
+ applyModifications(g, n, modRule, ruleModified);\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect2(g);\r
+ }\r
+ \r
+ for (GraphNode<Identifiable> m : ruleModified) {\r
+ if (m.isDisposed()) {\r
+ nodes.remove(m);\r
+ }\r
+ else if (!nodes.contains(m)) {\r
+ nodes.add(m);\r
+ }\r
+ }\r
+ monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ \r
+ \r
+ private void applyGenerations(WriteGraph graph, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ \r
+ int size = nodes.size();\r
+ int count = 0;\r
+ monitor.subTask("Assigning generation rules ("+ count + "/" + size + ")");\r
+ // populate generation rules\r
+ for (GraphNode<Identifiable> n : nodes) {\r
+ \r
+ for (Pair<IdentificationRule,Pair<Integer,GenerationRule>> r : generationRules) {\r
+ if (r.first.matches(graph, n)) {\r
+ MappingTools.assignGenerationRule(n, r.second.first,r.second.second);\r
+ }\r
+ }\r
+ monitor.subTask("Assigning generation rules ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect2(graph);\r
+ }\r
+ \r
+ count = 0;\r
+ monitor.subTask("Generating objects ("+ count + "/" + size + ")");\r
+ \r
+ // apply generation rules.\r
+ //WriteWrapper g = new WriteWrapper(graph);\r
+ \r
+ //Collection<GenerationRule> usedRules = new ArrayList<GenerationRule>();\r
+ for (int stage = 0; stage <= maxGenPass; stage++) {\r
+ count = 0;\r
+ for (GraphNode<Identifiable> n : nodes) {\r
+\r
+ MapList<Integer,GenerationRule> priRules = n.getHint(MappingHints.KEY_GENERATION_RULES);\r
+ List<GenerationRule> rules = priRules.getValues(stage);\r
+ for (GenerationRule r : rules) {\r
+ r.generate(graph, n);\r
+ }\r
+\r
+ monitor.subTask("Generating objects, stage " + stage + " : ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect2(graph);\r
+ }\r
+ }\r
+ }\r
+ \r
+ private void applyConnections(WriteGraph g, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ int size = nodes.size();\r
+ int count = 0;\r
+ \r
+ monitor.subTask("Generating connections ("+ count + "/" + size + ")");\r
+ \r
+ for (GraphNode<Identifiable> node : nodes) {\r
+ applyConnections(g, node);\r
+ monitor.subTask("Generating connections ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect2(g);\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ protected String getName(ReadGraph g, Identifiable res) throws DatabaseException {\r
+ if (res instanceof ResourceIdentifiable)\r
+ return NameUtils.getSafeName(g, ((ResourceIdentifiable)res).getResource());\r
+ else\r
+ return res.toString();\r
+ }\r
+ \r
+ public class WriteWrapper extends WriteGraphProxy {\r
+ \r
+ \r
+ private Collection<Resource> createdResources = new ArrayList<Resource>();\r
+ \r
+ public WriteWrapper(WriteGraph graph) {\r
+ super(graph);\r
+ }\r
+ \r
+ public Collection<Resource> getCreatedResources() {\r
+ return createdResources;\r
+ }\r
+ \r
+ public void clearCreated() {\r
+ createdResources = new ArrayList<Resource>();\r
+ }\r
+ \r
+ @Override\r
+ public Resource newResource() throws ServiceException {\r
+ Resource res = graph.newResource();\r
+ createdResources.add(res);\r
+ return res;\r
+ }\r
+ \r
+ @Override\r
+ public Resource newResource(long clusterId) throws ServiceException {\r
+ Resource res = graph.newResource(clusterId);\r
+ createdResources.add(res);\r
+ return res;\r
+ }\r
+ \r
+ \r
+ }\r
+ \r
+ private void initializeRules(Session session, VirtualGraph vg, final Resource model ) throws DatabaseException{\r
+ session.syncRequest(new WriteRequest(vg) {\r
+ @Override\r
+ public void perform(WriteGraph g) throws DatabaseException {\r
+ for (InitializedRule rule : initializedRules)\r
+ rule.initialize(g, model);\r
+ \r
+ }\r
+ });\r
+ \r
+ }\r
+ \r
+ private void collect(ReadGraph g) throws DatabaseException {\r
+ if (vg != null)\r
+ return;\r
+ SessionGarbageCollection.gc(g, 0, -1);\r
+ }\r
+ \r
+ int collect = 0;\r
+ \r
+ private void collect2(ReadGraph g) throws DatabaseException {\r
+ if (vg != null)\r
+ return;\r
+ \r
+ if (collect == OBJECTS_BEFORE_COLLECT) {\r
+ SessionGarbageCollection.gc(g, 0, -1);\r
+ collect = 0;\r
+ } else {\r
+ collect++;\r
+ }\r
+ }\r
+ \r
+ private void applyModifications(Session session, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
+ \r
+ \r
+ \r
+ int passCount = Math.max(globalModificationRules.size(),modificationRules.size());\r
+ \r
+ for (int pass = 0; pass <passCount; pass++) {\r
+ // Apply global modification rules first\r
+ if (globalModificationRules.size() > pass) {\r
+ int count = 0;\r
+ List<ModificationRule> modRules = globalModificationRules.get(pass);\r
+ int size = modRules.size();\r
+ monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ for (final ModificationRule r : modRules) {\r
+ session.syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph g) throws DatabaseException {\r
+ try {\r
+ Collection<GraphNode<Identifiable>> ruleModified = r.modify(g, nodes);\r
+ \r
+ if (ruleModified == null)\r
+ return;\r
+ for (GraphNode<Identifiable> m : ruleModified) {\r
+ if (m.isDisposed()) {\r
+ nodes.remove(m);\r
+ }\r
+ else if (!nodes.contains(m)) {\r
+ nodes.add(m);\r
+ }\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect(g);\r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ \r
+ }\r
+ });\r
+ //SessionGarbageCollection.gc(null, session, true, null);\r
+ monitor.subTask("Running global modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ }\r
+ }\r
+ if (modificationRules.size() > pass) {\r
+ int count = 0;\r
+ List<Pair<IdentificationRule, ModificationRule>> modRules = modificationRules.get(pass);\r
+ int size = modRules.size();\r
+ monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ \r
+ // Apply per object modification rules \r
+ for (final Pair<IdentificationRule, ModificationRule> modRule : modRules) {\r
+ final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
+ final Collection<GraphNode<Identifiable>> ruleModified = new ArrayList<GraphNode<Identifiable>>();\r
+ while (iter.hasNext()) {\r
+ session.syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph g) throws DatabaseException {\r
+ try {\r
+ \r
+ int j = 0; \r
+ //for (GraphNode<Identifiable> n : nodes) {\r
+ while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
+ GraphNode<Identifiable> n = iter.next();\r
+ applyModifications(g, n, modRule, ruleModified);\r
+ j++;\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect(g);\r
+ \r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ \r
+ }\r
+ });\r
+ }\r
+ for (GraphNode<Identifiable> m : ruleModified) {\r
+ if (m.isDisposed()) {\r
+ nodes.remove(m);\r
+ }\r
+ else if (!nodes.contains(m)) {\r
+ nodes.add(m);\r
+ }\r
+ }\r
+ ruleModified.clear();\r
+ \r
+ //SessionGarbageCollection.gc(null, session, true, null);\r
+ monitor.subTask("Running object modification rules: pass (" + (pass+1) + "/" + passCount + "), rule ("+ (++count) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ }\r
+ } \r
+ }\r
+ \r
+ }\r
+ \r
+ private void applyModifications2(Session session, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
+ session.syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph g) throws DatabaseException {\r
+ try {\r
+ applyModifications(g, nodes, monitor);\r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ \r
+ }\r
+ });\r
+ }\r
+ \r
+ private void applyGenerations(Session session, VirtualGraph vg, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ \r
+ int size = nodes.size();\r
+ int count = 0;\r
+ monitor.subTask("Assigning generation rules ("+ count + "/" + size + ")");\r
+ // populate generation rules\r
+\r
+ {\r
+ final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
+ while (iter.hasNext()) {\r
+ int c = session.syncRequest(new Read<Integer>() {\r
+ \r
+ @Override\r
+ public Integer perform(ReadGraph graph)\r
+ throws DatabaseException {\r
+ int j = 0;\r
+ while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
+ GraphNode<Identifiable> n = iter.next();\r
+ for (Pair<IdentificationRule,Pair<Integer,GenerationRule>> r : generationRules) {\r
+ if (r.first.matches(graph, n)) {\r
+ MapList<Integer,GenerationRule> rules = n.getHint(MappingHints.KEY_GENERATION_RULES);\r
+ if (rules == null) {\r
+ rules = new MapList<Integer,GenerationRule>(); \r
+ }\r
+ rules.add(r.second.first,r.second.second);\r
+ n.setHint(MappingHints.KEY_GENERATION_RULES, rules);\r
+ }\r
+ }\r
+ j++;\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect(graph);\r
+ return j;\r
+ \r
+ }\r
+ });\r
+ collect(session);\r
+ monitor.subTask("Assigning generation rules ("+ (count+=c) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ sleep();\r
+ }\r
+ }\r
+ \r
+ count = 0;\r
+ monitor.subTask("Generating objects ("+ (count) + "/" + size + ")");\r
+ \r
+ // apply generation rules.\r
+ \r
+ {\r
+ for (int stage = 0; stage <= maxGenPass; stage++) {\r
+ final int fStage = stage;\r
+ count = 0;\r
+ final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
+ while (iter.hasNext()) {\r
+ int c = session.syncRequest(new WriteResultRequest<Integer>(vg) {\r
+ \r
+ @Override\r
+ public Integer perform(WriteGraph graph) throws DatabaseException {\r
+ int j = 0;\r
+ try {\r
+ while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
+ GraphNode<Identifiable> n = iter.next();\r
+ \r
+ MapList<Integer,GenerationRule> priRules = n.getHint(MappingHints.KEY_GENERATION_RULES);\r
+ if (priRules == null) {\r
+ j++;\r
+ continue;\r
+ }\r
+ final List<GenerationRule> rules = priRules.getValues(fStage);\r
+ \r
+ if (fStage == 0 && rules.size() == 0)\r
+ System.out.println();\r
+ for (GenerationRule r : rules) {\r
+ r.generate(graph, n);\r
+\r
+ }\r
+\r
+ \r
+ j++;\r
+ \r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect(graph);\r
+ return j;\r
+ \r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }});\r
+ collect(session);\r
+ monitor.subTask("Generating objects, stage " + stage + " : ("+ (count+=c) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ sleep();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ private void applyGenerations2(Session session, VirtualGraph vg, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
+ session.syncRequest(new WriteRequest(vg) {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ try {\r
+ applyGenerations(graph, nodes, monitor);\r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ \r
+ }\r
+ });\r
+ }\r
+ \r
+ private void collect(Session session) {\r
+ if (COLLECT_BETWEEN_WRITES)\r
+ SessionGarbageCollection.gc(null, session, true, null);\r
+ }\r
+ \r
+ \r
+ private void sleep() {\r
+ if (SLEEP_BETWEEN_WRITES) {\r
+ try {\r
+ Thread.sleep(SLEEP_TIME);\r
+ } catch (InterruptedException e) {\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ private void applyConnections(Session session, VirtualGraph vg, Collection<GraphNode<Identifiable>> nodes, IProgressMonitor monitor) throws Exception {\r
+ int size = nodes.size();\r
+ int count = 0;\r
+ \r
+ monitor.subTask("Generating connections ("+ count + "/" + size + ")");\r
+ \r
+ final Iterator<GraphNode<Identifiable>> iter = nodes.iterator();\r
+ while (iter.hasNext()) {\r
+ int c = session.syncRequest(new WriteResultRequest<Integer>(vg) {\r
+ \r
+ @Override\r
+ public Integer perform(WriteGraph g) throws DatabaseException {\r
+ int j = 0;\r
+ try {\r
+ while (iter.hasNext() && j < OBJECTS_PER_TRANSACTION) {\r
+ GraphNode<Identifiable> node = iter.next();\r
+ applyConnections(g, node);\r
+ j++;\r
+ }\r
+ if (COLLECT_WITHIN_TRANSACTIONS)\r
+ collect(g);\r
+ return j;\r
+ \r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ } \r
+ } \r
+ });\r
+ collect(session);\r
+ monitor.subTask("Generating connections ("+ (count+=c) + "/" + size + ")");\r
+ if(monitor.isCanceled()) {\r
+ throw new CancelException("Cancel requested.");\r
+ }\r
+ sleep();\r
+ }\r
+ }\r
+ \r
+ private void applyConnections2(Session session, VirtualGraph vg, final Collection<GraphNode<Identifiable>> nodes, final IProgressMonitor monitor) throws Exception {\r
+ session.syncRequest(new WriteRequest(vg) {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ try {\r
+ applyConnections(graph, nodes, monitor);\r
+ } catch (Exception e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ \r
+ }\r
+ });\r
+ }\r
+\r
+ private void applyModifications(ReadGraph g, GraphNode<Identifiable> n, Pair<IdentificationRule, ModificationRule> modRule, Collection<GraphNode<Identifiable>> ruleModified) throws Exception {\r
+ if (!n.isDisposed() && modRule.first.matches(g, n)) { // we have to check \r
+ Collection<GraphNode<Identifiable>> perRule = new ArrayList<GraphNode<Identifiable>>();\r
+ perRule.add(n);\r
+ ruleModified.addAll(modRule.second.modify(g, perRule));\r
+ }\r
+ }\r
+ \r
+ private void applyConnections(WriteGraph g, GraphNode<Identifiable> node) throws Exception {\r
+ for (Link<Identifiable> link : node.getLinks()) {\r
+ if (link.isMain()) {\r
+ \r
+ for (Pair<ConnectionIdentificationRule, ConnectionGenerationRule> r : connectionRules) {\r
+ if (r.first.mathces(g, node, link.to(), link)) {\r
+ Logger.defaultLogInfo("Connecting " + getName(g, node.getData()) + " to " + getName(g, link.to().getData()) + " " + link.getName() + "/"+link.getInverseName());\r
+ r.second.generate(g, node, link.to(), link);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r