/*- * Copyright © 2009 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.DeviceException; import gda.device.Scannable; import gda.device.scannable.ScannableStatus; import gda.factory.Findable; import gda.factory.Finder; import gda.observable.IObserver; import java.util.ArrayList; import java.util.List; import org.csstudio.dal.Timestamp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class ProvideStatusRunnable<T> implements ProvideRunnable<T> { private static final Logger logger = LoggerFactory.getLogger(ProvideStatusRunnable.class); private Scannable scannable; private boolean running = false; private int currentStatus = ScannableStatus.IDLE; // TODO: listeners list isn't used thread safely private List<ProvideDataEventListener<T>> listeners = new ArrayList<ProvideDataEventListener<T>>(1); private IObserver observer; private ProvideDataEvent<T> event; @Override public T getCurrentValue() { return createValue(currentStatus); } @Override public void setTargetValue(Object targetValue) { try { if (scannable.isBusy()) { Runnable x = new Runnable() { @Override public void run() { try { scannable.stop(); } catch (DeviceException e) { logger.error(e.getMessage(), e); } } }; Thread t = new Thread(x, "stop"); t.start(); } } catch (DeviceException e) { logger.error(e.getMessage(), e); } } public ProvideStatusRunnable(String scannableName) { int index = scannableName.indexOf("."); if (index != -1) scannableName = scannableName.substring(0, index); Findable findable = Finder.getInstance().find(scannableName); if (findable instanceof Scannable) { scannable = (Scannable) findable; scannable.addIObserver(observer = new IObserver() { @Override public void update(Object source, Object arg) { if (source instanceof Scannable && arg instanceof ScannableStatus) sendStatusUpdate(((ScannableStatus) arg).getStatus()); } }); try { sendStatusUpdate(scannable.isBusy()? ScannableStatus.BUSY : ScannableStatus.IDLE); running = true; } catch (DeviceException e) { logger.error(e.getMessage(), e); } } else { stop(); throw new RuntimeException("ProvideDataRunnable. " + scannableName + " is not a Scannable"); } } private void sendStatusUpdate(int isBusy) { event = new ProvideDataEvent<T>(); event.value = createValue(isBusy); event.timestamp = new Timestamp(); for (ProvideDataEventListener<T> listener : listeners) listener.newData(event); } abstract T createValue(int val); @Override public void stop() { running = false; if (scannable != null && observer != null) { scannable.deleteIObserver(observer); observer = null; } } @Override public boolean isRunning() { return running; } @Override public void addListener(ProvideDataEventListener<T> newListener) { listeners.add(newListener); if (event != null) newListener.newData(event); } @Override public void removeListener(ProvideDataEventListener<T> listenerToRemove) { listeners.remove(listenerToRemove); } @Override public void refresh() { } }