1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.simulation.data;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
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;
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;
37 * This adapter reads data from Datasource and writes to an open Subscription.
38 * This class is used as a listener.
40 * @author Toni Kalajainen <toni.kalajainen@semantum.fi>
42 public class DatasourceAdapter implements DatasourceListener {
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>();
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.
56 protected Set<String> failedIds = new HashSet<String>();
58 protected Lock stepLock = new ReentrantLock();
61 * Create new adapter. Subscribed items are read from collector.
65 public DatasourceAdapter(Collector subscription) {
66 this.session = subscription;
69 public void setSubscriptionSession(Collector session) {
70 this.session = session;
73 public Collector getSubscriptionSession() {
77 public void flush() throws HistoryException {
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
88 public Lock stepLock() {
93 * Reset internal caches. Call this when subscribed items in collector
97 for (VariableHandle h : handles) if (h!=null) h.dispose();
105 protected void load(Datasource source) {
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 );
125 protected void list(Collection<Triple<String,Binding,Object>> result, Collection<GraphHandle> graphHandles) {
128 for (int i=0; i<c; i++) {
129 String key = ids.get(i);
130 VariableHandle handle = handles.get(i);
132 if (handle != null) {
133 if (handle instanceof GraphHandle) {
134 graphHandles.add((GraphHandle)handle);
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);
147 Binding binding = bindings.get(i);
148 result.add(Triple.make(key, binding, value));
154 public void onStep(Datasource source) {
157 NumberBinding timeBinding = Bindings.DOUBLE;
158 Object time = source.getTime( timeBinding );
159 session.beginStep( timeBinding, time );
161 if (!loaded) load( source );
166 for (int i=0; i<c; i++) {
167 String key = ids.get(i);
168 VariableHandle handle = handles.get(i);
170 if (handle != null) {
172 value = handle.getValue(source);
173 } catch (AccessorException e) {
174 if (failedIds.add(key))
175 logger.log(Level.SEVERE, e.toString(), e);
178 Binding binding = handle.binding();
180 session.setValue( key, binding, value );
181 } catch (HistoryException e) {
182 logger.log(Level.SEVERE, e.toString(), e);
185 Binding binding = bindings.get(i);
186 if (binding != null) {
187 session.setValue( key, binding, value );
195 } catch (HistoryException e) {
196 logger.log(Level.SEVERE, e.toString(), e);
199 } catch (HistoryException e) {
200 logger.log(Level.SEVERE, e.toString(), e);
207 public Executor getExecutor() {