]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/connection/ModelledConnectionAdvisor.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / connection / ModelledConnectionAdvisor.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.diagram.connection;
13
14 import java.util.ArrayList;
15 import java.util.Arrays;
16
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.RequestProcessor;
19 import org.simantics.db.Resource;
20 import org.simantics.db.Session;
21 import org.simantics.db.exception.DatabaseException;
22 import org.simantics.db.request.Read;
23 import org.simantics.diagram.content.ConnectionUtil;
24 import org.simantics.g2d.connection.IConnectionAdvisor;
25 import org.simantics.g2d.diagram.handler.Topology.Terminal;
26 import org.simantics.g2d.element.ElementUtils;
27 import org.simantics.g2d.element.IElement;
28 import org.simantics.g2d.elementclass.FlagHandler;
29 import org.simantics.structural2.modelingRules.CPIgnore;
30 import org.simantics.structural2.modelingRules.ConnectionJudgement;
31 import org.simantics.structural2.modelingRules.ConnectionJudgementType;
32 import org.simantics.structural2.modelingRules.IConnectionPoint;
33 import org.simantics.structural2.modelingRules.IModelingRules;
34
35 /**
36  * To customize, prefer overriding
37  * {@link #canBeConnected(ReadGraph, IElement, Terminal, IElement, Terminal)}
38  * and {@link #canBeginConnection(ReadGraph, IElement, Terminal)}.
39  * 
40  * @author Hannu Niemistö
41  */
42 public class ModelledConnectionAdvisor implements IConnectionAdvisor {
43
44     protected IModelingRules modelingRules;
45     protected Session        session;
46
47     /**
48      * @param modelingRules
49      * @param session
50      */
51     public ModelledConnectionAdvisor(IModelingRules modelingRules,
52             Session session) {
53         this.modelingRules = modelingRules;
54         this.session = session;
55     }
56
57     protected IConnectionPoint getConnectionPoint(ReadGraph g, IElement element, Terminal term) throws DatabaseException {
58         return getConnectionPoint(g, element, term, false);
59     }
60
61     protected IConnectionPoint getConnectionPoint(ReadGraph g, IElement element, Terminal term, boolean ignoreUnrecognized) throws DatabaseException {
62         Object obj = null;
63         if (element != null)
64             obj = ElementUtils.getObject(element);
65
66         if (obj instanceof Resource) {
67             Resource elementResource = (Resource) obj;
68             return ConnectionUtil.toConnectionPoint(g, elementResource, term);
69         }
70
71         // FIXME: this currently allows connections to begin from flags
72         // but is rather hackish.
73         if (element.getElementClass().containsClass(FlagHandler.class)) {
74             return CPIgnore.NULL_INSTANCE;
75         }
76
77         if (ignoreUnrecognized)
78             return CPIgnore.NULL_INSTANCE;
79
80         throw new IllegalArgumentException("Cannot get IConnectionPoint for (element,terminal) pair:\n\t" + element + "\n\t" + term);
81     }
82
83     @Override
84     public Object canBeConnected(Object backend,
85             final IElement element1, final Terminal term1,
86             final IElement element2, final Terminal term2) {
87         try {
88             if (backend == null)
89                 backend = session;
90             return ((RequestProcessor)backend).syncRequest(new Read<Object>() {
91                 @Override
92                 public Object perform(ReadGraph g) throws DatabaseException {
93                     return canBeConnected(g, element1, term1, element2, term2);
94                 }
95             });
96         } catch(DatabaseException e) {
97             e.printStackTrace();
98             return null;
99         }
100     }
101
102     @Override
103     public boolean canBeginConnection(Object backend,
104             final IElement element, final Terminal term) {
105         try {
106             if (backend == null)
107                 backend = session;
108             return ((RequestProcessor)backend).syncRequest(new Read<Boolean>() {
109                 @Override
110                 public Boolean perform(ReadGraph g) throws DatabaseException {
111                     return canBeginConnection(g, element, term);
112                 }
113             });
114         } catch (DatabaseException e) {
115             e.printStackTrace();
116             return false;
117         }
118     }
119
120     protected Object canBeConnected(ReadGraph graph,
121             IElement element1, Terminal term1,
122             IElement element2, Terminal term2) throws DatabaseException {
123         ArrayList<IConnectionPoint> cps = new ArrayList<IConnectionPoint>(2);
124         if (element1 != null)
125             cps.add(getConnectionPoint(graph, element1, term1, true));
126         if (element2 != null)
127             cps.add(getConnectionPoint(graph, element2, term2, true));
128
129         ConnectionJudgement judgement = modelingRules.judgeConnection(graph, cps);
130         if (judgement.type == ConnectionJudgementType.LEGAL
131                 // #6751, Apros #12404: a connection should not be automatically
132                 // denied just because it is not perfectly legal. Further legality
133                 // should be decided on the client side even though the IConnectionAdvisor
134                 // interface is not documented to return ConnectionJudgement instances,
135                 // because the interface knows nothing about this class.
136                 || judgement.type == ConnectionJudgementType.CANBEMADELEGAL) 
137             return judgement;
138         return null;
139     }
140
141     protected boolean canBeginConnection(ReadGraph graph,
142             IElement element, Terminal term) throws DatabaseException {
143         return modelingRules.judgeConnection(graph,
144                 Arrays.asList(getConnectionPoint(graph, element, term)))
145                 .type != ConnectionJudgementType.ILLEGAL;
146     }
147
148 }