]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.graph.impl/src/org/simantics/browsing/ui/graph/impl/contribution/FinalImageDecoratorContributionImpl.java
Merge "Multiple reader thread support for db client"
[simantics/platform.git] / bundles / org.simantics.browsing.ui.graph.impl / src / org / simantics / browsing / ui / graph / impl / contribution / FinalImageDecoratorContributionImpl.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.contribution;
13
14 import org.simantics.browsing.ui.BuiltinKeys.ImageDecoratorKey;
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.content.ImageDecorator;
19 import org.simantics.browsing.ui.graph.impl.request.ResourceQuery;
20 import org.simantics.db.AsyncReadGraph;
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.exception.DatabaseException;
23 import org.simantics.db.layer0.exception.PendingVariableException;
24 import org.simantics.db.procedure.Listener;
25 import org.simantics.db.procedure.Procedure;
26 import org.simantics.utils.ui.ErrorLogger;
27
28 public abstract class FinalImageDecoratorContributionImpl implements ImageDecorator {
29
30     final ImageDecorator FRESH = new ImageDecorator.Stub();
31     final ImageDecorator PENDING = new ImageDecorator.Stub();
32     final ImageDecorator NO_DECORATION = new ImageDecorator.Stub();
33
34     protected final PrimitiveQueryUpdater       updater;
35     private final ResourceQuery<ImageDecorator> imageQuery;
36     private final ImageDecoratorKey             key;
37
38     /**
39      * The current decorator result produced for this contribution. The value
40      * should never be <code>null</code>, but one of {@link #FRESH},
41      * {@link #PENDING}, {@link #NO_DECORATION} instead.
42      */
43     protected ImageDecorator                      decorator = FRESH;
44
45     final protected NodeContext                   context;
46
47     public Object getIdentity(ImageDecoratorKey key) {
48         return key;
49     }
50
51     private void request() {
52
53         final DataSource<AsyncReadGraph> source = updater.getDataSource(AsyncReadGraph.class);
54         assert(source != null);
55
56         final Procedure<ImageDecorator> procedure = createProcedure();
57         
58         source.schedule(graph -> {
59             if(procedure instanceof Listener<?>)
60                 graph.asyncRequest(imageQuery, (Listener<ImageDecorator>)procedure);
61             else
62                 graph.asyncRequest(imageQuery, procedure);
63         });
64
65     }
66
67     @Override
68     public <Image> Image decorateImage(Image image, String column, int itemIndex) {
69         if(FRESH == decorator) {
70             decorator = PENDING;
71             request();
72         }
73         return decorator.decorateImage(image, column, itemIndex);
74     }
75
76     public FinalImageDecoratorContributionImpl(final PrimitiveQueryUpdater updater, final NodeContext context, final ImageDecoratorKey key) {
77
78         this.updater = updater;
79         this.context = context;
80         this.key = key;
81
82         imageQuery = new ResourceQuery<ImageDecorator>(getIdentity(key), context) {
83
84             @Override
85             public ImageDecorator perform(ReadGraph graph) throws DatabaseException {
86                 try {
87                     return getDecorator(graph, context);
88                 } catch (PendingVariableException e) {
89                     return PENDING;
90                 } catch (DatabaseException e) {
91                     throw e;
92                 } catch (Throwable t) {
93                     ErrorLogger.defaultLogError("FinalImageDecoratorContributionImpl.imageQuery produced unexpected exception.", t);
94                     return null;
95                 }
96             }
97
98             @Override
99             public String toString() {
100                 return FinalImageDecoratorContributionImpl.this + " with context " + context;
101             }
102
103         };
104         
105     }
106
107     protected Procedure<ImageDecorator> createProcedure() {
108
109         return new Procedure<ImageDecorator>() {
110
111             @Override
112             public void execute(ImageDecorator result) {
113                 replaceResult(result);
114             }
115
116             @Override
117             public void exception(Throwable t) {
118                 ErrorLogger.defaultLogError("FinalImageDecoratorContributionImpl.imageQuery failed, see exception for details.", t);
119             }
120
121         };
122
123     }
124
125     protected void replaceResult(ImageDecorator result) {
126         // Never let decorator become null, use a stub decorator instead.
127         if (result == null)
128             result = NO_DECORATION;
129
130         decorator = result;
131         updater.scheduleReplace(context, key, this);
132     }
133
134     // OVERRIDE
135
136     public abstract ImageDecorator getDecorator(ReadGraph graph, NodeContext context) throws DatabaseException;
137
138 }