/** * Global Sensor Networks (GSN) Source Code * Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL) * * This file is part of GSN. * * GSN 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 3 of the License, or * (at your option) any later version. * * GSN 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 GSN. If not, see <http://www.gnu.org/licenses/>. * * File: gsn-tiny/src/tinygsn/beans/Queue.java * * @author Do Ngoc Hoan */ package tinygsn.beans; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import tinygsn.model.wrappers.AbstractWrapper; public class StreamSource implements Serializable{ private static final long serialVersionUID = 7791682194678539871L; public static final String[] AGGREGATOR = { "Average", "Max", "Min", "Window" }; //properties private int id = 0; private int step = 1; private int windowSize = 1; private boolean timeBased = false; private int aggregator = 0; //references private transient AbstractWrapper wrapper; private transient InputStream inputStream; //internals private Date lastTimeAdded; private ArrayList<StreamElement> values = new ArrayList<StreamElement>(); public StreamSource(){} public StreamSource(int windowSize, int step, boolean timeBased, int aggregator){ setStep(step); setWindowSize(windowSize); setTimeBased(timeBased); setAggregator(aggregator); } /** * Assume step <= windowSize * We keep the Queue's size is double of window size */ public boolean isFull(){ if (isTimeBased()){ return values.get(values.size()-1).getTimeStamp() - values.get(0).getTimeStamp() >= windowSize * 1000; } else{ return values.size() >= windowSize; } } public boolean isEmpty(){ return values.size() == 0; } public synchronized void add(StreamElement element){ values.add(element); lastTimeAdded = new Date(); if (this.isFull()){ notifyInputStream(values); moveToNextStep(); } } private synchronized void moveToNextStep(){ if (isTimeBased()){ long ref = values.get(0).getTimeStamp() + step*1000; while (!isEmpty() && values.get(0).getTimeStamp() < ref){ values.remove(0); } }else{ for (int i = 0; i < step; i++){ values.remove(0); } } } public void notifyInputStream(ArrayList<StreamElement> data) { // Use Aggregator to process data s StreamElement se = data.get(0); if (inputStream == null) { return; } switch (aggregator) { case 0: // Average for (int i = 1; i < data.size(); i++) { for (int j = 0; j < se.getFieldNames().length; j++) { StreamElement se_i = data.get(i); se.setData(j, getDouble(se.getData()[j]) + getDouble(se_i.getData()[j])); } } for (int j = 0; j < se.getFieldNames().length; j++) { se.setData(j, getDouble(se.getData()[j]) / data.size()); } case 1: // Max for (int i = 1; i < data.size(); i++) { if (getDouble(data.get(i).getData()[0]) > getDouble(se.getData()[0])) { se = data.get(i); } } case 2: // Min for (int i = 1; i < data.size(); i++) { if (getDouble(data.get(i).getData()[0]) < getDouble(se.getData()[0])) { se = data.get(i); } } case 3: // No aggregation inputStream.getVirtualSensor().dataAvailable(getWrapper().getWrapperName(),data); return; } inputStream.getVirtualSensor().dataAvailable(getWrapper().getWrapperName(),se); } private double getDouble(Serializable s){ double d = ((Number) s).doubleValue() ; return d; } /** * Get the first windowSize elements * @return */ public ArrayList<StreamElement> getWindowValues(){ ArrayList<StreamElement> window = new ArrayList<StreamElement>(); if (isTimeBased()){ int i = 0; long ref = values.get(0).getTimeStamp() + windowSize * 1000; while (i < values.size() && values.get(i).getTimeStamp() < ref){ window.add(values.get(i)); } }else{ int w = windowSize; if (w < values.size()) w = values.size(); for (int i = 0; i < w; i++){ window.add(values.get(i)); } } return window; } public void dispose(){ wrapper.unregisterListener(this); } public ArrayList<StreamElement> getAllValues(){ return values; } public String toString(){ String s = ""; for (StreamElement i: getAllValues()){ s += i.toString() + " "; } return s; } public int getStep() { return step; } public void setStep(int step) { this.step = step; } public int getWindowSize() { return windowSize; } public void setWindowSize(int windowSize) { this.windowSize = windowSize; } public Date getLastTimeAdded() { return lastTimeAdded; } public boolean isTimeBased() { return timeBased; } public void setTimeBased(boolean timeBased) { this.timeBased = timeBased; } public int getAggregator() { return aggregator; } public void setAggregator(int aggregator) { this.aggregator = aggregator; } public AbstractWrapper getWrapper() { return wrapper; } public void setWrapper(AbstractWrapper wrapper) { this.wrapper = wrapper; wrapper.registerListener(this); } public InputStream getInputStream() { return inputStream; } public void setInputStream(InputStream inputStream) { this.inputStream = inputStream; } public int getId() { return id; } public void setId(int id) { this.id = id; } }