/**
 * @author    STF 424_ITS_Test_Platform
 * @version    $id$
 */
package org.etsi.its.tool.elvior;

import java.util.logging.Logger;

import org.elvior.ttcn.tritci.TciProvider;
import org.elvior.ttcn.tritci.TriFactory;
import org.elvior.ttcn.tritci.TriProvider;
import org.elvior.ttcn.tritci.TriTciChannel;
import org.elvior.ttcn.tritci.ChannelEventHandler;
import org.etsi.adapter.TERFactory;
import org.etsi.codec.ITciCDWrapper;
import org.etsi.codec.TciCDWrapperFactory;
import org.etsi.common.ByteHelper;
import org.etsi.its.extfunc.IItsExternalFunctionsProvider;
import org.etsi.its.extfunc.ItsExternalFunctionsProvider;
import org.etsi.tool.elvior.TciCDWrapper;
import org.etsi.tool.elvior.TeRequiredImpl;
import org.etsi.ttcn.tci.FloatValue;
import org.etsi.ttcn.tci.IntegerValue;
import org.etsi.ttcn.tci.OctetstringValue;
import org.etsi.ttcn.tci.TciParameterList;
import org.etsi.ttcn.tci.TciValueList;
import org.etsi.ttcn.tci.Value;
import org.etsi.ttcn.tri.*;
import org.etsi.ttcn.xtri.xTriCommunicationSA;

public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xTriCommunicationSA, TriPlatformPA, ChannelEventHandler {
    /**
     * This is the main PluginAdapter class
     */
    private org.etsi.its.adapter.TestAdapter _itsTestAdapter;
    
    /**
     * Logger instance
     */
    private final static Logger _logger = Logger.getLogger("org.etsi.its");
    
    private TriStatus m_triOK;
    
    private TriStatus m_triKO;
    
    private IItsExternalFunctionsProvider _extfuncsImpl;

    public PluginAdapter() {
        _logger.entering("PluginAdapter", "Constructor");
        
        // Register this object as the instance implementing the TRI-SA interface
        TriProvider.getInstance().setTriCommunicationSA(this);
        // Register this object as the instance implementing the TRI-PA interface
        TriProvider.getInstance().setTriPlatformPA(this);
        TriTciChannel channel = TriTciChannel.getInstance();
        // Set application name that will be displayed in the TestCast log
        channel.setApplicationName("ItsPlatform");
        // Register this object as the receiver of events generated by TestCast framework
        channel.setEventHandler(this);
        TriFactory factory = TriProvider.getInstance().getTriFactory(); 
        m_triOK = factory.createOkStatus();
        m_triKO = factory.createErrorStatus();
        TERFactory.setImpl(new TeRequiredImpl(this));
        // External functions
        TciCDWrapperFactory.getInstance().setImpl(new TciCDWrapper());
        _extfuncsImpl = new ItsExternalFunctionsProvider();
    }
    
    public void run() {
        _logger.entering("PluginAdapter", "run");
        
        // Attempt to connect to TestCast
        if (TriTciChannel.getInstance().open()) {
            _itsTestAdapter = new org.etsi.its.adapter.TestAdapter();
            try {
                synchronized(this) {
                    wait();
                }
            } catch (InterruptedException e) {
            }
        }
        _logger.exiting("PluginAdapter", "run");
    }
    
    public TriStatus triCall(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress sutAddress, TriSignatureId signatureId,
            TriParameterList parameterList) {
        return _itsTestAdapter.triCall(componentId, tsiPortId, sutAddress, signatureId, parameterList);
    }

    public TriStatus triCallBC(TriComponentId componentId, TriPortId tsiPortId,
            TriSignatureId signatureId, TriParameterList parameterList) {
        return _itsTestAdapter.triCallBC(componentId, tsiPortId, signatureId, parameterList);
    }

    public TriStatus triCallMC(TriComponentId componentId, TriPortId tsiPortId,
            TriAddressList sutAddresses, TriSignatureId signatureId,
            TriParameterList parameterList) {
        return _itsTestAdapter.triCallMC(componentId, tsiPortId, sutAddresses, signatureId, parameterList);
    }

    public TriStatus triEndTestCase() {
        return _itsTestAdapter.triEndTestCase();
    }

    public TriStatus triExecuteTestCase(TriTestCaseId testCaseId, TriPortIdList tsiPorts) {
//        System.out.println("triExecuteTestCase");
        // Disable XTRI functionality for all ports, so that existing SA implementation can be reused
        for(int i = 0; i < tsiPorts.size(); i++) {
            TriTciChannel.getInstance().enableXTriForPort(tsiPorts.get(i), false);
        }
        return _itsTestAdapter.triExecuteTestcase(testCaseId, tsiPorts);
    }

    public TriStatus triMap(TriPortId compPortId, TriPortId tsiPortId) {
//        System.out.println("triMap: " + compPortId.getComponent().getComponentName() + " - " + tsiPortId.getPortName());
        return _itsTestAdapter.triMap(compPortId, tsiPortId);
    }

    public TriStatus triRaise(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress sutAddress, TriSignatureId signatureId, TriException exception) {
//        System.out.println("triRaise");
        return _itsTestAdapter.triRaise(componentId, tsiPortId, sutAddress, signatureId, exception);
    }

    public TriStatus triRaiseBC(TriComponentId componentId,
            TriPortId tsiPortId, TriSignatureId signatureId, TriException exc) {
//        System.out.println("triRaiseBC");
        return _itsTestAdapter.triRaiseBC(componentId, tsiPortId, signatureId, exc);
    }

    public TriStatus triRaiseMC(TriComponentId componentId,
            TriPortId tsiPortId, TriAddressList sutAddresses,
            TriSignatureId signatureId, TriException exc) {
//        System.out.println("triRaiseMC");
        return _itsTestAdapter.triRaiseMC(componentId, tsiPortId, sutAddresses, signatureId, exc);
    }

    public TriStatus triReply(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress sutAddress, TriSignatureId signatureId,
            TriParameterList parameterList, TriParameter returnValue) {
//        System.out.println("triReply");
        return _itsTestAdapter.triReply(componentId, tsiPortId, sutAddress, signatureId, parameterList, returnValue);
    }

    public TriStatus triReplyBC(TriComponentId componentId,
            TriPortId tsiPortId, TriSignatureId signatureId,
            TriParameterList parameterList, TriParameter returnValue) {
//        System.out.println("triReplyBC");
        return _itsTestAdapter.triReplyBC(componentId, tsiPortId, signatureId, parameterList, returnValue);
    }

    public TriStatus triReplyMC(TriComponentId componentId,
            TriPortId tsiPortId, TriAddressList sutAddresses,
            TriSignatureId signatureId, TriParameterList parameterList,
            TriParameter returnValue) {
//        System.out.println("triReplyMC");
        return _itsTestAdapter.triReplyMC(componentId, tsiPortId, sutAddresses, signatureId, parameterList, returnValue);
    }

    public TriStatus triSAReset() {
//        System.out.println("triSAReset");
        return _itsTestAdapter.triSAReset();
    }

    public TriStatus triSend(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress address, TriMessage sendMessage) {
//        System.out.println("triSend");
        return _itsTestAdapter.triSend(componentId, tsiPortId, address, sendMessage);
    }

    public TriStatus triSendBC(TriComponentId componentId, TriPortId tsiPortId,
            TriMessage sendMessage) {
//        System.out.println("triSendBC");
        return _itsTestAdapter.triSendBC(componentId, tsiPortId, sendMessage);
    }

    public TriStatus triSendMC(TriComponentId componentId, TriPortId tsiPortId,
            TriAddressList addresses, TriMessage sendMessage) {
//        System.out.println("triSendMC");
        return _itsTestAdapter.triSendMC(componentId, tsiPortId, addresses, sendMessage);
    }

    public TriStatus triSutActionInformal(String description) {
//        System.out.println("triSutActionInformal");
        return _itsTestAdapter.triSutActionInformal(description);
    }

    public TriStatus triUnmap(TriPortId compPortId, TriPortId tsiPortId) {
//        System.out.println("triUnmap");
        return _itsTestAdapter.triUnmap(compPortId, tsiPortId);
    }

    public TriStatus triExternalFunction(TriFunctionId functionId, TriParameterList parameterList, TriParameter returnValue) {
        _logger.entering("PluginAdapter", "triExternalFunction", functionId.getFunctionName() + " - " + parameterList + " - " + returnValue.getParameterName() + " - " + returnValue.getParameterPassingMode());
        
        TriStatus result = m_triOK;
        if (
                functionId.getFunctionName().endsWith("fx_computeIPv6CheckSum") && 
                (parameterList.size() == 5)
        ) { 
            // Calculate ICMPv6 checksum on pseudo header according RFC 4443 - Clause 2.3
            exec_computeIPv6CheckSum(parameterList, returnValue);
        } else if (
                functionId.getFunctionName().endsWith("fx_computeDistance") && 
                (parameterList.size() == 4)
        ) { 
            // Compute a distance between two points 
            exec_computeDistance(parameterList, returnValue);
        } else if (
                functionId.getFunctionName().endsWith("fx_computePositionUsingDistance") && 
                (parameterList.size() == 6)
        ) { 
            // Compute a position using a reference position, a distance and an orientation 
            exec_computePositionUsingDistance(parameterList, returnValue);
        } else if (functionId.getFunctionName().endsWith("fx_computeGnTimestamp")) { 
            // Compute timestamp based on current time 
            exec_computeGnTimestamp(returnValue);
        } else if (functionId.getFunctionName().endsWith("fx_getCurrentTime")) { 
            // Gets the current time 
            exec_getCurrentTime(returnValue);
        } else {
            result = m_triKO;
        }
        _logger.exiting("PluginAdapter", "triExternalFunction", String.format("%d", result.getStatus())); 
        return result;
    }

    public void onConnectionClosed() {
        _logger.entering("PluginAdapter", "onConnectionClosed");
        synchronized(this) { 
            notify();
        }
    }

    public void onConnectionEstablished() {
        _logger.entering("PluginAdapter", "onConnectionEstablished");
    }

    public void onError(String error) {
        _logger.entering("PluginAdapter", "onError", error);
    }

    @Override
    public TriStatus triPAReset() {
//        System.out.println("triPAReset");
        return m_triOK;
    }

    @Override
    public TriStatus triReadTimer(TriTimerId timerId, TriTimerDuration elapsedTime) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStartTimer(TriTimerId timerId, TriTimerDuration timerDuration) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStopTimer(TriTimerId timerId) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triTimerRunning(TriTimerId timerId, TriBoolean running) {
        throw new RuntimeException();
    }

    @Override
    public void triEnqueueCall(TriPortId tsiPortId, TriAddress SUTaddress, TriComponentId componentId, TriSignatureId signatureId, TriParameterList parameterList) {
        throw new RuntimeException();
    }

    @Override
    public void triEnqueueException(TriPortId tsiPortId, TriAddress sutAddress, TriComponentId componentId, TriSignatureId signatureId,
            TriException exception) {
        throw new RuntimeException();
    }

    @Override
    public void triEnqueueMsg(TriPortId tsiPortId, TriAddress sutAddress, TriComponentId componentId, TriMessage receivedMessage) {
        TriProvider.getInstance().getTriCommunicationTE().triEnqueueMsg(
            tsiPortId, 
            null, 
            componentId, 
            receivedMessage);
    }

    @Override
    public void triEnqueueReply(TriPortId tsiPortId, TriAddress address, TriComponentId componentId, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triMapParam(TriPortId arg0, TriPortId arg1, TriParameterList arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triUnmapParam(TriPortId arg0, TriPortId arg1, TriParameterList arg2) {
        throw new RuntimeException();
    }
    
    @Override
    public TriStatus xtriCall(TriComponentId arg0, TriPortId arg1, Value arg2, TriSignatureId arg3, TciParameterList arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriCallBC(TriComponentId arg0, TriPortId arg1, TriSignatureId arg2, TciParameterList arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriCallMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, TriSignatureId arg3, TciParameterList arg4) {
        throw new RuntimeException();
    }

    @Override
    public Value xtriConvert(Object arg0, org.etsi.ttcn.tci.Type arg1) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriMapParam(TriPortId arg0, TriPortId arg1, TciParameterList arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriRaise(TriComponentId arg0, TriPortId arg1, Value arg2, TriSignatureId arg3, Value arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriRaiseBC(TriComponentId arg0, TriPortId arg1, TriSignatureId arg2, Value arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriRaiseMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, TriSignatureId arg3, Value arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriReply(TriComponentId arg0, TriPortId arg1, Value arg2, TriSignatureId arg3, TciParameterList arg4, Value arg5) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriReplyBC(TriComponentId arg0, TriPortId arg1, TriSignatureId arg2, TciParameterList arg3, Value arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriReplyMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, TriSignatureId arg3, TciParameterList arg4, Value arg5) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriSend(TriComponentId compPortId, TriPortId tsiPortId, Value arg2, Value arg3) {
    	throw new RuntimeException();
    }

    @Override
    public TriStatus xtriSendBC(TriComponentId arg0, TriPortId arg1, Value arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriSendMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, Value arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriUnmapParam(TriPortId arg0, TriPortId arg1, TciParameterList arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStaticMap(TriPortId arg0, TriPortId arg1) {
    	throw new RuntimeException();
    }
    
    private void exec_computeIPv6CheckSum(TriParameterList parameterList, TriParameter returnValue) {
        _logger.entering("PluginAdapter", "exec_computeIPv6CheckSum");
        
        // Source address (128 bits)
        byte[] value = parameterList.get(0).getEncodedParameter();
        ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance();
        OctetstringValue sourceAddress = (OctetstringValue)wrapper.getOctetstring();
        sourceAddress.setLength(value.length);
        for (int i = 0; i < value.length; i++) {
            sourceAddress.setOctet(i, value[i]);
        }
        // Destination address (128 bits)
        _logger.info(String.format("Setting parameter %s", parameterList.get(1).getParameterName())); 
        value = parameterList.get(1).getEncodedParameter();
        OctetstringValue destinationAddress = (OctetstringValue)TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance();
        destinationAddress.setLength(value.length);
        for (int i = 0; i < value.length; i++) {
            destinationAddress.setOctet(i, value[i]);
        }
        // Upper-Layer Packet Length (32 bits)
        _logger.info(String.format("Setting parameter %s", parameterList.get(2).getParameterName())); 
        value = parameterList.get(2).getEncodedParameter();
        IntegerValue payloadLength = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        payloadLength.setInteger(ByteHelper.byteArrayToInt(value));
        // Upper-Layer payload
        _logger.info(String.format("Setting parameter %s", parameterList.get(3).getParameterName())); 
        value = parameterList.get(3).getEncodedParameter();
        OctetstringValue payload = (OctetstringValue)TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance();
        payload.setLength(value.length);
        for (int i = 0; i < value.length; i++) {
            payload.setOctet(i, value[i]);
        }
        // Next header value (e.g. 0x3a for ICMPv6) (8bits)
        _logger.info(String.format("Setting parameter %s", parameterList.get(4).getParameterName())); 
        value = parameterList.get(4).getEncodedParameter();
        IntegerValue nextHdr = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        nextHdr.setInteger(ByteHelper.byteArrayToInt(value));
        // Execute the function
        OctetstringValue checksum = _extfuncsImpl.fx_computeIPv6CheckSum(
            sourceAddress, 
            destinationAddress, 
            payloadLength, 
            payload, 
            nextHdr 
        );
        _logger.info(String.format("fx_computeIPv6CheckSum returns 0x%02x%02x", checksum.getOctet(0), checksum.getOctet(1))); 
        value = new byte[checksum.getLength()];
        for (int i = 0; i < value.length; i++) {
            value[i] = (byte)checksum.getOctet(i);
        }
        returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT);
        returnValue.setNumberOfBits(value.length * Byte.SIZE);
        returnValue.setEncodedParameter(value);
        
        _logger.exiting("PluginAdapter", "exec_computeIPv6CheckSum", String.format("Return value: %d", returnValue.getNumberOfBits())); 
    } // End of method exec_computeIPv6CheckSum
    
    private void exec_computeDistance(TriParameterList parameterList, TriParameter returnValue) {
        _logger.entering("PluginAdapter", "exec_computeDistance");
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(0).getParameterName())); 
        byte[] value = parameterList.get(0).getEncodedParameter();
        IntegerValue latitudeA = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        latitudeA.setInteger(ByteHelper.byteArrayToInt(value));
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(1).getParameterName())); 
        value = parameterList.get(1).getEncodedParameter();
        IntegerValue longitudeA = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        longitudeA.setInteger(ByteHelper.byteArrayToInt(value));
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(2).getParameterName())); 
        value = parameterList.get(2).getEncodedParameter();
        IntegerValue latitudeB = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        latitudeB.setInteger(ByteHelper.byteArrayToInt(value));
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(3).getParameterName())); 
        value = parameterList.get(3).getEncodedParameter();
        IntegerValue longitudeB = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        longitudeB.setInteger(ByteHelper.byteArrayToInt(value));
        
        // Execute the function
        FloatValue distance = _extfuncsImpl.fx_computeDistance(
            latitudeA, 
            longitudeA, 
            latitudeB, 
            longitudeB 
        );
        _logger.info(String.format("fx_computeDistance returns %f", distance.getFloat())); 
        returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT);
        returnValue.setNumberOfBits(Float.SIZE);
        int convert = Float.floatToIntBits(distance.getFloat());
        returnValue.setEncodedParameter(ByteHelper.intToByteArray(convert, Integer.SIZE / Byte.SIZE));
        
        _logger.exiting("PluginAdapter", "exec_computeDistance", String.format("Return value: %d", returnValue.getNumberOfBits())); 
    } // End of method exec_computeDistance
    
    private void exec_computePositionUsingDistance(TriParameterList parameterList, TriParameter returnValue) {
        _logger.entering("PluginAdapter", "exec_computePositionUsingDistance");
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(0).getParameterName())); 
        byte[] value = parameterList.get(0).getEncodedParameter();
        IntegerValue refLatitude = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        refLatitude.setInteger(ByteHelper.byteArrayToInt(value));
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(1).getParameterName())); 
        value = parameterList.get(1).getEncodedParameter();
        IntegerValue refLongitude = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        refLongitude.setInteger(ByteHelper.byteArrayToInt(value));
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(2).getParameterName())); 
        value = parameterList.get(2).getEncodedParameter();
        IntegerValue distance = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        distance.setInteger(ByteHelper.byteArrayToInt(value));
        
        _logger.info(String.format("Setting parameter %s", parameterList.get(3).getParameterName())); 
        value = parameterList.get(3).getEncodedParameter();
        IntegerValue orientation = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        orientation.setInteger(ByteHelper.byteArrayToInt(value));
        
        IntegerValue latitude = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        IntegerValue longitude = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance();
        _extfuncsImpl.fx_computePositionUsingDistance(refLatitude, refLongitude, distance, orientation, latitude, longitude);
        
        TriParameter param = parameterList.get(4);
        param.setParameterPassingMode(TriParameterPassingMode.TRI_OUT);
        param.setNumberOfBits(Integer.SIZE);
        param.setEncodedParameter(ByteHelper.intToByteArray(latitude.getInteger(), Integer.SIZE / Byte.SIZE));
        
        param = parameterList.get(5);
        param.setParameterPassingMode(TriParameterPassingMode.TRI_OUT);
        param.setNumberOfBits(Integer.SIZE);
        param.setEncodedParameter(ByteHelper.intToByteArray(longitude.getInteger(), Integer.SIZE / Byte.SIZE));
        
        _logger.exiting("PluginAdapter", "exec_computePositionUsingDistance"); 
    } // End of method exec_computePositionUsingDistance
    
    private void exec_computeGnTimestamp(TriParameter returnValue) {
        _logger.entering("PluginAdapter", "exec_computeGnTimestamp");
        
        // Execute the function
        IntegerValue timestamp = _extfuncsImpl.fx_computeGnTimestamp();
        _logger.info(String.format("exec_computeGnTimestamp returns %d", timestamp.getInteger())); 
        returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT);
        returnValue.setNumberOfBits(Integer.SIZE);
        returnValue.setEncodedParameter(ByteHelper.intToByteArray(timestamp.getInteger(), Integer.SIZE / Byte.SIZE));
        
        _logger.exiting("PluginAdapter", "exec_computeGnTimestamp", String.format("Return value: %d", returnValue.getNumberOfBits())); 
    } // End of method exec_computeGnTimestamp
    
    private void exec_getCurrentTime(TriParameter returnValue) {
        _logger.entering("PluginAdapter", "exec_getCurrentTime");
        
        // Execute the function
        IntegerValue time = _extfuncsImpl.fx_getCurrentTime();
        // FIXME To be removed and integer size lenght bug fixed
        if (time.getInteger() < 0) time.setInteger(-1 * time.getInteger());
        _logger.info(String.format("exec_getCurrentTime returns %d", time.getInteger())); 
        returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT);
        returnValue.setNumberOfBits(Integer.SIZE);
        returnValue.setEncodedParameter(ByteHelper.intToByteArray(time.getInteger(), Integer.SIZE / Byte.SIZE));
        
        _logger.exiting("PluginAdapter", "exec_getCurrentTime", String.format("Return value: %d", returnValue.getNumberOfBits())); 
    } // End of method exec_getCurrentTime
    
} // End of class PluginAdapter
