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.connection;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Arrays;
\r
17 import org.simantics.db.ReadGraph;
\r
18 import org.simantics.db.RequestProcessor;
\r
19 import org.simantics.db.Resource;
\r
20 import org.simantics.db.Session;
\r
21 import org.simantics.db.exception.DatabaseException;
\r
22 import org.simantics.db.request.Read;
\r
23 import org.simantics.diagram.content.ConnectionUtil;
\r
24 import org.simantics.g2d.connection.IConnectionAdvisor;
\r
25 import org.simantics.g2d.diagram.handler.Topology.Terminal;
\r
26 import org.simantics.g2d.element.ElementUtils;
\r
27 import org.simantics.g2d.element.IElement;
\r
28 import org.simantics.g2d.elementclass.FlagHandler;
\r
29 import org.simantics.structural2.modelingRules.CPIgnore;
\r
30 import org.simantics.structural2.modelingRules.ConnectionJudgement;
\r
31 import org.simantics.structural2.modelingRules.ConnectionJudgementType;
\r
32 import org.simantics.structural2.modelingRules.IConnectionPoint;
\r
33 import org.simantics.structural2.modelingRules.IModelingRules;
\r
36 * To customize, prefer overriding
\r
37 * {@link #canBeConnected(ReadGraph, IElement, Terminal, IElement, Terminal)}
\r
38 * and {@link #canBeginConnection(ReadGraph, IElement, Terminal)}.
\r
40 * @author Hannu Niemistö
\r
42 public class ModelledConnectionAdvisor implements IConnectionAdvisor {
\r
44 protected IModelingRules modelingRules;
\r
45 protected Session session;
\r
48 * @param modelingRules
\r
51 public ModelledConnectionAdvisor(IModelingRules modelingRules,
\r
53 this.modelingRules = modelingRules;
\r
54 this.session = session;
\r
57 protected IConnectionPoint getConnectionPoint(ReadGraph g, IElement element, Terminal term) throws DatabaseException {
\r
58 return getConnectionPoint(g, element, term, false);
\r
61 protected IConnectionPoint getConnectionPoint(ReadGraph g, IElement element, Terminal term, boolean ignoreUnrecognized) throws DatabaseException {
\r
63 if (element != null)
\r
64 obj = ElementUtils.getObject(element);
\r
66 if (obj instanceof Resource) {
\r
67 Resource elementResource = (Resource) obj;
\r
68 return ConnectionUtil.toConnectionPoint(g, elementResource, term);
\r
71 // FIXME: this currently allows connections to begin from flags
\r
72 // but is rather hackish.
\r
73 if (element.getElementClass().containsClass(FlagHandler.class)) {
\r
74 return CPIgnore.NULL_INSTANCE;
\r
77 if (ignoreUnrecognized)
\r
78 return CPIgnore.NULL_INSTANCE;
\r
80 throw new IllegalArgumentException("Cannot get IConnectionPoint for (element,terminal) pair:\n\t" + element + "\n\t" + term);
\r
84 public Object canBeConnected(Object backend,
\r
85 final IElement element1, final Terminal term1,
\r
86 final IElement element2, final Terminal term2) {
\r
88 if (backend == null)
\r
90 return ((RequestProcessor)backend).syncRequest(new Read<Object>() {
\r
92 public Object perform(ReadGraph g) throws DatabaseException {
\r
93 return canBeConnected(g, element1, term1, element2, term2);
\r
96 } catch(DatabaseException e) {
\r
97 e.printStackTrace();
\r
103 public boolean canBeginConnection(Object backend,
\r
104 final IElement element, final Terminal term) {
\r
106 if (backend == null)
\r
108 return ((RequestProcessor)backend).syncRequest(new Read<Boolean>() {
\r
110 public Boolean perform(ReadGraph g) throws DatabaseException {
\r
111 return canBeginConnection(g, element, term);
\r
114 } catch (DatabaseException e) {
\r
115 e.printStackTrace();
\r
120 protected Object canBeConnected(ReadGraph graph,
\r
121 IElement element1, Terminal term1,
\r
122 IElement element2, Terminal term2) throws DatabaseException {
\r
123 ArrayList<IConnectionPoint> cps = new ArrayList<IConnectionPoint>(2);
\r
124 if (element1 != null)
\r
125 cps.add(getConnectionPoint(graph, element1, term1, true));
\r
126 if (element2 != null)
\r
127 cps.add(getConnectionPoint(graph, element2, term2, true));
\r
129 ConnectionJudgement judgement = modelingRules.judgeConnection(graph, cps);
\r
130 if (judgement.type == ConnectionJudgementType.LEGAL
\r
131 // #6751, Apros #12404: a connection should not be automatically
\r
132 // denied just because it is not perfectly legal. Further legality
\r
133 // should be decided on the client side even though the IConnectionAdvisor
\r
134 // interface is not documented to return ConnectionJudgement instances,
\r
135 // because the interface knows nothing about this class.
\r
136 || judgement.type == ConnectionJudgementType.CANBEMADELEGAL)
\r
141 protected boolean canBeginConnection(ReadGraph graph,
\r
142 IElement element, Terminal term) throws DatabaseException {
\r
143 return modelingRules.judgeConnection(graph,
\r
144 Arrays.asList(getConnectionPoint(graph, element, term)))
\r
145 .type != ConnectionJudgementType.ILLEGAL;
\r