package gov.nasa.gsfc.spdf.cdfj; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.nio.*; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.*; /** * Abstract base class for each versions of CDF, containing common functionality. * * @see CDF2 * @see CDF3 * @author jbf */ public abstract class CDFImpl implements java.io.Serializable { /** * CDF constants */ public static final int GDR_RECORD = 2; public static final int FLAGS_MAJORITY_MASK = 0x01; public static final int ROW_MAJOR = 1; public static final int VXR_RECORD_TYPE = 6; public static final int VVR_RECORD_TYPE = 7; public static final int CVVR_RECORD_TYPE = 13; public static final int CCR_RECORD_TYPE = 10; public static final int CPR_RECORD_TYPE = 11; public static final String STRINGDELIMITER = new String("\\N "); /** * CDF offsets */ int offset_NEXT_VDR; int offset_NEXT_ADR; int offset_ATTR_NAME; int offset_SCOPE; int offset_AgrEDRHead; int offset_AzEDRHead; int offset_NEXT_AEDR; int offset_ENTRYNUM; int offset_ATTR_DATATYPE; int offset_ATTR_NUM_ELEMENTS; int offset_VALUE; int offset_VAR_NAME; int offset_VAR_NUM_ELEMENTS; int offset_NUM; int offset_FLAGS; int offset_sRecords; int offset_CPR_offset; int offset_BLOCKING_FACTOR; int offset_VAR_DATATYPE; int offset_zNumDims; int offset_FIRST_VXR; int offset_NEXT_VXR; int offset_NENTRIES; int offset_NUSED; int offset_FIRST; int offset_RECORD_TYPE; int offset_RECORDS; int offset_CSIZE; int offset_CDATA; int offset_CVR; int offset_cType; int offset_cParm; /** * CDF metadata */ int version; int release; int encoding; int flags; int increment; transient ByteOrder byteOrder; boolean bigEndian; long GDROffset; /** * Extracted from GDR */ long rVDRHead; long zVDRHead; long ADRHead; int numberOfRVariables; int numberOfAttributes; int numberOfZVariables; int[] rDimSizes; int lastLeapSecondId; /** * Extracted from CCR */ long CPROffset; long uSize; /** * Extracted from CPR */ int compression; int compLevel; transient ByteBuffer buf; protected String[] varNames; protected Hashtable variableTable; private HashMap ivariableTable; Hashtable attributeTable; protected CDFCore thisCDF; protected CDFFactory.CDFSource source; protected CDFFactory.ProcessingOption processingOption; private static final Logger LOGGER = Logger.getLogger("cdfj.cdfimpl"); protected CDFImpl(ByteBuffer buf) { this.buf = buf; } protected ByteBuffer getRecord(long offset) { ByteBuffer _buf = buf.duplicate(); _buf.position((int) offset); return _buf.slice(); } /** * returns byte order of source CDF */ public ByteOrder getByteOrder() { return byteOrder; } /** * returns row majority of source CDF */ public boolean rowMajority() { return ((flags & FLAGS_MAJORITY_MASK) == ROW_MAJOR); } /** * returns name to Variable map */ protected Hashtable variables() { if (variableTable != null) { return variableTable; } LOGGER.entering("CDFImpl", "variables"); int[] offsets = new int[]{(int) zVDRHead, (int) rVDRHead}; String[] vtypes = {"z", "r"}; Hashtable table = new Hashtable(); HashMap ivariableTable = new HashMap<>(); Vector v = new Vector(); for (int vtype = 0; vtype < 2; vtype++) { long offset = offsets[vtype]; if (offset == 0) { continue; } ByteBuffer _buf = getRecord(offset); while (true) { _buf.position(offset_NEXT_VDR); //int next = lowOrderInt(_buf); long next = longInt(_buf); CDFVariable cdfv = new CDFVariable(offset, vtypes[vtype]); String name = cdfv.getName(); v.add(name); ivariableTable.put(cdfv.number, cdfv); table.put(name, cdfv); if (next == 0) { break; } offset = next; _buf = getRecord(offset); } } varNames = new String[v.size()]; for (int i = 0; i < v.size(); i++) { varNames[i] = (String) v.elementAt(i); } variableTable = table; this.ivariableTable = ivariableTable; LOGGER.exiting("CDFImpl", "variables"); return table; } /** * returns variable names in a String[] */ public String[] getVariableNames() { String[] sa = new String[varNames.length]; for (int i = 0; i < sa.length; i++) { sa[i] = varNames[i]; } return sa; } /** * returns the object that implements the Variable interface for the named * variable */ public Variable getVariable(String name) { return (Variable) variableTable.get(name); } /** * returns variable names of a given VAR_TYPE in a String[] */ public String[] getVariableNames(String type) { Vector vars = new Vector(); for (String varName : varNames) { Vector v = (Vector) getAttribute(varName, "VAR_TYPE"); if (v == null) { continue; } if (v.size() == 0) { continue; } String s = (String) v.elementAt(0); if (s.equals(type)) { vars.add(varName); } } String[] sa = new String[vars.size()]; for (int i = 0; i < sa.length; i++) { sa[i] = (String) vars.elementAt(i); } return sa; } /** * returns names of global attributes in a String[] */ public String[] globalAttributeNames() { Vector vec = new Vector(); if (attributeTable == null) { return new String[0]; } Set set = attributeTable.keySet(); Iterator iter = set.iterator(); while (iter.hasNext()) { CDFAttribute attr = (CDFAttribute) attributeTable.get(iter.next()); if (attr.isGlobal()) { vec.add(attr.name); } } String[] sa = new String[vec.size()]; for (int i = 0; i < vec.size(); i++) { sa[i] = (String) vec.elementAt(i); } return sa; } /** * returns names of variable attributes in a String[] */ public String[] variableAttributeNames(String name) { CDFVariable var = (CDFVariable) variableTable.get(name); if (var == null) { return null; } String[] sa = new String[var.attributes.size()]; for (int i = 0; i < sa.length; i++) { AttributeEntry ae = (AttributeEntry) var.attributes.elementAt(i); sa[i] = ae.getAttributeName(); } return sa; } /** * returns value of the named global attribute */ public Object getAttribute(String atr) { if (attributeTable == null) { return null; } CDFAttribute a = (CDFAttribute) attributeTable.get(atr); if (a == null) { return null; } if (!a.isGlobal()) { return null; } if (a.gEntries.size() == 0) { return null; } AttributeEntry ae = (AttributeEntry) a.gEntries.elementAt(0); if (ae.isStringType()) { String[] sa = new String[a.gEntries.size()]; for (int i = 0; i < a.gEntries.size(); i++) { ae = (AttributeEntry) a.gEntries.elementAt(i); sa[i] = (String) ae.getValue(); } return sa; } return ae.getValue(); } /** * returns value of the named global attribute as GlobalAttribute object. */ public GlobalAttribute getGlobalAttribute(String atr) throws Throwable { if (attributeTable == null) { throw new Throwable("No attribute named " + atr); } final CDFAttribute a = (CDFAttribute) attributeTable.get(atr); if (a == null) { throw new Throwable("No attribute named " + atr); } if (!a.isGlobal()) { throw new Throwable("No global attribute named " + atr); } return new GlobalAttribute() { @Override public String getName() { return a.getName(); } @Override public boolean isGlobal() { return true; } @Override public int getNum() { return a.num; } @Override public int getEntryCount() { return a.gEntries.size(); } @Override public Object getEntry(int n) { if (n > a.gEntries.size()) { return null; } if (n < 0) { return null; } AttributeEntry ae = (AttributeEntry) a.gEntries.elementAt(n); return ae.getValue(); } @Override public boolean isStringType(int n) throws Throwable { if ((n < 0) || (n > a.gEntries.size())) { throw new Throwable("Invalid attribute index"); } AttributeEntry ae = (AttributeEntry) a.gEntries.elementAt(n); return ae.isStringType(); } @Override public boolean isLongType(int n) throws Throwable { if ((n < 0) || (n > a.gEntries.size())) { throw new Throwable("Invalid attribute index"); } AttributeEntry ae = (AttributeEntry) a.gEntries.elementAt(n); return ae.isLongType(); } }; } /** * returns value of the named attribute for the named variable */ public Object getAttribute(String var, String atr) { CDFVariable c = (CDFVariable) variableTable.get(var); if (c == null) { return null; } Vector attrs = c.attributes; Vector values = new Vector(); for (int i = 0; i < attrs.size(); i++) { AttributeEntry ae = (AttributeEntry) attrs.elementAt(i); if (ae.getAttributeName().equals(atr)) { values.add(ae.getValue()); } } return values; } /** * returns list of AttributeEntry objects for the named global attribute. */ public Vector getAttributeEntries(String atr) throws Throwable { if (attributeTable == null) { throw new Throwable("No attribute named " + atr); } final CDFAttribute a = (CDFAttribute) attributeTable.get(atr); if (a == null) { throw new Throwable("No attribute named " + atr); } if (!a.isGlobal()) { throw new Throwable("No global attribute named " + atr); } return a.gEntries; } /** * returns list of AttributeEntry objects for the named attribute for the * named variable. */ public Vector getAttributeEntries(String var, String atr) { CDFVariable c = (CDFVariable) variableTable.get(var); if (c == null) { return null; } Vector attrs = c.attributes; Vector entries = new Vector(); for (int i = 0; i < attrs.size(); i++) { AttributeEntry ae = (AttributeEntry) attrs.elementAt(i); if (ae.getAttributeName().equals(atr)) { entries.add(ae); } } return entries; } /** * returns Variable object associated with a given type at a given number */ Variable getCDFVariable(String vtype, int number) { CDFVariable var = ivariableTable.get(number); if (vtype.equals(var.vtype)) { return var; } else { throw new IllegalArgumentException("unsupported case, file must contain only zvariables or rvariables"); } } /** * returns name to Attribute object map */ Hashtable attributes() { if (attributeTable != null) { return attributeTable; } LOGGER.entering("CDFImpl", "attributes"); long offset = ADRHead; if (offset == 0) { return null; } Hashtable table = new Hashtable(); ByteBuffer _buf = getRecord(offset); while (true) { _buf.position(offset_NEXT_ADR); long next = longInt(_buf); CDFAttribute cdfa = new CDFAttribute(offset); Object o; if ((o = table.put(cdfa.getName(), cdfa)) != null) { System.out.println("possibly duplicate attribute " + cdfa.getName()); } if (next == 0) { break; } offset = next; _buf = getRecord(offset); } attributeTable = table; LOGGER.exiting("CDFImpl", "attributes"); return table; } /** * CDFAttribute class */ /*public*/ class CDFAttribute implements java.io.Serializable, Attribute { String name; int scope; int num; Vector zEntries = new Vector(); Vector gEntries = new Vector(); public CDFAttribute(long offset) { name = getString(offset + offset_ATTR_NAME); LOGGER.log(Level.FINER, "new attribute {0} at {1}", new Object[]{name, offset}); ByteBuffer _buf = getRecord(offset); _buf.position(offset_SCOPE); scope = _buf.getInt(); num = _buf.getInt(); _buf.position(offset_AgrEDRHead); long n = longInt(_buf); if (n > 0) { gEntries = getAttributeEntries(n); LOGGER.log(Level.FINEST, "link attr {0} to {1} gEntries", new Object[]{name, gEntries.size()}); if ((scope == 2) || (scope == 4)) { // variable scope linkToVariables(gEntries, "r"); } } _buf.position(offset_AzEDRHead); n = longInt(_buf); if (n > 0) { zEntries = getAttributeEntries(n); LOGGER.log(Level.FINEST, "link attr {0} to {1} zEntries", new Object[]{name, zEntries.size()}); linkToVariables(zEntries, "z"); } } /** * returns name of the attribute */ @Override public String getName() { return name; } /** * returns attribute entries */ public Vector getAttributeEntries(long offset) { if (offset == 0) { return null; } Vector list = new Vector(); ByteBuffer _buf = getRecord(offset); while (true) { _buf.position(offset_NEXT_AEDR); long next = longInt(_buf); _buf.position(0); AttributeEntry ae = new CDFAttributeEntry(_buf, name); list.add(ae); if (next == 0) { break; } _buf = getRecord(next); } return list; } /** * link variable attribute entries to the appropriate variable */ public void linkToVariables(Vector entries, String type) { for (int e = 0; e < entries.size(); e++) { AttributeEntry ae = (AttributeEntry) entries.elementAt(e); CDFVariable var = (CDFVariable) getCDFVariable(type, ae.getVariableNumber()); if (var == null) { System.out.println("An attribute entry for " + ae.getAttributeName() + " of type " + type + " links to variable number " + ae.getVariableNumber() + "."); System.out.println("Variable whose number is " + ae.getVariableNumber() + " was not found."); } else { var.attributes.add(ae); } } } /** * is this a global attribute? */ @Override public boolean isGlobal() { return !((scope == 2) || (scope == 4)); } } /** * AttributeEntry class */ public class CDFAttributeEntry implements AttributeEntry, Serializable { transient ByteBuffer _buf; int variableNumber; int type; int nelement; String attribute; String stringValue; String[] stringValues = null; Object value; public CDFAttributeEntry(ByteBuffer buf, String name) { attribute = name; _buf = buf.duplicate(); _buf.position(offset_ENTRYNUM); variableNumber = _buf.getInt(); _buf.position(offset_ATTR_DATATYPE); type = _buf.getInt(); _buf.position(offset_ATTR_NUM_ELEMENTS); nelement = _buf.getInt(); _buf.position(offset_VALUE); if (type > 50) { byte[] ba = new byte[nelement]; int i = 0; for (; i < nelement; i++) { ba[i] = _buf.get(); if (ba[i] == 0) { break; } } stringValue = new String(ba, 0, i); _buf.position(offset_ATTR_NUM_ELEMENTS + 4); int numStrings = _buf.getInt(); if (numStrings > 1) { stringValues = new String[numStrings]; int lastIndex = 0; int begin = 0, count = 0; while ((lastIndex = stringValue.indexOf(STRINGDELIMITER, begin)) != -1) { stringValues[count] = stringValue.substring(begin, lastIndex); begin += stringValues[count].length() + STRINGDELIMITER.length(); count++; } stringValues[count] = stringValue.substring(begin); } else { stringValues = null; } } else { value = getNumberAttribute(type, nelement, _buf, byteOrder); } } @Override public int getType() { return type; } @Override public int getNumberOfElements() { return nelement; } @Override public boolean isLongType() { return (DataTypes.typeCategory[type] == DataTypes.LONG); } @Override public boolean isStringType() { return DataTypes.isStringType(type); } @Override public Object getValue() { return (isStringType()) ? (stringValues != null ? stringValues : stringValue) : value; } @Override public String getAttributeName() { return attribute; } @Override public int getVariableNumber() { return variableNumber; } @Override public boolean isSameAs(AttributeEntry ae) { if (getType() != ae.getType()) { return false; } if (getNumberOfElements() != ae.getNumberOfElements()) { return false; } if (isStringType() != ae.isStringType()) { return false; } if (isStringType()) { if (stringValues != null) { Object newValue = ae.getValue(); if (!newValue.getClass().isArray()) { return false; } String[] oldStrings = (String[]) stringValues; String[] newStrings = (String[]) newValue; return Arrays.equals(oldStrings, newStrings); } else { return (stringValue.equals(ae.getValue())); } } if (isLongType() != ae.isLongType()) { return false; } if (isLongType()) { return Arrays.equals((long[]) value, (long[]) ae.getValue()); } return Arrays.equals((double[]) value, (double[]) ae.getValue()); } } /** * CDFVariable class */ public class CDFVariable implements java.io.Serializable, Variable { int DIMENSION_VARIES = -1; public Vector attributes = new Vector(); String name; public int number; String vtype; int flags; int sRecords; int type; int numberOfElements; protected int numberOfValues; public int[] dimensions; public boolean[] varies; public Object padValue; long offset; boolean completed = false; transient ByteBuffer _buf; int dataItemSize; long cprOffset; int blockingFactor; DataLocator locator; public int compressionType; public CDFVariable(long offset, String vtype) { this.offset = offset; this.vtype = vtype; _buf = getRecord(offset); name = getString(offset + offset_VAR_NAME); _buf.position(offset_VAR_NUM_ELEMENTS); numberOfElements = _buf.getInt(); _buf.position(offset_NUM); number = _buf.getInt(); _buf.position(offset_FLAGS); flags = _buf.getInt(); boolean compressed = ((flags & 0x04) != 0); _buf.position(offset_sRecords); sRecords = _buf.getInt(); _buf.position(offset_CPR_offset); cprOffset = longInt(_buf); _buf.position(offset_BLOCKING_FACTOR); blockingFactor = _buf.getInt(); _buf.position(offset_VAR_DATATYPE); type = _buf.getInt(); numberOfValues = _buf.getInt() + 1; _buf.position(offset_zNumDims); if (vtype.equals("r")) { dimensions = rDimSizes; } if (vtype.equals("z")) { dimensions = new int[_buf.getInt()]; for (int i = 0; i < dimensions.length; i++) { dimensions[i] = _buf.getInt(); } } varies = new boolean[dimensions.length]; for (int i = 0; i < dimensions.length; i++) { varies[i] = (_buf.getInt() == DIMENSION_VARIES); } if (type == DataTypes.EPOCH16) { dimensions = new int[]{2}; } if (type == DataTypes.EPOCH16) { varies = new boolean[]{true}; } dataItemSize = DataTypes.size[type]; // PadValue immediately follows DimVarys padValue = null; int padValueSize = getDataItemSize() / dataItemSize; Object _padValue = DataTypes.defaultPad(type); if (DataTypes.isStringType(type)) { byte[] ba = new byte[numberOfElements]; if (padValueSpecified()) { _buf.get(ba); for (int i = 0; i < numberOfElements; i++) { if (ba[i] <= 0) { ba[i] = 0x20; } } } else { for (int i = 0; i < numberOfElements; i++) { ba[i] = ((Byte) _padValue); } } _padValue = new String(ba); String[] sa = new String[padValueSize]; for (int i = 0; i < padValueSize; i++) { sa[i] = (String) _padValue; } padValue = sa; } else { if (padValueSpecified()) { _padValue = getNumberAttribute(type, 1, _buf, byteOrder); } if (DataTypes.isLongType(type)) { long[] lpad = new long[padValueSize]; if (padValueSpecified()) { lpad[0] = ((long[]) _padValue)[0]; } else { lpad[0] = ((Long) _padValue); } for (int i = 1; i < padValueSize; i++) { lpad[i] = lpad[0]; } padValue = lpad; } else { double[] dpad = new double[padValueSize]; if (padValueSpecified()) { dpad[0] = ((double[]) _padValue)[0]; } else { dpad[0] = ((Double) _padValue); } for (int i = 1; i < padValueSize; i++) { dpad[i] = dpad[0]; } padValue = dpad; } } // ignore numberOfElements for numeric data types if (DataTypes.isStringType(type)) { dataItemSize *= numberOfElements; } if (compressed) { ByteBuffer _cpr = getRecord(cprOffset); _cpr.position(offset_cType); compressionType = _cpr.getInt(); } else compressionType = 0; } synchronized void complete() { if (completed) { return; } if (numberOfValues > 0) { locator = new DataLocator(_buf, numberOfValues, ((flags & 4) != 0)); checkContinuity(); } completed = true; } boolean isComplete() { return completed; } boolean recordGap = false; void checkContinuity() { if (numberOfValues == 0) { return; } long[][] locations = locator.getLocations(); long last = locations[0][0] - 1; for (long[] location : locations) { if (location[0] != (last + 1)) { recordGap = true; break; } last = location[1]; } if (recordGap) { if (sRecords == 0) { System.out.println("Variable " + name + " is missing " + "records. This is not consistent with sRecords = 0"); } } } @Override public boolean isTypeR() { return (vtype.equals("r")); } /** * Return whether the missing record should be assigned the last seen * value. If none has been seen, pad value is assigned. */ @Override public boolean missingRecordValueIsPrevious() { return (sRecords == 2); } /** * Return whether the missing record should be assigned the pad value. */ @Override public boolean missingRecordValueIsPad() { return (sRecords == 1); } /** * Shows whether one or more records (in the range returned by * getRecordRange()) are missing. */ @Override public boolean isMissingRecords() { if (!completed) { complete(); } return recordGap; } /** * Gets a list of regions that contain data for the variable. Each * element of the vector describes a region as an int[3] array. Array * elements are: record number of first point in the region, record * number of last point in the region, and offset of the start of * region. */ @Override public VariableDataLocator getLocator() { if (!completed) { complete(); } return locator; } /** * Gets an array of VariableDataBuffer objects that provide location of * data for this variable if this variable is not compressed. This * method throws a Throwable if invoked for a compressed variable. * getBuffer method of VariableDataBuffer object returns a read only * ByteBuffer that contains data for this variable for a range of * records. getFirstRecord() and getLastRecord() define the range of * records. */ @Override public VariableDataBuffer[] getDataBuffers(boolean raw) throws Throwable { if (!completed) { complete(); } if (!raw) { if ((flags & 4) != 0) { throw new Throwable("Function not " + "supported for compressed variables "); } } long[][] locations = locator.getLocations(); Vector dbufs = new Vector(); int size = getDataItemSize(); for (long[] location : locations) { int first = (int) location[0]; int last = (int) location[1]; ByteBuffer bv = getRecord(location[2]); int clen = (last - first + 1) * size; //System.out.println("uclen: " + clen); boolean compressed = false; if (!isCompressed()) { bv.position(offset_RECORDS); } else { if (bv.getInt(offset_RECORD_TYPE) == VVR_RECORD_TYPE) { bv.position(offset_RECORDS); } else { compressed = true; bv.position(offset_CDATA); clen = lowOrderInt(bv, offset_CSIZE); //System.out.println("clen: " + clen); } } ByteBuffer bbuf = bv.slice(); bbuf.order(getByteOrder()); bbuf.limit(clen); dbufs.add(new VariableDataBuffer(first, last, bbuf, compressed)); } VariableDataBuffer[] vdbuf = new VariableDataBuffer[dbufs.size()]; dbufs.toArray(vdbuf); return vdbuf; } @Override public VariableDataBuffer[] getDataBuffers() throws Throwable { return getDataBuffers(false); } /** * returns whether row major ordering is in use */ @Override public boolean rowMajority() { return CDFImpl.this.rowMajority(); } /** * returns whether value of this variable can vary from record to record */ @Override public boolean recordVariance() { return ((flags & 1) != 0); } /** * returns whether pad value is specified for this variable */ public boolean padValueSpecified() { return ((flags & 2) != 0); } /** * returns whether variable values have been compressed */ @Override public boolean isCompressed() { if (!completed) { complete(); } if (locator == null) { return false; } return locator.isReallyCompressed(); } /** * returns pad value */ @Override public Object getPadValue() { if (padValue == null) { return null; } if (DataTypes.isStringType(type)) { return padValue; } return getPadValue(false); } /** * Gets an object that represents a padded instance for a variable of * numeric type. A double[] is returned, unless the variable type is * long and preservePrecision is set to true; */ @Override public Object getPadValue(boolean preservePrecision) { if (padValue == null) { return null; } if (DataTypes.isStringType(type)) { return padValue; } if (padValue.getClass().getComponentType() == Long.TYPE) { long[] ltemp = (long[]) padValue; if (preservePrecision) { long[] la = new long[ltemp.length]; System.arraycopy(ltemp, 0, la, 0, ltemp.length); return la; } else { double[] dtemp = new double[ltemp.length]; for (int i = 0; i < ltemp.length; i++) { dtemp[i] = (double) ltemp[i]; } return dtemp; } } double[] dtemp = (double[]) padValue; double[] da = new double[dtemp.length]; System.arraycopy(dtemp, 0, da, 0, dtemp.length); return da; } @Override public CDFImpl getCDF() { return CDFImpl.this; } /** * returns type of values of this variable */ @Override public int getType() { return type; } /** * returns blocking factor used in compression */ @Override public int getBlockingFactor() { return blockingFactor; } /** * returns compression type */ @Override public int getCompressionType() { return compressionType; } /** * returns effective rank */ @Override public int getEffectiveRank() { int rank = 0; for (int i = 0; i < dimensions.length; i++) { if (!varies[i]) { continue; } if (dimensions[i] == 1) { continue; } rank++; } return rank; } /** * Returns effective dimensions */ @Override public int[] getEffectiveDimensions() { int rank = getEffectiveRank(); if (rank == 0) { return new int[0]; } int[] edim = new int[rank]; int n = 0; for (int i = 0; i < dimensions.length; i++) { if (!varies[i]) { continue; } if (dimensions[i] == 1) { continue; } edim[n++] = dimensions[i]; } return edim; } /** * returns size of value of this variable */ @Override public int getDataItemSize() { int size = dataItemSize; for (int i = 0; i < dimensions.length; i++) { if (varies[i]) { size *= dimensions[i]; } } return size; } /** * returns number of elements in the value of this variable */ @Override public int getNumberOfElements() { return numberOfElements; } /** * returns number of values */ @Override public int getNumberOfValues() { return numberOfValues; } /** * Gets the name of this of this variable */ @Override public String getName() { return name; } /** * Gets the sequence number of the variable inside the CDF. */ @Override public int getNumber() { return number; } /** * Gets the dimensions. */ @Override public int[] getDimensions() { int[] ia = new int[dimensions.length]; System.arraycopy(dimensions, 0, ia, 0, dimensions.length); return ia; } /** * Returns record range for this variable */ @Override public int[] getRecordRange() { if (!completed) { complete(); } if (locator == null) { return null; } long[][] locations = locator.getLocations(); return new int[]{(int) locations[0][0], (int) locations[locations.length - 1][1]}; } /** * Gets the dimensional variance. This determines the effective * dimensionality of values of the variable. */ @Override public boolean[] getVarys() { boolean[] ba = new boolean[varies.length]; System.arraycopy(varies, 0, ba, 0, varies.length); return ba; } public ByteBuffer getBuffer() throws Throwable { return getBuffer(Double.TYPE, null, false, ByteOrder.nativeOrder()); } public ByteBuffer getBuffer(int[] recordRange) throws Throwable { return getBuffer(Double.TYPE, recordRange, false, ByteOrder.nativeOrder()); } /** * Returns ByteBuffer containing uncompressed values converted to a * stream of numbers of the type specified by 'type' using the specified * byte ordering (specified by bo) for the specified range of records. * Original ordering of values (row majority) is preserved. * recordRange[0] specifies the first record, and recordRange[1] the * last record. If 'preserve' is true, a Throwable is thrown if the * conversion to specified type will result in loss of precision. If * 'preserve' is * false, compatible conversions will be made even if it * results in loss of precision. */ @Override public ByteBuffer getBuffer(Class cl, int[] recordRange, boolean preserve, ByteOrder bo) throws Throwable { if (!completed) { complete(); } if (cl == Byte.TYPE) { VDataContainer.CByte container; container = new ByteVarContainer(CDFImpl.this, this, recordRange); container.run(); return container.getBuffer(); } if (cl == Double.TYPE) { VDataContainer.CDouble container; if (DoubleVarContainer.isCompatible(type, preserve)) { container = new DoubleVarContainer(CDFImpl.this, this, recordRange, preserve, bo); container.run(); return container.getBuffer(); } } if (cl == Float.TYPE) { VDataContainer.CFloat container; if (FloatVarContainer.isCompatible(type, preserve)) { container = new FloatVarContainer(CDFImpl.this, this, recordRange, preserve, bo); container.run(); return container.getBuffer(); } } if (cl == Integer.TYPE) { VDataContainer.CInt container; if (IntVarContainer.isCompatible(type, preserve)) { container = new IntVarContainer(CDFImpl.this, this, recordRange, preserve, bo); container.run(); return container.getBuffer(); } } if (cl == Short.TYPE) { VDataContainer.CShort container; if (ShortVarContainer.isCompatible(type, preserve)) { container = new ShortVarContainer(CDFImpl.this, this, recordRange, preserve, bo); container.run(); return container.getBuffer(); } } if (cl == Long.TYPE) { VDataContainer.CLong container; if (LongVarContainer.isCompatible(type, preserve)) { container = new LongVarContainer(CDFImpl.this, this, recordRange, bo); container.run(); return container.getBuffer(); } } throw new Throwable("Inconsistent constraints for " + "this variable"); } /** * returns whether conversion of this variable to type specified by cl * is supported while preserving precision. equivalent to * isCompatible(Class cl, true) */ @Override public boolean isCompatible(Class cl) { return BaseVarContainer.isCompatible(getType(), true, cl); } /** * returns whether conversion of this variable to type specified by cl * is supported under the given precision preserving constraint. */ @Override public boolean isCompatible(Class cl, boolean preserve) { return BaseVarContainer.isCompatible(getType(), preserve, cl); } @Override public VDataContainer.CByte getByteContainer(int[] pt) throws Throwable { VDataContainer.CByte container; if (ByteVarContainer.isCompatible(type, true)) { return new ByteVarContainer(CDFImpl.this, this, pt); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.CByte."); } /** * Returns this variable's values for a range of records as byte[] if * variable type is byte, unsigned byte or char. Otherwise, throws * Throwable */ @Override public byte[] asByteArray(int[] pt) throws Throwable { VDataContainer.CByte container; if (ByteVarContainer.isCompatible(type, true)) { container = new ByteVarContainer(CDFImpl.this, this, pt); container.run(); return container.as1DArray(); } throw new Throwable("Variable " + getName() + " cannot return " + "byte[]."); } /** * Returns this variable's values as byte[] if variable type is byte, * unsigned byte or char. Otherwise, throws Throwable */ @Override public byte[] asByteArray() throws Throwable { return asByteArray(null); } public byte[] asByteArray(int[] pt, boolean columnMajor) throws Throwable { VDataContainer.CByte container; if (ByteVarContainer.isCompatible(type, true)) { container = new ByteVarContainer(CDFImpl.this, this, pt); container.run(); return container.asOneDArray(columnMajor); } throw new Throwable("Variable " + getName() + " cannot return " + "byte[]."); } @Override public VDataContainer.CString getStringContainer(int[] pt) throws Throwable { VDataContainer.CString container; if (StringVarContainer.isCompatible(type, true)) { return new StringVarContainer(CDFImpl.this, this, pt); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.CString."); } @Override public VDataContainer.CFloat getFloatContainer(int[] pt, boolean preserve, ByteOrder bo) throws Throwable { VDataContainer.CFloat container; if (FloatVarContainer.isCompatible(type, preserve)) { return new FloatVarContainer(CDFImpl.this, this, pt, preserve, ByteOrder.nativeOrder()); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.Float."); } @Override public VDataContainer.CFloat getFloatContainer(int[] pt, boolean preserve) throws Throwable { return getFloatContainer(pt, preserve, ByteOrder.nativeOrder()); } /** * Returns this variable's values for the specified range of records as * float[]. If variable type cannot be cast to float, a Throwable is * thrown. If preserve is true, a Throwable is thrown for variables of * type double, long or int to signal possible loss of precision. */ @Override public float[] asFloatArray(boolean preserve, int[] pt) throws Throwable { VDataContainer.CFloat container; try { container = getFloatContainer(pt, preserve, ByteOrder.nativeOrder()); } catch (Throwable th) { throw new Throwable("Variable " + getName() + " cannot return " + "float[]."); } container.run(); return container.as1DArray(); } /** * Returns this variable's values as float[]. If variable type cannot be * cast to float, a Throwable is thrown. */ @Override public float[] asFloatArray() throws Throwable { return asFloatArray(false, null); } /** * Returns this variable's values for the specified range of records as * float[]. If variable type cannot be cast to float, a Throwable is * thrown. */ @Override public float[] asFloatArray(int[] pt) throws Throwable { return asFloatArray(false, pt); } @Override public VDataContainer.CDouble getDoubleContainer(int[] pt, boolean preserve, ByteOrder bo) throws Throwable { VDataContainer.CDouble container; if (DoubleVarContainer.isCompatible(type, preserve)) { return new DoubleVarContainer(CDFImpl.this, this, pt, preserve, ByteOrder.nativeOrder()); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.CDouble."); } @Override public VDataContainer.CDouble getDoubleContainer(int[] pt, boolean preserve) throws Throwable { return getDoubleContainer(pt, preserve, ByteOrder.nativeOrder()); } /** * Returns this variable's values for the specified range of records as * double[]. If variable type cannot be cast to double, a Throwable is * thrown. If preserve is true, a Throwable is thrown for variables of * type long to signal possible loss of precision. */ @Override public double[] asDoubleArray(boolean preserve, int[] pt) throws Throwable { TargetAttribute ta = new TargetAttribute(preserve, false); return asDoubleArray(ta, pt); } public double[] asDoubleArray(TargetAttribute tattr, int[] pt) throws Throwable { VDataContainer.CDouble container; try { container = getDoubleContainer(pt, tattr.preserve, ByteOrder.nativeOrder()); } catch (Throwable th) { throw new Throwable("Variable " + getName() + " cannot return " + "double[]."); } container.run(); return container.asOneDArray(tattr.columnMajor); } /** * Returns this variable's values as double[]. If variable type cannot * be cast to double, a Throwable is thrown. */ @Override public double[] asDoubleArray() throws Throwable { return asDoubleArray(false, null); } /** * Returns this variable's values for the specified range of records as * double[]. If variable type cannot be cast to double, a Throwable is * thrown. */ @Override public double[] asDoubleArray(int[] pt) throws Throwable { return asDoubleArray(false, pt); } @Override public VDataContainer.CLong getLongContainer(int[] pt, ByteOrder bo) throws Throwable { VDataContainer.CLong container; if (LongVarContainer.isCompatible(type, true)) { return new LongVarContainer(CDFImpl.this, this, pt, ByteOrder.nativeOrder()); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.CLong."); } @Override public VDataContainer.CLong getLongContainer(int[] pt) throws Throwable { return getLongContainer(pt, ByteOrder.nativeOrder()); } long[] asLongArray(boolean preserve, int[] pt) throws Throwable { VDataContainer.CLong container; try { container = getLongContainer(pt, ByteOrder.nativeOrder()); } catch (Throwable th) { throw new Throwable("Variable " + getName() + " cannot return " + "long[]."); } container.run(); return container.as1DArray(); } /** * Returns this variable's values as long[] for variables of type long. * throws Throwable for variables of other types. */ @Override public long[] asLongArray() throws Throwable { return asLongArray(false, null); } /** * Returns this variable's values for the specified range of records as * long[] for variables of type long. throws Throwable for variables of * other types. */ @Override public long[] asLongArray(int[] pt) throws Throwable { return asLongArray(false, pt); } @Override public VDataContainer.CInt getIntContainer(int[] pt, boolean preserve, ByteOrder bo) throws Throwable { VDataContainer.CInt container; if (IntVarContainer.isCompatible(type, preserve)) { return new IntVarContainer(CDFImpl.this, this, pt, preserve, ByteOrder.nativeOrder()); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.CInt."); } @Override public VDataContainer.CInt getIntContainer(int[] pt, boolean preserve) throws Throwable { return getIntContainer(pt, preserve, ByteOrder.nativeOrder()); } /** * Returns this variable's values for the specified range of records as * int[] for variables of type int, short or unsigned short, byte or * unsigned byte, or unsigned int (only if preserve is false). throws * Throwable for variables of other types. */ @Override public int[] asIntArray(boolean preserve, int[] pt) throws Throwable { VDataContainer.CInt container; try { container = getIntContainer(pt, preserve, ByteOrder.nativeOrder()); } catch (Throwable th) { throw new Throwable("Variable " + getName() + " cannot return " + "int[]."); } container.run(); return container.as1DArray(); } /** * Returns this variable's values as int[] for variables of type int, * short or unsigned short, byte or unsigned byte. throws Throwable for * variables of other types. */ @Override public int[] asIntArray() throws Throwable { return asIntArray(true, null); } /** * Returns this variable's values for the specified range of records as * int[] for variables of type int, short or unsigned short, byte or * unsigned byte. throws Throwable for variables of other types. */ @Override public int[] asIntArray(int[] pt) throws Throwable { return asIntArray(true, pt); } @Override public VDataContainer.CShort getShortContainer(int[] pt, boolean preserve, ByteOrder bo) throws Throwable { VDataContainer.CShort container; if (ShortVarContainer.isCompatible(type, preserve)) { return new ShortVarContainer(CDFImpl.this, this, pt, preserve, ByteOrder.nativeOrder()); } throw new Throwable("Variable " + getName() + " cannot return " + "VDataContainer.CShort."); } @Override public VDataContainer.CShort getShortContainer(int[] pt, boolean preserve) throws Throwable { return getShortContainer(pt, preserve, ByteOrder.nativeOrder()); } /** * Returns this variable's values for the specified range of records as * short[] for variables of type short, byte or unsigned byte, or * unsigned short (only if preserve is false). throws Throwable for * variables of other types. */ @Override public short[] asShortArray(boolean preserve, int[] pt) throws Throwable { VDataContainer.CShort container; try { container = getShortContainer(pt, preserve, ByteOrder.nativeOrder()); } catch (Throwable th) { throw new Throwable("Variable " + getName() + " cannot return " + "short[]."); } container.run(); return container.as1DArray(); } /** * Returns this variable's values as long[] for variables of type long. * throws Throwable for variables of other types. */ @Override public short[] asShortArray() throws Throwable { return asShortArray(true, null); } /** * Returns this variable's values for the specified range of records as * short[] for variables of type short, byte or unsigned byte. throws * Throwable for variables of other types. */ @Override public short[] asShortArray(int[] pt) throws Throwable { return asShortArray(true, pt); } /** * Return element count for this variable's dimensions. */ @Override public Vector getElementCount() { int[] dimensions = getDimensions(); Vector ecount = new Vector(); for (int i = 0; i < dimensions.length; i++) { if (getVarys()[i]) { ecount.add(dimensions[i]); } } return ecount; } } /** * DataLocator */ public class DataLocator implements VariableDataLocator, java.io.Serializable { private transient ByteBuffer _buf; private int numberOfValues; private boolean compressed; protected Vector locations = new Vector(); protected DataLocator(ByteBuffer b, int n, boolean compr) { _buf = b; numberOfValues = n; compressed = compr; _buf.position(offset_FIRST_VXR); long offset = longInt(_buf); ByteBuffer bx = getRecord(offset); Vector v = _getLocations(bx); registerNodes(bx, v); } public boolean isReallyCompressed() { return compressed; } @Override public long[][] getLocations() { long[][] loc = new long[locations.size()][3]; for (int i = 0; i < locations.size(); i++) { long[] ia = (long[]) locations.elementAt(i); loc[i][0] = ia[0]; loc[i][1] = ia[1]; loc[i][2] = ia[2]; } return loc; } Vector _getLocations(ByteBuffer bx) { Vector locations = new Vector(); while (true) { bx.position(offset_NEXT_VXR); long next = longInt(bx); bx.position(offset_NENTRIES); int nentries = bx.getInt(); bx.position(offset_NUSED); int nused = bx.getInt(); bx.position(offset_FIRST); ByteBuffer bf = bx.slice(); bx.position(offset_FIRST + nentries * 4); ByteBuffer bl = bx.slice(); bx.position(offset_FIRST + 2 * nentries * 4); ByteBuffer bo = bx.slice(); for (int entry = 0; entry < nused; entry++) { long first = bf.getInt(); long last = bl.getInt(); if (last > (numberOfValues - 1)) { last = (numberOfValues - 1); } long off = longInt(bo); locations.add(new long[]{first, last, off}); } if (next == 0) { break; } bx = getRecord(next); } return locations; } void registerNodes(ByteBuffer bx, Vector v) { int vrtype = VVR_RECORD_TYPE; if (compressed) { vrtype = CVVR_RECORD_TYPE; } for (int i = 0; i < v.size(); i++) { long[] loc = (long[]) v.elementAt(i); ByteBuffer bb = getRecord(loc[2]); if (bb.getInt(offset_RECORD_TYPE) == VXR_RECORD_TYPE) { Vector vin = _getLocations(bb); registerNodes(bb, vin); } else { locations.add(loc); } } } public Vector getLocationsAsVector() { Vector _locations = new Vector(); long[][] loc = getLocations(); for (int i = 0; i < locations.size(); i++) { _locations.add(loc[i]); } return _locations; } } Object getPadValue(Variable var) { return var.getPadValue(true); } Object getFillValue(Variable var) { Vector fill = (Vector) getAttribute(var.getName(), "FILLVAL"); int type = var.getType(); if (fill.size() != 0) { if (fill.get(0).getClass().getComponentType() == Double.TYPE) { double dfill = ((double[]) fill.get(0))[0]; if (DataTypes.typeCategory[type] == DataTypes.LONG) { return new long[]{0l, (long) dfill}; } else { return new double[]{0, dfill}; } } else { long lfill = ((long[]) fill.get(0))[0]; if (DataTypes.typeCategory[type] == DataTypes.LONG) { return new long[]{0l, lfill}; } else { return new double[]{0, (double) lfill}; } } } else { if (DataTypes.typeCategory[type] == DataTypes.LONG) { return new long[]{Long.MIN_VALUE, 0l}; } else { return new double[]{Double.NEGATIVE_INFINITY, 0}; } } } /** * returns ByteBuffer containing count values for variable var starting at * CDF offset value offset. */ ByteBuffer positionBuffer(Variable var, long offset, int count) { ByteBuffer bv; if (!var.isCompressed()) { bv = getValueBuffer(offset); } else { int size = var.getDataItemSize(); bv = getValueBuffer(var, offset, size, count); } bv.order(getByteOrder()); return bv; } public ByteBuffer getValueBuffer(long offset) { ByteBuffer bv = getRecord(offset); bv.position(offset_RECORDS); return bv; } public ByteBuffer getValueBuffer(Variable var, long offset, int size, int number) { ByteBuffer bv = getRecord(offset); if (bv.getInt(offset_RECORD_TYPE) == VVR_RECORD_TYPE) { /* System.out.println("Encountered uncompressed instead of " + " compressed at offset " + offset); */ bv.position(offset_RECORDS); return bv; } int clen = lowOrderInt(bv, offset_CSIZE); byte[] work = new byte[clen]; bv.position(offset_CDATA); bv.get(work); int ulen = size * number; byte[] udata = null; int compType = var.getCompressionType(); // variable-level compression if (compType == CDFFactory.GZIP_COMPRESSION) { udata = new byte[ulen]; int n = 0; try { GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(work)); int toRead = udata.length; int off = 0; while (toRead > 0) { n = gz.read(udata, off, toRead); if (n == -1) { break; } off += n; toRead -= n; } } catch (IOException ex) { System.out.println(ex.toString() + " at offset " + offset); System.out.println("Trying to get data as uncompressed"); return getValueBuffer(offset); } if (n < 0) { return null; } } else if (compType == CDFFactory.RLE_COMPRESSION) { udata = new CDFRLE().decompress(work, ulen); } else if (compType == CDFFactory.HUFF_COMPRESSION) { udata = new CDFHuffman().decompress(work, ulen); } else if (compType == CDFFactory.AHUFF_COMPRESSION) { udata = new CDFAHuffman().decompress(work, ulen); } return ByteBuffer.wrap(udata); } /** * returns dimensions of the named variable. */ public int[] variableDimensions(String name) { Variable var = (Variable) variableTable.get(name); if (var == null) { return null; } int[] dims = var.getDimensions(); int[] ia = new int[dims.length]; System.arraycopy(ia, 0, dims, 0, dims.length); return ia; } protected abstract long longInt(ByteBuffer buf); protected abstract int lowOrderInt(ByteBuffer buf); protected abstract int lowOrderInt(ByteBuffer buf, int offset); protected abstract String getString(long offset); protected String getString(long offset, int max) { return getString(getRecord(offset), max); } protected String getString(ByteBuffer _buf, int max) { byte[] ba = new byte[max]; int i = 0; for (; i < max; i++) { ba[i] = _buf.get(); if (ba[i] == 0) { break; } } return new String(ba, 0, i); } public static Object getNumberAttribute(int type, int nelement, ByteBuffer vbuf, ByteOrder byteOrder) { ByteBuffer vbufLocal = vbuf.duplicate(); vbufLocal.order(byteOrder); int ne = nelement; if (type == DataTypes.EPOCH16) { ne = 2 * nelement; } long[] lvalue = null; double[] value = null; long longInt = DataTypes.longInt[type]; boolean longType = false; try { if ((type > 20) || (type < 10)) { if (DataTypes.typeCategory[type] == DataTypes.LONG) { lvalue = new long[ne]; longType = true; } else { value = new double[ne]; } for (int i = 0; i < ne; i++) { Number num = (Number) DataTypes.method[type].invoke(vbufLocal, new Object[]{}); if (!longType) { value[i] = num.doubleValue(); } if (longType) { lvalue[i] = num.longValue(); } } } else { value = new double[ne]; for (int i = 0; i < nelement; i++) { Number num = (Number) DataTypes.method[type].invoke(vbufLocal, new Object[]{}); int n = num.intValue(); value[i] = (n >= 0) ? (double) n : (double) (longInt + n); } } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { System.out.println("getNumberAttribute: " + vbuf); System.out.println("type: " + type); ex.printStackTrace(); return null; } if (longType) { return lvalue; } return value; } protected void setByteOrder(ByteOrder bo) { bigEndian = bo.equals(ByteOrder.BIG_ENDIAN); } protected void setByteOrder(boolean _bigEndian) { byteOrder = (_bigEndian) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; setByteOrder(byteOrder); } public boolean isBigEndian() { return bigEndian; } protected void setBuffer(ByteBuffer b) { buf = b; } protected ByteBuffer getBuffer() { return buf; } public void extractBytes(int bufOffset, byte[] ba, int offset, int len) { ((ByteBuffer) buf.duplicate().position(bufOffset)).get(ba, offset, len); } protected int getRecordOffset() { return offset_RECORDS; } protected void setSource(CDFFactory.CDFSource source) { this.source = source; } public CDFFactory.CDFSource getSource() { return source; } protected void setOption(CDFFactory.ProcessingOption option) { processingOption = option; } public double[] get1D(String varName) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (!var.isCompatible(Double.TYPE)) { throw new Throwable("Variable " + varName + " cannot be " + "converted to double, or the conversion may result in loss of " + "precision. Use get1D(" + varName + ", Boolean.TRUE) for " + "string type. Otherwise use get1D(" + varName + ", false"); } return var.asDoubleArray(); } public double[] getOneD(String varName, boolean columnMajor) throws Throwable { CDFVariable var = (CDFVariable) getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (!var.isCompatible(Double.TYPE)) { throw new Throwable("Variable " + varName + " cannot be " + "converted to double, or the conversion may result in loss of " + "precision. Use getOneD(" + varName + ", Boolean.TRUE) for " + "string type. Otherwise use get1D(" + varName + ", false"); } TargetAttribute ta = new TargetAttribute(false, columnMajor); return var.asDoubleArray(ta, null); } public byte[] get1D(String varName, Boolean stringType) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } int type = var.getType(); if (!DataTypes.isStringType(type)) { throw new Throwable( "Variable " + varName + " is not a string variable"); } return var.asByteArray(null); } public byte[] getOneD(String varName, Boolean stringType, boolean columnMajor) throws Throwable { CDFVariable var = (CDFVariable) getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } int type = var.getType(); if (!DataTypes.isStringType(type)) { throw new Throwable( "Variable " + varName + " is not a string variable"); } return var.asByteArray(null, columnMajor); } public Object get1D(String varName, boolean preserve) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } int type = var.getType(); if (DataTypes.isStringType(type)) { return var.asByteArray(null); } if (preserve) { if (DataTypes.isLongType(type)) { return var.asLongArray(null); } } return var.asDoubleArray(); } public Object get1D(String varName, int point) throws Throwable { return get1D(varName, point, -1); } /* public double[] get1D(String varName, int first, int last, int[] stride) throws Throwable { DoubleVarContainer dbuf = getRangeBuffer(varName, first, last); return dbuf.asSampledArray(stride); } */ public Object get1D(String varName, int first, int last) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } int type = var.getType(); int[] range = (last >= 0) ? new int[]{first, last} : new int[]{first}; if (DataTypes.isLongType(type)) { return var.asLongArray(range); } if (DataTypes.isStringType(type)) { return var.asByteArray(range); } return var.asDoubleArray(range); } public Object get(String varName) throws Throwable { DoubleVarContainer dbuf; Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (DataTypes.isStringType(var.getType())) { VDataContainer.CString container = var.getStringContainer(null); container.run(); StringArray sa = (StringArray) container.asArray(); return sa.array(); } VDataContainer.CDouble container = var.getDoubleContainer(null, false); container.run(); DoubleArray da = (DoubleArray) container.asArray(); return da.array(); } public Object getLong(String varName) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (!DataTypes.isLongType(var.getType())) { throw new Throwable("getLong method appropriate for " + "TT2000 and INT8 types. "); } VDataContainer.CLong container = var.getLongContainer(null); container.run(); LongArray la = (LongArray) container.asArray(); return la.array(); } public Object get(String varName, int element) throws Throwable { return get(varName, new int[]{element}); } public Object get(String varName, int[] elements) throws Throwable { DoubleVarContainer dbuf; Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (DataTypes.isStringType(var.getType())) { throw new Throwable("Function not supported for string variables"); } dbuf = new DoubleVarContainer(this, var, null, false, ByteOrder.nativeOrder()); dbuf.run(); return dbuf.asArrayElement(elements); } public Object get(String varName, int index0, int index1) throws Throwable { DoubleVarContainer dbuf; Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (DataTypes.isStringType(var.getType())) { throw new Throwable("Function not supported for string variables"); } dbuf = new DoubleVarContainer(this, var, null, false, ByteOrder.nativeOrder()); dbuf.run(); return dbuf.asArrayElement(index0, index1); } public Object get(String varName, int first, int last, int element) throws Throwable { return get(varName, first, last, new int[]{element}); } public Object get(String varName, int first, int last, int[] elements) throws Throwable { DoubleVarContainer dbuf = getRangeBuffer(varName, first, last); return dbuf.asArrayElement(elements); } // --- POINT public Object getPoint(String varName, int point) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (DataTypes.isStringType(var.getType())) { VDataContainer.CString container = var.getStringContainer(null); container.run(); StringArray sa = (StringArray) container.asArray(); return sa.array(); } else { DoubleVarContainer dbuf = new DoubleVarContainer(this, var, new int[]{point}, false, ByteOrder.nativeOrder()); dbuf.run(); return dbuf.asArray().array(); } } // --- RANGE public Object getRange(String varName, int first, int last, boolean oned) throws Throwable { DoubleVarContainer dbuf = getRangeBuffer(varName, first, last); if (oned) { return dbuf.as1DArray(); } return dbuf.asArray().array(); } public Object getRange(String varName, int first, int last) throws Throwable { return getRange(varName, first, last, false); } public Object getRangeOneD(String varName, int first, int last, boolean columnMajor) throws Throwable { DoubleVarContainer dbuf = getRangeBuffer(varName, first, last); return dbuf.asOneDArray(columnMajor); } DoubleVarContainer getRangeBuffer(String varName, int first, int last) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (DataTypes.isStringType(var.getType())) { throw new Throwable("Function not supported for string variables"); } int[] range = new int[]{first, last}; DoubleVarContainer dbuf; dbuf = new DoubleVarContainer(this, var, range, false, ByteOrder.nativeOrder()); dbuf.run(); return dbuf; } public Object getRange(String varName, int first, int last, int element) throws Throwable { return getRange(varName, first, last, new int[]{element}); } public Object getRange(String varName, int first, int last, int[] elements) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } if (DataTypes.isStringType(var.getType())) { throw new Throwable("Function not supported for string variables"); } DoubleVarContainer dbuf = getRangeBuffer(varName, first, last); return dbuf.asArrayElement(elements); } public boolean isCompatible(String varName, Class cl) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.isCompatible(cl); } public byte[] getByteArray(String varName, int[] pt) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.asByteArray(pt); } public double[] getDoubleArray(String varName, int[] pt) throws Throwable { return getDoubleArray(varName, pt, true); } public double[] getDoubleArray(String varName, int[] pt, boolean preserve) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.asDoubleArray(preserve, pt); } public float[] getFloatArray(String varName, int[] pt) throws Throwable { return getFloatArray(varName, pt, true); } public float[] getFloatArray(String varName, int[] pt, boolean preserve) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.asFloatArray(preserve, pt); } public int[] getIntArray(String varName, int[] pt) throws Throwable { return getIntArray(varName, pt, true); } public int[] getIntArray(String varName, int[] pt, boolean preserve) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.asIntArray(preserve, pt); } public long[] getLongArray(String varName, int[] pt) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.asLongArray(pt); } public short[] getShortArray(String varName, int[] pt) throws Throwable { return getShortArray(varName, pt, true); } public short[] getShortArray(String varName, int[] pt, boolean preserve) throws Throwable { Variable var = getVariable(varName); if (var == null) { throw new Throwable("No such variable: " + varName); } return var.asShortArray(preserve, pt); } static class TargetAttribute { public final boolean preserve; public final boolean columnMajor; TargetAttribute(boolean p, boolean c) { preserve = p; columnMajor = c; } } public static TargetAttribute targetAttributeInstance(boolean p, boolean c) { return new TargetAttribute(p, c); } }