/* ==============================================
* Simtools : The tools library used in JSynoptic
* ==============================================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This library 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 library 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
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2003, by :
* Corporate:
* Astrium SAS
* EADS CRC
* Individual:
* Nicolas Brodu
*
* $Id: DynamicDataSource.java,v 1.5 2008/04/10 16:42:45 ogor Exp $
*
* Changes
* -------
* 21-Jan-2004: made initial version from animated collection (NB)
*
*/
package simtools.data;
import simtools.data.buffer.DelayedBuffer;
import simtools.util.NumberStringComparator;
public class DynamicDataSource extends DataSource {
/**
* Builds a new dynamic data source with the given data information.
* Only the last value will be available, no buffer is set up.
* @param di the data information for this source (name, comment, unit...)
* @param kind the type of the data source. @see ValueProvider
*/
public DynamicDataSource(DataInfo di, int kind) {
this(di,kind,0);
}
/**
* Builds a new dynamic data source with the given data information, and backed
* by a data buffer of the given size
* @param di the data information for this source (name, comment, unit...)
* @param kind the type of the data source. @see ValueProvider
* @param delay the size of the buffer for past values
*/
public DynamicDataSource(DataInfo di, int kind, int delay) {
info = di;
if (delay>0) buffer = new DelayedBuffer(kind, this, delay);
else buffer = null;
this.kind = kind;
lastIndex = -1;
hasValue = false; // Uninitialized
autoRegister = true;
}
/** This class contains info necessary to handle the data sources.
* The vector has the same size as this object (reminder: Vector inheritance).
*/
public DataInfo info;
protected long lastIndex;
/** Set this to true to register the values as soon as they are set
* True by default, but this behaviour is not the same as the source collection so it can be set off
*/
protected boolean autoRegister = true;
/** See valueProvider
*/
protected int kind;
/** Whether or not values were set, or if they are unititialized. Itself false when uninitialized, so OK
*/
protected boolean hasValue;
/** current / cached values
* current values are positioned by setvalue but not registered yet
* cached values are registered and returned by the collection until the next register.
* current values correspond to currentIndex, cached values to the next.
*/
// /o protected type currentType, cachedType;
// / protected type minType, maxType;
// ------ START of perl-generated corresponding code --------
protected byte currentByte, cachedByte;
protected byte minByte, maxByte;
protected short currentShort, cachedShort;
protected short minShort, maxShort;
protected int currentInteger, cachedInteger;
protected int minInteger, maxInteger;
protected long currentLong, cachedLong;
protected long minLong, maxLong;
protected float currentFloat, cachedFloat;
protected float minFloat, maxFloat;
protected double currentDouble, cachedDouble;
protected double minDouble, maxDouble;
protected Object currentObject, cachedObject;
protected Object minObject, maxObject;
// -------- END of perl-generated corresponding code --------
DelayedBuffer buffer;
/**
* Adds a buffer to this source so it can keep previous values in memory
*/
public void bufferize(int delay) throws UnsupportedOperation {
buffer = new DelayedBuffer(kind, this,delay);
}
/**
* @return Returns the autoRegister.
*/
public boolean isAutoRegister() {
return autoRegister;
}
/**
* @param autoRegister The autoRegister to set.
*/
public void setAutoRegister(boolean autoRegister) {
this.autoRegister = autoRegister;
}
/** Other functions have a reasonable default implementation
*/
public Object getMin() throws UnsupportedOperation {
if (hasValue==false) throw new UnsupportedOperation();
switch (kind) {
// / case ValueProvider.TypeProvider: return new Type(minType);
// ------ START of perl-generated corresponding code --------
case ValueProvider.ByteProvider: return new Byte(minByte);
case ValueProvider.ShortProvider: return new Short(minShort);
case ValueProvider.IntegerProvider: return new Integer(minInteger);
case ValueProvider.LongProvider: return new Long(minLong);
case ValueProvider.FloatProvider: return new Float(minFloat);
case ValueProvider.DoubleProvider: return new Double(minDouble);
// -------- END of perl-generated corresponding code --------
case ValueProvider.ObjectProvider: return minObject;
}
return null;
}
public Object getMax() throws UnsupportedOperation {
if (hasValue==false) throw new UnsupportedOperation();
switch (kind) {
// / case ValueProvider.TypeProvider: return new Type(maxType);
// ------ START of perl-generated corresponding code --------
case ValueProvider.ByteProvider: return new Byte(maxByte);
case ValueProvider.ShortProvider: return new Short(maxShort);
case ValueProvider.IntegerProvider: return new Integer(maxInteger);
case ValueProvider.LongProvider: return new Long(maxLong);
case ValueProvider.FloatProvider: return new Float(maxFloat);
case ValueProvider.DoubleProvider: return new Double(maxDouble);
// -------- END of perl-generated corresponding code --------
case ValueProvider.ObjectProvider: return maxObject;
}
return null;
}
// / public type getTypeMin() throws DataException {
// / if (kind == ValueProvider.TypeProvider) return minType;
// / return super.getTypeMin();
// / }
// /
// / public type getTypeMax() throws DataException {
// / if (kind == ValueProvider.TypeProvider) return maxType;
// / return super.getTypeMax();
// / }
// /
// ------ START of perl-generated corresponding code --------
public byte getByteMin() throws DataException {
if (kind == ValueProvider.ByteProvider) return minByte;
return super.getByteMin();
}
public byte getByteMax() throws DataException {
if (kind == ValueProvider.ByteProvider) return maxByte;
return super.getByteMax();
}
public short getShortMin() throws DataException {
if (kind == ValueProvider.ShortProvider) return minShort;
return super.getShortMin();
}
public short getShortMax() throws DataException {
if (kind == ValueProvider.ShortProvider) return maxShort;
return super.getShortMax();
}
public int getIntegerMin() throws DataException {
if (kind == ValueProvider.IntegerProvider) return minInteger;
return super.getIntegerMin();
}
public int getIntegerMax() throws DataException {
if (kind == ValueProvider.IntegerProvider) return maxInteger;
return super.getIntegerMax();
}
public long getLongMin() throws DataException {
if (kind == ValueProvider.LongProvider) return minLong;
return super.getLongMin();
}
public long getLongMax() throws DataException {
if (kind == ValueProvider.LongProvider) return maxLong;
return super.getLongMax();
}
public float getFloatMin() throws DataException {
if (kind == ValueProvider.FloatProvider) return minFloat;
return super.getFloatMin();
}
public float getFloatMax() throws DataException {
if (kind == ValueProvider.FloatProvider) return maxFloat;
return super.getFloatMax();
}
public double getDoubleMin() throws DataException {
if (kind == ValueProvider.DoubleProvider) return minDouble;
return super.getDoubleMin();
}
public double getDoubleMax() throws DataException {
if (kind == ValueProvider.DoubleProvider) return maxDouble;
return super.getDoubleMax();
}
/**
* Compute the min and the max of this data source
* @return - true if min or max values have changed
* @throws UnsupportedOperation
*/
public boolean computeMinMax() throws UnsupportedOperation {
boolean hasChanged = false;
if (hasValue == false) {
throw new UnsupportedOperation();
}
if (buffer==null) {
switch (kind) {
case ValueProvider.ByteProvider:
minByte = maxByte = cachedByte;
break;
case ValueProvider.ShortProvider:
minShort = maxShort = cachedShort;
break;
case ValueProvider.IntegerProvider:
minInteger = maxInteger = cachedInteger;
break;
case ValueProvider.LongProvider:
minLong = maxLong = cachedLong;
break;
case ValueProvider.FloatProvider:
minFloat = maxFloat = cachedFloat;
break;
case ValueProvider.DoubleProvider:
minDouble = maxDouble = cachedDouble;
break;
case ValueProvider.ObjectProvider:
minObject = maxObject = cachedObject;
break;
}
hasChanged = true; // If there is no buffer, the range changes on each new value
} else {
int order = sortedOrder();
hasChanged = (order != 0);
switch (kind) {
case ValueProvider.ByteProvider:
if (cachedByte < minByte){
minByte = cachedByte;
hasChanged = true;
}
if (cachedByte > maxByte){
maxByte = cachedByte;
hasChanged = true;
}
case ValueProvider.ShortProvider:
if (cachedShort < minShort){
minShort = cachedShort;
hasChanged = true;
}
if (cachedShort > maxShort){
maxShort = cachedShort;
hasChanged = true;
}
case ValueProvider.IntegerProvider:
if (cachedInteger < minInteger){
minInteger = cachedInteger;
hasChanged = true;
}
if (cachedInteger > maxInteger){
maxInteger = cachedInteger;
hasChanged = true;
}
case ValueProvider.LongProvider:
if (cachedLong < minLong){
minLong = cachedLong;
hasChanged = true;
}
if (cachedLong > maxLong){
maxLong = cachedLong;
hasChanged = true;
}
case ValueProvider.FloatProvider:
if (cachedFloat < minFloat){
minFloat = cachedFloat;
hasChanged = true;
}
if (cachedFloat > maxFloat){
maxFloat = cachedFloat;
hasChanged = true;
}
case ValueProvider.DoubleProvider:
if (cachedDouble < minDouble){
minDouble = cachedDouble;
hasChanged = true;
}
if (cachedDouble > maxDouble){
maxDouble = cachedDouble;
hasChanged = true;
}
case ValueProvider.ObjectProvider:
if (cachedObject instanceof Comparable){
Comparable cco = (Comparable)cachedObject;
if (cco.compareTo(minObject) < 0){
minObject = cco;
hasChanged = true;
}
if (cco.compareTo(maxObject) > 0){
maxObject = cco;
hasChanged = true;
}
}
}
}
return hasChanged;
}
public boolean isComparable(int i) {
return false; // not comparable by default
}
// In this source, we use delay buffer. Those buffers privilege new values over the old ones.
// Thus, if a buffer is present for a datasource, use it.
// Otherwise, only the last data is available
public long getStartIndex() {
if (buffer==null) return lastIndex;
return buffer.getStartIndex();
}
public long getLastIndex() {
if (buffer==null) return lastIndex;
return buffer.getEndIndex();
}
public long computeStartIndex() {
return getStartIndex();
}
public long computeLastIndex() {
return getLastIndex();
}
/**
* Change our own information. May be called any time, and will notify
* the our listeners.
*/
protected void changeInfo(DataInfo di) {
info = di;
notifyListenersForInfoChange(di);
}
// /o /**
// / * Sets the value of this Datasource to the type v
// / * @param v the type value to set
// / */
// / protected void setTypeValue(type v) {
// / currentType = v;
// / if (autoRegister) registerNewValue();
// / }
// /
// ------ START of perl-generated corresponding code --------
/**
* Sets the value of this Datasource to the byte v
* @param v the byte value to set
*/
protected void setByteValue(byte v) {
currentByte = v;
if (autoRegister) registerNewValue();
}
/**
* Sets the value of this Datasource to the short v
* @param v the short value to set
*/
protected void setShortValue(short v) {
currentShort = v;
if (autoRegister) registerNewValue();
}
/**
* Sets the value of this Datasource to the int v
* @param v the int value to set
*/
protected void setIntegerValue(int v) {
currentInteger = v;
if (autoRegister) registerNewValue();
}
/**
* Sets the value of this Datasource to the long v
* @param v the long value to set
*/
protected void setLongValue(long v) {
currentLong = v;
if (autoRegister) registerNewValue();
}
/**
* Sets the value of this Datasource to the float v
* @param v the float value to set
*/
protected void setFloatValue(float v) {
currentFloat = v;
if (autoRegister) registerNewValue();
}
/**
* Sets the value of this Datasource to the double v
* @param v the double value to set
*/
protected void setDoubleValue(double v) {
currentDouble = v;
if (autoRegister) registerNewValue();
}
/**
* Sets the value of this Datasource to the Object v
* @param v the Object value to set
*/
protected void setObjectValue(Object v) {
currentObject = v;
if (autoRegister) registerNewValue();
}
// -------- END of perl-generated corresponding code --------
/**
* Call this function once you have set up all the values with setValue.
* The last value is reused if no new value is set.
* Note that by default, auto registering is true, so just calling setXXXValue will do the job
* @param dsnum
* @param v
*/
protected void registerNewValue() {
lastIndex++;
switch (kind) {
case ValueProvider.ByteProvider:
cachedByte = currentByte;
if (buffer!=null) {
try {
buffer.setByteValue(lastIndex,cachedByte);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minByte = maxByte = cachedByte;
}
break;
case ValueProvider.ShortProvider:
cachedShort = currentShort;
if (buffer!=null) {
try {
buffer.setShortValue(lastIndex,cachedShort);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minShort = maxShort = cachedShort;
}
break;
case ValueProvider.IntegerProvider:
cachedInteger = currentInteger;
if (buffer!=null) {
try {buffer.setIntegerValue(lastIndex,cachedInteger);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minInteger = maxInteger = cachedInteger;
}
break;
case ValueProvider.LongProvider:
cachedLong = currentLong;
if (buffer!=null){
try {buffer.setLongValue(lastIndex,cachedLong);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minLong = maxLong = cachedLong;
}
break;
case ValueProvider.FloatProvider:
cachedFloat = currentFloat;
if (buffer!=null) {
try {buffer.setFloatValue(lastIndex,cachedFloat);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minFloat = maxFloat = cachedFloat;
}
break;
case ValueProvider.DoubleProvider:
cachedDouble = currentDouble;
if (buffer!=null){
try {buffer.setDoubleValue(lastIndex,cachedDouble);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minDouble = maxDouble = cachedDouble;
}
break;
case ValueProvider.ObjectProvider:
cachedObject = currentObject;
if (buffer!=null) {
try {buffer.setValue(lastIndex,cachedObject);
} catch (DataException e) {}
}
if (hasValue==false) {
hasValue = true;
minObject = maxObject = cachedObject;
}
break;
}
// Update sorted order value
updateSortedOrder();
boolean vRangeChanged;
try {
vRangeChanged = computeMinMax();
} catch (UnsupportedOperation e) {
vRangeChanged = true;
}
if (vRangeChanged) {
notifyListenersForValueRangeChange();
}
notifyListenersForIndexRangeChange(getStartIndex(), getLastIndex());
notifyEndNotificationListeners();
}
/* (non-Javadoc)
* @see simtools.data.DataSourceCollection#getInformation()
*/
public DataInfo getInformation() {
return info;
}
/* (non-Javadoc)
* @see simtools.data.DataSourceCollection#getValue(int, long)
*/
public Object getValue(long index) throws DataException {
if (index==lastIndex) switch (kind) {
// / case ValueProvider.TypeProvider: return new Type(cachedType);
// ------ START of perl-generated corresponding code --------
case ValueProvider.ByteProvider: return new Byte(cachedByte);
case ValueProvider.ShortProvider: return new Short(cachedShort);
case ValueProvider.IntegerProvider: return new Integer(cachedInteger);
case ValueProvider.LongProvider: return new Long(cachedLong);
case ValueProvider.FloatProvider: return new Float(cachedFloat);
case ValueProvider.DoubleProvider: return new Double(cachedDouble);
// -------- END of perl-generated corresponding code --------
default: return cachedObject;
}
if (buffer==null) throw new NoSuchIndex(index);
long start = buffer.getStartIndex(); // ask buffer
long last = buffer.getEndIndex(); // ask buffer
if ((index<start) || (index>last)) throw new NoSuchIndex(index);
return buffer.getValue(index);
}
public int getKind() {
return kind;
}
/* (non-Javadoc)
* @see simtools.data.DataSourceCollection#valueClass(int)
*/
public Class valueClass() {
switch (kind) {
// / case ValueProvider.TypeProvider: return Type.class;
// ------ START of perl-generated corresponding code --------
case ValueProvider.ByteProvider: return Byte.class;
case ValueProvider.ShortProvider: return Short.class;
case ValueProvider.IntegerProvider: return Integer.class;
case ValueProvider.LongProvider: return Long.class;
case ValueProvider.FloatProvider: return Float.class;
case ValueProvider.DoubleProvider: return Double.class;
// -------- END of perl-generated corresponding code --------
}
return Object.class;
}
}