/* * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.dal.impl; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import org.csstudio.dal.DataExchangeException; import org.csstudio.dal.DynamicValueAdapter; import org.csstudio.dal.DynamicValueCondition; import org.csstudio.dal.DynamicValueEvent; import org.csstudio.dal.DynamicValueListener; import org.csstudio.dal.DynamicValueMonitor; import org.csstudio.dal.ExpertMonitor; import org.csstudio.dal.RemoteException; import org.csstudio.dal.Response; import org.csstudio.dal.ResponseEvent; import org.csstudio.dal.ResponseListener; import org.csstudio.dal.SimpleProperty; import org.csstudio.dal.Suspendable; import org.csstudio.dal.proxy.MonitorProxy; import com.cosylab.util.ListenerList; // TODO type safety /** * Wrapper clas for <code>MonitorProxy</code>. * */ public class MonitorProxyWrapper<T, P extends SimpleProperty<T>> implements ResponseListener<T>, ExpertMonitor, DynamicValueMonitor, Suspendable{ private DynamicValueListener<T, P> dvl; private ListenerList dvls; private MonitorProxy proxy; private ListenerList plistners; private P property; private Object lastValue = null; private DynamicValueCondition lastCondition; private int suspendCount; private Map<String, Object> initialParameters; private DynamicValueAdapter internalListener = new DynamicValueAdapter<T, P>() { /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueAdapter#conditionChange(org.csstudio.dal.DynamicValueEvent) */ @Override public void conditionChange(DynamicValueEvent<T, P> event) { if (dvl != null) dvl.conditionChange(event); else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) dvlArray[i].conditionChange(event); } } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueAdapter#timelagStarts(org.csstudio.dal.DynamicValueEvent) */ @Override public void timelagStarts(DynamicValueEvent<T, P> event) { if (dvl != null) dvl.timelagStarts(event); else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) dvlArray[i].timelagStarts(event); } } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueAdapter#timelagStops(org.csstudio.dal.DynamicValueEvent) */ @Override public void timelagStops(DynamicValueEvent<T, P> event) { if (dvl != null) dvl.timelagStops(event); else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) dvlArray[i].timelagStops(event); } } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueAdapter#timeoutStarts(org.csstudio.dal.DynamicValueEvent) */ @Override public void timeoutStarts(DynamicValueEvent<T, P> event) { if (dvl != null) dvl.timeoutStarts(event); else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) dvlArray[i].timeoutStarts(event); } } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueAdapter#timeoutStops(org.csstudio.dal.DynamicValueEvent) */ @Override public void timeoutStops(DynamicValueEvent<T, P> event) { if (dvl != null) dvl.timeoutStops(event); else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) dvlArray[i].timeoutStops(event); } } }; /** * Creates a new MonitorProxyWrapper object. * * @param property paretn property * @param listener listener to events */ public MonitorProxyWrapper(P property, DynamicValueListener<T,P> listener){ this(property, listener, null); } /** * Creates a new MonitorProxyWrapper object. * * @param property paretn property * @param listener listener to events * @param parameters the monitor parameters */ public MonitorProxyWrapper(P property, DynamicValueListener<T,P> listener, Map<String, Object> parameters){ dvl = listener; this.property = property; this.property.addDynamicValueListener(internalListener); this.initialParameters = parameters; } /** * Creates a new MonitorProxyWrapper object. * * @param property paretn property * @param listeners listeners to events */ public MonitorProxyWrapper(P property, ListenerList listeners){ dvls = listeners; this.property = property; } /** * Initializes the proxy wrapper * * @param p Monitor proxy */ public void initialize(MonitorProxy p){ proxy = p; } /** * Returns <code>true</code> if this <code>MonitorProxyWrapper</code> is * initialized. * @return <code>true</code> if already initialized and <code>false</code> * otherwise */ public boolean isInitialized() { return proxy != null; } private final static String ERROR_MESSAGE = "Error response"; /* (non-Javadoc) * @see org.csstudio.dal.ResponseListener#responseError(org.csstudio.dal.ResponseEvent) */ @Override public void responseError(ResponseEvent<T> event){ Response<T> response = event.getResponse(); if (property instanceof DynamicValuePropertyImpl) ((DynamicValuePropertyImpl<T>)property).updateLastValueCache(response, false, false); else if (property instanceof SimplePropertyImpl) ((SimplePropertyImpl<T>)property).updateLastValueCache(null, response.getTimestamp(), false, false); lastCondition = response.getCondition(); // TODO better message DynamicValueEvent<T, P> dynamicEvent = new DynamicValueEvent<T,P>(property,property, response.getValue(), lastCondition, response.getTimestamp(), ERROR_MESSAGE, response.getError()); if (dvl != null) dvl.errorResponse(dynamicEvent); else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) dvlArray[i].errorResponse(dynamicEvent); } } /* (non-Javadoc) * @see org.csstudio.dal.ResponseListener#responseReceived(org.csstudio.dal.ResponseEvent) */ @Override public void responseReceived(ResponseEvent<T> event){ Response<T> response = event.getResponse(); T value = response.getValue(); // TODO can value be null? boolean valueChanged = !value.equals(lastValue); lastValue = value; if (property instanceof DynamicValuePropertyImpl) ((DynamicValuePropertyImpl<T>)property).updateLastValueCache(response, true, valueChanged); else if (property instanceof SimplePropertyImpl) ((SimplePropertyImpl<T>)property).updateLastValueCache(value, response.getTimestamp(), true, valueChanged); lastCondition = response.getCondition(); // TODO better message DynamicValueEvent<T,P> dynamicEvent = new DynamicValueEvent<T,P>(property, property, value, lastCondition, response.getTimestamp(), null); if (dvl != null) { if (valueChanged) dvl.valueChanged(dynamicEvent); else dvl.valueUpdated(dynamicEvent); } else if (dvls != null) { DynamicValueListener<T,P>[] dvlArray = (DynamicValueListener<T,P>[])dvls.toArray(); for (int i = 0; i < dvlArray.length; i++) { if (valueChanged) dvlArray[i].valueChanged(dynamicEvent); else dvlArray[i].valueUpdated(dynamicEvent); } } } /** * Returns <code>true</code> if there is a timelag from actual event delivered * * @return <code>true</code> if timelag */ public boolean isTimelag(){ return lastCondition != null ? lastCondition.isTimelag() : false; } /** * Returns <code>true</code> if there is a timeout from actual event delivered * * @return <code>true</code> if timelag */ public boolean isTimeout(){ return lastCondition != null ? lastCondition.isTimeout() : false; } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueMonitor#getDefaultTimerTrigger() */ @Override public long getDefaultTimerTrigger() throws DataExchangeException{ return proxy.getDefaultTimerTrigger(); } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueMonitor#getTimerTrigger() */ @Override public long getTimerTrigger() throws DataExchangeException{ return proxy.getTimerTrigger(); } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueMonitor#isDefault() */ @Override public boolean isDefault(){ return proxy.isDefault(); } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueMonitor#isHeartbeat() */ @Override public boolean isHeartbeat(){ return proxy.isHeartbeat(); } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueMonitor#setHeartbeat(boolean) */ @Override public void setHeartbeat(boolean heartbeat) throws DataExchangeException, UnsupportedOperationException{ proxy.setHeartbeat(heartbeat); } /* (non-Javadoc) * @see org.csstudio.dal.DynamicValueMonitor#setTimerTrigger(long) */ @Override public void setTimerTrigger(long trigger) throws DataExchangeException, UnsupportedOperationException{ proxy.setTimerTrigger(trigger); } /* (non-Javadoc) * @see org.csstudio.dal.CharacteristicContext#addPropertyChangeListener(java.beans.PropertyChangeListener) */ @Override public void addPropertyChangeListener(PropertyChangeListener l){ if (plistners==null) plistners = new ListenerList(PropertyChangeListener.class); plistners.add(l); } /* (non-Javadoc) * @see org.csstudio.dal.CharacteristicContext#getCharacteristic(java.lang.String) */ @Override public Object getCharacteristic(String name) throws DataExchangeException{ if (C_DEFAULT_TIMER_TRIGGER.equals(name)) return proxy.getDefaultTimerTrigger(); if (C_HEARTBEAT.equals(name)) return proxy.isHeartbeat(); if (C_TIMER_TRIGGER.equals(name)) return proxy.getTimerTrigger(); return null; } /* (non-Javadoc) * @see org.csstudio.dal.CharacteristicContext#getCharacteristicNames() */ @Override public String[] getCharacteristicNames() throws DataExchangeException{ return new String[]{ C_DEFAULT_TIMER_TRIGGER, C_HEARTBEAT, C_TIMER_TRIGGER }; } /* (non-Javadoc) * @see org.csstudio.dal.CharacteristicContext#getCharacteristics(java.lang.String[]) */ @Override public Map<String, Object> getCharacteristics(String[] names) throws DataExchangeException{ Map<String, Object> m = new HashMap<String, Object>(names.length); for (int i = 0; i < names.length; i++) m.put(names[i], getCharacteristic(names[i])); return m; } /* (non-Javadoc) * @see org.csstudio.dal.CharacteristicContext#getPropertyChangeListeners() */ @Override public PropertyChangeListener[] getPropertyChangeListeners(){ return plistners == null ? new PropertyChangeListener[0] : (PropertyChangeListener[])plistners.toArray(new PropertyChangeListener[plistners.size()]); } /* (non-Javadoc) * @see org.csstudio.dal.CharacteristicContext#removePropertyChangeListener(java.beans.PropertyChangeListener) */ @Override public void removePropertyChangeListener(PropertyChangeListener l){ if (plistners!=null) plistners.remove(l); } /* (non-Javadoc) * @see org.csstudio.dal.SimpleMonitor#destroy() */ @Override public void destroy(){ ((SimplePropertyImpl)property).removeMonitor(this); property.removeDynamicValueListener(internalListener); if (proxy != null) proxy.destroy(); } /* (non-Javadoc) * @see org.csstudio.dal.SimpleMonitor#isDestroyed() */ @Override public boolean isDestroyed(){ return proxy.isDestroyed(); } @Override public void suspend() { if (!(proxy instanceof Suspendable)) throw new UnsupportedOperationException("Monitor proxy doesn't support suspend/resume operations!"); if (suspendCount == 0) ((Suspendable)proxy).suspend(); suspendCount++; } @Override public void resume() { if (!(proxy instanceof Suspendable)) throw new UnsupportedOperationException("Monitor proxy doesn't support suspend/resume operations!"); if (suspendCount == 1) ((Suspendable)proxy).resume(); if (suspendCount > 0) suspendCount--;; } @Override public boolean isSuspended() { if (!(proxy instanceof Suspendable)) throw new UnsupportedOperationException("Monitor proxy doesn't support suspend/resume operations!"); return suspendCount > 0; } public MonitorProxy releaseProxy(boolean destroy) { if (destroy) { destroy(); dvls=null; dvl=null; if (plistners!=null) plistners.clear(); } MonitorProxy p= proxy; if (proxy != null) proxy.destroy(); return p; } @Override public Map<String, Object> getParameters() { if (proxy instanceof ExpertMonitor) return ((ExpertMonitor)proxy).getParameters(); return null; } @Override public void setParameters(Map<String, Object> param) throws RemoteException { if (proxy instanceof ExpertMonitor) ((ExpertMonitor)proxy).setParameters(param); } public Map<String, Object> getInitialParameters() { return initialParameters; } }