]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java
1b6f9b6f8ea9e4fa58c1764e59d2b12719630e84
[simantics/platform.git] / bundles / org.simantics.simulation / src / org / simantics / simulation / data / DatasourceAdapter.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
3  * 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.simulation.data;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.concurrent.Executor;
20 import java.util.concurrent.locks.Lock;
21 import java.util.concurrent.locks.ReentrantLock;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
24
25 import org.simantics.databoard.Bindings;
26 import org.simantics.databoard.accessor.error.AccessorException;
27 import org.simantics.databoard.binding.Binding;
28 import org.simantics.databoard.binding.NumberBinding;
29 import org.simantics.databoard.type.Datatype;
30 import org.simantics.history.Collector;
31 import org.simantics.history.HistoryException;
32 import org.simantics.history.util.subscription.SubscriptionItem;
33 import org.simantics.simulation.data.Datasource.DatasourceListener;
34 import org.simantics.utils.datastructures.Triple;
35
36 /**
37  * This adapter reads data from Datasource and writes to an open Subscription.
38  * This class is used as a listener. 
39  * 
40  * @author Toni Kalajainen <toni.kalajainen@semantum.fi>
41  */
42 public class DatasourceAdapter implements DatasourceListener {
43
44         protected Logger logger = Logger.getLogger( DatasourceAdapter.class.toString() );
45         protected Collector session;
46         protected boolean loaded = false;
47         protected List<VariableHandle> handles = new ArrayList<VariableHandle>();
48         protected List<String> ids = new ArrayList<String>();
49         protected List<Binding> bindings = new ArrayList<Binding>();
50
51         /**
52          * Variables whose {@link VariableHandle#getValue()} has previously failed
53          * and has been reported to have failed through {@link #logger}. Resetting
54          * the adapter will also reset this set.
55          */
56         protected Set<String> failedIds = new HashSet<String>();
57
58         protected Lock stepLock = new ReentrantLock();
59         
60         /**
61          * Create new adapter. Subscribed items are read from collector. 
62          * 
63          * @param subscription
64          */
65         public DatasourceAdapter(Collector subscription) {
66                 this.session = subscription;
67         }
68         
69         public void setSubscriptionSession(Collector session) {
70                 this.session = session;
71         }
72         
73         public Collector getSubscriptionSession() {
74                 return session;
75         }
76         
77         public void flush() throws HistoryException {
78                 session.flush();
79         }
80
81         /**
82          * @return the lock that is used for synchronizing each
83          *         {@link #onStep(Datasource)} invocation. The lock can be used
84          *         elsewhere to guarantee that history collection steps are not
85          *         taken meanwhile. For example, while setting up history
86          *         collection.
87          */
88         public Lock stepLock() {
89                 return stepLock;
90         }
91
92         /**
93          * Reset internal caches. Call this when subscribed items in collector
94          * have changed.
95          */
96         public void reset() {
97                 for (VariableHandle h : handles) if (h!=null) h.dispose();
98                 bindings.clear();
99                 handles.clear();
100                 ids.clear();
101                 failedIds.clear();
102                 loaded = false;
103         }
104
105         protected void load(Datasource source) {
106                 reset();
107
108                 // Read ids             
109                 SubscriptionItem[] items = session.getItems();
110                 Set<String> idSet = new HashSet<String>(items.length);
111                 for (SubscriptionItem bean : items) {
112                         String variableId = (String) bean.getFieldUnchecked("variableId");
113                         if (!idSet.add( variableId )) continue;
114                         Datatype variableType = source.getType( variableId );
115                         if (variableType == null) continue;
116                         Binding valueBinding = Bindings.getBinding( variableType );
117                         VariableHandle handle = source.openHandle( bean, variableId, valueBinding );
118                         handles.add( handle );
119                         ids.add( variableId );
120                         bindings.add( valueBinding );
121                 }
122                 loaded = true;
123         }
124
125         protected void list(Collection<Triple<String,Binding,Object>> result, Collection<GraphHandle> graphHandles) {
126             
127         int c = ids.size();
128         for (int i=0; i<c; i++) {
129             String key = ids.get(i);
130             VariableHandle handle = handles.get(i);
131             Object value = null;
132             if (handle != null) {
133                 if (handle instanceof GraphHandle) {
134                     graphHandles.add((GraphHandle)handle);
135                 } else {
136                     try {
137                         value = handle.getValue();
138                         Binding binding = bindings.get(i);
139                         result.add(Triple.make(key, binding, value));
140                     } catch (AccessorException e) {
141                         if (failedIds.add(key))
142                             logger.log(Level.SEVERE, e.toString(), e);
143                         continue;
144                     }
145                 }
146             } else {
147                 Binding binding = bindings.get(i);
148                 result.add(Triple.make(key, binding, value));
149             }
150         }
151         }
152         
153         @Override
154     public void onStep(Datasource source) {
155         stepLock.lock();
156         try {
157             NumberBinding timeBinding = Bindings.DOUBLE;
158             Object time = source.getTime( timeBinding );
159             session.beginStep( timeBinding, time );
160
161             if (!loaded) load( source );
162
163             try {
164
165                 int c = ids.size();
166                 for (int i=0; i<c; i++) {
167                     String key = ids.get(i);
168                     VariableHandle handle = handles.get(i);
169                     Object value = null;
170                     if (handle != null) {
171                         try {
172                             value = handle.getValue();
173                         } catch (AccessorException e) {
174                             if (failedIds.add(key))
175                                 logger.log(Level.SEVERE, e.toString(), e);
176                             continue;
177                         }
178                         Binding binding = handle.binding();
179                         try {
180                             session.setValue( key, binding, value );
181                         } catch (HistoryException e) {
182                             logger.log(Level.SEVERE, e.toString(), e);
183                         }
184                     } else {
185                         Binding binding = bindings.get(i);
186                         if (binding != null) { 
187                             session.setValue( key, binding, value );
188                         }                       
189                     }
190                 }
191
192             } finally {
193                 try {
194                     session.endStep();
195                 } catch (HistoryException e) {
196                     logger.log(Level.SEVERE, e.toString(), e);
197                 }
198             }
199         } catch (HistoryException e) {
200             logger.log(Level.SEVERE, e.toString(), e);
201         } finally {
202             stepLock.unlock();
203         }
204     }
205
206         @Override
207         public Executor getExecutor() {
208                 return null;
209         }
210         
211
212 }