X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fadapters%2FRemovers.java;h=90ee3db2ffa3fb8e5a1928b1c479677d5e567944;hp=e08a765cc6ab4258dc9b84903af7a57af1de9175;hb=3c524553c98b56075d854f355bc7bab2e3ae17f7;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java index e08a765cc..90ee3db2f 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java @@ -1,249 +1,250 @@ -/******************************************************************************* - * Copyright (c) 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.adapters; - -import gnu.trove.set.hash.THashSet; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.simantics.databoard.Bindings; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.NamedResource; -import org.simantics.db.common.request.PossibleIndexRoot; -import org.simantics.db.common.request.PossibleObjectWithType; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.exception.VariableException; -import org.simantics.db.layer0.request.PossibleModel; -import org.simantics.db.layer0.variable.RVI; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -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.operation.Layer0X; -import org.simantics.scl.runtime.function.Function; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.utils.ui.ErrorLogger; - -/** - * @author Tuukka Lehtonen - */ -final class Removers { - - public static ValidationResult validateFlagRemoval(ReadGraph graph, Resource flag) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - - for (Resource connectionRelation : graph.getObjects(flag, DIA.IsLiftedAs)) { - ValidationResult result = validateConnectionRelationRemoval(graph, connectionRelation, null); - if (!result.inUse()) - continue; - return result; - } - return new ValidationResult(); - } - - public static ValidationResult validateConnectionRelationRemoval(ReadGraph graph, Resource connectionRelation, Resource diagramConnectionRelation) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - StructuralResource2 STR = StructuralResource2.getInstance(graph); - - ValidationResult result = new ValidationResult(); - - // This is a connection point of a structural component type configuration. - String connectionRelationName = NameUtils.getSafeLabel(graph, connectionRelation); - result.connectionRelation = new NamedResource(connectionRelationName, connectionRelation); - if (diagramConnectionRelation != null) { - String diagramConnectionRelationName = NameUtils.getSafeLabel(graph, diagramConnectionRelation); - result.diagramConnectionRelation = new NamedResource(diagramConnectionRelationName, diagramConnectionRelation); - } - - // 1. Get component type - Resource componentType = graph.sync( new PossibleObjectWithType(connectionRelation, L0.PartOf, STR.ComponentType) ); - if (componentType == null) - return result; - String componentTypeName = graph.getPossibleRelatedValue(componentType, L0.HasName, Bindings.STRING); - if (componentTypeName == null) - return result; - result.componentType = new NamedResource(componentTypeName, componentType); - - // 2. Find index roots that may contain references to this component type - Set indexRoots = new THashSet(); - Resource indexRoot = graph.sync( new PossibleIndexRoot(componentType) ); - if (indexRoot == null) - return result; - String indexRootName = graph.getPossibleRelatedValue(indexRoot, L0.HasName, Bindings.STRING); - if (indexRootName == null) - return result; - result.containingIndexRoot = new NamedResource(indexRootName, indexRoot); - - Resource model = graph.sync( new PossibleModel(indexRoot) ); - if (model == null) { - // Need to look for references in all models that use this shared library. - indexRoots.addAll( graph.getObjects(indexRoot, L0.IsLinkedTo_Inverse) ); - } else { - // The component type is in a model, other models can't reference it. - indexRoots.add(model); - } - - // 3. Check whether this connection point is in use in any - // instances of this component type within the containing model. - for (Resource root : indexRoots) { - validateConnectionRelationRemovalForIndexRoot(graph, root, connectionRelation, diagramConnectionRelation, result); - } - - return result; - } - - private static void validateConnectionRelationRemovalForIndexRoot(ReadGraph graph, Resource root, Resource connectionRelation, Resource diagramConnectionRelation, ValidationResult result) throws DatabaseException { - String rootURI = graph.getPossibleURI(root); - if (rootURI == null) - return; - - Layer0 L0 = Layer0.getInstance(graph); - String rootName = graph.getPossibleRelatedValue(root, L0.HasName, Bindings.STRING); - if (rootName == null) - return; - NamedResource namedRoot = new NamedResource(rootName, root); - - @SuppressWarnings("rawtypes") - Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class); - @SuppressWarnings("unchecked") - List> rows = (List>) modules.apply(graph, root, "Types:\"" + result.componentType.getName() + "\""); - if (rows.isEmpty()) - return; - - ModelingResources MOD = ModelingResources.getInstance(graph); - StructuralResource2 STR = StructuralResource2.getInstance(graph); - - for (Map row : rows) { - Resource component = (Resource) row.get("Resource"); - if (graph.isInstanceOf(component, result.componentType.getResource())) { - String componentName = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING); - next_connection: - for (Resource connection : graph.getObjects(component, connectionRelation)) { - if (graph.isInstanceOf(connection, STR.Connection)) { - - if (diagramConnectionRelation != null) { - // When diagram connection relation is defined, validate that - // exactly the specified diagram connection relation is being - // used and not some other relation from another symbol. - for (Resource element : graph.getObjects(component, MOD.ComponentToElement)) { - for (Resource diagramConnector : graph.getObjects(element, diagramConnectionRelation)) { - Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, diagramConnector); - if (diagramConnection == null) - continue; - Resource correspondingConnection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection); - Resource correspondingConnectionSpecial = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnectionSpecial); - if (connection.equals(correspondingConnection) || connection.equals(correspondingConnectionSpecial)) { - addUse(graph, component, componentName, namedRoot, rootURI, result); - continue next_connection; - } - } - } - } else { - addUse(graph, component, componentName, namedRoot, rootURI, result); - } - } - - } - } - } - } - - private static boolean addUse(ReadGraph graph, Resource component, String componentName, NamedResource namedRoot, String rootURI, ValidationResult result) throws DatabaseException { - String uri = null; - try { - Variable variable = Variables.getVariable(graph, component); - if (!result.usedVariables.add(variable)) - return false; - - Use use = new Use(); - use.resource = component; - use.name = componentName; - use.variable = variable; - use.root = namedRoot; - uri = use.rootUri = use.variable.getURI(graph).replace(rootURI, ""); - use.context = Variables.getPossibleContext(graph, use.variable); - if (use.context != null) { - use.path = Variables.getPossibleRVI2(graph, variable); - } - result.uses.add( use ); - return true; - } catch (VariableException e) { - // Might happen with corrupt data, don't panic, just ignore. - ErrorLogger.defaultLogWarning("Connection relation removal validation ignored invalid connection to component " + uri, e); - return false; - } - } - - public static String formatError(ReadGraph graph, ValidationResult result) throws DatabaseException { - StringBuilder sb = new StringBuilder(); - sb.append("Cannot remove connection point '" + result.connectionRelation.getName() + "'\nfrom user component '" + result.componentType.getName() + "'.") - .append("\nIt is used in " + result.uses.size() + " instance(s):\n\n"); - - // See whether the uses contain references from other libraries/models - // than the containing index root. - boolean absoluteUris = false; - for (Use use : result.uses) { - if (!use.root.getResource().equals(result.containingIndexRoot.getResource())) { - absoluteUris = true; - break; - } - } - - for (Use use : result.uses) { - if (use.context != null) { - if (absoluteUris) { - sb.append("/").append(use.root.getName()).append(use.rootUri); - } else { - sb.append(use.path.toPossibleString(graph, use.context)); - } - } else { - if (absoluteUris) - sb.append("/").append(use.root.getName()); - sb.append(use.rootUri); - } - sb.append("\n"); - } - return sb.toString(); - } - - public static class Use { - public String name; - public Resource resource; - public Variable variable; - public Variable context; - public RVI path; - public NamedResource root; - public String rootUri; - } - - public static class ValidationResult { - public NamedResource containingIndexRoot; - public NamedResource componentType; - public NamedResource connectionRelation; - public NamedResource diagramConnectionRelation; - public Set usedVariables = new THashSet(); - public Collection uses = new ArrayList(); - - public boolean inUse() { - return !uses.isEmpty(); - } - } - -} +/******************************************************************************* + * Copyright (c) 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.adapters; + +import gnu.trove.set.hash.THashSet; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.NamedResource; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.PossibleObjectWithType; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.exception.VariableException; +import org.simantics.db.layer0.genericrelation.IndexQueries; +import org.simantics.db.layer0.request.PossibleModel; +import org.simantics.db.layer0.variable.RVI; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +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.operation.Layer0X; +import org.simantics.scl.runtime.function.Function; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.utils.ui.ErrorLogger; + +/** + * @author Tuukka Lehtonen + */ +final class Removers { + + public static ValidationResult validateFlagRemoval(ReadGraph graph, Resource flag) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + + for (Resource connectionRelation : graph.getObjects(flag, DIA.IsLiftedAs)) { + ValidationResult result = validateConnectionRelationRemoval(graph, connectionRelation, null); + if (!result.inUse()) + continue; + return result; + } + return new ValidationResult(); + } + + public static ValidationResult validateConnectionRelationRemoval(ReadGraph graph, Resource connectionRelation, Resource diagramConnectionRelation) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + ValidationResult result = new ValidationResult(); + + // This is a connection point of a structural component type configuration. + String connectionRelationName = NameUtils.getSafeLabel(graph, connectionRelation); + result.connectionRelation = new NamedResource(connectionRelationName, connectionRelation); + if (diagramConnectionRelation != null) { + String diagramConnectionRelationName = NameUtils.getSafeLabel(graph, diagramConnectionRelation); + result.diagramConnectionRelation = new NamedResource(diagramConnectionRelationName, diagramConnectionRelation); + } + + // 1. Get component type + Resource componentType = graph.sync( new PossibleObjectWithType(connectionRelation, L0.PartOf, STR.ComponentType) ); + if (componentType == null) + return result; + String componentTypeName = graph.getPossibleRelatedValue(componentType, L0.HasName, Bindings.STRING); + if (componentTypeName == null) + return result; + result.componentType = new NamedResource(componentTypeName, componentType); + + // 2. Find index roots that may contain references to this component type + Set indexRoots = new THashSet(); + Resource indexRoot = graph.sync( new PossibleIndexRoot(componentType) ); + if (indexRoot == null) + return result; + String indexRootName = graph.getPossibleRelatedValue(indexRoot, L0.HasName, Bindings.STRING); + if (indexRootName == null) + return result; + result.containingIndexRoot = new NamedResource(indexRootName, indexRoot); + + Resource model = graph.sync( new PossibleModel(indexRoot) ); + if (model == null) { + // Need to look for references in all models that use this shared library. + indexRoots.addAll( graph.getObjects(indexRoot, L0.IsLinkedTo_Inverse) ); + } else { + // The component type is in a model, other models can't reference it. + indexRoots.add(model); + } + + // 3. Check whether this connection point is in use in any + // instances of this component type within the containing model. + for (Resource root : indexRoots) { + validateConnectionRelationRemovalForIndexRoot(graph, root, connectionRelation, diagramConnectionRelation, result); + } + + return result; + } + + private static void validateConnectionRelationRemovalForIndexRoot(ReadGraph graph, Resource root, Resource connectionRelation, Resource diagramConnectionRelation, ValidationResult result) throws DatabaseException { + String rootURI = graph.getPossibleURI(root); + if (rootURI == null) + return; + + Layer0 L0 = Layer0.getInstance(graph); + String rootName = graph.getPossibleRelatedValue(root, L0.HasName, Bindings.STRING); + if (rootName == null) + return; + NamedResource namedRoot = new NamedResource(rootName, root); + + @SuppressWarnings("rawtypes") + Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class); + @SuppressWarnings("unchecked") + List> rows = (List>) modules.apply(graph, root, "Types:" + IndexQueries.quoteTerm(result.componentType.getName())); + if (rows.isEmpty()) + return; + + ModelingResources MOD = ModelingResources.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + for (Map row : rows) { + Resource component = (Resource) row.get("Resource"); + if (graph.isInstanceOf(component, result.componentType.getResource())) { + String componentName = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING); + next_connection: + for (Resource connection : graph.getObjects(component, connectionRelation)) { + if (graph.isInstanceOf(connection, STR.Connection)) { + + if (diagramConnectionRelation != null) { + // When diagram connection relation is defined, validate that + // exactly the specified diagram connection relation is being + // used and not some other relation from another symbol. + for (Resource element : graph.getObjects(component, MOD.ComponentToElement)) { + for (Resource diagramConnector : graph.getObjects(element, diagramConnectionRelation)) { + Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, diagramConnector); + if (diagramConnection == null) + continue; + Resource correspondingConnection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection); + Resource correspondingConnectionSpecial = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnectionSpecial); + if (connection.equals(correspondingConnection) || connection.equals(correspondingConnectionSpecial)) { + addUse(graph, component, componentName, namedRoot, rootURI, result); + continue next_connection; + } + } + } + } else { + addUse(graph, component, componentName, namedRoot, rootURI, result); + } + } + + } + } + } + } + + private static boolean addUse(ReadGraph graph, Resource component, String componentName, NamedResource namedRoot, String rootURI, ValidationResult result) throws DatabaseException { + String uri = null; + try { + Variable variable = Variables.getVariable(graph, component); + if (!result.usedVariables.add(variable)) + return false; + + Use use = new Use(); + use.resource = component; + use.name = componentName; + use.variable = variable; + use.root = namedRoot; + uri = use.rootUri = use.variable.getURI(graph).replace(rootURI, ""); + use.context = Variables.getPossibleContext(graph, use.variable); + if (use.context != null) { + use.path = Variables.getPossibleRVI2(graph, variable); + } + result.uses.add( use ); + return true; + } catch (VariableException e) { + // Might happen with corrupt data, don't panic, just ignore. + ErrorLogger.defaultLogWarning("Connection relation removal validation ignored invalid connection to component " + uri, e); + return false; + } + } + + public static String formatError(ReadGraph graph, ValidationResult result) throws DatabaseException { + StringBuilder sb = new StringBuilder(); + sb.append("Cannot remove connection point '" + result.connectionRelation.getName() + "'\nfrom user component '" + result.componentType.getName() + "'.") + .append("\nIt is used in " + result.uses.size() + " instance(s):\n\n"); + + // See whether the uses contain references from other libraries/models + // than the containing index root. + boolean absoluteUris = false; + for (Use use : result.uses) { + if (!use.root.getResource().equals(result.containingIndexRoot.getResource())) { + absoluteUris = true; + break; + } + } + + for (Use use : result.uses) { + if (use.context != null) { + if (absoluteUris) { + sb.append("/").append(use.root.getName()).append(use.rootUri); + } else { + sb.append(use.path.toPossibleString(graph, use.context)); + } + } else { + if (absoluteUris) + sb.append("/").append(use.root.getName()); + sb.append(use.rootUri); + } + sb.append("\n"); + } + return sb.toString(); + } + + public static class Use { + public String name; + public Resource resource; + public Variable variable; + public Variable context; + public RVI path; + public NamedResource root; + public String rootUri; + } + + public static class ValidationResult { + public NamedResource containingIndexRoot; + public NamedResource componentType; + public NamedResource connectionRelation; + public NamedResource diagramConnectionRelation; + public Set usedVariables = new THashSet(); + public Collection uses = new ArrayList(); + + public boolean inUse() { + return !uses.isEmpty(); + } + } + +}