/* ==============================================
* 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: Buffer.java,v 1.2 2004/02/02 16:04:45 brodu Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/
package simtools.data.buffer;
import java.io.IOException;
import simtools.data.DataException;
import simtools.data.ValueProvider;
/** A Buffer provides a buffering service for values, based on an index.
* To do that, it asks a ValueProvider for new unbuffered values when
* necessary.
* It should implement a strategy in order to minimize calls
* to the ValueProvider getUnbuffered method.
* The Buffer is also a ValueProvider itself, of course.
*
* A simple strategy is proposed with the AgeBufferPolicy, where the oldest
* entry is removed to make space for a new entry when the buffer is full.
* More intelligent or faster policies may be implemented by subclasses,
* such as using the values access frequency, or managing ranges of index.
* @author Nicolas Brodu
* @version 1.0 2001
*/
public abstract class Buffer extends ValueProvider implements Cloneable, java.io.Serializable {
static final long serialVersionUID = -3321655645846219948L;
protected transient ValueProvider provider;
protected transient ObjectManipulator objectManipulator;
/// protected transient TypeManipulator typeManipulator;
// ------ START of perl-generated corresponding code --------
protected transient ByteManipulator byteManipulator;
protected transient ShortManipulator shortManipulator;
protected transient IntegerManipulator intManipulator;
protected transient LongManipulator longManipulator;
protected transient FloatManipulator floatManipulator;
protected transient DoubleManipulator doubleManipulator;
// -------- END of perl-generated corresponding code --------
/* Note about the index:
* - startIndex is the index for the value in buffer[0]
* - endIndex is the largest index for which a buffer value is valid.
* => Always true: startIndex <= endIndex < startIndex + buffer.length
* - Exception for this at init: use negative and invalid values so that
* there can't be any index lying in the buffer: start = -1, end = -2.
*/
protected transient long startIndex, endIndex;
public Buffer() {
this(null);
}
public Buffer(int type) {
this(type, null);
}
public Buffer(ValueProvider vp) {
this(ObjectProvider, null);
}
public Buffer(int type, ValueProvider vp) {
setProvider(vp);
startIndex = -1; // makes it impossible for the index to be in buffer.
endIndex = -2; // -> negative, and even then, cannot be >=-1 and <=-2
kind = type;
}
public void setProvider(ValueProvider vp) {
provider = vp;
}
public ValueProvider getProvider() {
return provider;
}
/** Sets a new value in the buffer, if possible.
* With getValue(), the buffer is polling information from ValueProviders
* With setValue(), an external source may push information to the buffer
* The buffer implementation may, or may not, take the new value into
* account. But if it does, this may lead to quite a big optimization.
*
* For example, pathIterators in graphical shapes are run one after the
* other. But a collective data source may read those values in the same
* file, all the source values for a given index on the same line.
* So, the pathIterators would run through the file n times, when they
* could have run through it only once if only they were doing their job
* in parallel. Since it's not possible to change that, the data source
* collection pushes the other values read on the same line directly to
* the data source buffers.
*
* @param index The index for which a new value is given
* @param value The new value
* @return true if the new value could be put in the buffer.
*/
public boolean setValue(long index, Object value) throws DataException {
if (kind!=ObjectProvider) return false;
if (objectManipulator==null) objectManipulator = (ObjectManipulator)createManipulator(kind);
if (objectManipulator!=null) return objectManipulator.setValue(index, value);
return false;
}
/**
* Sets a region of interest in the buffer. This is a purely
* informative function, but the buffer may use this information
* to optimize itself on this specific range.
*/
public void setSlice(long min, long max) {
// Invoke setSlice on manipulator
switch (kind) {
/// case TypeProvider:
/// if (typeManipulator==null) typeManipulator = (TypeManipulator)createManipulator(kind);
/// if (typeManipulator!=null) typeManipulator.setSlice(min, max);
/// return;
// ------ START of perl-generated corresponding code --------
case ByteProvider:
if (byteManipulator==null) byteManipulator = (ByteManipulator)createManipulator(kind);
if (byteManipulator!=null) byteManipulator.setSlice(min, max);
return;
case ShortProvider:
if (shortManipulator==null) shortManipulator = (ShortManipulator)createManipulator(kind);
if (shortManipulator!=null) shortManipulator.setSlice(min, max);
return;
case IntegerProvider:
if (intManipulator==null) intManipulator = (IntegerManipulator)createManipulator(kind);
if (intManipulator!=null) intManipulator.setSlice(min, max);
return;
case LongProvider:
if (longManipulator==null) longManipulator = (LongManipulator)createManipulator(kind);
if (longManipulator!=null) longManipulator.setSlice(min, max);
return;
case FloatProvider:
if (floatManipulator==null) floatManipulator = (FloatManipulator)createManipulator(kind);
if (floatManipulator!=null) floatManipulator.setSlice(min, max);
return;
case DoubleProvider:
if (doubleManipulator==null) doubleManipulator = (DoubleManipulator)createManipulator(kind);
if (doubleManipulator!=null) doubleManipulator.setSlice(min, max);
return;
// -------- END of perl-generated corresponding code --------
case ObjectProvider:
if (objectManipulator==null) objectManipulator = (ObjectManipulator)createManipulator(kind);
if (objectManipulator!=null) objectManipulator.setSlice(min, max);
return;
}
}
public Object clone() {
try{
Buffer b = (Buffer)super.clone();
if (objectManipulator!=null) b.objectManipulator = (ObjectManipulator)objectManipulator.clone();
/// if (typeManipulator!=null) b.typeManipulator = (TypeManipulator)typeManipulator.clone();
// ------ START of perl-generated corresponding code --------
if (byteManipulator!=null) b.byteManipulator = (ByteManipulator)byteManipulator.clone();
if (shortManipulator!=null) b.shortManipulator = (ShortManipulator)shortManipulator.clone();
if (intManipulator!=null) b.intManipulator = (IntegerManipulator)intManipulator.clone();
if (longManipulator!=null) b.longManipulator = (LongManipulator)longManipulator.clone();
if (floatManipulator!=null) b.floatManipulator = (FloatManipulator)floatManipulator.clone();
if (doubleManipulator!=null) b.doubleManipulator = (DoubleManipulator)doubleManipulator.clone();
// -------- END of perl-generated corresponding code --------
return b;
}
catch(CloneNotSupportedException cnse) {
return null;
}
}
/**
* @return long
*/
public long getEndIndex() {
return endIndex;
}
/**
* @return long
*/
public long getStartIndex() {
return startIndex;
}
public interface Manipulator {
}
///o /** This class handles optimization for type objects.
/// */
/// public abstract class TypeManipulator implements Cloneable, Manipulator {
/// public abstract type getValue(long index) throws DataException;
/// public boolean setValue(long index, type value) throws DataException {
/// return false;
/// }
/// public Object clone() {
/// try {
/// return super.clone();
/// } catch (CloneNotSupportedException e) {
/// return null;
/// }
/// }
/// public void setSlice(long min, long max) {/* Do nothing by default*/}
/// }
///
// ------ START of perl-generated corresponding code --------
/** This class handles optimization for byte objects.
*/
public abstract class ByteManipulator implements Cloneable, Manipulator {
public abstract byte getValue(long index) throws DataException;
public boolean setValue(long index, byte value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
/** This class handles optimization for short objects.
*/
public abstract class ShortManipulator implements Cloneable, Manipulator {
public abstract short getValue(long index) throws DataException;
public boolean setValue(long index, short value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
/** This class handles optimization for int objects.
*/
public abstract class IntegerManipulator implements Cloneable, Manipulator {
public abstract int getValue(long index) throws DataException;
public boolean setValue(long index, int value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
/** This class handles optimization for long objects.
*/
public abstract class LongManipulator implements Cloneable, Manipulator {
public abstract long getValue(long index) throws DataException;
public boolean setValue(long index, long value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
/** This class handles optimization for float objects.
*/
public abstract class FloatManipulator implements Cloneable, Manipulator {
public abstract float getValue(long index) throws DataException;
public boolean setValue(long index, float value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
/** This class handles optimization for double objects.
*/
public abstract class DoubleManipulator implements Cloneable, Manipulator {
public abstract double getValue(long index) throws DataException;
public boolean setValue(long index, double value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
/** This class handles optimization for Object objects.
*/
public abstract class ObjectManipulator implements Cloneable, Manipulator {
public abstract Object getValue(long index) throws DataException;
public boolean setValue(long index, Object value) throws DataException {
return false;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public void setSlice(long min, long max) {/* Do nothing by default*/}
}
// -------- END of perl-generated corresponding code --------
public Object getValue(long index) throws DataException {
/// if (kind==TypeProvider) {
/// if (typeManipulator==null) typeManipulator = (TypeManipulator)createManipulator(kind);
/// if (typeManipulator!=null) return new Type(typeManipulator.getValue(index));
/// } else
// ------ START of perl-generated corresponding code --------
if (kind==ByteProvider) {
if (byteManipulator==null) byteManipulator = (ByteManipulator)createManipulator(kind);
if (byteManipulator!=null) return new Byte(byteManipulator.getValue(index));
} else
if (kind==ShortProvider) {
if (shortManipulator==null) shortManipulator = (ShortManipulator)createManipulator(kind);
if (shortManipulator!=null) return new Short(shortManipulator.getValue(index));
} else
if (kind==IntegerProvider) {
if (intManipulator==null) intManipulator = (IntegerManipulator)createManipulator(kind);
if (intManipulator!=null) return new Integer(intManipulator.getValue(index));
} else
if (kind==LongProvider) {
if (longManipulator==null) longManipulator = (LongManipulator)createManipulator(kind);
if (longManipulator!=null) return new Long(longManipulator.getValue(index));
} else
if (kind==FloatProvider) {
if (floatManipulator==null) floatManipulator = (FloatManipulator)createManipulator(kind);
if (floatManipulator!=null) return new Float(floatManipulator.getValue(index));
} else
if (kind==DoubleProvider) {
if (doubleManipulator==null) doubleManipulator = (DoubleManipulator)createManipulator(kind);
if (doubleManipulator!=null) return new Double(doubleManipulator.getValue(index));
} else
// -------- END of perl-generated corresponding code --------
if (kind==ObjectProvider) {
if (objectManipulator==null) objectManipulator = (ObjectManipulator)createManipulator(kind);
if (objectManipulator!=null) return objectManipulator.getValue(index);
}
throw new DataException();
}
/// public type getTypeValue(long index) throws DataException {
/// if (kind!=TypeProvider) return super.getTypeValue(index);
/// if (typeManipulator==null) typeManipulator = (TypeManipulator)createManipulator(kind);
/// if (typeManipulator!=null) return typeManipulator.getValue(index);
/// return super.getTypeValue(index);
/// }
///
/// public boolean setTypeValue(long index, type value) throws DataException {
/// if (kind!=TypeProvider) return false;
/// if (typeManipulator==null) typeManipulator = (TypeManipulator)createManipulator(kind);
/// if (typeManipulator!=null) return typeManipulator.setValue(index, value);
/// return false;
/// }
///
// ------ START of perl-generated corresponding code --------
public byte getByteValue(long index) throws DataException {
if (kind!=ByteProvider) return super.getByteValue(index);
if (byteManipulator==null) byteManipulator = (ByteManipulator)createManipulator(kind);
if (byteManipulator!=null) return byteManipulator.getValue(index);
return super.getByteValue(index);
}
public boolean setByteValue(long index, byte value) throws DataException {
if (kind!=ByteProvider) return false;
if (byteManipulator==null) byteManipulator = (ByteManipulator)createManipulator(kind);
if (byteManipulator!=null) return byteManipulator.setValue(index, value);
return false;
}
public short getShortValue(long index) throws DataException {
if (kind!=ShortProvider) return super.getShortValue(index);
if (shortManipulator==null) shortManipulator = (ShortManipulator)createManipulator(kind);
if (shortManipulator!=null) return shortManipulator.getValue(index);
return super.getShortValue(index);
}
public boolean setShortValue(long index, short value) throws DataException {
if (kind!=ShortProvider) return false;
if (shortManipulator==null) shortManipulator = (ShortManipulator)createManipulator(kind);
if (shortManipulator!=null) return shortManipulator.setValue(index, value);
return false;
}
public int getIntegerValue(long index) throws DataException {
if (kind!=IntegerProvider) return super.getIntegerValue(index);
if (intManipulator==null) intManipulator = (IntegerManipulator)createManipulator(kind);
if (intManipulator!=null) return intManipulator.getValue(index);
return super.getIntegerValue(index);
}
public boolean setIntegerValue(long index, int value) throws DataException {
if (kind!=IntegerProvider) return false;
if (intManipulator==null) intManipulator = (IntegerManipulator)createManipulator(kind);
if (intManipulator!=null) return intManipulator.setValue(index, value);
return false;
}
public long getLongValue(long index) throws DataException {
if (kind!=LongProvider) return super.getLongValue(index);
if (longManipulator==null) longManipulator = (LongManipulator)createManipulator(kind);
if (longManipulator!=null) return longManipulator.getValue(index);
return super.getLongValue(index);
}
public boolean setLongValue(long index, long value) throws DataException {
if (kind!=LongProvider) return false;
if (longManipulator==null) longManipulator = (LongManipulator)createManipulator(kind);
if (longManipulator!=null) return longManipulator.setValue(index, value);
return false;
}
public float getFloatValue(long index) throws DataException {
if (kind!=FloatProvider) return super.getFloatValue(index);
if (floatManipulator==null) floatManipulator = (FloatManipulator)createManipulator(kind);
if (floatManipulator!=null) return floatManipulator.getValue(index);
return super.getFloatValue(index);
}
public boolean setFloatValue(long index, float value) throws DataException {
if (kind!=FloatProvider) return false;
if (floatManipulator==null) floatManipulator = (FloatManipulator)createManipulator(kind);
if (floatManipulator!=null) return floatManipulator.setValue(index, value);
return false;
}
public double getDoubleValue(long index) throws DataException {
if (kind!=DoubleProvider) return super.getDoubleValue(index);
if (doubleManipulator==null) doubleManipulator = (DoubleManipulator)createManipulator(kind);
if (doubleManipulator!=null) return doubleManipulator.getValue(index);
return super.getDoubleValue(index);
}
public boolean setDoubleValue(long index, double value) throws DataException {
if (kind!=DoubleProvider) return false;
if (doubleManipulator==null) doubleManipulator = (DoubleManipulator)createManipulator(kind);
if (doubleManipulator!=null) return doubleManipulator.setValue(index, value);
return false;
}
// -------- END of perl-generated corresponding code --------
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeInt(kind);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
kind = in.readInt();
// transient manipulators set to null and will be allocated on first use
}
/** Manipulator factory
* Subclasses shall implement it to return their specialized versions of Manipulators.
* @param kind
* @return Manipulator a Manipulator which must be a subclass of the corresponding TypeManipulator.
*/
protected abstract Manipulator createManipulator(int kind);
/**
* @return the buffer type as one of the constants defined in this class
*/
public int getKind() {
return kind;
}
public void clear() {
startIndex = -1; // makes it impossible for the index to be in buffer.
endIndex = -2; // -> negative, and even then, cannot be >=-1 and <=-2
}
}