1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.diagram.flag;
\r
14 import java.util.Collection;
\r
15 import java.util.Collections;
\r
16 import java.util.HashSet;
\r
17 import java.util.List;
\r
18 import java.util.Set;
\r
20 import org.simantics.db.ReadGraph;
\r
21 import org.simantics.db.Resource;
\r
22 import org.simantics.db.Statement;
\r
23 import org.simantics.db.WriteGraph;
\r
24 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
\r
25 import org.simantics.db.common.request.PossibleObjectWithType;
\r
26 import org.simantics.db.common.request.TernaryRead;
\r
27 import org.simantics.db.common.utils.NameUtils;
\r
28 import org.simantics.db.common.utils.OrderedSetUtils;
\r
29 import org.simantics.db.exception.DatabaseException;
\r
30 import org.simantics.db.exception.ServiceException;
\r
31 import org.simantics.db.function.DbConsumer;
\r
32 import org.simantics.db.layer0.util.RemoverUtil;
\r
33 import org.simantics.db.layer0.variable.Variable;
\r
34 import org.simantics.diagram.content.ConnectionUtil;
\r
35 import org.simantics.diagram.flag.IFlagType.FlagInfo;
\r
36 import org.simantics.diagram.stubs.DiagramResource;
\r
37 import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
\r
38 import org.simantics.g2d.elementclass.FlagClass;
\r
39 import org.simantics.layer0.Layer0;
\r
40 import org.simantics.layer0.utils.triggers.IActivationManager;
\r
41 import org.simantics.modeling.ModelingResources;
\r
42 import org.simantics.structural.stubs.StructuralResource2;
\r
43 import org.simantics.structural2.modelingRules.IModelingRules;
\r
44 import org.simantics.structural2.queries.Terminal;
\r
45 import org.simantics.structural2.variables.ConnectionBrowser;
\r
46 import org.simantics.structural2.variables.ResourceWithContext;
\r
47 import org.simantics.utils.datastructures.Triple;
\r
49 import gnu.trove.set.hash.THashSet;
\r
52 * @author Tuukka Lehtonen
\r
54 public final class FlagUtil {
\r
56 public static boolean isDisconnected(ReadGraph graph, Resource flag) throws DatabaseException {
\r
57 return !isJoined(graph, flag) && !isMarkedExternal(graph, flag);
\r
60 private static boolean isMarkedExternal(ReadGraph graph, Resource flag) throws DatabaseException {
\r
61 return graph.hasStatement(flag, DiagramResource.getInstance(graph).ExternalFlag);
\r
64 public static boolean isExternal(ReadGraph graph, Resource flag) throws DatabaseException {
\r
65 return isMarkedExternal(graph, flag) && !isJoined(graph, flag);
\r
68 public static boolean isJoined(ReadGraph graph, Resource flag) throws DatabaseException {
\r
69 return countCounterparts(graph, flag) > 0;
\r
72 public static boolean isLifted(ReadGraph graph, Resource flag) throws DatabaseException {
\r
73 Resource cp = getPossibleConnectionPoint(graph, flag);
\r
74 return cp == null ? false : graph.isInstanceOf(cp, StructuralResource2.getInstance(graph).ConnectionRelation);
\r
77 public static Resource getPossibleConnectionPoint(ReadGraph graph, Resource flag) throws DatabaseException {
\r
78 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
79 return graph.getPossibleObject(flag, DIA.IsLiftedAs);
\r
82 public static Resource getPossibleCounterpart(ReadGraph graph, Resource flag) throws DatabaseException {
\r
83 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
84 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
85 for (Resource otherFlag : graph.getObjects(connectionJoin, DIA.JoinsFlag)) {
\r
86 if (flag.equals(otherFlag))
\r
94 public static int countCounterparts(ReadGraph graph, Resource flag) throws DatabaseException {
\r
95 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
97 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
98 for (Resource otherFlag : graph.getObjects(connectionJoin, DIA.JoinsFlag)) {
\r
99 if (flag.equals(otherFlag))
\r
107 public static Set<Resource> getCounterparts(ReadGraph graph, Resource flag, Set<Resource> result) throws DatabaseException {
\r
108 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
109 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
110 for (Resource otherFlag : graph.getObjects(connectionJoin, DIA.JoinsFlag)) {
\r
111 if (flag.equals(otherFlag))
\r
113 result.add(otherFlag);
\r
119 public static int forCounterparts(ReadGraph graph, Resource flag, DbConsumer<Resource> procedure) throws DatabaseException {
\r
120 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
122 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
123 for (Resource otherFlag : graph.getObjects(connectionJoin, DIA.JoinsFlag)) {
\r
124 if (!flag.equals(otherFlag)) {
\r
125 procedure.accept(otherFlag);
\r
134 * Returns all flags that are joined with the given flag including the flag given as parameter.
\r
136 public static Set<Resource> getCounterparts(ReadGraph graph, Resource flag) throws DatabaseException {
\r
137 return getCounterparts(graph, flag, new HashSet<Resource>(8));
\r
140 public static Set<Resource> getCounterpartsAndSelf(ReadGraph graph, Resource flag, Set<Resource> result) throws DatabaseException {
\r
141 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
142 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
143 for (Resource otherFlag : graph.getObjects(connectionJoin, DIA.JoinsFlag)) {
\r
144 result.add(otherFlag);
\r
147 if (result.size() == 0)
\r
152 public static Set<Resource> getCounterpartsAndSelf(ReadGraph graph, Resource flag) throws DatabaseException {
\r
153 return getCounterpartsAndSelf(graph, flag, new HashSet<Resource>(8));
\r
159 * @return the created DIA.ConnectionJoin instance
\r
160 * @throws DatabaseException
\r
162 public static Resource join(WriteGraph g, Resource flag, Resource otherFlag) throws DatabaseException {
\r
163 DiagramResource DIA = DiagramResource.getInstance(g);
\r
164 StructuralResource2 STR = StructuralResource2.getInstance(g);
\r
165 Resource connectionJoin = g.newResource();
\r
166 Layer0 L0 = Layer0.getInstance(g);
\r
167 g.claim(connectionJoin, L0.InstanceOf, null, STR.ConnectionJoin);
\r
168 g.claim(connectionJoin, DIA.JoinsFlag, flag);
\r
169 g.claim(connectionJoin, DIA.JoinsFlag, otherFlag);
\r
171 IActivationManager manager = g.getService(IActivationManager.class);
\r
172 for(Resource diagram : OrderedSetUtils.getSubjects(g, flag))
\r
173 manager.activateOnce(diagram);
\r
174 for(Resource diagram : OrderedSetUtils.getSubjects(g, otherFlag))
\r
175 manager.activateOnce(diagram);
\r
176 return connectionJoin;
\r
179 public static void disconnectFlag(WriteGraph graph, Resource flag) throws DatabaseException {
\r
180 // Remove any :ConnectionJoin's this flag is joined by
\r
181 // if there's less than two flags joined by the join.
\r
182 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
183 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
184 THashSet<Resource> affectedConnections = new THashSet<Resource>(4);
\r
185 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
186 affectedConnections.addAll(graph.getObjects(connectionJoin, STR.Joins));
\r
187 graph.deny(flag, DIA.FlagIsJoinedBy, connectionJoin);
\r
188 if (graph.getObjects(connectionJoin, DIA.JoinsFlag).size() < 2) {
\r
189 RemoverUtil.remove(graph, connectionJoin);
\r
192 fixBindsStatements(graph, STR, DIA, affectedConnections);
\r
195 private static boolean isBindsStatementLegimite(ReadGraph graph,
\r
196 DiagramResource DIA,
\r
197 Resource connection,
\r
198 Resource connectionRelation) throws DatabaseException {
\r
199 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
200 for(Resource diagramConnection : graph.getObjects(connection, MOD.ConnectionToDiagramConnection))
\r
201 for(Resource connector : graph.getObjects(diagramConnection, DIA.HasConnector))
\r
202 for(Resource flag : graph.getObjects(connector, DIA.Flag_ConnectionPoint_Inverse))
\r
203 if(graph.hasStatement(flag, DIA.IsLiftedAs, connectionRelation))
\r
208 private static void fixBindsStatements(WriteGraph graph, StructuralResource2 STR, DiagramResource DIA, Collection<Resource> connections) throws DatabaseException {
\r
209 for(Resource connection : connections)
\r
210 for(Resource connectionRelation : graph.getObjects(connection, STR.Binds))
\r
211 if(!isBindsStatementLegimite(graph, DIA, connection, connectionRelation))
\r
212 graph.denyStatement(connection, STR.Binds, connectionRelation);
\r
215 public static void fixBindsStatements(WriteGraph graph, Resource connection) throws DatabaseException {
\r
216 if(connection == null)
\r
218 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
219 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
220 for(Resource connectionRelation : graph.getObjects(connection, STR.Binds))
\r
221 if(!isBindsStatementLegimite(graph, DIA, connection, connectionRelation))
\r
222 graph.denyStatement(connection, STR.Binds, connectionRelation);
\r
225 public static void disconnectFlag(WriteGraph graph, Resource flag, Resource fromFlag) throws DatabaseException {
\r
226 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
227 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
228 THashSet<Resource> affectedConnections = new THashSet<Resource>(4);
\r
229 for (Resource connectionJoin : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
\r
230 affectedConnections.addAll(graph.getObjects(connectionJoin, STR.Joins));
\r
231 for (Resource otherFlag : graph.getObjects(connectionJoin, DIA.JoinsFlag)) {
\r
232 if (flag.equals(otherFlag))
\r
234 if (otherFlag.equals(fromFlag)) {
\r
235 graph.deny(connectionJoin, DIA.JoinsFlag, DIA.FlagIsJoinedBy, flag);
\r
236 if (graph.getObjects(connectionJoin, DIA.JoinsFlag).size() < 2) {
\r
237 RemoverUtil.remove(graph, connectionJoin);
\r
242 fixBindsStatements(graph, STR, DIA, affectedConnections);
\r
245 public static void removeFlag(WriteGraph graph, Resource flag) throws DatabaseException {
\r
246 disconnectFlag(graph, flag);
\r
247 RemoverUtil.remove(graph, flag);
\r
250 public static boolean isJoinedInSingleDiagram(ReadGraph graph, Resource flag) throws DatabaseException {
\r
251 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
252 Resource counterpart = getPossibleCounterpart(graph, flag);
\r
253 if (counterpart == null)
\r
255 return !Collections.disjoint(
\r
256 OrderedSetUtils.getOwnerLists(graph, flag, DIA.Diagram),
\r
257 OrderedSetUtils.getOwnerLists(graph, counterpart, DIA.Diagram));
\r
260 public static boolean isJoinedBetweenDiagrams(ReadGraph graph, Resource flag) throws DatabaseException {
\r
261 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
262 Collection<Resource> counterparts = getCounterparts(graph, flag);
\r
263 if (counterparts.isEmpty())
\r
265 Collection<Resource> flagDiagrams = OrderedSetUtils.getOwnerLists(graph, flag, DIA.Diagram);
\r
266 for (Resource counterpart : counterparts)
\r
267 if (Collections.disjoint(
\r
269 OrderedSetUtils.getOwnerLists(graph, counterpart, DIA.Diagram)))
\r
276 * @throws DatabaseException
\r
278 public static FlagClass.Type getFlagType(ReadGraph graph, Resource flag) throws DatabaseException {
\r
279 return getFlagType(graph, flag, null);
\r
284 * @throws DatabaseException
\r
286 public static FlagClass.Type getFlagType(ReadGraph graph, Resource flag, FlagClass.Type defaultFlagType) throws DatabaseException {
\r
287 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
288 Resource type = graph.getPossibleObject(flag, DIA.HasFlagType);
\r
289 return DiagramGraphUtil.toFlagType(DIA, type, defaultFlagType);
\r
294 * @throws DatabaseException
\r
296 public static void setFlagType(WriteGraph graph, Resource flag, FlagClass.Type type) throws DatabaseException {
\r
297 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
298 Resource flagType = DiagramGraphUtil.toFlagTypeResource(DIA, type);
\r
299 Resource existingFlagType = graph.getPossibleObject(flag, DIA.HasFlagType);
\r
300 if (flagType.equals(existingFlagType))
\r
302 graph.deny(flag, DIA.HasFlagType);
\r
303 // Resource defaultFlagType = graph.getPossibleObject(flag, DIA.HasFlagType);
\r
304 // if (flagType.equals(defaultFlagType))
\r
306 graph.claim(flag, DIA.HasFlagType, null, flagType);
\r
309 public static Set<Resource> findDirectlyConnectedComponents(ReadGraph graph, Resource flag) throws DatabaseException {
\r
310 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
311 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
313 for (Resource connector : graph.getObjects(flag, STR.IsConnectedTo)) {
\r
314 Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, connector);
\r
315 if (diagramConnection == null)
\r
318 Resource connection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);
\r
319 if (connection == null)
\r
322 return new HashSet<Resource>(graph.getObjects(connection, STR.Connects));
\r
324 return Collections.emptySet();
\r
327 public static Set<Terminal> findDirectlyConnectedTerminals(ReadGraph graph, Resource flag) throws DatabaseException {
\r
328 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
329 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
331 for (Resource connector : graph.getObjects(flag, STR.IsConnectedTo)) {
\r
332 Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, connector);
\r
333 if (diagramConnection == null)
\r
336 Resource connection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);
\r
337 if (connection == null)
\r
340 Set<Terminal> terminals = new HashSet<Terminal>();
\r
341 for (Statement stm : graph.getStatements(connection, STR.Connects)) {
\r
342 terminals.add(new Terminal(stm.getObject(), graph.getInverse(stm.getPredicate())));
\r
346 return Collections.emptySet();
\r
352 * @return set of (module, terminal relation, attachment relation) triples
\r
353 * @throws DatabaseException
\r
355 public static Set<Triple<Resource,Resource,Resource>> findDirectlyConnectedElementTerminals(ReadGraph graph, Resource toElement) throws DatabaseException {
\r
356 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
357 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
359 Set<Triple<Resource, Resource, Resource>> result = new HashSet<Triple<Resource, Resource, Resource>>();
\r
361 for (Resource connector : graph.getObjects(toElement, STR.IsConnectedTo)) {
\r
362 Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, connector);
\r
363 if (diagramConnection == null)
\r
366 //System.out.println("DC: " + NameUtils.getSafeName(graph, diagramConnection, true));
\r
368 for (Statement connectionToConnector : graph.getStatements(diagramConnection, DIA.HasConnector)) {
\r
369 Resource connector2 = connectionToConnector.getObject();
\r
370 if (connector.equals(connector2))
\r
373 Resource attachmentRelation = connectionToConnector.getPredicate();
\r
375 // Get element + terminal relation
\r
376 for (Statement connectorToElement : graph.getStatements(connector2, STR.Connects)) {
\r
377 Resource element = connectorToElement.getObject();
\r
378 if (diagramConnection.equals(element))
\r
380 Resource terminalRelation = graph.getPossibleInverse(connectorToElement.getPredicate());
\r
381 if (terminalRelation == null)
\r
383 result.add(Triple.make(element, terminalRelation, attachmentRelation));
\r
391 public static Variable getPossibleFlagSignal(ReadGraph graph, Variable configuration, Resource flag, Resource type) throws DatabaseException {
\r
393 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
394 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
396 Resource component = graph.getPossibleObject(flag, MOD.ElementToComponent);
\r
397 if (component != null && graph.isInstanceOf(component, type)) {
\r
398 Variable v = configuration.browsePossible(graph, component);
\r
403 Resource connector = graph.getPossibleObject(flag, DIA.Flag_ConnectionPoint);
\r
404 if(connector == null) return null;
\r
406 Resource connection = graph.sync(new PossibleObjectWithType(connector, DIA.IsConnectorOf, DIA.Connection));
\r
407 if(connection == null) return null;
\r
409 return getPossibleConnectionSignal(graph, configuration, connection, type);
\r
413 public static Variable getPossibleConnectionSignal(ReadGraph graph, Variable configuration, Resource connection, Resource type) throws DatabaseException {
\r
415 return graph.syncRequest(new PossibleConnectionSignal(configuration, connection, type), TransientCacheListener.<Variable>instance());
\r
419 public static class PossibleConnectionSignal extends TernaryRead<Variable, Resource, Resource, Variable> {
\r
421 public PossibleConnectionSignal(Variable configuration, Resource connection, Resource type) {
\r
422 super(configuration, connection, type);
\r
426 public Variable perform(ReadGraph graph) throws DatabaseException {
\r
428 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
429 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
431 Resource connection = parameter2;
\r
432 Resource mapped = graph.getPossibleObject(connection, MOD.DiagramConnectionToConnection);
\r
433 if(mapped != null) connection = mapped;
\r
435 for (ResourceWithContext module : ConnectionBrowser.findConnectedComponents(graph, connection, parameter)) {
\r
436 if (graph.isInstanceOf(module.getResource(), parameter3)) {
\r
437 Resource element = graph.getPossibleObject(module.getResource(), MOD.ComponentToElement);
\r
438 if(element != null) {
\r
439 if(graph.isInstanceOf(element, DIA.Flag) || graph.isInstanceOf(element, DIA.Connection))
\r
440 return module.getContext();
\r
442 System.err.println("no element for " + NameUtils.getSafeName(graph, module.getResource()));
\r
454 * Verifies that the specified flag has the correct flag type as resolved
\r
455 * through {@link IFlagType}. Please note that using this method assumes
\r
456 * that the diagram mapping has been executed and the configuration is in
\r
457 * sync with the diagram.
\r
460 * @param modelingRules
\r
461 * modeling rules for getting the connection type of the flag for
\r
462 * retrieving {@link IFlagTypeReader} and {@link IFlagType}
\r
464 * the flag for to verify type
\r
466 * the current type of the flag
\r
467 * @throws DatabaseException
\r
469 public static void verifyFlagType(WriteGraph graph, IModelingRules modelingRules, Resource flag, FlagClass.Type flagType) throws DatabaseException {
\r
470 if (modelingRules != null) {
\r
471 // Follows the flag loading logic in FlagClassFactory.
\r
472 IFlagTypeReader ftr = null;
\r
473 Resource connectionType = DiagramGraphUtil.getConnectionTypeForFlag(graph, flag);
\r
474 if (connectionType != null) {
\r
475 //System.out.println("FLAG " + NameUtils.getSafeName(g, flag) + ", CONNECTION TYPE " + NameUtils.getSafeName(g, connectionType));
\r
476 ftr = graph.getPossibleAdapter(connectionType, IFlagTypeReader.class);
\r
479 //System.out.println("FLAG " + NameUtils.getSafeName(g, flag) + ", NO CONNECTION TYPE");
\r
480 ftr = graph.getPossibleAdapter(flag, IFlagTypeReader.class);
\r
484 IFlagType ft = ftr.read(graph, flag, modelingRules);
\r
486 FlagInfo info = ft.getInfo(graph);
\r
487 if (flagType != info.getType()) {
\r
488 FlagUtil.setFlagType(graph, flag, info.getType());
\r
495 public static List<Resource> setFlagExternal (WriteGraph graph, List<Resource> flags, boolean external) throws ServiceException {
\r
497 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
498 for (Resource flag : flags) {
\r
500 graph.claim(flag, DIA.ExternalFlag, DIA.ExternalFlag, flag);
\r
502 graph.deny(flag, DIA.ExternalFlag);
\r