From f2f1f3fe7b467654a0afa4e586ebcd06a54ebfea Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Tue, 4 Jul 2017 13:57:34 +0300 Subject: [PATCH] Fixed diagram copy/paste implementations to re-identify diagram elements Previously copying elements within or between diagram editors and also copying diagrams in the model browser would preserve GUID identifiers for the diagram ordered set structure itself and all its elements. The correct behavior is now implemented which is to force the system to generate new GUID identifiers for all copied structures that have identifiers. refs #7348 Change-Id: I811bb4a118ffb9321577ef46f6651459379cdd08 --- .../simantics/db/layer0/util/Layer0Utils.java | 23 +++++ .../org/simantics/diagram/handler/Paster.java | 6 ++ .../adapters/CompositeCopyHandler.java | 83 ++++++++++++------- .../modeling/mapping/ElementCopyAdvisor.java | 3 + 4 files changed, 85 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 3da57809a..c04ca3cd1 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 @@ -1407,4 +1407,27 @@ public class Layer0Utils { 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 667259907..75b0473a1 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.1