ucar.ma2.ArrayStructure Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.ma2;
import ucar.nc2.util.Indent;
import java.io.IOException;
import java.util.Formatter;
import java.util.Iterator;
import java.util.List;
/**
* Superclass for implementations of Array of StructureData.
*
* The general way to access data in an ArrayStructure is to use
* StructureData getStructureData(Index index).
*
* For 1D arrays (or by calculating your own recnum for nD arrays), you can also use:
* StructureData getStructureData(int recnum).
*
* Once you have a StructureData object, you can access data in a general way by using:
* Array StructureData.getArray(Member m)
*
* When dealing with large arrays of Structures, there can be significant overhead in using the generic interfaces.
* A number of convenience routines may be able to avoid extra Object creation, and so are recommended for efficiency.
* The following may avoid the overhead of creating the StructureData object:
* Array getArray(int recno, StructureMembers.Member m)
*
* The following can be convenient for accessing all the data in the ArrayStructure for one member, but its efficiency
* depends on the implementation:
* Array getMemberArray(StructureMembers.Member m)
*
* These require that you know the data types of the member data, but they are the most efficent:
*
* getScalarXXX(int recnum, Member m)
* getJavaArrayXXX(int recnum, Member m)
* where XXX is Byte, Char, Double, Float, Int, Long, Short, or String. For members that are themselves Structures,
* the equivilent is:
*
* StructureData getScalarStructure(int recnum, Member m)
* ArrayStructure getArrayStructure(int recnum, Member m)
*
* These will return any compatible type as a double or float, but will have extra overhead when the types dont match:
*
* convertScalarXXX(int recnum, Member m)
* convertJavaArrayXXX(int recnum, Member m)
* where XXX is Double or Float
*
* @author caron
* @see Array
* @see StructureData
*/
public abstract class ArrayStructure extends Array implements Iterable {
/* Implementation notes
ArrayStructure contains the default implementation of storing the data in individual member arrays.
ArrayStructureMA uses all of these.
ArrayStructureW uses some of these.
ArrayStructureBB override all such methods.
*/
protected StructureMembers members;
protected int nelems;
protected StructureData[] sdata;
/**
* Create a new Array of type StructureData and the given members and shape.
* dimensions.length determines the rank of the new Array.
*
* @param members a description of the structure members
* @param shape the shape of the Array.
*/
protected ArrayStructure(StructureMembers members, int[] shape) {
super(DataType.STRUCTURE, shape);
this.members = members;
this.nelems = (int) indexCalc.getSize();
}
// for subclasses to create views
protected ArrayStructure(StructureMembers members, Index ima) {
super(DataType.STRUCTURE, ima);
this.members = members;
this.nelems = (int) indexCalc.getSize();
}
// copy from javaArray to storage using the iterator: used by factory( Object);
protected void copyFrom1DJavaArray(IndexIterator iter, Object javaArray) {
Object[] ja = (Object[]) javaArray;
for (Object aJa : ja)
iter.setObjectNext(aJa);
}
// copy to javaArray from storage using the iterator: used by copyToNDJavaArray;
protected void copyTo1DJavaArray(IndexIterator iter, Object javaArray) {
Object[] ja = (Object[]) javaArray;
for (int i = 0; i < ja.length; i++)
ja[i] = iter.getObjectNext();
}
public Class getElementType() {
return StructureData.class;
}
/**
* Get the StructureMembers object.
*
* @return the StructureMembers object.
*/
public StructureMembers getStructureMembers() {
return members;
}
/**
* Get a list of structure members.
*
* @return the structure members.
*/
public List getMembers() {
return members.getMembers();
}
/**
* Get a list structure member names.
*
* @return the structure members.
*/
public List getStructureMemberNames() {
return members.getMemberNames();
}
/**
* Find a member by its name.
*
* @param memberName find member with this name
* @return StructureMembers.Member matching the name, or null if not found
*/
public StructureMembers.Member findMember(String memberName) {
return members.findMember(memberName);
}
@Override
public long getSizeBytes() {
return indexCalc.getSize() * members.getStructureSize();
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param i which one to get, specified by an Index.
* @return object of type StructureData.
*/
public Object getObject(Index i) {
return getObject(i.currentElement());
}
/**
* Set one of the StructureData of this ArrayStructure.
*
* @param i which one to set, specified by an Index.
* @param value must be type StructureData.
*/
public void setObject(Index i, Object value) {
setObject(i.currentElement(), value);
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param index which one to get, specified by an integer.
* @return object of type StructureData.
*/
public Object getObject(int index) {
return getStructureData(index);
}
/**
* Set the index-th StructureData of this ArrayStructure.
*
* @param index which one to set.
* @param value must be type StructureData.
*/
public void setObject(int index, Object value) {
if (sdata == null)
sdata = new StructureData[nelems];
sdata[index] = (StructureData) value;
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param i which one to get, specified by an Index.
* @return object of type StructureData.
*/
public StructureData getStructureData(Index i) {
return getStructureData(i.currentElement());
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param index which one to get, specified by an integer.
* @return object of type StructureData.
*/
public StructureData getStructureData(int index) {
if (sdata == null)
sdata = new StructureData[nelems];
if (index >= sdata.length)
throw new IllegalArgumentException(index + " > " + sdata.length);
if (sdata[index] == null)
sdata[index] = makeStructureData(this, index);
return sdata[index];
}
public Object getStorage() {
// this fills the sdata array
for (int i = 0; i < nelems; i++)
getStructureData(i);
return sdata;
}
abstract protected StructureData makeStructureData(ArrayStructure as, int recno);
/**
* Get the size of each StructureData object in bytes.
*
* @return the size of each StructureData object in bytes.
*/
public int getStructureSize() {
return members.getStructureSize();
}
public Iterator iterator() { // throws java.io.IOException {
return new ArrayStructureIterator();
}
public StructureDataIterator getStructureDataIterator() { // throws java.io.IOException {
return new ArrayStructureIterator();
}
public class ArrayStructureIterator implements StructureDataIterator, Iterator {
private int count = 0;
private int size = (int) getSize();
@Override
public boolean hasNext() {
return count < size;
}
@Override
public StructureData next() {
return getStructureData(count++);
}
@Override
public StructureDataIterator reset() {
count = 0;
return this;
}
@Override
public int getCurrentRecno() {
return count - 1;
}
// debugging
public ArrayStructure getArrayStructure() {
return ArrayStructure.this;
}
}
///////////////////////////////////////////////////////////////////////////////
/**
* Get member data of any type for a specific record as an Array.
* This may avoid the overhead of creating the StructureData object, but is equivilent to
* getStructure(recno).getArray( Member m).
*
* @param recno get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
* @param m get data from this StructureMembers.Member.
* @return Array values.
*/
public Array getArray(int recno, StructureMembers.Member m) {
DataType dataType = m.getDataType();
switch (dataType) {
case DOUBLE:
double[] da = getJavaArrayDouble(recno, m);
return Array.factory(dataType, m.getShape(), da);
case FLOAT:
float[] fa = getJavaArrayFloat(recno, m);
return Array.factory(dataType, m.getShape(), fa);
case BYTE:
case UBYTE:
case ENUM1:
byte[] ba = getJavaArrayByte(recno, m);
return Array.factory(dataType, m.getShape(), ba);
case SHORT:
case USHORT:
case ENUM2:
short[] sa = getJavaArrayShort(recno, m);
return Array.factory(dataType, m.getShape(), sa);
case INT:
case UINT:
case ENUM4:
int[] ia = getJavaArrayInt(recno, m);
return Array.factory(dataType, m.getShape(), ia);
case ULONG:
case LONG:
long[] la = getJavaArrayLong(recno, m);
return Array.factory(dataType, m.getShape(), la);
case CHAR:
char[] ca = getJavaArrayChar(recno, m);
return Array.factory(dataType, m.getShape(), ca);
case STRING:
String[] str = getJavaArrayString(recno, m);
return Array.factory(dataType, m.getShape(), str);
case STRUCTURE:
return getArrayStructure(recno, m);
case SEQUENCE:
return getArraySequence(recno, m);
case OPAQUE:
return getArrayObject(recno, m);
}
throw new RuntimeException("Dont have implemenation for " + dataType);
}
/**
* Set data for one member, over all structures.
* This is used by VariableDS to do scale/offset.
*
* @param m set data for this StructureMembers.Member.
* @param memberArray Array values.
*/
public void setMemberArray(StructureMembers.Member m, Array memberArray) {
m.setDataArray(memberArray);
if (memberArray instanceof ArrayStructure) { // LOOK
ArrayStructure as = (ArrayStructure) memberArray;
m.setStructureMembers(as.getStructureMembers());
}
}
/**
* Extract data for one member, over all structures.
*
* @param m get data from this StructureMembers.Member.
* @return Array values.
* @throws java.io.IOException on read error (only happens for Sequences, otherwise data is already read)
*/
public Array extractMemberArray(StructureMembers.Member m) throws IOException {
if (m.getDataArray() != null)
return m.getDataArray();
DataType dataType = m.getDataType();
/* special handling for sequences
if (dataType == DataType.SEQUENCE) {
List sdataList = new ArrayList();
for (int recno=0; recno ranges) throws InvalidRangeException {
Section viewSection = new Section(ranges);
ArrayStructureW result = new ArrayStructureW(this.members, viewSection.getShape());
int count = 0;
Section.Iterator iter = viewSection.getIterator(getShape());
while (iter.hasNext()) {
int recno = iter.next(null);
StructureData sd = getStructureData(recno);
result.setStructureData(sd, count++);
}
return result;
}
/**
* DO NOT USE, throws UnsupportedOperationException
*/
public Array copy() {
throw new UnsupportedOperationException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public double getDouble(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setDouble(Index i, double value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public float getFloat(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setFloat(Index i, float value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public long getLong(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setLong(Index i, long value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public int getInt(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setInt(Index i, int value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public short getShort(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setShort(Index i, short value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public byte getByte(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setByte(Index i, byte value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public boolean getBoolean(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setBoolean(Index i, boolean value) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public char getChar(Index i) {
throw new ForbiddenConversionException();
}
/**
* DO NOT USE, throw ForbiddenConversionException
*/
public void setChar(Index i, char value) {
throw new ForbiddenConversionException();
}
// trusted, assumes that individual dimension lengths have been checked
// package private : mostly for iterators
public double getDouble(int index) {
throw new ForbiddenConversionException();
}
public void setDouble(int index, double value) {
throw new ForbiddenConversionException();
}
public float getFloat(int index) {
throw new ForbiddenConversionException();
}
public void setFloat(int index, float value) {
throw new ForbiddenConversionException();
}
public long getLong(int index) {
throw new ForbiddenConversionException();
}
public void setLong(int index, long value) {
throw new ForbiddenConversionException();
}
public int getInt(int index) {
throw new ForbiddenConversionException();
}
public void setInt(int index, int value) {
throw new ForbiddenConversionException();
}
public short getShort(int index) {
throw new ForbiddenConversionException();
}
public void setShort(int index, short value) {
throw new ForbiddenConversionException();
}
public byte getByte(int index) {
throw new ForbiddenConversionException();
}
public void setByte(int index, byte value) {
throw new ForbiddenConversionException();
}
public char getChar(int index) {
throw new ForbiddenConversionException();
}
public void setChar(int index, char value) {
throw new ForbiddenConversionException();
}
public boolean getBoolean(int index) {
throw new ForbiddenConversionException();
}
public void setBoolean(int index, boolean value) {
throw new ForbiddenConversionException();
}
}