/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program 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;
* either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2004, by :
* Corporate:
* EADS Astrium SAS
* EADS CRC
* Individual:
* Claude Cazenave
*
* $Id: StreamingMSDataSource.java,v 1.27 2008/09/08 10:09:10 ogor Exp $
*
* Changes
* -------
* 11 jan. 2005 : Initial public release (CC);
*
*/
package simtools.data.async;
import java.io.IOException;
import java.text.ChoiceFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import simtools.data.DataException;
import simtools.data.DataInfo;
import simtools.data.NoSuchIndex;
import simtools.data.UnsupportedOperation;
import simtools.data.async.TimeStampedDataSourceCollection.InvalidFormatException;
/**
* A streaming data source with optional label, raw and status values in
* addition to the time/value pair of StreamingTSDataSource
*
* @author Claude Cazenave
*/
public class StreamingMSDataSource extends StreamingTSDataSource {
protected StreamingLabelSource _label;
protected StreamingIntegerSource _raw;
protected StreamingIntegerSource _status;
/**
*
* Create a streaming data source with optional time2, label, raw and status values
*
* @param label
* The data source name
* @param id
* The data source id
* @param c
* Its collection parent
* @param minSize
* The minimum number of values to keep
* @param maxSize
* The maximum number of values to keep
* @param minDuration
* The minimun duration of value to keep
* @param auxiliaryMinSize
* The minimum number of values to keep for all auxiliary data
* @param auxiliaryMinDuration
* The minimun duration of value to keep for all auxiliary data
* @param withLabel
* If true label values ar also stored (see add method)
* @param withRawValue
* If true raw values are also stored
* @param withStatus
* If true status values are also stored
* @param withTime2
* If true time2 values are also stored
*
* @throws IOException
* @throws InvalidFormatException
*/
public StreamingMSDataSource(
String label,
String id,
StreamingTSDataSourceCollection c,
int minSize,
int maxSize,
double minDuration,
int auxiliaryMinSize,
double auxiliaryMinDuration,
boolean withLabel,
boolean withRawValue,
boolean withStatus,
boolean withTime2
) throws IOException, InvalidFormatException {
super(label, id, c, minSize, maxSize, minDuration, withTime2);
// auxiliary buffer size must be equal or shorter than main data source
auxiliaryMinDuration = (auxiliaryMinDuration <= minDuration) ? auxiliaryMinDuration : minDuration;
auxiliaryMinSize = (auxiliaryMinSize <= minSize) ? auxiliaryMinSize : minSize;
if (withLabel) {
_label = new StreamingLabelSource("label", "label", auxiliaryMinSize, maxSize, auxiliaryMinDuration);
}
if (withRawValue) {
_raw = new StreamingIntegerSource("raw", "raw", auxiliaryMinSize, maxSize, auxiliaryMinDuration);
}
if (withStatus) {
_status = new StreamingIntegerSource("status", "status", auxiliaryMinSize, maxSize, auxiliaryMinDuration);
}
_auxiliaries = new AuxiliaryCollection();
}
/**
* Create a streaming data source with optional time2, label, raw and status values
* @param id
* The data source id
* @param c
* Its collection parent
* @param minSize
* The minimum number of values to keep
* @param maxSize
* The maximum number of values to keep
* @param minDuration
* The minimun duration of value to keep
* @param auxiliaryMinSize
* The minimum number of values to keep for all auxiliary data
* @param auxiliaryMinDuration
* The minimun duration of value to keep for all auxiliary data
* @param withLabel
* If true label values ar also stored (see add method)
* @param withRawValue
* If true raw values are also stored
* @param withStatus
* If true status values are also stored
* @param withTime2
* If true time2 values are also stored
*
* @throws IOException
* @throws InvalidFormatException
*/
public StreamingMSDataSource(String id, StreamingTSDataSourceCollection c, int minSize, int maxSize, double minDuration,
int auxiliaryMinSize, double auxiliaryMinDuration, boolean withLabel, boolean withRawValue,
boolean withStatus, boolean withTime2) throws IOException, InvalidFormatException {
this(id, id, c, minSize, maxSize, minDuration, auxiliaryMinSize, auxiliaryMinDuration, withLabel, withRawValue,
withStatus, withTime2);
}
/**
* Create a streaming data source with optional label, raw and status values
* @param id
* The data source id
* @param c
* Its collection parent
* @param minSize
* The minimum number of values to keep
* @param maxSize
* The maximum number of values to keep
* @param minDuration
* The minimun duration of value to keep
* @param auxiliaryMinSize
* The minimum number of values to keep for all auxiliary data
* @param auxiliaryMinDuration
* The minimun duration of value to keep for all auxiliary data
* @param withLabel
* If true label values ar also stored (see add method)
* @param withRawValue
* If true raw values are also stored
* @param withStatus
* If true status values are also stored
* @throws IOException
* @throws InvalidFormatException
*/
public StreamingMSDataSource(String id, StreamingTSDataSourceCollection c, int minSize, int maxSize, double minDuration,
boolean withLabel, boolean withRawValue, boolean withStatus, boolean withTime2) throws IOException,
InvalidFormatException {
this(id, c, minSize, maxSize, minDuration, minSize, minDuration, withLabel, withRawValue, withStatus, withTime2);
}
/**
* Create a streaming data source with optional label, raw and status values
* @param id
* The data source id
* @param c
* Its collection parent
* @param minSize
* The minimum number of values to keep
* @param maxSize
* The maximum number of values to keep
* @param minDuration
* The minimun duration of value to keep
* @param auxiliaryMinSize
* The minimum number of values to keep for all auxiliary data
* @param auxiliaryMinDuration
* The minimun duration of value to keep for all auxiliary data
* @param withLabel
* If true label values ar also stored (see add method)
* @param withRawValue
* If true raw values are also stored
* @param withStatus
* If true status values are also stored
* @throws IOException
* @throws InvalidFormatException
*/
public StreamingMSDataSource(String id, StreamingTSDataSourceCollection c, int minSize, int maxSize, double minDuration,
boolean withLabel, boolean withRawValue, boolean withStatus) throws IOException, InvalidFormatException {
this(id, c, minSize, maxSize, minDuration, withLabel, withRawValue, withStatus, false);
}
/* (non-Javadoc)
* @see simtools.data.async.StreamingTSDataSource#initialiseIndex()
*/
public void initialiseIndex() {
super.initialiseIndex();
if (_label != null) {
_label.initialiseIndex();
}
if (_raw != null) {
_raw.initialiseIndex();
}
if (_status != null) {
_status.initialiseIndex();
}
}
public void clearBuffers(){
super.clearBuffers();
if (_label != null) {
_label.clearBuffers();
}
if (_raw != null) {
_raw.clearBuffers();
}
if (_status != null) {
_status.clearBuffers();
}
}
/**
* @return Returns the _label.
*/
public StreamingLabelSource getLabel() {
return _label;
}
/**
* @return Returns the _raw.
*/
public StreamingIntegerSource getRaw() {
return _raw;
}
/**
* @return Returns the _status.
*/
public StreamingIntegerSource getStatus() {
return _status;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getDataSourceInformationClass()
*/
public String getDataSourceInformationClass() {
return "simtools.ui.StreamingMSDataSourceInformation";
}
/**
* Add a new set of values and notify listeners
*
* @param t
* @param v
* @param l
* @param r
* @param s
*/
public void add(double t, double v, String l, long r, long s) {
add(t, v, l, r, s, 0);
}
/**
* Add a new set of values and notify listeners
*
* @param t
* @param v
* @param l
* @param r
* @param s
* @param t2
* @param t2Enabled
*/
public void add(double t, double v, String l, long r, long s, double t2) {
addValues(t, v, l, r, s, t2);
notifyAllEndNotificationListeners();
}
/**
* Add a new set of values
*
* @param t
* @param v
* @param l
* @param r
* @param s
* @param t2
* @param t2Enabled
*/
public void addValues(double t, double v, String l, long r, long s, double t2) {
addValues(t, v, t2);
if (_label != null){
_label.addValues(l);
}
if (_raw != null){
_raw.addValues(r);
}
if (_status != null){
_status.addValues(s);
}
}
public void notifyAllEndNotificationListeners() {
super.notifyAllEndNotificationListeners();
if (_label != null) {
getLabel().notifyEndNotificationListeners();
}
if (_raw != null) {
getRaw().notifyEndNotificationListeners();
}
if (_status != null) {
getStatus().notifyEndNotificationListeners();
}
}
public class StreamingLabelSource extends TimeStampedDataSource {
protected double[] _l; // label values
protected int _startIndex;
protected int _lastIndex;
protected double _dmin;
protected double _dmax;
protected int _size;
protected final double _minDuration;
protected final int _minSize;
protected int _maxSize = Integer.MAX_VALUE;
/** We store numerical values instead of received string values.
* An HashMap (Double --> String) converts them into string values.*/
protected HashMap mapping;
protected int mappingCounter;
protected ChoiceFormat choiceFormat;
public StreamingLabelSource(
String type,
String name,
int minSize,
int maxSize,
double minDuration) throws IOException, InvalidFormatException {
super(
DataInfo.getLabel( StreamingMSDataSource.this) + "." + name,
DataInfo.getId(StreamingMSDataSource.this) + "." + name,
(StreamingTSDataSourceCollection) StreamingMSDataSource.this.getCollection());
setTime(StreamingMSDataSource.this.getTime());
this._minDuration = minDuration;
this._minSize = minSize;
this._maxSize = maxSize;
initialiseIndex();
_size = _minSize;
_l = new double[_size];
this. mappingCounter = 0;
this.choiceFormat = null;
getInfo().extendedLabel = DataInfo.getExtentedId(StreamingMSDataSource.this);
}
public void initialiseIndex() {
_startIndex = -1;
_lastIndex = -1;
}
public void clearBuffers() {
initialiseIndex();
_size = _minSize;
_l = new double[_size];
}
/*
* (non-Javadoc)
*
* @see simtools.data.ValueProvider#getValue(long)
*/
public Object getValue(long index) throws DataException {
if (_startIndex < 0) {
throw new NoSuchIndex(index);
}
if (index < _startIndex) {
throw new NoSuchIndex(index);
}
if (index > _lastIndex) {
throw new NoSuchIndex(index);
}
Double doubleValue = new Double(_l[(int) index % _size]);
return mapping.get(doubleValue);
}
/*
* (non-Javadoc)
*
* @see simtools.data.ValueProvider#getDoubleValue(long)
*/
public double getDoubleValue(long index) throws DataException {
if (_startIndex < 0) {
throw new NoSuchIndex(index);
}
if (index < _startIndex) {
throw new NoSuchIndex(index);
}
if (index > _lastIndex) {
throw new NoSuchIndex(index);
}
return _l[(int) index % _size];
}
/**
* Add a label value
* @param l
*/
public void addValues(String l){
if (_startIndex < 0) {
_startIndex = 0;
_lastIndex = 0;
double dl = getNumericalValue(l);
_l[0] = dl;
notifyListenersForValueRangeChange();
notifyListenersForIndexRangeChange(0, 0);
} else {
_lastIndex++;
if (_lastIndex >= _size) {
if ((StreamingMSDataSource.this._startIndex == 0) && (_minDuration >= 0.)) {
// the first time check buffer duration and increase buffer size if needed
double elapsedTime = StreamingMSDataSource.this._t[StreamingMSDataSource.this._lastIndex] - StreamingMSDataSource.this._t[0];
if ( ( elapsedTime < _minDuration) && ((_size * 2) <= _maxSize) ){
int nsize = _size * 2;
double[] nl = new double[nsize];
System.arraycopy(_l, 0, nl, 0, _size);
_l = nl;
_size = nsize;
} else {
_startIndex++;
}
} else {
_startIndex++;
}
}
int k = _lastIndex % _size;
double dl = getNumericalValue(l);
_l[k] = dl;
boolean notifyListenersForValueRangeChange = false;
if (dl < _dmin) {
_dmin = dl;
if (dl > _dmax) {
_dmax = dl;
}
notifyListenersForValueRangeChange = true;
} else if (dl > _dmax) {
_dmax = dl;
notifyListenersForValueRangeChange = true;
}
notifyListenersForIndexRangeChange(_startIndex, _lastIndex);
if (notifyListenersForValueRangeChange) {
notifyListenersForValueRangeChange();
}
}
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#getStart()
*/
public double getStart() throws DataException{
return getTime().getDoubleValue(_startIndex);
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getStartIndex()
*/
public long getStartIndex() throws UnsupportedOperation {
return _startIndex;
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#getEnd()
*/
public double getEnd() throws DataException{
return getTime().getDoubleValue(_lastIndex);
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getLastIndex()
*/
public long getLastIndex() throws UnsupportedOperation {
return _lastIndex;
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#computeMinMax()
*/
protected void computeMinMax() throws UnsupportedOperation {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getDoubleMin()
*/
public double getDoubleMin() throws DataException {
return _dmin;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getMin()
*/
public Object getMin() {
return new Double(_dmin);
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getDoubleMin()
*/
public double getDoubleMax() throws DataException {
return _dmax;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getMax()
*/
public Object getMax() {
return new Double(_dmax);
}
/*
* (non-Javadoc)
*
* @see simtools.data.ValueProvider#getLongValue(long)
*/
public long getLongValue(long index) throws DataException {
if (_startIndex < 0) {
throw new NoSuchIndex(index);
}
if (index < _startIndex) {
throw new NoSuchIndex(index);
}
if (index > _lastIndex) {
throw new NoSuchIndex(index);
}
return (long) _l[(int) index % _size];
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#auxiliarySources()
*/
public Collection getAuxiliarySources() {
return null;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#isCompound()
*/
public boolean isCompound() {
return false;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#isAuxiliary()
*/
public boolean isAuxiliary() {
return true;
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#isValid()
*/
public boolean isValid() {
// TODO Auto-generated method stub
return false;
}
/*
* (non-Javadoc)
*
* @see simtools.data.async.StreamingTSDataSource#getChoiceFormat()
*/
public ChoiceFormat getChoiceFormat() {
return choiceFormat;
}
public double getNumericalValue(String value) {
if (mapping == null) {
mapping = new HashMap();
}
Iterator it = mapping.keySet().iterator();
while (it.hasNext()) {
Double doubleValue = (Double) it.next();
if (((String) mapping.get(doubleValue)).equals(value)) {
return doubleValue.doubleValue();
}
}
// Add a new value to mapping.
int res = mappingCounter;
mapping.put(new Double(res), value);
mappingCounter++;
// Update choiceFormat
if (mappingCounter > 100) {
choiceFormat = null; // Do not display more than 100 labels
} else if (mappingCounter == 1) { // Flank 0 value with -1 and 1
double[] limits = new double[3];
String[] formats = new String[3];
limits[0] = -1;
formats[0] = "";
limits[1] = 0;
formats[1] = (String) mapping.get(new Double(0));
limits[2] = 1;
formats[2] = " ";
choiceFormat = new ChoiceFormat(limits, formats);
} else {
double[] limits = new double[mappingCounter];
String[] formats = new String[mappingCounter];
for (int i = 0; i < mappingCounter; i++) {
limits[i] = i;
formats[i] = (String) mapping.get(new Double(i));
}
choiceFormat = new ChoiceFormat(limits, formats);
}
return res;
}
}
public class StreamingIntegerSource extends TimeStampedDataSource {
protected int _startIndex;
protected int _lastIndex;
protected double _dmin;
protected double _dmax;
protected int _size;
protected final double _minDuration;
protected final int _minSize;
protected int _maxSize = Integer.MAX_VALUE;
protected long[] _i; // integer values
public StreamingIntegerSource(
String type,
String name,
int minSize,
int maxSize,
double minDuration
) throws IOException, InvalidFormatException {
super(
DataInfo.getLabel(StreamingMSDataSource.this) + "." + name,
DataInfo.getId(StreamingMSDataSource.this) + "." + name,
(StreamingTSDataSourceCollection) StreamingMSDataSource.this.getCollection());
setTime(StreamingMSDataSource.this.getTime());
this._minDuration = minDuration;
this._maxSize = maxSize;
this._minSize = minSize;
initialiseIndex();
_size = _minSize;
_i = new long[_size];
setTime(StreamingMSDataSource.this.getTime());
getInfo().extendedLabel = DataInfo.getExtentedId(StreamingMSDataSource.this);
}
public void initialiseIndex() {
_startIndex = -1;
_lastIndex = -1;
}
public void clearBuffers() {
initialiseIndex();
_size = _minSize;
_i = new long[_size];
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getStartIndex()
*/
public long getStartIndex() throws UnsupportedOperation {
return _startIndex;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getLastIndex()
*/
public long getLastIndex() throws UnsupportedOperation {
return _lastIndex;
}
/**
* Add an integer value
* @param i
*/
public void addValues(long i){
if (_startIndex < 0) {
_startIndex = 0;
_lastIndex = 0;
_i[0] = i;
notifyListenersForValueRangeChange();
notifyListenersForIndexRangeChange(0, 0);
} else {
_lastIndex++;
if (_lastIndex >= _size) {
if ((StreamingMSDataSource.this._startIndex == 0) && (_minDuration >= 0.)) {
// the first time check buffer duration and increase buffer size if needed
double elapsedTime = StreamingMSDataSource.this._t[StreamingMSDataSource.this._lastIndex] - StreamingMSDataSource.this._t[0];
if ( ( elapsedTime < _minDuration) && ((_size * 2) <= _maxSize) ){
int nsize = _size * 2;
long[] nl = new long[nsize];
System.arraycopy(_i, 0, nl, 0, _size);
_i = nl;
_size = nsize;
} else {
_startIndex++;
}
} else {
_startIndex++;
}
}
int k = _lastIndex % _size;
_i[k] = i;
updateSortedOrder();
boolean notifyListenersForValueRangeChange = false;
if (i < _dmin) {
_dmin = i;
if (i > _dmax) {
_dmax = i;
}
notifyListenersForValueRangeChange = true;
} else if (i > _dmax) {
_dmax = i;
notifyListenersForValueRangeChange = true;
}
notifyListenersForIndexRangeChange(_startIndex, _lastIndex);
if (notifyListenersForValueRangeChange) {
notifyListenersForValueRangeChange();
}
}
}
/*
* (non-Javadoc)
*
* @see simtools.data.ValueProvider#getValue(long)
*/
public Object getValue(long index) throws DataException {
if (_startIndex < 0) {
throw new NoSuchIndex(index);
}
if (index < _startIndex) {
throw new NoSuchIndex(index);
}
if (index > _lastIndex) {
throw new NoSuchIndex(index);
}
return new Long( _i[(int) index % _size] );
}
/*
* (non-Javadoc)
*
* @see simtools.data.ValueProvider#getLongValue(long)
*/
public long getLongValue(long index) throws DataException {
if (StreamingMSDataSource.this._startIndex < 0) {
throw new NoSuchIndex(index);
}
if (index < _startIndex) {
throw new NoSuchIndex(index);
}
if (index > _lastIndex) {
throw new NoSuchIndex(index);
}
return _i[(int) index % _size];
}
/*
* (non-Javadoc)
*
* @see simtools.data.ValueProvider#getDoubleValue(long)
*/
public double getDoubleValue(long index) throws DataException {
if (StreamingMSDataSource.this._startIndex < 0) {
throw new NoSuchIndex(index);
}
if (index < _startIndex) {
throw new NoSuchIndex(index);
}
if (index > _lastIndex) {
throw new NoSuchIndex(index);
}
return _i[(int) index % _size];
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#getStart()
*/
public double getStart() throws DataException{
return getTime().getDoubleValue(_startIndex);
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#getEnd()
*/
public double getEnd() throws DataException{
return getTime().getDoubleValue(_lastIndex);
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#computeMinMax()
*/
protected void computeMinMax() throws UnsupportedOperation {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getDoubleMin()
*/
public double getDoubleMin() throws DataException {
return _dmin;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getMin()
*/
public Object getMin() {
return new Double(_dmin);
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getDoubleMin()
*/
public double getDoubleMax() throws DataException {
return _dmax;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#getMax()
*/
public Object getMax() {
return new Double(_dmax);
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#isValid()
*/
public boolean isValid() {
// TODO Auto-generated method stub
return false;
}
/*
* (non-Javadoc)
*
* @see simtools.data.stamped.TimeStampedDataSource#getChoiceFormat()
*/
public ChoiceFormat getChoiceFormat() {
// TODO Auto-generated method stub
return null;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#auxiliarySources()
*/
public Collection getAuxiliarySources() {
return null;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#isCompound()
*/
public boolean isCompound() {
return false;
}
/*
* (non-Javadoc)
*
* @see simtools.data.DataSource#isAuxiliary()
*/
public boolean isAuxiliary() {
return true;
}
}
protected class AuxiliaryCollection extends StreamingTSDataSource.AuxiliaryCollection {
/*
* (non-Javadoc)
*
* @see java.util.AbstractList#get(int)
*/
public Object get(int index) {
Object ret = super.get(index);
if (ret != null) {
return ret;
}
index = index - super.size();
if (index == 0) {
return _label != null ? (Object) _label : _raw != null ? _raw : _status;
}
if (index == 1) {
return ((_label != null) && (_raw != null)) ? _raw : ((_label != null) || (_raw != null)) ? _status
: null;
}
if (index == 2) {
return _status;
}
return null;
}
/*
* (non-Javadoc)
*
* @see java.util.AbstractCollection#size()
*/
public int size() {
return super.size() + (_label == null ? 0 : 1) + (_raw == null ? 0 : 1) + (_status == null ? 0 : 1);
}
}
}