Fix CopyAdvisorUtil.copy2 to copy IsRelatedTo-statements left out before 59/4459/1 master
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Thu, 17 Sep 2020 11:45:47 +0000 (14:45 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Thu, 17 Sep 2020 11:45:47 +0000 (14:45 +0300)
This implementation works so that it copies any IsRelatedTo statements
where both the subject and object have been copied during the normal
(old) copy process. The statements are marked as pending during the copy
and post-processed after everything else has been copied.

gitlab #607

Change-Id: I9170a448c127e0c7de6eae4260db5799ad7644bb

bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/CopyAdvisorUtil.java
bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ComponentCopyAdvisor.java

index ab28463e84d5a8e3d3ae81af98b52f990393f167..bbf9a8e5b23d2134f536bacb21cae26d058e815e 100644 (file)
@@ -11,8 +11,6 @@
  *******************************************************************************/
 package org.simantics.diagram.synchronization.graph;
 
-import gnu.trove.map.hash.THashMap;
-
 import java.util.Map;
 import java.util.Set;
 import java.util.function.BiFunction;
@@ -46,6 +44,10 @@ import org.simantics.diagram.synchronization.SynchronizationHints;
 import org.simantics.graph.db.TransferableGraphs;
 import org.simantics.graph.representation.TransferableGraph1;
 import org.simantics.layer0.Layer0;
+import org.simantics.utils.datastructures.BinaryFunction;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
 
 /**
  * This class contains utility methods for the basic cut/copy operations
@@ -82,6 +84,15 @@ public class CopyAdvisorUtil {
 
     public static final boolean DEBUG_COPY = DebugPolicy.DEBUG_COPY_PASTE;
 
+    private static class Statement4 {
+        public final Statement stm;
+        public final Resource inverse;
+        public Statement4(Statement stm, Resource inverse) {
+            this.stm = stm;
+            this.inverse = inverse;
+        }
+    }
+
     /**
      * @param context a synchronization context instance, such as
      *        {@link GraphToDiagramSynchronizer}
@@ -364,8 +375,10 @@ public class CopyAdvisorUtil {
      * @throws DatabaseException
      */
     public static Resource copy2(WriteGraph graph, Resource source,
-            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor) throws DatabaseException {
-        return copy2(graph, source, 0, advisor, new THashMap<Object, Object>());
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor)
+                    throws DatabaseException
+    {
+        return copy2(graph, source, advisor, new THashMap<>());
     }
 
     /**
@@ -380,13 +393,52 @@ public class CopyAdvisorUtil {
      * @throws DatabaseException 
      */
     public static Resource copy2(WriteGraph graph, Resource source,
-            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap)
-            throws DatabaseException {
-        return copy2(graph, source, 0, advisor, copyMap);
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor,
+            Map<Object, Object> copyMap)
+                    throws DatabaseException
+    {
+        Set<Statement4> pendingStatements = new THashSet<>();
+        Resource result = copy2(graph, source, 0, advisor, copyMap, pendingStatements);
+        postProcessStatements(graph, copyMap, pendingStatements);
+        return result;
+    }
+
+    /**
+     * Post-process pending statement
+     *  
+     * Rule: If both the subject and object of a pending source statement have
+     *       been copied, then the pending statement should also be copied.
+     */
+    private static void postProcessStatements(
+            WriteGraph graph,
+            Map<Object, Object> copyMap,
+            Set<Statement4> pendingStatements)
+                    throws DatabaseException
+    {
+        if (pendingStatements.isEmpty())
+            return;
+
+        if (DEBUG_COPY)
+            System.out.println("post processing " + pendingStatements.size() + " pending statements");
+        for (Statement4 srcStm : pendingStatements) {
+            // At this point, it is certain that srcStm subject has been copied
+            // but test it anyway.
+            Resource subjectCopy = (Resource) copyMap.get(srcStm.stm.getSubject());
+            Resource objectCopy = (Resource) copyMap.get(srcStm.stm.getObject());
+            if (subjectCopy == null || objectCopy == null) {
+                if (DEBUG_COPY)
+                    System.out.println("skipping pending statement: " + NameUtils.toString(graph, srcStm.stm));
+                continue;
+            }
+            if (DEBUG_COPY)
+                System.out.println("copying pending statement: " + NameUtils.toString(graph, srcStm.stm));
+            graph.claim(subjectCopy, srcStm.stm.getPredicate(), srcStm.inverse, objectCopy);
+        }
     }
 
     private static Resource copy2(final WriteGraph graph, final Resource source, final int level,
-            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap)
+            BiFunction<ReadGraph, Statement, StatementEvaluation> advisor, Map<Object, Object> copyMap,
+            Set<Statement4> pendingSourceStatements)
     throws DatabaseException {
         if (DEBUG_COPY)
             System.out.println("[" + level + "] CopyAdvisorUtil.copy(" + NameUtils.getSafeName(graph, source) + ", advisor=" + advisor + ")");
@@ -497,12 +549,18 @@ public class CopyAdvisorUtil {
                             if (DEBUG_COPY)
                                 System.out.println("[" + level + "]\t\tcopy whole object");
 
-                            Resource clone = copy2(graph, obj, level + 1, advisor, copyMap);
+                            Resource clone = copy2(graph, obj, level + 1, advisor, copyMap, pendingSourceStatements);
                             graph.claim(copy, relation, inverse, clone);
                         }
                     } else {
-                        if (DEBUG_COPY)
-                            System.out.println("[" + level + "]\t\tskipping statement");
+                        if (graph.isSubrelationOf(relation, L0.IsRelatedTo)) {
+                            if (DEBUG_COPY)
+                                System.out.println("[" + level + "]\t\tmarking statement as pending for post-processing");
+                            pendingSourceStatements.add(new Statement4(stm, inverse));
+                        } else {
+                            if (DEBUG_COPY)
+                                System.out.println("[" + level + "]\t\tskipping weak statement");
+                        }
                     }
                 }
             }
index 3e6e9c1b9527096cfa1835a50e43f6b2dfb97c7f..021ecc436b86c5d82af28d062cd45d4a88b38148 100644 (file)
@@ -32,7 +32,6 @@ import org.simantics.modeling.ModelingUtils;
 import org.simantics.modeling.services.ComponentNamingUtil;
 import org.simantics.modeling.services.NamingException;
 import org.simantics.project.IProject;
-import org.simantics.structural.stubs.StructuralResource2;
 
 import gnu.trove.map.hash.THashMap;
 
@@ -58,7 +57,6 @@ public class ComponentCopyAdvisor extends GraphCopyAdvisor {
     @Override
     public Object copy(ISynchronizationContext context, WriteGraph graph, Resource source, Resource sourceContainer,
             Resource targetContainer, Map<Object, Object> map) throws DatabaseException {
-        StructuralResource2 STR = StructuralResource2.getInstance(graph);
         Resource copy = CopyAdvisorUtil.copy2(graph, source, null, map);
 
         Layer0 L0 = Layer0.getInstance(graph);