package org.csstudio.dal.simple.impl; import java.util.concurrent.ConcurrentHashMap; import org.csstudio.dal.DynamicValueAdapter; import org.csstudio.dal.DynamicValueCondition; import org.csstudio.dal.DynamicValueEvent; import org.csstudio.dal.DynamicValueListener; import org.csstudio.dal.DynamicValueProperty; import org.csstudio.dal.context.ConnectionEvent; import org.csstudio.dal.context.LinkListener; import org.csstudio.dal.simple.AnyDataChannel; import org.csstudio.dal.simple.ChannelListener; public class ChannelListenerNotifier { private final ConcurrentHashMap<Integer, ChannelListener> listeners = new ConcurrentHashMap<Integer, ChannelListener>(); private AnyDataChannel channel; private DynamicValueCondition lastCondition = null; private boolean initialStateUpdate = false; private boolean initialDataUpdate = false; private final LinkListener<DynamicValueProperty<?>> linkListener = new LinkListener<DynamicValueProperty<?>>() { @Override public void connected(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void operational(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void connectionFailed(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void connectionLost(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void destroyed(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void disconnected(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void resumed(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } @Override public void suspended(ConnectionEvent<DynamicValueProperty<?>> e) { fireChannelStateUpdate(); } }; private final DynamicValueListener dvListener = new DynamicValueAdapter() { @Override public void conditionChange(DynamicValueEvent event) { DynamicValueCondition cond = event.getCondition(); if (initialStateUpdate && cond != null && lastCondition != null && lastCondition.areStatesEqual(cond) && lastCondition.hasValue() == cond.hasValue()) { return; } lastCondition = cond; initialStateUpdate = true; fireChannelStateUpdate(); } @Override public void valueChanged(DynamicValueEvent event) { initialDataUpdate = true; fireChannelDataUpdate(); } }; // private PropertyChangeListener pcListener = new PropertyChangeListener() { // public void propertyChange(java.beans.PropertyChangeEvent evt) { // if (evt.getPropertyName().equals(CharacteristicInfo.C_META_DATA.getName())) // fireChannelDataUpdate(); // }; // }; public ChannelListenerNotifier(AnyDataChannel channel) { this.channel = channel; } public synchronized void addChannelListener(ChannelListener listener) { listeners.put(listener.hashCode(), listener); if (initialStateUpdate) listener.channelStateUpdate(channel); if (initialDataUpdate) listener.channelDataUpdate(channel); if (listeners.size() == 1) subscribe(channel); } public synchronized void removeChannelListener(ChannelListener listener) { listeners.remove(listener.hashCode()); if (listeners.size() == 0) unsubscribe(); } public synchronized ChannelListener[] getChannelListeners() { return (ChannelListener[]) listeners.values().toArray(new ChannelListener[listeners.size()]); } public void subscribe(AnyDataChannel channel) { if (this.channel != channel) unsubscribe(); this.channel = channel; if (channel == null) return; channel.getProperty().addLinkListener(linkListener); channel.getProperty().addDynamicValueListener(dvListener); // channel.getProperty().addPropertyChangeListener(pcListener); } public void unsubscribe() { if (channel == null) return; // channel.getProperty().removePropertyChangeListener(pcListener); channel.getProperty().removeDynamicValueListener(dvListener); channel.getProperty().removeLinkListener(linkListener); initialStateUpdate = false; initialDataUpdate = false; } private void fireChannelStateUpdate() { for (ChannelListener listener : getChannelListenerArray()) { listener.channelStateUpdate(channel); } } private void fireChannelDataUpdate() { for (ChannelListener listener : getChannelListenerArray()) { listener.channelDataUpdate(channel); } } private ChannelListener[] getChannelListenerArray() { return (ChannelListener[]) listeners.values().toArray(new ChannelListener[listeners.size()]); } }