Package wpn.hdri.ss.client.tine

Source Code of wpn.hdri.ss.client.tine.TineClient

/*
* The main contributor to this project is Institute of Materials Research,
* Helmholtz-Zentrum Geesthacht,
* Germany.
*
* This project is a contribution of the Helmholtz Association Centres and
* Technische Universitaet Muenchen to the ESS Design Update Phase.
*
* The project's funding reference is FKZ05E11CG1.
*
* Copyright (c) 2012. Institute of Materials Research,
* Helmholtz-Zentrum Geesthacht,
* Germany.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

package wpn.hdri.ss.client.tine;

import de.desy.tine.client.TCallback;
import de.desy.tine.client.TLink;
import de.desy.tine.dataUtils.TDataType;
import de.desy.tine.definitions.TAccess;
import de.desy.tine.definitions.TErrorList;
import de.desy.tine.definitions.TMode;
import de.desy.tine.queryUtils.TPropertyQuery;
import de.desy.tine.queryUtils.TQuery;
import org.apache.log4j.Logger;
import wpn.hdri.ss.client.Client;
import wpn.hdri.ss.client.ClientException;
import wpn.hdri.ss.client.EventCallback;
import wpn.hdri.ss.client.EventData;
import wpn.hdri.ss.data.Timestamp;

import java.lang.reflect.Array;
import java.util.AbstractMap;
import java.util.Map;
import java.util.concurrent.*;

/**
* This instance stores a number of {@link TLink} and reads data from them.
*
* @author Igor Khokhriakov <igor.khokhriakov@hzg.de>
* @since 27.04.12
*/
public class TineClient extends Client {
    private final String context;
    private final String serverName;
    private final String deviceName;
    private ConcurrentMap<String, Future<TLink>> tlinks = new ConcurrentHashMap<String, Future<TLink>>();

    public TineClient(String deviceName) {
        super(deviceName);
        String[] deviceInfo = deviceName.split("/");
        this.context = deviceInfo[1];//skip leading '/'
        this.serverName = deviceInfo[2];
        this.deviceName = deviceInfo[3];
    }

    /**
     * Implementation stores {@link TLink} instances wrapped by {@link FutureTask} in private {@link this#tlinks} field.
     * This is done to prevent multiply dummy TLink instances creation.
     *
     * @param attrName
     * @return
     * @throws ClientException
     */
    @Override
    public <T> Map.Entry<T, Timestamp> readAttribute(final String attrName) throws ClientException {
        Future<TLink> futureLink = getFutureLink(attrName);
        try {
            TLink tLink = futureLink.get();
            int rc = tLink.execute();
            if (rc != TErrorList.success) {
                throw new RuntimeException("TLink has failed: " + TErrorList.getErrorString(rc));
            }
            TDataType dout = tLink.dOutput;
            long time = tLink.getLastTimeStamp();
            Timestamp timestamp = new Timestamp(time);
            return new AbstractMap.SimpleImmutableEntry<T, wpn.hdri.ss.data.Timestamp>((T) getDataObject(dout), timestamp);
        } catch (Exception e) {
            throw new ClientException("Read from " + getDeviceName() + "/" + attrName + " failed.", e);
        }
    }

    private Future<TLink> getFutureLink(final String attrName) {
        Future<TLink> futureLink = tlinks.get(attrName);
        if (futureLink == null) {
            FutureTask<TLink> ft =
                    new FutureTask<TLink>(
                            new Callable<TLink>() {
                                @Override
                                public TLink call() throws Exception {
                                    TPropertyQuery meta = getTPropertyQuery(attrName);
                                    int size = getTPropertySize(meta);
                                    short dataFormat = getTPropertyFormat(meta);
                                    TDataType dout = new TDataType(size, dataFormat);
                                    // get a reference array : synchronous call ...
                                    TLink result = new TLink(getDeviceName(), attrName, dout, null, TAccess.CA_READ);
                                    return result;
                                }
                            });


            futureLink = tlinks.putIfAbsent(attrName, ft);
            if (futureLink == null) {
                ft.run();
                futureLink = ft;
            }
        }
        return futureLink;
    }

    /**
     * @param dout
     * @return Object or Object[]
     */
    private Object getDataObject(TDataType dout) {
        int length = Array.getLength(dout.getDataObject());
        Object dataObject = dout.getDataObject();
        //TODO it appears that TINE always returns array of values
        //TODO and the only interesting value is always the first one in this array
        //if (length > 1) {
        //    return dataObject;
        //} else {
        return Array.get(dataObject, 0);
        //}
    }

    @Override
    public void subscribeEvent(final String attrName, final EventCallback cbk) throws ClientException {
        Future<TLink> futureLink = getFutureLink(attrName);
        try {
            final TLink link = futureLink.get();
            final TDataType dout = link.dOutput;
            long time = link.getLastTimeStamp();
            //read data for the first time
            cbk.onEvent(new EventData<Object>(getDataObject(dout), time));
            //attach event listener
            int rc = link.attach(TMode.CM_DATACHANGE, new TCallback() {
                @Override
                public void callback(int LinkIndex, int LinkStatus) {
                    if (TErrorList.isLinkSuccess(LinkStatus)) {
                        long time = link.getLastTimeStamp();
                        cbk.onEvent(new EventData<Object>(getDataObject(dout), time));
                    } else {
                        cbk.onError(new Exception(TErrorList.getErrorString(LinkStatus)));
                    }
                }
            });
            if (rc < 0) {
                throw new IllegalStateException(link.getLastError());
            }
        } catch (Exception e) {
            throw new ClientException("Failed subscribe to " + getDeviceName() + "/" + attrName, e);
        }
    }

    @Override
    public boolean checkAttribute(String attrName) {
        try {
            getTPropertyQuery(attrName);
            return true;
        } catch (ClientException e) {
            return false;
        }
    }

    private int getTPropertySize(TPropertyQuery meta) {
        int result = meta.prpSize;
        return result;
    }

    private short getTPropertyFormat(TPropertyQuery meta) {
        short result = meta.prpFormat;
        return result;
    }

    @Override
    public Class<?> getAttributeClass(String attrName) throws ClientException {
        TPropertyQuery meta = getTPropertyQuery(attrName);
        int size = getTPropertySize(meta);
        short dataFormat = getTPropertyFormat(meta);
        TDataType dataType = new TDataType(size, dataFormat);
        //TODO it appears that TINE always returns array of values
        //TODO and the only interesting value is always the first one in this array
        //if (size > 1) {
//            return dataType.getDataObject().getClass();
        //      } else {
        return dataType.getDataObject().getClass().getComponentType();
        //    }
    }

    @Override
    public boolean isArrayAttribute(String attrName) throws ClientException {
        //see comment in getAttributeClass
        return false;
    }

    @Override
    public void unsubscribeEvent(String attrName) throws ClientException {
        Future<TLink> futureLink = tlinks.remove(attrName);
        try {
            final TLink link = futureLink.get();
            int rc = link.close();
            if (rc < 0) {
                throw new ClientException(link.getLastError(), null);
            }
        } catch (Exception e) {
            throw new ClientException("Failed subscribe to " + getDeviceName() + "/" + attrName, e);
        }
    }

    private TPropertyQuery getTPropertyQuery(String attrName) throws ClientException {
        TPropertyQuery[] result = TQuery.getPropertyInformation(context, serverName, deviceName, attrName);
        if (result == null) {
            throw new ClientException("Cannot read meta info for " + getDeviceName() + "/" + attrName, new NullPointerException());
        }
        return result[0];
    }

    @Override
    public void printAttributeInfo(String name, Logger logger) {
        //TODO
    }
}
TOP

Related Classes of wpn.hdri.ss.client.tine.TineClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.