/*-
* 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.propproxy;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import org.csstudio.dal.DataExchangeException;
import org.csstudio.dal.DynamicValueCondition;
import org.csstudio.dal.DynamicValueState;
import org.csstudio.dal.RemoteException;
import org.csstudio.dal.Request;
import org.csstudio.dal.ResponseListener;
import org.csstudio.dal.SimpleProperty;
import org.csstudio.dal.Timestamp;
import org.csstudio.dal.context.ConnectionState;
import org.csstudio.dal.impl.PropertyUtilities;
import org.csstudio.dal.impl.RequestImpl;
import org.csstudio.dal.impl.ResponseImpl;
import org.csstudio.dal.proxy.AbstractPropertyProxyImpl;
import org.csstudio.dal.proxy.DirectoryProxy;
import org.csstudio.dal.proxy.MonitorProxy;
import org.csstudio.dal.proxy.PropertyProxy;
import org.csstudio.dal.proxy.SyncPropertyProxy;
import uk.ac.gda.dal.GdaPlug;
import uk.ac.gda.dal.MonitorProxyImpl;
import uk.ac.gda.dal.dataprovider.ProvideRunnable;
import com.cosylab.naming.URIName;
public class PropertyProxyImpl<T> extends AbstractPropertyProxyImpl<T,GdaPlug,MonitorProxyImpl<T>> implements
PropertyProxy<T,GdaPlug>, SyncPropertyProxy<T,GdaPlug>, DirectoryProxy<GdaPlug>{
protected ProvideRunnable<Object> dataProvider=null;
protected List<MonitorProxyImpl<T>> monitors = new ArrayList<MonitorProxyImpl<T>>(1);
protected DynamicValueCondition condition;
public PropertyProxyImpl(String name, GdaPlug plug) {
super(name, plug);
}
protected void connect(){
condition = new DynamicValueCondition(EnumSet.of(DynamicValueState.NORMAL), new Timestamp(),"NORMAL");
// *** Race condition, the state can't go to Connected until all the listeners have been setup.
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run(){
setConnectionState(ConnectionState.CONNECTED);
dataProvider.refresh();
}
}, 1000);
}
@Override
public void destroy() {
dataProvider.stop();
destroyMonitors();
super.destroy();
}
@Override
protected void destroyMonitors(){
MonitorProxyImpl<T>[] array = new MonitorProxyImpl[monitors.size()];
synchronized (monitors) {
array = monitors.toArray(array);
}
// destroy all
for (int i = 0; i < array.length; i++)
array[i].destroy();
}
@Override
public MonitorProxy createMonitor(ResponseListener<T> callback, Map<String,Object> parameters) throws RemoteException {
if (getConnectionState() == ConnectionState.DESTROYED)
throw new RemoteException(this, "Proxy destroyed.");
MonitorProxyImpl<T> m = new MonitorProxyImpl<T>(this, callback, (ProvideRunnable<T>) dataProvider);
monitors.add(m);
return m;
}
@Override
public DynamicValueCondition getCondition() {
return condition;
}
@Override
public Request<T> getValueAsync(ResponseListener<T> callback) throws DataExchangeException {
if (getConnectionState() != ConnectionState.CONNECTED)
throw new DataExchangeException(this, "Proxy not connected");
RequestImpl<T> r = new RequestImpl<T>(this, callback);
r.addResponse(new ResponseImpl<T>(this, r, (T) dataProvider.getCurrentValue(), "value", true, null, getCondition(), null, true));
return r;
}
@Override
public boolean isSettable() {
// TODO Auto-generated method stub
return true;
}
@Override
public Request<T> setValueAsync(T value, ResponseListener<T> callback) throws DataExchangeException {
if (getConnectionState() != ConnectionState.CONNECTED)
throw new DataExchangeException(this, "Proxy not connected");
dataProvider.setTargetValue(value);
RequestImpl<T> r = new RequestImpl<T>(this, callback);
r.addResponse(new ResponseImpl<T>(this, r, value, "", true, null, condition, null, true));
return r;
}
@Override
public Object getCharacteristic(String characteristicName) throws DataExchangeException {
DirContext ctx = GdaPlug.getInstance().getDefaultDirectory();
try {
URIName uri = new URIName(null, GdaPlug.DEFAULT_AUTHORITY, this.getUniqueName(), null);
Attributes attr = ctx.getAttributes(uri);
Object characteristic = null;
if (attr instanceof org.epics.css.dal.directory.Attributes) {
org.epics.css.dal.directory.Attributes at = (org.epics.css.dal.directory.Attributes)attr;
characteristic = at.getAttributeValue(characteristicName);
}
else if (attr != null)
characteristic = attr.get(characteristicName).get();
if (characteristic == null) {
uri = new URIName(null, GdaPlug.DEFAULT_AUTHORITY, this.getClass().getSimpleName(), null);
attr = ctx.getAttributes(uri);
if (attr instanceof org.epics.css.dal.directory.Attributes) {
org.epics.css.dal.directory.Attributes at = (org.epics.css.dal.directory.Attributes)attr;
characteristic = at.getAttributeValue(characteristicName);
}
else if (attr != null)
characteristic = attr.get(characteristicName).get();
}
return characteristic;
} catch (NamingException e) {
throw new RuntimeException("Cannot instanitate URIName.", e);
}
}
public static Object putCharacteristic(String characteristicName, String propertyUniqueName, Object value){
DirContext ctx = GdaPlug.getInstance().getDefaultDirectory();
try {
URIName uri = new URIName(null, GdaPlug.DEFAULT_AUTHORITY, propertyUniqueName, null);
Attributes attr = ctx.getAttributes(uri);
if (attr==null) {
attr=new org.epics.css.dal.directory.Attributes();
ctx.bind(uri, null, attr);
}
Object characteristic = null;
if (attr instanceof org.epics.css.dal.directory.Attributes) {
org.epics.css.dal.directory.Attributes at = (org.epics.css.dal.directory.Attributes)attr;
characteristic = at.putAttributeValue(characteristicName, value);
}
characteristic = attr.put(characteristicName, value);
return characteristic;
} catch (NamingException e) {
throw new RuntimeException("Cannot instanitate URIName.", e);
}
}
@Override
public String[] getCharacteristicNames() throws DataExchangeException{
DirContext ctx = GdaPlug.getInstance().getDefaultDirectory();
try {
URIName uri = new URIName(null, GdaPlug.DEFAULT_AUTHORITY, this.getUniqueName(), null);
Attributes attr = ctx.getAttributes(uri);
if (attr == null) {
uri = new URIName(null, GdaPlug.DEFAULT_AUTHORITY, this.getClass().getSimpleName(), null);
attr = ctx.getAttributes(uri);
}
NamingEnumeration<String> en = attr.getIDs();
ArrayList<String> list = new ArrayList<String>();
while (en.hasMore())
list.add(en.next());
String[] names = new String[list.size()];
return list.toArray(names);
} catch (NamingException e) {
throw new RuntimeException("Cannot instanitate URIName.", e);
}
}
@Override
@SuppressWarnings("unchecked")
public Request<? extends Object> getCharacteristics(String[] characteristics, ResponseListener<? extends Object> callback) throws DataExchangeException{
RequestImpl<Object> r = new RequestImpl<Object>(this, (ResponseListener<Object>) callback);
for (int i = 0; i < characteristics.length; i++) {
Object value = PropertyUtilities.verifyCharacteristic(this, characteristics[i], getCharacteristic(characteristics[i]));
r.addResponse(new ResponseImpl<Object>(this, r, value, characteristics[i],
value != null, null, condition, null, true));
}
return r;
}
@Override
public String[] getCommandNames() throws DataExchangeException {
// TODO Auto-generated method stub
return null;
}
@Override
public String[] getPropertyNames() throws RemoteException {
// TODO Auto-generated method stub
return null;
}
@Override
public Class<? extends SimpleProperty<?>> getPropertyType(
String propertyName) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
@Override
public void refresh() {
// TODO Auto-generated method stub
}
@Override
public T getValueSync() throws DataExchangeException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setValueSync(T value) throws DataExchangeException {
// TODO Auto-generated method stub
}
@Override
protected Object processCharacteristicAfterCache(Object value, String characteristicName) {
// TODO Auto-generated method stub
return null;
}
@Override
protected Object processCharacteristicBeforeCache(Object value, String characteristicName) {
// TODO Auto-generated method stub
return null;
}
}