]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.graph.impl/src/org/simantics/browsing/ui/graph/impl/LazyParametrizedViewpoint.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.browsing.ui.graph.impl / src / org / simantics / browsing / ui / graph / impl / LazyParametrizedViewpoint.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.browsing.ui.graph.impl;
13
14 import org.simantics.browsing.ui.BuiltinKeys;
15 import org.simantics.browsing.ui.DataSource;
16 import org.simantics.browsing.ui.NodeContext;
17 import org.simantics.browsing.ui.PrimitiveQueryUpdater;
18 import org.simantics.browsing.ui.common.viewpoints.ViewpointStub;
19 import org.simantics.browsing.ui.content.Viewpoint;
20 import org.simantics.browsing.ui.graph.impl.request.ParametrizedResourceQuery;
21 import org.simantics.db.AsyncReadGraph;
22 import org.simantics.db.ReadGraph;
23 import org.simantics.db.exception.DatabaseException;
24 import org.simantics.db.procedure.Listener;
25 import org.simantics.utils.datastructures.Pair;
26
27 /**
28  * Implement {@link #children(ReadGraph)} and {@link #hasChildren(ReadGraph)}.
29  * 
30  * @author Tuukka Lehtonen
31  */
32 public abstract class LazyParametrizedViewpoint extends ViewpointStub {
33
34         /**
35          * Needed for separating childQuery and hasChildQuery from each other in the
36          * equals sense.
37          */
38         private static final Object                              CHILDREN     = new Object();
39         private static final Object                              HAS_CHILDREN = new Object();
40
41         private final ParametrizedResourceQuery<NodeContext[]> childQuery;
42         private final ParametrizedResourceQuery<Boolean>        hasChildQuery;
43
44     private final Listener<NodeContext[]>              childQueryProcedure;
45     private final Listener<Boolean>                     hasChildQueryProcedure;
46
47     private final PrimitiveQueryUpdater                      updater;
48     private final NodeContext                               context;
49     private final BuiltinKeys.ViewpointKey                   key;
50
51         /**
52          * @return
53          */
54         public abstract NodeContext[] children(ReadGraph graph) throws DatabaseException;
55
56         /**
57          * @param graph
58          * @return
59          */
60         public abstract Boolean hasChildren(ReadGraph graph) throws DatabaseException;
61
62
63         public LazyParametrizedViewpoint(PrimitiveQueryUpdater updater, NodeContext context, BuiltinKeys.ViewpointKey key, Object... parameters) {
64                 assert updater != null;
65                 assert context != null;
66                 assert key != null;
67
68                 this.updater = updater;
69                 this.context = context;
70                 this.key = key;
71
72                 this.childQuery = new ParametrizedResourceQuery<NodeContext[]>(Pair.make(getClass(), CHILDREN), context, parameters) {
73
74                         @Override
75                         public NodeContext[] perform(ReadGraph graph) throws DatabaseException {
76                                 return  children(graph);
77                         }
78
79                 };
80
81                 this.childQueryProcedure = new Listener<NodeContext[]>() {
82
83                         @Override
84                         public void execute(NodeContext[] result) {
85                                 replaceChildrenResult(result);
86                         }
87
88                         @Override
89                         public boolean isDisposed() {
90                                 return LazyParametrizedViewpoint.this.updater.isDisposed();
91                         }
92
93                         public void exception(Throwable t) {
94                                 System.out.print("LazyParametrizedViewpoint2.childQuery failed: ");
95                                 t.printStackTrace();
96                         }
97
98                 };
99
100                 this.hasChildQuery = new ParametrizedResourceQuery<Boolean>(Pair.make(getClass(), HAS_CHILDREN), context, parameters) {
101
102                         @Override
103                         public Boolean perform(ReadGraph graph) throws DatabaseException {
104                                 return hasChildren(graph);
105                         }
106
107                 };
108
109                 this.hasChildQueryProcedure = new Listener<Boolean>() {
110
111                         @Override
112                         public void execute(Boolean result) {
113                                 replaceHasChildrenResult(result);
114                         }
115
116                         @Override
117                         public boolean isDisposed() {
118                                 return LazyParametrizedViewpoint.this.updater.isDisposed();
119                         }
120
121                         public void exception(Throwable t) {
122                                 System.out.print("LazyParametrizedViewpoint2.hasChildQuery failed: ");
123                                 t.printStackTrace();
124                         }
125
126                 };
127
128         }
129
130         public NodeContext getContext() {
131                 return context;
132         }
133
134         @Override
135         public NodeContext[] getChildren() {
136                 if (children == Viewpoint.PENDING_CHILDREN) {
137                         DataSource<AsyncReadGraph> source = updater.getDataSource(AsyncReadGraph.class);
138                         if (source != null) {
139                                 source.schedule(graph -> graph.asyncRequest(childQuery, childQueryProcedure));
140                         }
141                 }
142
143                 return children;
144         }
145
146         @Override
147         public Boolean getHasChildren() {
148                 if (hasChildren == Viewpoint.PENDING_HAS_CHILDREN) {
149                         DataSource<AsyncReadGraph> source = updater.getDataSource(AsyncReadGraph.class);
150                         if (source != null) {
151                                 source.schedule(graph -> graph.asyncRequest(hasChildQuery, hasChildQueryProcedure));
152                         }
153                 }
154                 return hasChildren;
155         }
156
157         protected void replaceChildrenResult(NodeContext[] result) {
158                 setChildren(updater, result);
159                 updater.scheduleReplace(context, key, this);
160         }
161
162         protected void replaceHasChildrenResult(Boolean result) {
163                 setHasChildren(result);
164                 updater.scheduleReplace(context, key, this);
165         }
166
167         /**
168          * @param <T>
169          * @param clazz
170          * @return input of the specified class
171          * @throws ClassCastException if the input class does not match the
172          *         specified class
173          * @throws NullPointerException if the input is null
174          */
175          protected <T> T getInput(Class<T> clazz) throws ClassCastException {
176                  Object o = context.getConstant(BuiltinKeys.INPUT);
177                  if (o == null)
178                          throw new NullPointerException("null input");
179                  return clazz.cast(o);
180          }
181
182          /**
183           * @param <T>
184           * @param clazz
185           * @return <code>null</code> if input is <code>null</code> or if the class does not match
186           */
187          protected <T> T tryGetInput(Class<T> clazz) {
188                  Object o = context.getConstant(BuiltinKeys.INPUT);
189                  if (o != null && clazz.isInstance(o))
190                          return clazz.cast(o);
191                  return null;
192          }
193
194 }