/******************************************************************************* * Copyright (c) 2007, 2012 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.typicals; import java.util.Map; import org.simantics.db.MetadataI; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.changeset.GenericChangeListener; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.genericrelation.DependenciesRelation.DependencyChangesRequest; import org.simantics.db.layer0.genericrelation.DependencyChanges; import org.simantics.db.layer0.genericrelation.DependencyChanges.Change; import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition; import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification; import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval; import org.simantics.diagram.content.ConnectionUtil; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.utils.datastructures.MapSet; import org.simantics.utils.ui.ErrorLogger; import gnu.trove.set.hash.THashSet; /** * This listener needs to discover if changes are made to typical diagram * templates. * * It uses DependencyChange contents to find out if the changes affect any * dependencies of typical diagram templates. * * @author Tuukka Lehtonen * * @see SyncTypicalTemplatesToInstances * @deprecated not to be used anymore, will be removed */ public class TypicalDiagramTemplateListener extends GenericChangeListener { private static final boolean DEBUG = false; Layer0 L0; StructuralResource2 STR; DiagramResource DIA; ModelingResources MOD; THashSet visited = new THashSet(); THashSet typicals = new THashSet(); /** * For optimizing the synchronization visual element properties (transform) */ MapSet changedElementsByDiagram = new MapSet.Hash(); @Override public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException { this.L0 = Layer0.getInstance(graph); this.STR = StructuralResource2.getInstance(graph); this.DIA = DiagramResource.getInstance(graph); this.MOD = ModelingResources.getInstance(graph); visited.clear(); typicals.clear(); try { processChanges(graph, event); } finally { // Clear unwanted references visited.clear(); typicals.clear(); visited.compact(); } } private void processChanges(ReadGraph graph, DependencyChanges event) throws DatabaseException { for (Map.Entry entry : event.modelChanges.entrySet()) { Change[] changes = entry.getValue(); if (changes == null) continue; if (DEBUG) for (Change change : changes) System.out.println("CH: -" + change.toString(graph)); for (Change c : changes) { if (c instanceof ComponentAddition) { // element/module addition ComponentAddition add = (ComponentAddition) c; resolveDependentTypicalDiagrams(graph, add.component, false); } else if (c instanceof ComponentRemoval) { // element/module removal ComponentRemoval rm = (ComponentRemoval) c; resolveDependentTypicalDiagrams(graph, rm.parent, false); } else if (c instanceof ComponentModification) { // element transform changes // module property changes ComponentModification mod = (ComponentModification) c; resolveDependentTypicalDiagrams(graph, mod.component, true); } } } if (!typicals.isEmpty()) scheduleSynchronization(graph, typicals.toArray(Resource.NONE)); } private void scheduleSynchronization(ReadGraph graph, final Resource[] templates) { MapSet changes = this.changedElementsByDiagram; this.changedElementsByDiagram = new MapSet.Hash(); graph.asyncRequest(new SyncTypicalTemplatesToInstances(null, templates, changes), e -> { if (e != null) ErrorLogger.defaultLogError("Typical template diagram synchronization to instances failes, see exception for details.", e); }); } private void resolveDependentTypicalDiagrams(ReadGraph graph, Resource component, boolean modification) throws DatabaseException { if (visited.contains(component)) return; if (graph.isInstanceOf(component, DIA.Diagram)) { addVisited(component, graph.hasStatement(component, MOD.DiagramHasInstance)); } else if (graph.isInstanceOf(component, STR.Composite)) { Resource diagram = graph.getPossibleObject(component, MOD.CompositeToDiagram); addVisited(diagram, diagram != null && graph.hasStatement(diagram, MOD.DiagramHasInstance)); } else if (graph.isInstanceOf(component, STR.Component)) { Resource parent = graph.getPossibleObject(component, L0.PartOf); if (parent != null) { if (graph.isInstanceOf(component, DIA.Element)) { addVisited(parent, graph.hasStatement(parent, MOD.DiagramHasInstance)); if (modification) changedElementsByDiagram.add(parent, component); } else { Resource diagram = graph.getPossibleObject(parent, MOD.CompositeToDiagram); if (diagram != null) { addVisited(diagram, graph.hasStatement(diagram, MOD.DiagramHasInstance)); if (modification) { Resource element = graph.getPossibleObject(component, MOD.ComponentToElement); if (element != null) changedElementsByDiagram.add(diagram, element); } } } } } else { // handle changes to properties of components/elements ?? } if (modification) { // Recognize changes in template diagram connections. if (graph.isInstanceOf(component, DIA.RouteNode)) { Resource connection = ConnectionUtil.tryGetConnection(graph, component); if (connection != null) { Resource parent = graph.getPossibleObject(connection, L0.PartOf); if (parent != null) { boolean isTypical = graph.hasStatement(parent, MOD.DiagramHasInstance); addVisited(parent, isTypical); if (isTypical) changedElementsByDiagram.add(parent, connection); } } } } addVisited(component, false); } private void addVisited(Resource r, boolean isTypical) { if (r != null && visited.add(r)) { if (DEBUG) System.out.println("Visited: " + r); if (isTypical) { typicals.add(r); if (DEBUG) System.out.println("Added typical: " + r); } } } }