/*-
* Copyright © 2010 Diamond Light Source Ltd.
*
* This file is part of GDA.
*
* GDA is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 3 as published by the Free
* Software Foundation.
*
* GDA is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with GDA. If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.gda.dal.dataprovider;
import gda.device.Scannable;
import gda.factory.Findable;
import gda.factory.Finder;
import gda.jython.JythonServerFacade;
import gda.observable.IObserver;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.csstudio.dal.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class ProvideOffsetRunnable<T> implements ProvideRunnable<T> {
public static final Logger logger = LoggerFactory.getLogger(ProvideHighLimitRunnable.class);
private double currentValue = 0.0;
private boolean running;
private List<ProvideDataEventListener<T>> listeners = new ArrayList<ProvideDataEventListener<T>>(1);
private String scannableName;
private ProvideDataEvent<T> event = null;
private Scannable scannable;
private IObserver observer = null;
private TimerTask timerTask;
private Timer timer = new Timer();
public ProvideOffsetRunnable(String scannableName) {
createTimers(scannableName);
}
private void createTimers(String scannableName){
int index = scannableName.lastIndexOf(".");
if (index != -1)
this.scannableName = scannableName.substring(0, index);
updateListeners(readValue());
Findable findable = Finder.getInstance().find(scannableName.substring(0, scannableName.indexOf('.')));
if (findable instanceof Scannable) {
scannable = (Scannable) findable;
scannable.addIObserver(observer = new IObserver() {
@Override
public void update(Object source, Object arg) {
if (source == null) {
try {
if (timerTask != null)
timerTask.cancel();
timerTask = new TimerTask() {
@Override
public void run() {
refresh();
}
};
timer.schedule(timerTask, 100, 300);
} catch (IllegalStateException e) {
}
}
}
});
}
observer.update(null, null);
running = true;
}
private Object readValue() {
Double offset=0.0;
String evaluated = JythonServerFacade.getInstance().evaluateCommand(this.scannableName+".getOffset()[0]");
if(!evaluated.equals("")&&!evaluated.equals("nan"))
offset = Double.parseDouble(evaluated);
return offset;
}
private void updateListeners(Object position) {
event = new ProvideDataEvent<T>();
try {
event.value = createValue(position);
} catch (Exception e) {
logger.error(e.getMessage(), e);
event = null;
return;
}
event.timestamp = new Timestamp();
for (ProvideDataEventListener<T> listener : listeners)
listener.newData(event);
}
@Override
public void addListener(ProvideDataEventListener<T> newListener) {
listeners.add(newListener);
if (event != null)
newListener.newData(event);
}
abstract T createValue(Object val);
@Override
public T getCurrentValue() {
return createValue(currentValue);
}
@Override
public boolean isRunning() {
return running;
}
@Override
public void refresh() {
updateListeners(readValue());
}
@Override
public void removeListener(ProvideDataEventListener<T> listenerToRemove) {
listeners.remove(listenerToRemove);
}
@Override
public void setTargetValue(Object targetValue) {
String command = this.scannableName + ".setOffset(" + targetValue + ")";
JythonServerFacade.getInstance().runCommand(command);
}
@Override
public void stop() {
running = true;
}
}