/**
* 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 gsn_devs
* @author Mehdi Riahi
* @author Ali Salehi
*/
package org.openiot.gsn.wrappers;
import org.openiot.gsn.beans.AddressBean;
import org.openiot.gsn.beans.DataField;
import org.openiot.gsn.beans.StreamElement;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import javax.swing.Timer;
import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.buffer.SynchronizedBuffer;
import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.log4j.Logger;
/**
* This wrapper presents the system current clock.
*/
public class SystemTime extends AbstractWrapper implements ActionListener {
public static final String CLOCK_PERIOD_KEY = "clock-period";
public static final String MAX_DELAY_KEY = "max-delay";
private static final Serializable [ ] EMPTY_DATA_PART = new Serializable [ ] {};
private static final Byte [ ] EMPTY_FIELD_TYPES = new Byte [ ] {};
private static final int DEFAULT_CLOCK_PERIODS = 1 * 1000;
private static final int DEFAULT_MAX_DELAY = -1 ;//5 seconds;
private String [ ] EMPTY_FIELD_LIST = new String [ ] {};
private DataField [] collection = new DataField[] {};
private static int threadCounter = 0;
private transient Logger logger = Logger.getLogger( this.getClass() );
private Timer timer;
private boolean delayPostingElements = false;
private int maximumDelay = DEFAULT_MAX_DELAY;
private Buffer streamElementBuffer;
private Object objectLock = new Object();
public boolean initialize ( ) {
setName( "LocalTimeWrapper-Thread" + ( ++threadCounter ) );
AddressBean addressBean =getActiveAddressBean ( );
// TODO: negative values?
timer = new Timer( addressBean.getPredicateValueAsInt( CLOCK_PERIOD_KEY ,DEFAULT_CLOCK_PERIODS) , this );
maximumDelay = addressBean.getPredicateValueAsInt(MAX_DELAY_KEY, DEFAULT_MAX_DELAY);
if(maximumDelay > 0){
streamElementBuffer = SynchronizedBuffer.decorate(new UnboundedFifoBuffer());
delayPostingElements = true;
if(timer.getDelay() < maximumDelay)
logger.warn("Maximum delay is greater than element production interval. Running for a long time may lead to an OutOfMemoryException" );
}
return true;
}
public void run ( ) {
timer.start( );
if(delayPostingElements){
if(logger.isDebugEnabled())
logger.warn("Starting <" + getWrapperName() + "> with delayed elements.");
while(isActive()){
synchronized(objectLock){
while(streamElementBuffer.isEmpty()){
try {
objectLock.wait();
} catch (InterruptedException e) {
logger.error( e.getMessage( ) , e );
}
}
}
try{
int nextInt = RandomUtils.nextInt(maximumDelay);
Thread.sleep(nextInt);
// System.out.println("next delay : " + nextInt + " --> buffer size : " + streamElementBuffer.size());
}catch(InterruptedException e){
logger.error( e.getMessage( ) , e );
}
if(!streamElementBuffer.isEmpty()){
StreamElement nextStreamElement = (StreamElement)streamElementBuffer.remove();
postStreamElement(nextStreamElement);
}
}
}
}
public DataField [] getOutputFormat ( ) {
return collection;
}
public void actionPerformed ( ActionEvent actionEvent ) {
StreamElement streamElement = new StreamElement( EMPTY_FIELD_LIST , EMPTY_FIELD_TYPES , EMPTY_DATA_PART , actionEvent.getWhen( ) );
if(delayPostingElements){
streamElementBuffer.add(streamElement);
synchronized(objectLock){
objectLock.notifyAll();
}
}
else
postStreamElement( streamElement );
}
public void dispose ( ) {
timer.stop( );
threadCounter--;
}
public String getWrapperName() {
return "System Time";
}
public int getTimerClockPeriod() {
return timer.getDelay();
}
}