/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.modeling.adapters; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.simantics.db.ReadGraph; 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; import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec; import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec.SeedSpecType; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.modeling.ModelingUtils.CompositeInfo; import org.simantics.modeling.ModelingUtils.DiagramComponentInfo; import org.simantics.structural.stubs.StructuralResource2; /** * @author Tuukka Lehtonen */ public class CompositeCopyHandler extends DefaultCopyHandler { public CompositeCopyHandler(Resource composite) { super(composite); } public CompositeCopyHandler(Collection composites) { super(composites); } @Override protected TransferableGraphConfiguration2 createConfiguration(ReadGraph graph, boolean cut) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); StructuralResource2 SR = StructuralResource2.getInstance(graph); DiagramResource DIA = DiagramResource.getInstance(graph); ModelingResources MOD = ModelingResources.getInstance(graph); Set resourceSet = (resources instanceof Set) ? (Set) resources : new HashSet<>(resources); Set exclusions = new HashSet<>(); Set externals = new HashSet<>(); List roots = new ArrayList<>(); Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(resources.iterator().next())); 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)) { 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); } // 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 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); } } } } } // Leave any diagram monitors out of the export that are contained // by diagrams that are not part of this export, when the monitored // components happen to be a part of the exported composites. for (Resource ref : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) { for (Resource monitor : graph.getObjects(ref, DIA.HasMonitorComponent_Inverse)) { Resource monitorDiagram = graph.getPossibleObject(monitor, L0.PartOf); if (monitorDiagram != null) { Resource monitorComposite = graph.getPossibleObject(monitorDiagram, MOD.DiagramToComposite); if (monitorComposite != null && !resourceSet.contains(monitorComposite)) exclusions.add(monitor); } } } // Include resource as root CompositeInfo info = CompositeInfo.fromResource(graph, resource); roots.add(new SeedSpec(resource, info.getTGName(), SeedSpecType.ROOT, typeId(graph, L0, indexRootUri, resource))); 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); identifierExcluder.accept(child); roots.add(new SeedSpec(child, cinfo.getTGName(info), SeedSpecType.ROOT, typeId(graph, L0, indexRootUri, child))); } } roots.add(new SeedSpec(indexRoot, "%model", SeedSpecType.SPECIAL_ROOT)); TransferableGraphConfiguration2 config = TransferableGraphConfiguration2.createWithNames2(graph, roots, exclusions, true, false); for (Resource external : externals) config.preStatus.put(external, ExtentStatus.EXTERNAL); return config; } private static String typeId(ReadGraph graph, Layer0 L0, String indexRootUri, Resource r) throws DatabaseException { Resource type = graph.getPossibleType(r, L0.Entity); if (type == null) return Layer0.URIs.Entity; String typeUri = graph.getPossibleURI(type); if (typeUri == null || !typeUri.startsWith(indexRootUri)) return typeUri; return "%model" + typeUri.substring(indexRootUri.length()); } }