/**
* Copyright (c) 2011-2014, OpenIoT
*
* This file is part of OpenIoT.
*
* OpenIoT is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* OpenIoT 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenIoT. If not, see <http://www.gnu.org/licenses/>.
*
* Contact: OpenIoT mailto: info@openiot.eu
* @author Jerome Rousselot
* @author Ali Salehi
*/
package org.openiot.gsn.utils.protocols;
import org.openiot.gsn.wrappers.AbstractWrapper;
import java.util.Collection;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.naming.OperationNotSupportedException;
import org.apache.log4j.Logger;
/**
* This class implements a generic finite state machine
* for HostControllerInterface Protocols.
* For simple protocols that never wait for an answer
* from the controller, simply create a ProtocolManager
* instance with the appropriate Protocol object and
* then call the method sendQuery.
*
* Warning: other methods of this class may be refactored soon,
* and more states could be added.
*
* @see AbstractHCIProtocol
*/
public class ProtocolManager {
private static final transient Logger logger = Logger.getLogger( ProtocolManager.class );
private AbstractHCIProtocol protocol;
private ProtocolStates currentState;
private AbstractHCIQuery lastExecutedQuery = null;
private Vector < Object > lastParams;
private AbstractWrapper outputWrapper;
private Timer timer;
private TimerTask answerTimeout = new TimerTask() {
public synchronized void run ( ) {
lastExecutedQuery = null;
currentState = ProtocolStates.READY;
}
};
public enum ProtocolStates {
READY, WAITING
}
public ProtocolManager(AbstractHCIProtocol protocol, AbstractWrapper outputWrapper) {
this.protocol = protocol;
this.outputWrapper = outputWrapper;
currentState = ProtocolStates.READY;
}
public synchronized ProtocolStates getCurrentState() {
return currentState;
}
/*
* This method tries to execute a query named queryName with parameters params
* on the wrapper wrapper.
* If successful, it returns the raw command that has been sent.
*/
public synchronized byte[] sendQuery(String queryName, Vector<Object> params) {
byte[] answer = null;
if(currentState == ProtocolStates.READY) {
AbstractHCIQuery query = protocol.getQuery( queryName );
if(query != null) {
if(logger.isDebugEnabled())
logger.debug( "Retrieved query " + queryName + ", trying to build raw query.");
byte[] queryBytes = query.buildRawQuery( params );
if(queryBytes != null) {
try {
if(logger.isDebugEnabled())
logger.debug("Built query, it looks like: " + new String(queryBytes));
outputWrapper.sendToWrapper(null,null,new Object[] {queryBytes});
lastExecutedQuery = query;
lastParams = params;
answer = queryBytes;
if(logger.isDebugEnabled())
logger.debug("Query succesfully sent!");
if(query.needsAnswer( params )) {
if(logger.isDebugEnabled())
logger.debug("Now entering wait mode for answer.");
timer = new Timer();
currentState = ProtocolStates.WAITING;
timer.schedule( answerTimeout , new Date());
}
} catch( OperationNotSupportedException e ) {
if(logger.isDebugEnabled())
logger.debug("Query could not be sent ! See error message.");
logger.error( e.getMessage( ) , e );
currentState = ProtocolStates.READY;
}
}
} else {
logger.warn("Query " + queryName + " found but no bytes produced to send to device. Implementation may be missing.");
}
}
return answer;
}
/*
* This tries to match incoming data to the pattern
* expected by the query. If the pattern describes
* several groups then all the different String
* matching these groups are returned.
*/
public synchronized Object[] getAnswer(byte[] rawData) {
Object[] answer = null;
if(currentState == ProtocolStates.WAITING) {
answer = lastExecutedQuery.getAnswers(rawData);
}
return answer;
}
/**
* @return
*/
public String getProtocolName() {
if(protocol != null)
return protocol.getName();
return null;
}
/**
* @param string
* @return
*/
public AbstractHCIQuery getQuery(String string) {
if(protocol != null)
return protocol.getQuery(string);
return null;
}
/**
* @return
*/
public Collection<AbstractHCIQuery> getQueries() {
if(protocol != null)
return protocol.getQueries();
return null;
}
}