From 13a80a14b87f94af7daa6cd5ab5b9b5f5ae379c1 Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Tue, 28 Nov 2017 10:52:29 +0200 Subject: [PATCH] Manually merged commit f2f1f3fe changes to release/1.28.1 branch. Without these changes using copy-paste on diagrams will cause large amounts of overlapping GUID identifiers for diagram elements to accumulate in models. refs #7348 Change-Id: I1b5bc5d06e8815bf5a50f234e793a1bbef0e5fb7 --- .../simantics/db/layer0/util/Layer0Utils.java | 44 ++++++++++ .../org/simantics/diagram/handler/Paster.java | 6 ++ .../adapters/CompositeCopyHandler.java | 83 ++++++++++++------- .../modeling/mapping/ElementCopyAdvisor.java | 3 + 4 files changed, 106 insertions(+), 30 deletions(-) diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java index adc51c16d..3a24102b2 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java @@ -54,6 +54,7 @@ import org.simantics.databoard.type.StringType; import org.simantics.databoard.type.UnionType; import org.simantics.databoard.type.VariantType; import org.simantics.databoard.util.ObjectUtils; +import org.simantics.datatypes.literal.GUID; import org.simantics.db.ChangeSetIdentifier; import org.simantics.db.Operation; import org.simantics.db.ReadGraph; @@ -1378,4 +1379,47 @@ public class Layer0Utils { } + /** + * Adds a random {@link GUID} as a value for L0.identifier + * + * @param graph + * @param component + * for which the identifier is added + * @param add + * true to invoke addLiteral, false to + * invoke claimLiteral + * @throws DatabaseException + */ + public static void claimNewIdentifier(WriteGraph graph, Resource component, boolean add) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + GUID guid = GUID.random(); + if (add) + graph.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING); + else + graph.claimLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING); + } + + /** + * Sets a new random unique identifier for the specified entity if it already + * has an identifier. If the entity does not have a previous identifier, nothing + * is done. + * + * @param graph + * @param entity + * for which the identifier is added + * @return true if the identifier was renewed, false + * otherwise + * @throws DatabaseException + * @see {@link #claimNewIdentifier(WriteGraph, Resource, boolean)} + */ + public static boolean renewIdentifier(WriteGraph graph, Resource entity) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Statement stm = graph.getPossibleStatement(entity, L0.identifier); + if (stm != null) { + graph.claimValue(stm.getObject(), GUID.random(), GUID.BINDING); + return true; + } + return false; + } + } diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/Paster.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/Paster.java index 03edda6bd..41b369ed6 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/Paster.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/Paster.java @@ -28,6 +28,7 @@ import org.simantics.db.common.utils.CommonDBUtils; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.layer0.util.RemoverUtil; import org.simantics.db.request.Write; import org.simantics.diagram.content.ConnectionUtil; @@ -863,6 +864,11 @@ public class Paster { graph.claim(copy, L0.ConsistsOf, L0.PartOf, relationCopy); graph.claim(copy, MOD.HasReferenceRelation, MOD.HasReferenceRelation_Inverse, relationCopy); + // #7348: renew reference relation GUID identifiers properly + Layer0Utils.renewIdentifier(graph, relationCopy); + for (Resource invRel : graph.getObjects(relationCopy, L0.ConsistsOf)) + Layer0Utils.renewIdentifier(graph, invRel); + return copy; } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/CompositeCopyHandler.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/CompositeCopyHandler.java index ae65e87f8..6167334fd 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/CompositeCopyHandler.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/CompositeCopyHandler.java @@ -22,6 +22,7 @@ import org.simantics.db.Resource; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.PossibleIndexRoot; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.function.DbConsumer; import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus; import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler; import org.simantics.db.layer0.util.TransferableGraphConfiguration2; @@ -64,39 +65,63 @@ public class CompositeCopyHandler extends DefaultCopyHandler { if(indexRoot == null) throw new DatabaseException("Composite is not part of any index root"); String indexRootUri = graph.getURI(indexRoot); + DbConsumer identifierExcluder = r -> { + if (r != null) + exclusions.addAll(graph.getObjects(r, L0.identifier)); + }; + for(Resource resource : resources) { // Process all connection joins. // This is the only way to access all of them. for (Resource diagram : graph.getObjects(resource, MOD.CompositeToDiagram)) { - for (Resource flag : graph.syncRequest(new ObjectsWithType(diagram, L0.ConsistsOf, DIA.Flag))) { - for (Resource join : graph.getObjects(flag, DIA.FlagIsJoinedBy)) { - // Joins with external references are omitted - for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) { - if (!resourceSet.contains(comp)) - exclusions.add(join); - } - // This code excludes joins with flags to external - // diagrams that are not connected (have no - // configuration for the flag) - for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) { - Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf); - if (diagram2 != null) { - Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite); + identifierExcluder.accept(diagram); + + for (Resource element : graph.getObjects(diagram, L0.ConsistsOf)) { + identifierExcluder.accept(element); + + Set types = graph.getTypes(element); + + // Check all diagram flag elements for necessary exclusions. + if (types.contains(DIA.Flag)) { + for (Resource join : graph.getObjects(element, DIA.FlagIsJoinedBy)) { + // Joins with external references are omitted + for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) { if (!resourceSet.contains(comp)) - exclusions.add(join); + exclusions.add(join); + } + // This code excludes joins with flags to external + // diagrams that are not connected (have no + // configuration for the flag) + for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) { + Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf); + if (diagram2 != null) { + Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite); + if (!resourceSet.contains(comp)) + exclusions.add(join); + } + } + } + } + + // Check all diagram monitor elements. + // Any components referenced that are external to the exported diagrams must be excluded from the export. + // This will leave the monitors without a monitored component but export and import will work anyway. + if (types.contains(DIA.Monitor)) { + for (Resource monitoredComponent : graph.getObjects(element, DIA.HasMonitorComponent)) { + Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf); + if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) { + exclusions.add(monitoredComponent); } } } - } - // Check all diagram monitor elements. - // Any components referenced that are external to the exported diagrams must be excluded from the export. - // This will leave the monitors without a monitored component but export and import will work anyway. - for (Resource ref : graph.syncRequest(new ObjectsWithType(diagram, L0.ConsistsOf, DIA.Monitor))) { - for (Resource monitoredComponent : graph.getObjects(ref, DIA.HasMonitorComponent)) { - Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf); - if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) { - exclusions.add(monitoredComponent); + // Check all diagram reference elements for necessary exclusions. + if (types.contains(MOD.ReferenceElement)) { + for (Resource rel : graph.getObjects(element, L0.ConsistsOf)) { + identifierExcluder.accept(rel); + for (Resource invRel : graph.getObjects(rel, L0.ConsistsOf)) { + identifierExcluder.accept(invRel); + } } } } @@ -119,13 +144,11 @@ public class CompositeCopyHandler extends DefaultCopyHandler { // Include resource as root CompositeInfo info = CompositeInfo.fromResource(graph, resource); roots.add(new RootSpec(resource, info.getTGName(), true, typeId(graph, L0, indexRootUri, resource))); - Resource id = graph.getPossibleObject(resource, L0.identifier); - if(id != null) exclusions.add(id); + identifierExcluder.accept(resource); // Include components as roots - for(Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) { - DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child); - id = graph.getPossibleObject(child, L0.identifier); - if(id != null) exclusions.add(id); + for (Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) { + DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child); + identifierExcluder.accept(child); roots.add(new RootSpec(child, cinfo.getTGName(info), true, typeId(graph, L0, indexRootUri, child))); } } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ElementCopyAdvisor.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ElementCopyAdvisor.java index 994aa1ab1..d666d63d5 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ElementCopyAdvisor.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ElementCopyAdvisor.java @@ -23,6 +23,7 @@ import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.CancelTransactionException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PossibleModel; +import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.diagram.stubs.G2DResource; import org.simantics.diagram.synchronization.ISynchronizationContext; @@ -89,6 +90,8 @@ public class ElementCopyAdvisor extends GraphCopyAdvisor { if (graph.hasStatement(sourceContainer, L0.ConsistsOf, source)) graph.claim(targetContainer, L0.ConsistsOf, copy); + Layer0Utils.claimNewIdentifier(graph, copy, false); + return copy; } -- 2.47.0