protected boolean addParameter2(CoordinateTransform rs, String paramName, NetcdfFile ds, AttributeContainer v, String attName, boolean readData) {
    String varName;
    if (null == (varName = v.findAttValueIgnoreCase(attName, null))) {
      parseInfo.format("CSMConvention No Attribute named %s%n", attName);
      return false;
    }
    varName = varName.trim();

    Variable dataVar;
    if (null == (dataVar = ds.findVariable(varName))) {
      parseInfo.format("CSMConvention No Variable named %s%n", varName);
      return false;
    }

    if (readData) {
      Array data;
      try {
        data = dataVar.read();
      } catch (IOException e) {
        parseInfo.format("CSMConvention failed on read of %s err= %s%n", varName, e.getMessage());
        return false;
      }
      double[] vals = (double []) data.get1DJavaArray(DataType.DOUBLE);
      rs.addParameter(new Parameter(paramName, vals));

    } else
      rs.addParameter(new Parameter(paramName, varName));

    return true;
  }

Add a Parameter to a CoordinateTransform. The variable attribute points to a another variable that has the data in it.
Make sure that atrribute and variable exist. Id readData is true, read the data and use it as the value of the
parameter, otherwise use the name as the value of the parameter.

@param rs        the CoordinateTransform
@param paramName the parameter name
@param ds        dataset
@param v         variable
@param attName   variable attribute name
@param readData  if true, read data and use a  s parameter value
@return true if success, false is failed

Add a Parameter to a CoordinateTransform . The variable attribute points to a another variable that has the data in it . Make sure that atrribute and variable exist . Id readData is true read the data and use it as the value of the parameter otherwise use the name as the value of the parameter .


public Group commonParent(Group other) {
    if (isParent(other)) return this;
    if (other.isParent(this)) return other;
    while (!other.isParent(this))
      other = other.getParentGroup();
    return other;
  }

public Group commonParent ( Group other ) { if ( isParent ( other ) ) return this ; if ( other . isParent ( this ) ) return other ; while ( ! other . isParent ( this ) ) other = other . getParentGroup ( ) ; return other ; }

Get the common parent of this and the other group.
Cant fail, since the root group is always a parent of any 2 groups.

@param other the other group
@return common parent of this and the other group

Get the common parent of this and the other group . Cant fail since the root group is always a parent of any 2 groups .


public boolean isParent(Group other) {
    while ((other != this) && (other.getParentGroup() != null))
      other = other.getParentGroup();
    return (other == this);
  }

public boolean isParent ( Group other ) { while ( ( other != this ) && ( other . getParentGroup ( ) != null ) ) other = other . getParentGroup ( ) ; return ( other == this ) ; }

Is this a parent of the other Group?

@param other another Group
@return true is it is equal or a parent


public void setParentGroup(Group parent) {
    if (immutable) throw new IllegalStateException("Cant modify");
    super.setParentGroup(parent == null ? ncfile.getRootGroup() : parent);
  }

public
void
setParentGroup
(
Group
parent
)
{
if
(
immutable
)
throw
new
IllegalStateException
(
"Cant modify"
)
;
super
.
setParentGroup
(
parent
==
ncfile
.
getRootGroup
(
)
:
parent
)
;
}

Set the Group's parent Group

@param parent parent group.


public void addDimension(Dimension dim) {
    if (immutable) throw new IllegalStateException("Cant modify");

    if (!dim.isShared()) {
      throw new IllegalArgumentException("Dimensions added to a group must be shared.");
    }

    if (findDimensionLocal(dim.getShortName()) != null)
      throw new IllegalArgumentException("Dimension name (" + dim.getShortName() + ") must be unique within Group " + getShortName());

    dimensions.add(dim);
    dim.setGroup(this);
  }

Adds the specified shared dimension to this group.

@param dim  the dimension to add.
@throws IllegalStateException  if this dimension is {@link #setImmutable() immutable}.
@throws IllegalArgumentException  if {@code dim} isn't shared or a dimension with {@code dim}'s name already
exists within the group.

Adds the specified shared dimension to this group .


public boolean addDimensionIfNotExists(Dimension dim) {
    if (immutable) throw new IllegalStateException("Cant modify");

    if (!dim.isShared()) {
      throw new IllegalArgumentException("Dimensions added to a group must be shared.");
    }

    if (findDimensionLocal(dim.getShortName()) != null)
      return false;

    dimensions.add(dim);
    dim.setGroup(this);
    return true;
  }

Adds the specified shared dimension to this group, but only if another dimension with the same name doesn't
already exist.

@param dim  the dimension to add.
@return {@code true} if {@code dim} was successfully added to the group. Otherwise, {@code false} will be returned,
meaning that a dimension with {@code dim}'s name already exists within the group.
@throws IllegalStateException  if this dimension is {@link #setImmutable() immutable}.
@throws IllegalArgumentException  if {@code dim} isn't shared.

Adds the specified shared dimension to this group but only if another dimension with the same name doesn t already exist .


public void addGroup(Group g) {
    if (immutable) throw new IllegalStateException("Cant modify");

    if (findGroup(g.getShortName()) != null)
      throw new IllegalArgumentException("Group name (" + g.getShortName() + ") must be unique within Group " + getShortName());

    groups.add(g);
    g.setParentGroup(this); // groups are a tree - only one parent
  }

public
void
addGroup
(
Group
g
)
{
if
(
immutable
)
throw
new
IllegalStateException
(
"Cant modify"
)
;
if
(
findGroup
(
g
.
getShortName
(
)
)
!=
)
throw
new
IllegalArgumentException
(
"Group name ("
+
g
.
getShortName
(
)
+
") must be unique within Group "
+
getShortName
(
)
)
;
groups
.
add
(
g
)
;
g
.
setParentGroup
(
this
)
;
// groups are a tree - only one parent
}

Add a nested Group

@param g add this Group.


public void addEnumeration(EnumTypedef e) {
    if (immutable) throw new IllegalStateException("Cant modify");
    if (e == null) return;
    e.setParentGroup(this);
    enumTypedefs.add(e);
  }

public
void
addEnumeration
(
EnumTypedef
e
)
{
if
(
immutable
)
throw
new
IllegalStateException
(
"Cant modify"
)
;
if
(
e
==
)
return
;
e
.
setParentGroup
(
this
)
;
enumTypedefs
.
add
(
e
)
;
}

Add an Enumeration

@param e add this Enumeration.


public void addVariable(Variable v) {
    if (immutable) throw new IllegalStateException("Cant modify");
    if (v == null) return;

    if (findVariable(v.getShortName()) != null) {
      //Variable other = findVariable(v.getShortName()); // debug
      throw new IllegalArgumentException("Variable name (" + v.getShortName() + ") must be unique within Group " + getShortName());
    }

    variables.add(v);
    v.setParentGroup(this); // variable can only be in one group
  }

Add a Variable

@param v add this Variable.


public boolean removeDimension(String dimName) {
    if (immutable) throw new IllegalStateException("Cant modify");
    for (int i = 0; i < dimensions.size(); i++) {
      Dimension d = dimensions.get(i);
      if (dimName.equals(d.getShortName())) {
        dimensions.remove(d);
        return true;
      }
    }
    return false;
  }

public
boolean
removeDimension
(
String
dimName
)
{
if
(
immutable
)
throw
new
IllegalStateException
(
"Cant modify"
)
;
for
(
int
i
=
0
;
i
<
dimensions
.
size
(
)
;
i
++
)
{
Dimension
d
=
dimensions
.
get
(
i
)
;
if
(
dimName
.
equals
(
d
.
getShortName
(
)
)
)
{
dimensions
.
remove
(
d
)
;
return
true
;
}
}
return
false
;
}

remove a Dimension using its name, in this group only

@param dimName Dimension name.
@return true if dimension found and removed

remove a Dimension using its name in this group only


public Group makeRelativeGroup(NetcdfFile ncf, String path, boolean ignorelast) {
    path = path.trim();
    path = path.replace("//", "/");
    boolean isabsolute = (path.charAt(0) == '/');
    if (isabsolute)
      path = path.substring(1);

    // iteratively create path
    String pieces[] = path.split("/");
    if (ignorelast) pieces[pieces.length - 1] = null;

    Group current = (isabsolute ? ncfile.getRootGroup() : this);
    for (String name : pieces) {
      if (name == null) continue;
      String clearname = NetcdfFile.makeNameUnescaped(name);  //??
      Group next = current.findGroup(clearname);
      if (next == null) {
        next = new Group(ncf, current, clearname);
        current.addGroup(next);
      }
      current = next;
    }
    return current;
  }

public
Group
makeRelativeGroup
(
NetcdfFile
ncf
,
String
path
,
boolean
ignorelast
)
{
path
=
path
.
trim
(
)
;
path
=
path
.
replace
(
"//"
,
"/"
)
;
boolean
isabsolute
=
(
path
.
charAt
(
0
)
==
'
'
)
;
if
(
isabsolute
)
path
=
path
.
substring
(
1
)
;
// iteratively create path
String
pieces
[
]
=
path
.
split
(
"/"
)
;
if
(
ignorelast
)
pieces
[
pieces
.
length
1
]
=
;
Group
current
=
(
isabsolute
ncfile
.
getRootGroup
(
)
:
this
)
;
for
(
String
name
:
pieces
)
{
if
(
name
==
)
continue
;
String
clearname
=
NetcdfFile
.
makeNameUnescaped
(
name
)
;
//??
Group
next
=
current
.
findGroup
(
clearname
)
;
if
(
next
==
)
{
next
=
new
Group
(
ncf
,
current
,
clearname
)
;
current
.
addGroup
(
next
)
;
}
current
=
next
;
}
return
current
;
}

Create groups to ensure path is defined

@param ncf        the containing netcdf file object
@param path       the path to the desired group
@param ignorelast true => ignore last element in the path
@return the Group, or null if not found


private String convertDDSAliasFieldsToDASAliasFields(String attribute) throws MalformedAliasException
    {

        String prefix = "";

        Vector aNames = tokenizeAliasField(attribute);

        // We know that the first token should be a dot, we look at the
        // second token to see if it references a variable in the DDS.

        String topName = (String) aNames.get(1);

        boolean foundIt = false;
        Enumeration e = getVariables();
        while (e.hasMoreElements()) {
            BaseType bt = (BaseType) e.nextElement();
            String normName = normalize(bt.getEncodedName());

            if (topName.equals(normName))
                foundIt = true;
        }

        if (!foundIt) {
// The Attribute referenced is at the top level of the DDS itself.
            // The Attributes at the top level of the DDS get repackaged into
            // a special AttributeTable, this makes the Aliases that point to
            // any of these Attribute resolve correctly.
            prefix = "." + getLooseEndsTableName();

        }

        return (prefix + attribute);

    }

This method just makes sure that the attribute field in each Aliases resolves correctly
if there ends up being a "looseEnds" Attribute Table at the top level.

@param attribute
@return
@throws MalformedAliasException

This method just makes sure that the attribute field in each Aliases resolves correctly if there ends up being a looseEnds Attribute Table at the top level .


public void printDAS(PrintWriter pw)
    {

        DAS myDAS = null;

        try {
            myDAS = this.getDAS();
            myDAS.print(pw);
        } catch (DASException dasE) {
            pw.println("\n\nCould not get a DAS object to print!\n" +
                    "DDS.getDAS() threw an Exception. Message: \n" +
                    dasE.getMessage());
        }
    }

Print a DAS constructed from this DDS and it's BaseType variables.

@param pw The PrintWriter to print to.

Print a DAS constructed from this DDS and it s BaseType variables .


public BaseType getVariable(String name) throws NoSuchVariableException
    {
        Stack s = new Stack();
        s = search(name, s);
        return (BaseType) s.pop();
    }

public BaseType getVariable ( String name ) throws NoSuchVariableException { Stack s = new Stack ( ) ; s = search ( name , s ) ; return ( BaseType ) s . pop ( ) ; }

Returns a reference to the named variable.

@param name the name of the variable to return.
@return the variable named name.
@throws NoSuchVariableException if the variable isn't found.

Returns a reference to the named variable .


public void writeGrid(GridDataset dataset, GridDatatype grid, Array data, boolean greyScale) throws IOException {
    GridCoordSystem gcs = grid.getCoordinateSystem();

    if (!gcs.isRegularSpatial()) {
      throw new IllegalArgumentException("Must have 1D x and y axes for " + grid.getFullName());
    }

    CoordinateAxis1D xaxis = (CoordinateAxis1D) gcs.getXHorizAxis();
    CoordinateAxis1D yaxis = (CoordinateAxis1D) gcs.getYHorizAxis();

    // units may need to be scaled to meters
    double scaler = (xaxis.getUnitsString().equalsIgnoreCase("km")) ? 1000.0 : 1.0;

    // data must go from top to bottom
    double xStart = xaxis.getCoordEdge(0) * scaler;
    double yStart = yaxis.getCoordEdge(0) * scaler;
    double xInc = xaxis.getIncrement() * scaler;
    double yInc = Math.abs(yaxis.getIncrement()) * scaler;

    if (yaxis.getCoordValue(0) < yaxis.getCoordValue(1)) {
      data = data.flip(0);
      yStart = yaxis.getCoordEdge((int) yaxis.getSize()) * scaler;
    }

    if (!xaxis.isRegular() || !yaxis.isRegular()) {
      throw new IllegalArgumentException("Must be evenly spaced grid = " + grid.getFullName());
    }

    if (pageNumber > 1) {
      geotiff.initTags();
    }

    // write it out
    writeGrid(grid, data, greyScale, xStart, yStart, xInc, yInc, pageNumber);
    pageNumber++;
  }

Write GridDatatype data to the geotiff file.

@param dataset   grid in contained in this dataset
@param grid      data is in this grid
@param data      2D array in YX order
@param greyScale if true, write greyScale image, else dataSample.
@throws IOException on i/o error

Write GridDatatype data to the geotiff file .


private ArrayFloat replaceMissingValues(IsMissingEvaluator grid, Array data, MAMath.MinMax dataMinMax) {
    float minValue = (float) (dataMinMax.min - 1.0);

    ArrayFloat floatArray = (ArrayFloat) Array.factory(DataType.FLOAT, data.getShape());
    IndexIterator dataIter = data.getIndexIterator();
    IndexIterator floatIter = floatArray.getIndexIterator();
    while (dataIter.hasNext()) {
      float v = dataIter.getFloatNext();
      if (grid.isMissing((double) v)) {
        v = minValue;
      }
      floatIter.setFloatNext(v);
    }

    return floatArray;
  }

private ArrayFloat replaceMissingValues ( IsMissingEvaluator grid , Array data , MAMath . MinMax dataMinMax ) { float minValue = ( float ) ( dataMinMax . min - 1.0 ) ; ArrayFloat floatArray = ( ArrayFloat ) Array . factory ( DataType . FLOAT , data . getShape ( ) ) ; IndexIterator dataIter = data . getIndexIterator ( ) ; IndexIterator floatIter = floatArray . getIndexIterator ( ) ; while ( dataIter . hasNext ( ) ) { float v = dataIter . getFloatNext ( ) ; if ( grid . isMissing ( ( double ) v ) ) { v = minValue ; } floatIter . setFloatNext ( v ) ; } return floatArray ; }

Replace missing values with dataMinMax.min - 1.0; return a floating point data array.

@param grid GridDatatype
@param data input data array
@return floating point data array with missing values replaced.

Replace missing values with dataMinMax . min - 1 . 0 ; return a floating point data array .


private ArrayByte replaceMissingValuesAndScale(IsMissingEvaluator grid, Array data, MAMath.MinMax dataMinMax) {
    double scale = 254.0 / (dataMinMax.max - dataMinMax.min);

    ArrayByte byteArray = (ArrayByte) Array.factory(DataType.BYTE, data.getShape());
    IndexIterator dataIter = data.getIndexIterator();
    IndexIterator resultIter = byteArray.getIndexIterator();

    byte bv;
    while (dataIter.hasNext()) {
      double v = dataIter.getDoubleNext();
      if (grid.isMissing(v)) {
        bv = 0;
      } else {
        int iv = (int) ((v - dataMinMax.min) * scale + 1);
        bv = (byte) (iv & 0xff);
      }
      resultIter.setByteNext(bv);
    }

    return byteArray;
  }

private ArrayByte replaceMissingValuesAndScale ( IsMissingEvaluator grid , Array data , MAMath . MinMax dataMinMax ) { double scale = 254.0 / ( dataMinMax . max - dataMinMax . min ) ; ArrayByte byteArray = ( ArrayByte ) Array . factory ( DataType . BYTE , data . getShape ( ) ) ; IndexIterator dataIter = data . getIndexIterator ( ) ; IndexIterator resultIter = byteArray . getIndexIterator ( ) ; byte bv ; while ( dataIter . hasNext ( ) ) { double v = dataIter . getDoubleNext ( ) ; if ( grid . isMissing ( v ) ) { bv = 0 ; } else { int iv = ( int ) ( ( v - dataMinMax . min ) * scale + 1 ) ; bv = ( byte ) ( iv & 0xff ) ; } resultIter . setByteNext ( bv ) ; } return byteArray ; }

Replace missing values with 0; scale other values between 1 and 255, return a byte data array.

@param grid GridDatatype
@param data input data array
@return byte data array with missing values replaced and data scaled from 1- 255.

Replace missing values with 0 ; scale other values between 1 and 255 return a byte data array .


private double geoShiftGetXstart(Array lon, double inc) {
    Index ilon = lon.getIndex();
    int[] lonShape = lon.getShape();
    IndexIterator lonIter = lon.getIndexIterator();
    double xlon = 0.0;

    LatLonPoint p0 = new LatLonPointImpl(0, lon.getFloat(ilon.set(0)));
    LatLonPoint pN = new LatLonPointImpl(0, lon.getFloat(ilon.set(lonShape[0] - 1)));

    xlon = p0.getLongitude();
    while (lonIter.hasNext()) {
      float l = lonIter.getFloatNext();
      LatLonPoint pn = new LatLonPointImpl(0, l);
      if (pn.getLongitude() < xlon) {
        xlon = pn.getLongitude();
      }
    }

    if (p0.getLongitude() == pN.getLongitude()) {
      xlon = xlon - inc;
    }

    return xlon;
  }

private double geoShiftGetXstart ( Array lon , double inc ) { Index ilon = lon . getIndex ( ) ; int [ ] lonShape = lon . getShape ( ) ; IndexIterator lonIter = lon . getIndexIterator ( ) ; double xlon = 0.0 ; LatLonPoint p0 = new LatLonPointImpl ( 0 , lon . getFloat ( ilon . set ( 0 ) ) ) ; LatLonPoint pN = new LatLonPointImpl ( 0 , lon . getFloat ( ilon . set ( lonShape [ 0 ] - 1 ) ) ) ; xlon = p0 . getLongitude ( ) ; while ( lonIter . hasNext ( ) ) { float l = lonIter . getFloatNext ( ) ; LatLonPoint pn = new LatLonPointImpl ( 0 , l ) ; if ( pn . getLongitude ( ) < xlon ) { xlon = pn . getLongitude ( ) ; } } if ( p0 . getLongitude ( ) == pN . getLongitude ( ) ) { xlon = xlon - inc ; } return xlon ; }

LOOK WTF ?? is this the seam crossing ??


public void writeGrid(GeoReferencedArray array, boolean greyScale) throws IOException {

    CoverageCoordSys gcs = array.getCoordSysForData();
    if (!gcs.isRegularSpatial())
      throw new IllegalArgumentException("Must have 1D x and y axes for " + array.getCoverageName());

    Projection proj = gcs.getProjection();
    CoverageCoordAxis1D xaxis = (CoverageCoordAxis1D) gcs.getXAxis();
    CoverageCoordAxis1D yaxis = (CoverageCoordAxis1D) gcs.getYAxis();

    // latlon coord does not need to be scaled
    double scaler = (xaxis.getUnits().equalsIgnoreCase("km")) ? 1000.0 : 1.0;

    // data must go from top to bottom
    double xStart = xaxis.getCoordEdge1(0) * scaler;
    double yStart = yaxis.getCoordEdge1(0) * scaler;
    double xInc = xaxis.getResolution() * scaler;
    double yInc = Math.abs(yaxis.getResolution()) * scaler;

    Array data = array.getData().reduce();
    if (yaxis.getCoordMidpoint(0) < yaxis.getCoordMidpoint(1)) {
      data = data.flip(0);
      yStart = yaxis.getCoordEdgeLast();
    }

    /*  remove - i think unneeded, monotonic lon handled in CoordinateAxis1D. JC 3/18/2013
     if (gcs.isLatLon()) {
      Array lon = xaxis.read();
      data = geoShiftDataAtLon(data, lon);
      xStart = geoShiftGetXstart(lon, xInc);
      //xStart = -180.0;
    }  */

    if (pageNumber > 1) {
      geotiff.initTags();
    }

    // write the data first
    int nextStart = 0;
    MAMath.MinMax dataMinMax = MAMath.getMinMaxSkipMissingData(data, array);
    if (greyScale) {
      ArrayByte result = replaceMissingValuesAndScale(array, data, dataMinMax);
      nextStart = geotiff.writeData((byte[]) result.getStorage(), pageNumber);
    } else {
      ArrayFloat result = replaceMissingValues(array, data, dataMinMax);
      nextStart = geotiff.writeData((float[]) result.getStorage(), pageNumber);
    }

    // set the width and the height
    int height = data.getShape()[0];         // Y
    int width = data.getShape()[1];         // X

    writeMetadata(greyScale, xStart, yStart, xInc, yInc, height, width, pageNumber, nextStart, dataMinMax, proj);
    pageNumber++;
  }

Write GridCoverage data to the geotiff file.

@param array      GeoReferencedArray array in YX order
@param greyScale if true, write greyScale image, else dataSample.
@throws IOException on i/o error

Write GridCoverage data to the geotiff file .


public void write(HttpServletResponse hsr) throws IOException{
		PrintWriter xmlResponse = hsr.getWriter();

		xmlResponse.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		xmlResponse.append("<ows:ExceptionReport xml:lang=\"en-US\" xsi:schemaLocation=\"http://www.opengis.net/ows/1.1"
				+ " http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd\" version=\"2.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\""
				+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
		xmlResponse.append("<ows:Exception ");
		if(locator != null) xmlResponse.append("locator=\"" + locator + "\" ");
		xmlResponse.append("exceptionCode=\"" + ExceptionCode + "\">");
		xmlResponse.append("<ows:ExceptionText>" + text + "</ows:ExceptionText>");
		xmlResponse.append("</ows:Exception>");
		xmlResponse.append("</ows:ExceptionReport>");
	}

Given the information on construction, writes the necessary exception information.

@param hsr the Servlet Response to write to
@throws IOException

Given the information on construction writes the necessary exception information .


@Override
    public synchronized
    String nc_inq_libvers() {
    String ret;
    try {ce();
    ret = nc4.nc_inq_libvers();
    if(TRACE) trace(ret,"nc_inq_libvers","-");
    } finally {cx();}
    return ret;
    }

@ Override public synchronized String nc_inq_libvers ( ) { String ret ; try { ce ( ) ; ret = nc4 . nc_inq_libvers ( ) ; if ( TRACE ) trace ( ret , "nc_inq_libvers" , "-" ) ; } finally { cx ( ) ; } return ret ; }


private static File makeTopIndexFileFromConfig(FeatureCollectionConfig config) {
    Formatter errlog = new Formatter();
    CollectionSpecParser specp = config.getCollectionSpecParser(errlog);

    String name = StringUtil2.replace(config.collectionName, '\\', "/");
    // String cname = DirectoryCollection.makeCollectionName(name, Paths.get(specp.getRootDir()));

    return makeIndexFile(name, new File(specp.getRootDir()));
  }

This is only used for the top level GribCollection.

@param config use this FeatureCollectionConfig
@return index File

This is only used for the top level GribCollection .


public static GribCollectionType getType(RandomAccessFile raf) throws IOException {
    String magic;

    raf.seek(0);
    magic = raf.readString(Grib2CollectionWriter.MAGIC_START.getBytes(CDM.utf8Charset).length);

    switch (magic) {
      case Grib2CollectionWriter.MAGIC_START:
        return GribCollectionType.GRIB2;

      case Grib1CollectionWriter.MAGIC_START:
        return GribCollectionType.GRIB1;

      case Grib2PartitionBuilder.MAGIC_START:
        return GribCollectionType.Partition2;

      case Grib1PartitionBuilder.MAGIC_START:
        return GribCollectionType.Partition1;

    }
    return GribCollectionType.none;
  }

public static GribCollectionType getType ( RandomAccessFile raf ) throws IOException { String magic ; raf . seek ( 0 ) ; magic = raf . readString ( Grib2CollectionWriter . MAGIC_START . getBytes ( CDM . utf8Charset ) . length ) ; switch ( magic ) { case Grib2CollectionWriter . MAGIC_START : return GribCollectionType . GRIB2 ; case Grib1CollectionWriter . MAGIC_START : return GribCollectionType . GRIB1 ; case Grib2PartitionBuilder . MAGIC_START : return GribCollectionType . Partition2 ; case Grib1PartitionBuilder . MAGIC_START : return GribCollectionType . Partition1 ; } return GribCollectionType . none ; }

Find out what kind of index this is

@param raf open RAF
@return GribCollectionType
@throws IOException on read error


public static boolean updateGribCollection(FeatureCollectionConfig config, CollectionUpdateType updateType, Logger logger) throws IOException {
    if (logger == null) logger = classLogger;

    long start = System.currentTimeMillis();

    Formatter errlog = new Formatter();
    CollectionSpecParser specp = config.getCollectionSpecParser(errlog);
    Path rootPath = Paths.get(specp.getRootDir());
    boolean isGrib1 = config.type == FeatureCollectionType.GRIB1;

    boolean changed;

    if (config.ptype == FeatureCollectionConfig.PartitionType.none || config.ptype == FeatureCollectionConfig.PartitionType.all) {

      try (CollectionAbstract dcm = new CollectionPathMatcher(config, specp, logger)) {
        changed = updateGribCollection(isGrib1, dcm, updateType, FeatureCollectionConfig.PartitionType.none, logger, errlog);
      }

    } else if (config.ptype == FeatureCollectionConfig.PartitionType.timePeriod) {

      try (TimePartition tp = new TimePartition(config, specp, logger)) {
        changed = updateTimePartition(isGrib1, tp, updateType, logger);
      }

    } else {

      // LOOK assume wantSubdirs makes it into a Partition. Isnt there something better ??
      if (specp.wantSubdirs()) {  // its a partition

        try (DirectoryPartition dpart = new DirectoryPartition(config, rootPath, true, new GribCdmIndex(logger), NCX_SUFFIX, logger)) {
          dpart.putAuxInfo(FeatureCollectionConfig.AUX_CONFIG, config);
          changed = updateDirectoryCollectionRecurse(isGrib1, dpart, config, updateType, logger);
        }

      } else { // otherwise its a leaf directory
        changed = updateLeafCollection(isGrib1, config, updateType, true, logger, rootPath);
      }
    }

    long took = System.currentTimeMillis() - start;
    logger.info("updateGribCollection {} changed {} took {} msecs", config.collectionName, changed, took);
    return changed;
  }

Update Grib Collection if needed

@return true if the collection was updated


private static boolean updateLeafCollection(boolean isGrib1, FeatureCollectionConfig config,
                                              CollectionUpdateType updateType, boolean isTop,
                                              Logger logger, Path dirPath) throws IOException {

    if (config.ptype == FeatureCollectionConfig.PartitionType.file) {
      return updateFilePartition(isGrib1, config, updateType, isTop, logger, dirPath);

    } else {
      Formatter errlog = new Formatter();
      CollectionSpecParser specp = config.getCollectionSpecParser(errlog);

      try (DirectoryCollection dcm = new DirectoryCollection(config.collectionName, dirPath, isTop, config.olderThan, logger)) {
        dcm.putAuxInfo(FeatureCollectionConfig.AUX_CONFIG, config);
        if (specp.getFilter() != null)
          dcm.setStreamFilter(new StreamFilter(specp.getFilter(), specp.getFilterOnName()));

        boolean changed = updateGribCollection(isGrib1, dcm, updateType, FeatureCollectionConfig.PartitionType.directory, logger, errlog);
        logger.debug("  GribCdmIndex.updateDirectoryPartition was updated=%s on %s%n", changed, dirPath);
        return changed;
      }
    }

  }

Update all the gbx indices in one directory, and the ncx index for that directory

@param config  FeatureCollectionConfig
@param dirPath directory path
@return true if collection was rewritten, exception on failure

Update all the gbx indices in one directory and the ncx index for that directory


public static GribCollectionImmutable openGribCollectionFromRaf(RandomAccessFile raf, FeatureCollectionConfig config,
                CollectionUpdateType updateType, org.slf4j.Logger logger) throws IOException {

    GribCollectionImmutable result;

    // check if its a plain ole GRIB1/2 data file
    boolean isGrib1 = false;
    boolean isGrib2 = Grib2RecordScanner.isValidFile(raf);
    if (!isGrib2) isGrib1 = Grib1RecordScanner.isValidFile(raf);

    if (isGrib1 || isGrib2) {
      result = openGribCollectionFromDataFile(isGrib1, raf, config, updateType, null, logger);
      // close the data file, the ncx raf file is managed by gribCollection
      raf.close();

    } else  {  // check its an ncx file
      result = openGribCollectionFromIndexFile(raf, config, logger);
    }

    return result;
  }


private static GribCollectionImmutable openGribCollectionFromDataFile(boolean isGrib1, RandomAccessFile dataRaf, FeatureCollectionConfig config,
                                                                        CollectionUpdateType updateType, Formatter errlog, org.slf4j.Logger logger) throws IOException {

    String filename = dataRaf.getLocation();
    File dataFile = new File(filename);

    MFile mfile = new MFileOS(dataFile);
    return openGribCollectionFromDataFile(isGrib1, mfile, updateType, config, errlog, logger);
  }

private static GribCollectionImmutable openGribCollectionFromDataFile ( boolean isGrib1 , RandomAccessFile dataRaf , FeatureCollectionConfig config , CollectionUpdateType updateType , Formatter errlog , org . slf4j . Logger logger ) throws IOException { String filename = dataRaf . getLocation ( ) ; File dataFile = new File ( filename ) ; MFile mfile = new MFileOS ( dataFile ) ; return openGribCollectionFromDataFile ( isGrib1 , mfile , updateType , config , errlog , logger ) ; }

Open a grib collection from a single grib1 or grib2 file.
Create the gbx9 and ncx2 files if needed.

@param isGrib1    true if grib1
@param dataRaf    the data file already open
@param config     special configuration
@param updateType force writing index
@return the resulting GribCollection
@throws IOException on io error

Open a grib collection from a single grib1 or grib2 file . Create the gbx9 and ncx2 files if needed .


@Nullable
  public static GribCollectionImmutable openGribCollectionFromDataFile(boolean isGrib1, MFile mfile, CollectionUpdateType updateType,
                                                                       FeatureCollectionConfig config, Formatter errlog, org.slf4j.Logger logger) throws IOException {

    MCollection dcm = new CollectionSingleFile(mfile, logger);
    dcm.putAuxInfo(FeatureCollectionConfig.AUX_CONFIG, config);
    if (isGrib1) {
      Grib1CollectionBuilder builder = new Grib1CollectionBuilder(dcm.getCollectionName(), dcm, logger);       // LOOK ignoring partition type
      boolean changed = (builder.updateNeeded(updateType) && builder.createIndex(FeatureCollectionConfig.PartitionType.file, errlog));
    } else {
      Grib2CollectionBuilder builder = new Grib2CollectionBuilder(dcm.getCollectionName(), dcm, logger);
      boolean changed = (builder.updateNeeded(updateType) && builder.createIndex(FeatureCollectionConfig.PartitionType.file, errlog));
    }

    // the index file should now exist, open it
    GribCollectionImmutable result = openCdmIndex(dcm.getIndexFilename(NCX_SUFFIX), config, true, logger);
    if (result != null) return result;

    // if open fails, force recreate the index
    if (updateType == CollectionUpdateType.never) return null; // not allowed to write
    if (updateType == CollectionUpdateType.always) return null;// already tried to force write, give up
    return openGribCollectionFromDataFile(isGrib1, mfile, CollectionUpdateType.always, config, errlog, logger);
  }

from a single file, read in the index, create if it doesnt exist; return null on failure

from a single file read in the index create if it doesnt exist ; return null on failure


static boolean
  urlMatch(URL pattern, URL url) {
    int relation;

    if (pattern == null)
      return (url == null);

    if (!(url.getHost().endsWith(pattern.getHost())))
      return false; // e.g. pattern=x.y.org url=y.org

    if (!(url.getPath().startsWith(pattern.getPath())))
      return false; // e.g. pattern=y.org/a/b url=y.org/a

    if (pattern.getPort() > 0 && pattern.getPort() != url.getPort())
      return false;

    // note: all other fields are ignored

    return true;
  }

static
boolean
urlMatch
(
URL
pattern
,
URL
url
)
{
int
relation
;
if
(
pattern
==
)
return
(
url
==
)
;
if
(
!
(
url
.
getHost
(
)
.
endsWith
(
pattern
.
getHost
(
)
)
)
)
return
false
;
// e.g. pattern=x.y.org url=y.org
if
(
!
(
url
.
getPath
(
)
.
startsWith
(
pattern
.
getPath
(
)
)
)
)
return
false
;
// e.g. pattern=y.org/a/b url=y.org/a
if
(
pattern
.
getPort
(
)
>
0
&&
pattern
.
getPort
(
)
!=
url
.
getPort
(
)
)
return
false
;
// note: all other fields are ignored
return
true
;
}

Match has different semantics than urlCompare


static synchronized public void
  add(String key, String value, String url) {
    if (key == null) return;
    if (!initialized) RC.initialize();
    Triple t = new Triple(key, value, url);
    dfaltRC.insert(t);
    // recompute well-knowns
    setWellKnown();
  }

static
synchronized
public
void
add
(
String
key
,
String
value
,
String
url
)
{
if
(
key
==
)
return
;
if
(
!
initialized
)
RC
.
initialize
(
)
;
Triple
t
=
new
Triple
(
key
,
value
,
url
)
;
dfaltRC
.
insert
(
t
)
;
// recompute well-knowns
setWellKnown
(
)
;
}

Allow users to add to the default rc

@param key
@param value
@param url   null => not url specific


static synchronized public String
  find(String key, String url) {
    if (key == null) return null;
    if (!initialized) RC.initialize();
    Triple t = dfaltRC.lookup(key, url);
    return (t == null ? null : t.value);
  }

static synchronized public String find ( String key , String url ) { if ( key == null ) return null ; if ( ! initialized ) RC . initialize ( ) ; Triple t = dfaltRC . lookup ( key , url ) ; return ( t == null ? null : t . value ) ; }

Allow users to search the default rc

@param key
@param url null => not url specific
@return value corresponding to key+url, or null if does not exist


static void
  setWellKnown() {
    if (dfaltRC.triplestore.size() == 0) return;
    // Walk the set of triples looking for those that have no url
    for (String key : dfaltRC.keySet()) {
      Triple triple = dfaltRC.lookup(key);
      if (triple.url == null) {
        RC.set(key, triple.value); // let set sort it out
      }
    }
  }


public boolean
  load(String abspath) {
    abspath = abspath.replace('\\', '/');
    File rcFile = new File(abspath);
    if (!rcFile.exists() || !rcFile.canRead()) {
      return false;
    }
    if (showlog) log.debug("Loading rc file: " + abspath);
    try (BufferedReader rdr = new BufferedReader(new InputStreamReader(new FileInputStream(rcFile), CDM.UTF8))) {
        for (int lineno = 1; ; lineno++) {
          URL url = null;
          String line = rdr.readLine();
          if (line == null) break;
          // trim leading blanks
          line = line.trim();
          if (line.length() == 0) continue; // empty line
          if (line.charAt(0) == '#') continue; // check for comment
          // parse the line
          if (line.charAt(0) == LTAG) {
            int rindex = line.indexOf(RTAG);
            if (rindex < 0) return false;
            if (showlog) log.error("Malformed [url] at " + abspath + "." + lineno);
            String surl = line.substring(1, rindex);
            try {
              url = new URL(surl);
            } catch (MalformedURLException mue) {
              if (showlog) log.error("Malformed [url] at " + abspath + "." + lineno);
            }
            line = line.substring(rindex + 1);
            // trim again
            line = line.trim();
          }
          // Get the key,value part
          String[] pieces = line.split("\\s*=\\s*");
          assert (pieces.length == 1 || pieces.length == 2);
          // Create the triple
          String value = "1";
          if (pieces.length == 2) value = pieces[1].trim();
          Triple triple = new Triple(pieces[0].trim(), value, url);
          List<Triple> list = triplestore.get(triple.key);
          if (list == null) list = new ArrayList<Triple>();
          Triple prev = addtriple(list, triple);
          triplestore.put(triple.key, list);
        }

      } catch (FileNotFoundException fe) {
        if (showlog) log.debug("Loading rc file: " + abspath);
        return false;

      } catch (IOException ioe) {
        if (showlog) log.error("File " + abspath + ": IO exception: " + ioe.getMessage());
        return false;
      }
      return true;
    }

public
boolean
load
(
String
abspath
)
{
abspath
=
abspath
.
replace
(
'
'
,
'
'
)
;
File
rcFile
=
new
File
(
abspath
)
;
if
(
!
rcFile
.
exists
(
)
||
!
rcFile
.
canRead
(
)
)
{
return
false
;
}
if
(
showlog
)
log
.
debug
(
"Loading rc file: "
+
abspath
)
;
try
(
BufferedReader
rdr
=
new
BufferedReader
(
new
InputStreamReader
(
new
FileInputStream
(
rcFile
)
,
CDM
.
UTF8
)
)
)
{
for
(
int
lineno
=
1
;
;
lineno
++
)
{
URL
url
=
;
String
line
=
rdr
.
readLine
(
)
;
if
(
line
==
)
break
;
// trim leading blanks
line
=
line
.
trim
(
)
;
if
(
line
.
length
(
)
==
0
)
continue
;
// empty line
if
(
line
.
charAt
(
0
)
==
'
'
)
continue
;
// check for comment
// parse the line
if
(
line
.
charAt
(
0
)
==
LTAG
)
{
int
rindex
=
line
.
indexOf
(
RTAG
)
;
if
(
rindex
<
0
)
return
false
;
if
(
showlog
)
log
.
error
(
"Malformed [url] at "
+
abspath
+
"."
+
lineno
)
;
String
surl
=
line
.
substring
(
1
,
rindex
)
;
try
{
url
=
new
URL
(
surl
)
;
}
catch
(
MalformedURLException
mue
)
{
if
(
showlog
)
log
.
error
(
"Malformed [url] at "
+
abspath
+
"."
+
lineno
)
;
}
line
=
line
.
substring
(
rindex
+
1
)
;
// trim again
line
=
line
.
trim
(
)
;
}
// Get the key,value part
String
[
]
pieces
=
line
.
split
(
"\\s*=\\s*"
)
;
assert
(
pieces
.
length
==
1
||
pieces
.
length
==
2
)
;
// Create the triple
String
value
=
"1"
;
if
(
pieces
.
length
==
2
)
value
=
pieces
[
1
]
.
trim
(
)
;
Triple
triple
=
new
Triple
(
pieces
[
0
]
.
trim
(
)
,
value
,
url
)
;
List
<
Triple
>
list
=
triplestore
.
get
(
triple
.
key
)
;
if
(
list
==
)
list
=
new
ArrayList
<
Triple
>
(
)
;
Triple
prev
=
addtriple
(
list
,
triple
)
;
triplestore
.
put
(
triple
.
key
,
list
)
;
}
}
catch
(
FileNotFoundException
fe
)
{
if
(
showlog
)
log
.
debug
(
"Loading rc file: "
+
abspath
)
;
return
false
;
}
catch
(
IOException
ioe
)
{
if
(
showlog
)
log
.
error
(
"File "
+
abspath
+
": IO exception: "
+
ioe
.
getMessage
(
)
)
;
return
false
;
}
return
true
;
}


public Triple
  insert(Triple t) {
    if (t.key == null) return null;
    List<Triple> list = triplestore.get(t.key);
    if (list == null) list = new ArrayList<Triple>();
    Triple prev = addtriple(list, t);
    triplestore.put(t.key, list);
    return prev;
  }

public Triple insert ( Triple t ) { if ( t . key == null ) return null ; List < Triple > list = triplestore . get ( t . key ) ; if ( list == null ) list = new ArrayList < Triple > ( ) ; Triple prev = addtriple ( list , t ) ; triplestore . put ( t . key , list ) ; return prev ; }


public List<Dataset> getDatasetsLocal() {
    List<Dataset> datasets = (List<Dataset>) flds.get(Dataset.Datasets);
    return datasets == null ? new ArrayList<>(0) : datasets;
  }

public List < Dataset > getDatasetsLocal ( ) { List < Dataset > datasets = ( List < Dataset > ) flds . get ( Dataset . Datasets ) ; return datasets == null ? new ArrayList <> ( 0 ) : datasets ; }

Get top level datasets contained directly in this catalog.
Do not dereference catRefs.

Get top level datasets contained directly in this catalog . Do not dereference catRefs .


public Dataset findDatasetByName(String name) {
    for (Dataset ds : getDatasets()) {
      if (ds.getName().equals(name)) return ds;
      Dataset result = ds.findDatasetByName(name);
      if (result != null) return result;
    }
    return null;
  }

public Dataset findDatasetByName ( String name ) { for ( Dataset ds : getDatasets ( ) ) { if ( ds . getName ( ) . equals ( name ) ) return ds ; Dataset result = ds . findDatasetByName ( name ) ; if ( result != null ) return result ; } return null ; }

Look though all datasets here or under here. do not go into catrefs

Look though all datasets here or under here . do not go into catrefs


public void setProjection(ProjectionImpl project) {
    displayProject = project;

    if (featSetList == null)
      return;
    Iterator iter = featSetList.iterator();
    while (iter.hasNext()) {
      FeatureSet fs = (FeatureSet) iter.next();
      fs.newProjection = true;
    }
  }

public void setProjection ( ProjectionImpl project ) { displayProject = project ; if ( featSetList == null ) return ; Iterator iter = featSetList . iterator ( ) ; while ( iter . hasNext ( ) ) { FeatureSet fs = ( FeatureSet ) iter . next ( ) ; fs . newProjection = true ; } }

Sets new projection for subsequent drawing.

@param project the new projection

Sets new projection for subsequent drawing .


protected Iterator getShapes(java.awt.Graphics2D g, AffineTransform normal2device) {
    long startTime = System.currentTimeMillis();

    if (featSetList == null) {
      initFeatSetList();
      assert !featSetList.isEmpty();
    }

    // which featureSet should we ue?
    FeatureSet fs = (FeatureSet) featSetList.get(0);
    if (featSetList.size() > 1) {
        // compute scale
      double scale = 1.0;
      try {
        AffineTransform world2device = g.getTransform();
        AffineTransform world2normal = normal2device.createInverse();
        world2normal.concatenate( world2device);
        scale = Math.max(Math.abs(world2normal.getScaleX()), Math.abs(world2normal.getShearX()));   // drawing or printing
        if (Debug.isSet("GisFeature/showTransform")) {
          System.out.println("GisFeature/showTransform: "+world2normal+ "\n scale = "+ scale);
        }
      } catch ( java.awt.geom.NoninvertibleTransformException e) {
        System.out.println( " GisRenderFeature: NoninvertibleTransformException on " + normal2device);
      }
      if (!displayProject.isLatLon())
        scale *= 111.0;  // km/deg
      double minD = Double.MAX_VALUE;
      for (Object aFeatSetList : featSetList) {
        FeatureSet tryfs = (FeatureSet) aFeatSetList;
        double d = Math.abs(scale * tryfs.minDist - pixelMatch);  // we want min features ~ 2 pixels
        if (d < minD) {
          minD = d;
          fs = tryfs;
        }
      }
      if (Debug.isSet("GisFeature/MapResolution")) {
        System.out.println("GisFeature/MapResolution: scale = "+scale+" minDist = "+fs.minDist);
      }
    }

    // we may have deferred the actual creation of the points
    if (fs.featureList == null)
      fs.createFeatures();

    // ok, now see if we need to project
    if (!displayProject.equals(fs.project)) {
      fs.setProjection( displayProject);
    } else {    // deal with LatLon
      if (fs.newProjection && displayProject.isLatLon()) {
        fs.setProjection( displayProject);
      }
    }
    fs.newProjection = false;

    if (Debug.isSet("GisFeature/timing/getShapes")) {
      long tookTime = System.currentTimeMillis() - startTime;
      System.out.println("timing.getShapes: " + tookTime*.001 + " seconds");
    }

      // so return it, already
    return fs.getShapes();
  }

we have to deal with both projections and resolution-dependence

we have to deal with both projections and resolution - dependence


private ArrayList makeShapes(Iterator featList) {
    Shape shape;
    ArrayList shapeList = new ArrayList();
    ProjectionImpl dataProject = getDataProjection();

    if (Debug.isSet("GisFeature/MapDraw")) {
      System.out.println("GisFeature/MapDraw: makeShapes with "+displayProject);
    }

/*    if (Debug.isSet("bug.drawShapes")) {
      int count =0;
      // make each GisPart a seperate shape for debugging
feats:while (featList.hasNext()) {
        AbstractGisFeature feature = (AbstractGisFeature) featList.next();
        java.util.Iterator pi = feature.getGisParts();
        while (pi.hasNext()) {
          GisPart gp = (GisPart) pi.next();
          int np = gp.getNumPoints();
          GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, np);
          double[] xx = gp.getX();
          double[] yy = gp.getY();
          path.moveTo((float) xx[0], (float) yy[0]);
          if (count == 63)
                System.out.println("moveTo x ="+xx[0]+" y= "+yy[0]);
          for(int i = 1; i < np; i++) {
            path.lineTo((float) xx[i], (float) yy[i]);
            if (count == 63)
                System.out.println("lineTo x ="+xx[i]+" y= "+yy[i]);
          }
          shapeList.add(path);
          if (count == 63)
            break feats;
          count++;
        }
      }
      System.out.println("bug.drawShapes: #shapes =" +shapeList.size());
      return shapeList;
    }  */

    while (featList.hasNext()) {
      AbstractGisFeature feature = (AbstractGisFeature) featList.next();
      if (dataProject.isLatLon())   // always got to run it through if its lat/lon
        shape = feature.getProjectedShape(displayProject);
      else if (dataProject == displayProject)
        shape = feature.getShape();
      else
        shape = feature.getProjectedShape(dataProject, displayProject);

      shapeList.add(shape);
    }

    return shapeList;
  }

make an ArrayList of Shapes from the given featureList and current display Projection


public final int
    compareTo(String string)
    {
	return getID().length() >= string.length()
		? getID().compareToIgnoreCase(string)
		: getID().compareToIgnoreCase(
		    string.substring(0, getID().length()));
    }

public final int compareTo ( String string ) { return getID ( ) . length ( ) >= string . length ( ) ? getID ( ) . compareToIgnoreCase ( string ) : getID ( ) . compareToIgnoreCase ( string . substring ( 0 , getID ( ) . length ( ) ) ) ; }

Compares this PrefixName with a string.
@param string		The string to compare this PrefixName against.
@return			A negative value, zero, or a positive value
depending on whether this PrefixName is less
than, equal to, or greater than
string, respectively.

Compares this PrefixName with a string .


public boolean startProgressMonitorTask( ProgressMonitorTask pmt) {
    if (busy) return false;
    busy = true;

    this.task = pmt;
    isCancelled = false;
    count = 0;
    setIcon(icon[0]);

    // create timer, whose events happen on the awt event Thread
    ActionListener watcher = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        //System.out.println("timer event"+evt);

        if (isCancelled && !task.isCancel()) {
          task.cancel();
          if (debug) System.out.println(" task.cancel");
          return; // give it a chance to finish up
        } else {
          // indicate progress
          count++;
          setIcon( icon[count % 2]);
          if (debug) System.out.println(" stop count="+count);
        }

        // need to make sure task acknowledges the cancel; so dont shut down
        // until the task is done
        if (task.isDone()) {
          if (myTimer != null)
            myTimer.stop();
          myTimer = null;

          if (task.isError())
            javax.swing.JOptionPane.showMessageDialog(null, task.getErrorMessage());

          if (task.isSuccess())
            fireEvent( new ActionEvent(this, 0, "success"));
          else if (task.isError())
            fireEvent( new ActionEvent(this, 0, "error"));
          else if (task.isCancel())
            fireEvent( new ActionEvent(this, 0, "cancel"));
          else
            fireEvent( new ActionEvent(this, 0, "done"));

          busy = false;
        }
      }
    };
    myTimer = new javax.swing.Timer(1000, watcher); // every second
    myTimer.start();

    // do task in a seperate, non-event, thread
    Thread taskThread = new Thread(task);
    taskThread.start();

    return true;
  }

The given task is run in a background thread.
Progress is indicated once a second.
You cannot call this method again till the task is completed.
@param pmt heres where the work is done.
@return true task was started, false if still busy with previous task.

The given task is run in a background thread . Progress is indicated once a second . You cannot call this method again till the task is completed .


private boolean needsUpdate(CollectionUpdateType ff, File collectionIndexFile) throws IOException {
    long collectionLastModified = collectionIndexFile.lastModified();
    Set<String> newFileSet = new HashSet<>();
    for (MCollection dcm : partitionManager.makePartitions(CollectionUpdateType.test)) {
      String partitionIndexFilename = StringUtil2.replace(dcm.getIndexFilename(GribCdmIndex.NCX_SUFFIX), '\\', "/");
      File partitionIndexFile = GribIndexCache.getExistingFileOrCache(partitionIndexFilename);
      if (partitionIndexFile == null)                                 // make sure each partition has an index
        return true;
      if (collectionLastModified < partitionIndexFile.lastModified())  // and the partition index is earlier than the collection index
        return true;
      newFileSet.add(partitionIndexFilename);
    }

    if (ff == CollectionUpdateType.testIndexOnly) return false;

    // now see if any files were deleted
    GribCdmIndex reader = new GribCdmIndex(logger);
    List<MFile> oldFiles = new ArrayList<>();
    reader.readMFiles(collectionIndexFile.toPath(), oldFiles);
    Set<String> oldFileSet = new HashSet<>();
    for (MFile oldFile : oldFiles) {
      if (!newFileSet.contains(oldFile.getPath()))
        return true;  // got deleted - must recreate the index
      oldFileSet.add(oldFile.getPath());
    }

    // now see if any files were added
    for (String newFilename : newFileSet) {
      if (!oldFileSet.contains(newFilename))
        return true;  // got added - must recreate the index
    }

    return false;
  }

LOOK need an option to only scan latest last partition or something


static public void normalize(EnsCoord result, List<EnsCoord> ecList) {
    List<EnsCoord> extra = new ArrayList<>();
    for (EnsCoord ec : ecList) {
      if (!result.equalsData(ec)) {
        // differences can only be greater
        extra.add(ec);
      }
    }
    if (extra.size() == 0)
      return;
    for (EnsCoord ec : extra) {
      if (ec.getNEnsembles() < result.getNEnsembles())
        continue;
      result = ec;
    }

  }

static
public
void
normalize
(
EnsCoord
result
,
List
<
EnsCoord
>
ecList
)
{
List
<
EnsCoord
>
extra
=
new
ArrayList
<>
(
)
;
for
(
EnsCoord
ec
:
ecList
)
{
if
(
!
result
.
equalsData
(
ec
)
)
{
// differences can only be greater
extra
.
add
(
ec
)
;
}
}
if
(
extra
.
size
(
)
==
0
)
return
;
for
(
EnsCoord
ec
:
extra
)
{
if
(
ec
.
getNEnsembles
(
)
<
result
.
getNEnsembles
(
)
)
continue
;
result
=
ec
;
}
}

Extend result with all the values in the list of EnsCoord

@param result extend this coord
@param ecList list of EnsCoord, may be empty


public void setObject(int index, Object value) {
    if (sdata == null)
      sdata = new StructureData[nelems];
    sdata[index] = (StructureData) value;
  }

public void setObject ( int index , Object value ) { if ( sdata == null ) sdata = new StructureData [ nelems ] ; sdata [ index ] = ( StructureData ) value ; }

Set the index-th StructureData of this ArrayStructure.

@param index which one to set.
@param value must be type StructureData.

Set the index - th StructureData of this ArrayStructure .


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
StructureData
getStructureData
(
int
index
)
{
if
(
sdata
==
)
sdata
=
new
StructureData
[
nelems
]
;
if
(
index
>=
sdata
.
length
)
throw
new
IllegalArgumentException
(
index
+
" > "
+
sdata
.
length
)
;
if
(
sdata
[
index
]
==
)
sdata
[
index
]
=
makeStructureData
(
this
,
index
)
;
return
sdata
[
index
]
;
}

Get the index-th StructureData of this ArrayStructure.

@param index which one to get, specified by an integer.
@return object of type StructureData.

Get the index - th StructureData of this ArrayStructure .


protected void copyStructures(int recnum, StructureMembers.Member m, IndexIterator result) {
    Array data = getArray(recnum, m);
    IndexIterator dataIter = data.getIndexIterator();
    while (dataIter.hasNext())
      result.setObjectNext(dataIter.getObjectNext());
  }

protected void copyStructures ( int recnum , StructureMembers . Member m , IndexIterator result ) { Array data = getArray ( recnum , m ) ; IndexIterator dataIter = data . getIndexIterator ( ) ; while ( dataIter . hasNext ( ) ) result . setObjectNext ( dataIter . getObjectNext ( ) ) ; }

member data is itself a structure, and may be an array of structures.

member data is itself a structure and may be an array of structures .


public Object getScalarObject(int recno, StructureMembers.Member m) {
    DataType dataType = m.getDataType();

    if (dataType == DataType.DOUBLE) {
      return getScalarDouble(recno, m);

    } else if (dataType == DataType.FLOAT) {
      return getScalarFloat(recno, m);

    } else if (dataType.getPrimitiveClassType() == byte.class) {
      return getScalarByte(recno, m);

    } else if (dataType.getPrimitiveClassType() == short.class) {
      return getScalarShort(recno, m);

    } else if (dataType.getPrimitiveClassType() == int.class) {
      return getScalarInt(recno, m);

    } else if (dataType.getPrimitiveClassType() == long.class) {
      return getScalarLong(recno, m);

    } else if (dataType == DataType.CHAR) {
      return getScalarString(recno, m);

    } else if (dataType == DataType.STRING) {
      return getScalarString(recno, m);

    } else if (dataType == DataType.STRUCTURE) {
      return getScalarStructure(recno, m);

    } else if (dataType == DataType.OPAQUE) {
      ArrayObject data = (ArrayObject) m.getDataArray();
      return data.getObject(recno * m.getSize()); // LOOK ??
    }

    throw new RuntimeException("Dont have implementation for " + dataType);
  }

public
Object
getScalarObject
(
int
recno
,
StructureMembers
.
Member
m
)
{
DataType
dataType
=
m
.
getDataType
(
)
;
if
(
dataType
==
DataType
.
DOUBLE
)
{
return
getScalarDouble
(
recno
,
m
)
;
}
else
if
(
dataType
==
DataType
.
FLOAT
)
{
return
getScalarFloat
(
recno
,
m
)
;
}
else
if
(
dataType
.
getPrimitiveClassType
(
)
==
byte
.
class
)
{
return
getScalarByte
(
recno
,
m
)
;
}
else
if
(
dataType
.
getPrimitiveClassType
(
)
==
short
.
class
)
{
return
getScalarShort
(
recno
,
m
)
;
}
else
if
(
dataType
.
getPrimitiveClassType
(
)
==
int
.
class
)
{
return
getScalarInt
(
recno
,
m
)
;
}
else
if
(
dataType
.
getPrimitiveClassType
(
)
==
long
.
class
)
{
return
getScalarLong
(
recno
,
m
)
;
}
else
if
(
dataType
==
DataType
.
CHAR
)
{
return
getScalarString
(
recno
,
m
)
;
}
else
if
(
dataType
==
DataType
.
STRING
)
{
return
getScalarString
(
recno
,
m
)
;
}
else
if
(
dataType
==
DataType
.
STRUCTURE
)
{
return
getScalarStructure
(
recno
,
m
)
;
}
else
if
(
dataType
==
DataType
.
OPAQUE
)
{
ArrayObject
data
=
(
ArrayObject
)
m
.
getDataArray
(
)
;
return
data
.
getObject
(
recno
*
m
.
getSize
(
)
)
;
// LOOK ??
}
throw
new
RuntimeException
(
"Dont have implementation for "
+
dataType
)
;
}

Get member data array of any type as an Object, eg, Float, Double, String, StructureData etc.

@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 value as Float, Double, etc..

Get member data array of any type as an Object eg Float Double String StructureData etc .


public double convertScalarDouble(int recnum, StructureMembers.Member m) {
    if (m.getDataType() == DataType.DOUBLE) return getScalarDouble(recnum, m);
    if (m.getDataType() == DataType.FLOAT) return (double) getScalarFloat(recnum, m);
    Object o = getScalarObject(recnum, m);
    if (o instanceof Number) return ((Number) o).doubleValue();
    throw new ForbiddenConversionException("Type is " + m.getDataType() + ", not convertible to double");
  }

public
double
convertScalarDouble
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
m
.
getDataType
(
)
==
DataType
.
DOUBLE
)
return
getScalarDouble
(
recnum
,
m
)
;
if
(
m
.
getDataType
(
)
==
DataType
.
FLOAT
)
return
(
double
)
getScalarFloat
(
recnum
,
m
)
;
Object
o
=
getScalarObject
(
recnum
,
m
)
;
if
(
o
instanceof
Number
)
return
(
(
Number
)
o
)
.
doubleValue
(
)
;
throw
new
ForbiddenConversionException
(
"Type is "
+
m
.
getDataType
(
)
+
", not convertible to double"
)
;
}

Get scalar value as a double, with conversion as needed. Underlying type must be convertible to double.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      member Variable.
@return scalar double value
@throws ForbiddenConversionException if not convertible to double.

Get scalar value as a double with conversion as needed . Underlying type must be convertible to double .


public int convertScalarInt(int recnum, StructureMembers.Member m) {
    if (m.getDataType() == DataType.INT || m.getDataType() == DataType.UINT) return getScalarInt(recnum, m);
    if (m.getDataType() == DataType.SHORT) return (int) getScalarShort(recnum, m);
    if (m.getDataType() == DataType.USHORT) return DataType.unsignedShortToInt( getScalarShort(recnum, m));
    if (m.getDataType() == DataType.BYTE) return (int) getScalarByte(recnum, m);
    if (m.getDataType() == DataType.UBYTE) return (int) DataType.unsignedByteToShort( getScalarByte(recnum, m));
    if (m.getDataType() == DataType.LONG || m.getDataType() == DataType.ULONG) return (int) getScalarLong(recnum, m);
    Object o = getScalarObject(recnum, m);
    if (o instanceof Number) return ((Number) o).intValue();
    throw new ForbiddenConversionException("Type is " + m.getDataType() + ", not convertible to int");
  }

public
int
convertScalarInt
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
m
.
getDataType
(
)
==
DataType
.
INT
||
m
.
getDataType
(
)
==
DataType
.
UINT
)
return
getScalarInt
(
recnum
,
m
)
;
if
(
m
.
getDataType
(
)
==
DataType
.
SHORT
)
return
(
int
)
getScalarShort
(
recnum
,
m
)
;
if
(
m
.
getDataType
(
)
==
DataType
.
USHORT
)
return
DataType
.
unsignedShortToInt
(
getScalarShort
(
recnum
,
m
)
)
;
if
(
m
.
getDataType
(
)
==
DataType
.
BYTE
)
return
(
int
)
getScalarByte
(
recnum
,
m
)
;
if
(
m
.
getDataType
(
)
==
DataType
.
UBYTE
)
return
(
int
)
DataType
.
unsignedByteToShort
(
getScalarByte
(
recnum
,
m
)
)
;
if
(
m
.
getDataType
(
)
==
DataType
.
LONG
||
m
.
getDataType
(
)
==
DataType
.
ULONG
)
return
(
int
)
getScalarLong
(
recnum
,
m
)
;
Object
o
=
getScalarObject
(
recnum
,
m
)
;
if
(
o
instanceof
Number
)
return
(
(
Number
)
o
)
.
intValue
(
)
;
throw
new
ForbiddenConversionException
(
"Type is "
+
m
.
getDataType
(
)
+
", not convertible to int"
)
;
}

Get scalar value as an int, with conversion as needed. Underlying type must be convertible to int.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      member Variable.
@return scalar double value
@throws ForbiddenConversionException if not convertible to double.

Get scalar value as an int with conversion as needed . Underlying type must be convertible to int .


public float getScalarFloat(int recnum, StructureMembers.Member m) {
    if (m.getDataType() != DataType.FLOAT)
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be float");
    Array data = m.getDataArray();
    return data.getFloat(recnum * m.getSize()); // gets first one in the array
  }

public
float
getScalarFloat
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
m
.
getDataType
(
)
!=
DataType
.
FLOAT
)
throw
new
IllegalArgumentException
(
"Type is "
+
m
.
getDataType
(
)
+
", must be float"
)
;
Array
data
=
m
.
getDataArray
(
)
;
return
data
.
getFloat
(
recnum
*
m
.
getSize
(
)
)
;
// gets first one in the array
}

Get scalar member data of type float.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type float.
@return scalar double value


public byte getScalarByte(int recnum, StructureMembers.Member m) {
    if (!(m.getDataType().getPrimitiveClassType() == byte.class))
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be byte");
    Array data = m.getDataArray();
    return data.getByte(recnum * m.getSize()); // gets first one in the array
  }

public
byte
getScalarByte
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
!
(
m
.
getDataType
(
)
.
getPrimitiveClassType
(
)
==
byte
.
class
)
)
throw
new
IllegalArgumentException
(
"Type is "
+
m
.
getDataType
(
)
+
", must be byte"
)
;
Array
data
=
m
.
getDataArray
(
)
;
return
data
.
getByte
(
recnum
*
m
.
getSize
(
)
)
;
// gets first one in the array
}

Get scalar member data of type byte.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type byte.
@return scalar double value


public short getScalarShort(int recnum, StructureMembers.Member m) {
    if (!(m.getDataType().getPrimitiveClassType() == short.class))
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be short");
    Array data = m.getDataArray();
    return data.getShort(recnum * m.getSize()); // gets first one in the array
  }

public
short
getScalarShort
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
!
(
m
.
getDataType
(
)
.
getPrimitiveClassType
(
)
==
short
.
class
)
)
throw
new
IllegalArgumentException
(
"Type is "
+
m
.
getDataType
(
)
+
", must be short"
)
;
Array
data
=
m
.
getDataArray
(
)
;
return
data
.
getShort
(
recnum
*
m
.
getSize
(
)
)
;
// gets first one in the array
}

Get scalar member data of type short.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type short.
@return scalar double value


public char getScalarChar(int recnum, StructureMembers.Member m) {
    if (m.getDataType() != DataType.CHAR)
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be char");
    Array data = m.getDataArray();
    return data.getChar(recnum * m.getSize()); // gets first one in the array
  }

public
char
getScalarChar
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
m
.
getDataType
(
)
!=
DataType
.
CHAR
)
throw
new
IllegalArgumentException
(
"Type is "
+
m
.
getDataType
(
)
+
", must be char"
)
;
Array
data
=
m
.
getDataArray
(
)
;
return
data
.
getChar
(
recnum
*
m
.
getSize
(
)
)
;
// gets first one in the array
}

Get scalar member data of type char.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type char.
@return scalar double value


public String getScalarString(int recnum, StructureMembers.Member m) {
    if (m.getDataType() == DataType.CHAR) {
      ArrayChar data = (ArrayChar) m.getDataArray();
      return data.getString(recnum);
    }

    if (m.getDataType() == DataType.STRING) {
      Array data = m.getDataArray();
      return (String) data.getObject(recnum);
    }

    throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be String or char");
  }

public
String
getScalarString
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
m
.
getDataType
(
)
==
DataType
.
CHAR
)
{
ArrayChar
data
=
(
ArrayChar
)
m
.
getDataArray
(
)
;
return
data
.
getString
(
recnum
)
;
}
if
(
m
.
getDataType
(
)
==
DataType
.
STRING
)
{
Array
data
=
m
.
getDataArray
(
)
;
return
(
String
)
data
.
getObject
(
recnum
)
;
}
throw
new
IllegalArgumentException
(
"Type is "
+
m
.
getDataType
(
)
+
", must be String or char"
)
;
}

Get member data of type String or char.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type String or char.
@return scalar String value

Get member data of type String or char .


public ArrayStructure getArrayStructure(int recnum, StructureMembers.Member m) {
    if ((m.getDataType() != DataType.STRUCTURE) && (m.getDataType() != DataType.SEQUENCE))
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be Structure or Sequence");

    if (m.getDataType() == DataType.SEQUENCE)
      return getArraySequence(recnum, m);

    ArrayStructure array = (ArrayStructure) m.getDataArray();
    int count = m.getSize();
    StructureData[] this_sdata = new StructureData[count];
    for (int i = 0; i < count; i++)
      this_sdata[i] = array.getStructureData(recnum * count + i);

    // make a copy of the members, but remove the data arrays, since the structureData must be used instead
    StructureMembers membersw = new StructureMembers(array.getStructureMembers());
    return new ArrayStructureW(membersw, m.getShape(), this_sdata);
  }

Get member data of type array of Structure.

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type Structure.
@return nested ArrayStructure.

Get member data of type array of Structure .


public ArraySequence getArraySequence(int recnum, StructureMembers.Member m) {
    if (m.getDataType() != DataType.SEQUENCE)
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be Sequence");

    // should store sequences as ArrayObject of ArraySequence objects
    ArrayObject array = (ArrayObject) m.getDataArray();
    return (ArraySequence) array.getObject(recnum);
  }

Get member data of type ArraySequence

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type Structure.
@return nested ArrayStructure.


public ArrayObject getArrayObject(int recnum, StructureMembers.Member m) {
    if (m.getDataType() != DataType.OPAQUE)
      throw new IllegalArgumentException("Type is " + m.getDataType() + ", must be Sequence");

    ArrayObject array = (ArrayObject) m.getDataArray();
    return (ArrayObject) array.getObject(recnum);     // LOOK ??
  }

public
ArrayObject
getArrayObject
(
int
recnum
,
StructureMembers
.
Member
m
)
{
if
(
m
.
getDataType
(
)
!=
DataType
.
OPAQUE
)
throw
new
IllegalArgumentException
(
"Type is "
+
m
.
getDataType
(
)
+
", must be Sequence"
)
;
ArrayObject
array
=
(
ArrayObject
)
m
.
getDataArray
(
)
;
return
(
ArrayObject
)
array
.
getObject
(
recnum
)
;
// LOOK ??
}

Get member data of type ArrayObject

@param recnum get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
@param m      get data from this StructureMembers.Member. Must be of type Structure.
@return ArrayObject.


static protected long
    minmax(long value, long min, long max)
    {
        if(value < min) return min;
        if(value > max) return max;
        return value;
    }

static protected long minmax ( long value , long min , long max ) { if ( value < min ) return min ; if ( value > max ) return max ; return value ; }

Peg a value to either the min or max
depending on sign.

@param value the value to peg
@param min   peg to this if value is < min
@param max   peg to this if value is > max
@return pegg'ed value

Peg a value to either the min or max depending on sign .


protected Object
    eval(DapVariable var, DapSequence seq, DataCursor record, CEAST expr)
            throws DapException
    {
        switch (expr.sort) {

        case CONSTANT:
            return expr.value;

        case SEGMENT:
            return fieldValue(var, seq, record, expr.name);

        case EXPR:
            Object lhs = eval(var, seq, record, expr.lhs);
            Object rhs = (expr.rhs == null ? null : eval(var, seq, record, expr.rhs));
            if(rhs != null)
                switch (expr.op) {
                case LT:
                    return compare(lhs, rhs) < 0;
                case LE:
                    return compare(lhs, rhs) <= 0;
                case GT:
                    return compare(lhs, rhs) > 0;
                case GE:
                    return compare(lhs, rhs) >= 0;
                case EQ:
                    return lhs.equals(rhs);
                case NEQ:
                    return !lhs.equals(rhs);
                case REQ:
                    return lhs.toString().matches(rhs.toString());
                case AND:
                    return ((Boolean) lhs) && ((Boolean) rhs);
                }
            else switch (expr.op) {
            case NOT:
                return !((Boolean) lhs);
            }
        }
        throw new DapException("Malformed Filter");
    }

protected
Object
eval
(
DapVariable
var
,
DapSequence
seq
,
DataCursor
record
,
CEAST
expr
)
throws
DapException
{
switch
(
expr
.
sort
)
{
case
CONSTANT
:
return
expr
.
value
;
case
SEGMENT
:
return
fieldValue
(
var
,
seq
,
record
,
expr
.
name
)
;
case
EXPR
:
Object
lhs
=
eval
(
var
,
seq
,
record
,
expr
.
lhs
)
;
Object
rhs
=
(
expr
.
rhs
==
:
eval
(
var
,
seq
,
record
,
expr
.
rhs
)
)
;
if
(
rhs
!=
)
switch
(
expr
.
op
)
{
case
LT
:
return
compare
(
lhs
,
rhs
)
<
0
;
case
LE
:
return
compare
(
lhs
,
rhs
)
<=
0
;
case
GT
:
return
compare
(
lhs
,
rhs
)
>
0
;
case
GE
:
return
compare
(
lhs
,
rhs
)
>=
0
;
case
EQ
:
return
lhs
.
equals
(
rhs
)
;
case
NEQ
:
return
!
lhs
.
equals
(
rhs
)
;
case
REQ
:
return
lhs
.
toString
(
)
.
matches
(
rhs
.
toString
(
)
)
;
case
AND
:
return
(
(
Boolean
)
lhs
)
&&
(
(
Boolean
)
rhs
)
;
}
else
switch
(
expr
.
op
)
{
case
NOT
:
return
!
(
(
Boolean
)
lhs
)
;
}
}
throw
new
DapException
(
"Malformed Filter"
)
;
}

Evaluate a filter with respect to a Sequence record.
Assumes the filter has been canonicalized so that
the lhs is a variable.

@param seq    the template
@param record the record to evaluate
@param expr   the filter
@throws DapException
@returns the value of the expression (usually a Boolean)

Evaluate a filter with respect to a Sequence record . Assumes the filter has been canonicalized so that the lhs is a variable .


public String toConstraintString()
    {
        StringBuilder buf = new StringBuilder();
        boolean first = true;
        for(int i = 0; i < segments.size(); i++) {
            Segment seg = segments.get(i);
            if(!seg.var.isTopLevel())
                continue;
            if(!first) buf.append(";");
            first = false;
            dumpvar(seg, buf, true);
        }
        return buf.toString();
    }

public String toConstraintString ( ) { StringBuilder buf = new StringBuilder ( ) ; boolean first = true ; for ( int i = 0 ; i < segments . size ( ) ; i ++ ) { Segment seg = segments . get ( i ) ; if ( ! seg . var . isTopLevel ( ) ) continue ; if ( ! first ) buf . append ( ";" ) ; first = false ; dumpvar ( seg , buf , true ) ; } return buf . toString ( ) ; }

Convert the view to a constraint string suitable
for use in a URL, except not URL encoded.

@return constraint string

Convert the view to a constraint string suitable for use in a URL except not URL encoded .


public boolean
    references(DapNode node)
    {
        boolean isref = false;
        switch (node.getSort()) {
        case DIMENSION:
            DapDimension dim = this.redef.get((DapDimension) node);
            if(dim == null) dim = (DapDimension) node;
            isref = this.dimrefs.contains(dim);
            break;
        case ENUMERATION:
            isref = (this.enums.contains((DapEnumeration) node));
            break;
        case VARIABLE:
            isref = (findVariableIndex((DapVariable) node) >= 0);
            break;
        case GROUP:
        case DATASET:
            isref = (this.groups.contains((DapGroup) node));
            break;
        default:
            break;
        }
        return isref;
    }

public boolean references ( DapNode node ) { boolean isref = false ; switch ( node . getSort ( ) ) { case DIMENSION : DapDimension dim = this . redef . get ( ( DapDimension ) node ) ; if ( dim == null ) dim = ( DapDimension ) node ; isref = this . dimrefs . contains ( dim ) ; break ; case ENUMERATION : isref = ( this . enums . contains ( ( DapEnumeration ) node ) ) ; break ; case VARIABLE : isref = ( findVariableIndex ( ( DapVariable ) node ) >= 0 ) ; break ; case GROUP : case DATASET : isref = ( this . groups . contains ( ( DapGroup ) node ) ) ; break ; default : break ; } return isref ; }

Reference X match

@param node to test
@return true if node is referenced by this constraint


protected boolean
    matches(DapVariable var, DapSequence seq, DataCursor rec, CEAST filter)
            throws DapException
    {
        Object value = eval(var, seq, rec, filter);
        return ((Boolean) value);
    }

protected boolean matches ( DapVariable var , DapSequence seq , DataCursor rec , CEAST filter ) throws DapException { Object value = eval ( var , seq , rec , filter ) ; return ( ( Boolean ) value ) ; }

Evaluate a filter with respect to a Sequence record.

@param seq    the template
@param rec    the record to evaluate
@param filter the filter
@throws DapException
@returns true if a match

Evaluate a filter with respect to a Sequence record .


protected int
    expansionCount(DapStructure struct)
    {
        int count = 0;
        for(DapVariable field : struct.getFields()) {
            if(findVariableIndex(field) >= 0) count++;
        }
        return count;
    }

protected int expansionCount ( DapStructure struct ) { int count = 0 ; for ( DapVariable field : struct . getFields ( ) ) { if ( findVariableIndex ( field ) >= 0 ) count ++ ; } return count ; }

Count the number of fields of a structure that
already in this view.

@param struct the dapstructure to check
@return # of fields in this view
@throws DapException

Count the number of fields of a structure that already in this view .


protected void computeenums()
    {
        for(int i = 0; i < variables.size(); i++) {
            DapVariable var = variables.get(i);
            if(var.getSort() != DapSort.VARIABLE)
                continue;
            DapType daptype = var.getBaseType();
            if(!daptype.isEnumType())
                continue;
            if(!this.enums.contains((DapEnumeration) daptype))
                this.enums.add((DapEnumeration) daptype);
        }
    }

protected void computeenums ( ) { for ( int i = 0 ; i < variables . size ( ) ; i ++ ) { DapVariable var = variables . get ( i ) ; if ( var . getSort ( ) != DapSort . VARIABLE ) continue ; DapType daptype = var . getBaseType ( ) ; if ( ! daptype . isEnumType ( ) ) continue ; if ( ! this . enums . contains ( ( DapEnumeration ) daptype ) ) this . enums . add ( ( DapEnumeration ) daptype ) ; } }

Walk all the included variables and accumulate
the referenced enums


protected void computegroups()
    {
        // 1. variables
        for(int i = 0; i < variables.size(); i++) {
            DapVariable var = variables.get(i);
            List<DapGroup> path = var.getGroupPath();
            for(DapGroup group : path) {
                if(!this.groups.contains(group))
                    this.groups.add(group);
            }
        }
        // 2. Dimensions
        for(DapDimension dim : this.dimrefs) {
            if(!dim.isShared())
                continue;
            List<DapGroup> path = dim.getGroupPath();
            for(DapGroup group : path) {
                if(!this.groups.contains(group))
                    this.groups.add(group);
            }
        }
        // 2. enumerations
        for(DapEnumeration en : this.enums) {
            List<DapGroup> path = en.getGroupPath();
            for(DapGroup group : path) {
                if(!this.groups.contains(group))
                    this.groups.add(group);
            }
        }
    }

protected
void
computegroups
(
)
{
// 1. variables
for
(
int
i
=
0
;
i
<
variables
.
size
(
)
;
i
++
)
{
DapVariable
var
=
variables
.
get
(
i
)
;
List
<
DapGroup
>
path
=
var
.
getGroupPath
(
)
;
for
(
DapGroup
group
:
path
)
{
if
(
!
this
.
groups
.
contains
(
group
)
)
this
.
groups
.
add
(
group
)
;
}
}
// 2. Dimensions
for
(
DapDimension
dim
:
this
.
dimrefs
)
{
if
(
!
dim
.
isShared
(
)
)
continue
;
List
<
DapGroup
>
path
=
dim
.
getGroupPath
(
)
;
for
(
DapGroup
group
:
path
)
{
if
(
!
this
.
groups
.
contains
(
group
)
)
this
.
groups
.
add
(
group
)
;
}
}
// 2. enumerations
for
(
DapEnumeration
en
:
this
.
enums
)
{
List
<
DapGroup
>
path
=
en
.
getGroupPath
(
)
;
for
(
DapGroup
group
:
path
)
{
if
(
!
this
.
groups
.
contains
(
group
)
)
this
.
groups
.
add
(
group
)
;
}
}
}

Walk all the included declarations
and accumulate the set of referenced groups


static public CEConstraint
    compile(String sce, DapDataset dmr)
            throws DapException
    {
        // Process any constraint
        if(sce == null || sce.length() == 0)
            return CEConstraint.getUniversal(dmr);
        CEParserImpl ceparser = new CEParserImpl(dmr);
        if(PARSEDEBUG)
            ceparser.setDebugLevel(1);
        if(DEBUG) {
            System.err.println("Dap4Servlet: parsing constraint: |" + sce + "|");
        }
        boolean ok;
        try {
            ok = ceparser.parse(sce);
        } catch (ParseException pe) {
            ok = false;
        }
        if(!ok)
            throw new DapException("Constraint parse failed: " + sce);
        CEAST root = ceparser.getCEAST();
        CECompiler compiler = new CECompiler();
        CEConstraint ce = compiler.compile(dmr, root);
        ce.expand();
        ce.finish();
        return ce;
    }

static
public
CEConstraint
compile
(
String
sce
,
DapDataset
dmr
)
throws
DapException
{
// Process any constraint
if
(
sce
==
||
sce
.
length
(
)
==
0
)
return
CEConstraint
.
getUniversal
(
dmr
)
;
CEParserImpl
ceparser
=
new
CEParserImpl
(
dmr
)
;
if
(
PARSEDEBUG
)
ceparser
.
setDebugLevel
(
1
)
;
if
(
DEBUG
)
{
System
.
err
.
println
(
"Dap4Servlet: parsing constraint: |"
+
sce
+
"|"
)
;
}
boolean
ok
;
try
{
ok
=
ceparser
.
parse
(
sce
)
;
}
catch
(
ParseException
pe
)
{
ok
=
false
;
}
if
(
!
ok
)
throw
new
DapException
(
"Constraint parse failed: "
+
sce
)
;
CEAST
root
=
ceparser
.
getCEAST
(
)
;
CECompiler
compiler
=
new
CECompiler
(
)
;
CEConstraint
ce
=
compiler
.
compile
(
dmr
,
root
)
;
ce
.
expand
(
)
;
ce
.
finish
(
)
;
return
ce
;
}

Static Utility for compiling a constraint string


@Override
  public boolean isValidFile(RandomAccessFile raf) throws IOException {
    if (raf instanceof HTTPRandomAccessFile) { // only do remote if memory resident
      if (raf.length() > raf.getBufferSize())
        return false;

    } else {                                  // wont accept remote index
      GribCdmIndex.GribCollectionType type = GribCdmIndex.getType(raf);
      if (type == GribCdmIndex.GribCollectionType.GRIB2) return true;
      if (type == GribCdmIndex.GribCollectionType.Partition2) return true;
    }

    // check for GRIB2 data file
    return Grib2RecordScanner.isValidFile(raf);
  }

@
Override
public
boolean
isValidFile
(
RandomAccessFile
raf
)
throws
IOException
{
if
(
raf
instanceof
HTTPRandomAccessFile
)
{
// only do remote if memory resident
if
(
raf
.
length
(
)
>
raf
.
getBufferSize
(
)
)
return
false
;
}
else
{
// wont accept remote index
GribCdmIndex
.
GribCollectionType
type
=
GribCdmIndex
.
getType
(
raf
)
;
if
(
type
==
GribCdmIndex
.
GribCollectionType
.
GRIB2
)
return
true
;
if
(
type
==
GribCdmIndex
.
GribCollectionType
.
Partition2
)
return
true
;
}
// check for GRIB2 data file
return
Grib2RecordScanner
.
isValidFile
(
raf
)
;
}


private void makeActionsSystem() {

    /* aboutAction = new AbstractAction() {
      public void actionPerformed(ActionEvent evt) {
        new AboutWindow();
      }
    };
    BAMutil.setActionProperties( aboutAction, null, "About", false, 'A', 0); */

    /* printAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        PrinterJob printJob = PrinterJob.getPrinterJob();
        PageFormat pf = printJob.defaultPage();

        // do we need to rotate ??
        if (panz.wantRotate( pf.getImageableWidth(), pf.getImageableHeight()))
          pf.setOrientation( PageFormat.LANDSCAPE);
        else
          pf.setOrientation(PageFormat.PORTRAIT);

        printJob.setPrintable(controller.getPrintable(), pf);
        if (printJob.printDialog()) {
          try {
            if (Debug.isSet("print.job")) System.out.println("call printJob.print");
            printJob.print();
            if (Debug.isSet("print.job")) System.out.println(" printJob done");
          } catch (Exception PrintException) {
            PrintException.printStackTrace();
          }
        }
      }
    };
    BAMutil.setActionProperties( printAction, "Print", "Print...", false, 'P', KeyEvent.VK_P);

    sysConfigAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        if (sysConfigDialog == null)
          makeSysConfigWindow();
        sysConfigDialog.show();
      }
    };
    BAMutil.setActionProperties( sysConfigAction, "Preferences", "Configure...", false, 'C', -1);

    clearDebugFlagsAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) { Debug.clear(); }
    };
    BAMutil.setActionProperties( clearDebugFlagsAction, null, "Clear DebugFlags", false, 'D', -1);

    clearRecentAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        recentDatasetList = new ArrayList();
      }
    };
    BAMutil.setActionProperties( clearRecentAction, null, "Clear Recent Datasets", false, 'R', -1);
    */

    AbstractAction clearDebugFlagsAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) { /* Debug.clear(); */ }
    };
    BAMutil.setActionProperties(clearDebugFlagsAction, null, "Clear Debug Flags", false, 'D', -1);

    /* AbstractAction setDebugFlagsAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        // LOOK set netcdf debug flags

        InvCatalogFactory.debugURL = Debug.isSet("InvCatalogFactory/debugURL");
        InvCatalogFactory.debugOpen = Debug.isSet("InvCatalogFactory/debugOpen");
        InvCatalogFactory.debugVersion = Debug.isSet("InvCatalogFactory/debugVersion");
        InvCatalogFactory.showParsedXML = Debug.isSet("InvCatalogFactory/showParsedXML");
        InvCatalogFactory.showStackTrace = Debug.isSet("InvCatalogFactory/showStackTrace");
        InvCatalogFactory.debugXML = Debug.isSet("InvCatalogFactory/debugXML");
        InvCatalogFactory.debugDBurl = Debug.isSet("InvCatalogFactory/debugDBurl");
        InvCatalogFactory.debugXMLopen = Debug.isSet("InvCatalogFactory/debugXMLopen");
        InvCatalogFactory.showCatalogXML = Debug.isSet("InvCatalogFactory/showCatalogXML");
      }
    };
    BAMutil.setActionProperties(setDebugFlagsAction, null, "Set Debug Flags", false, 'S', -1);  */

    /* exitAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
        topLevel.close();
      }
    };
    BAMutil.setActionProperties( exitAction, "Exit", "Exit", false, 'X', -1); */

  }


public int getByteOrder(int kmachn) {
    if ((kmachn == MTVAX) || (kmachn == MTULTX) || (kmachn == MTALPH)
            || (kmachn == MTLNUX) || (kmachn == MTIGPH)) {
      return RandomAccessFile.LITTLE_ENDIAN;
    }
    return RandomAccessFile.BIG_ENDIAN;
  }

public int getByteOrder ( int kmachn ) { if ( ( kmachn == MTVAX ) || ( kmachn == MTULTX ) || ( kmachn == MTALPH ) || ( kmachn == MTLNUX ) || ( kmachn == MTIGPH ) ) { return RandomAccessFile . LITTLE_ENDIAN ; } return RandomAccessFile . BIG_ENDIAN ; }

Get the byte order for the machine type.

@param kmachn maching type
@return byte order

Get the byte order for the machine type .


void setByteOrder() {
    String arch = System.getProperty("os.arch");
    if (arch.equals("x86") ||                    // Windows, Linux
            arch.equals("arm") ||                // Window CE
            arch.equals("x86_64") ||         // Windows64, Mac OS-X
            arch.equals("amd64") ||      // Linux64?
            arch.equals("alpha")) {  // Utrix, VAX, DECOS
      MTMACH = RandomAccessFile.LITTLE_ENDIAN;
    } else {
      MTMACH = RandomAccessFile.BIG_ENDIAN;
    }
  }

void
setByteOrder
(
)
{
String
arch
=
System
.
getProperty
(
"os.arch"
)
;
if
(
arch
.
equals
(
"x86"
)
||
// Windows, Linux
arch
.
equals
(
"arm"
)
||
// Window CE
arch
.
equals
(
"x86_64"
)
||
// Windows64, Mac OS-X
arch
.
equals
(
"amd64"
)
||
// Linux64?
arch
.
equals
(
"alpha"
)
)
{
// Utrix, VAX, DECOS
MTMACH
=
RandomAccessFile
.
LITTLE_ENDIAN
;
}
else
{
MTMACH
=
RandomAccessFile
.
BIG_ENDIAN
;
}
}

LOOK WTF ??
Set the machine type for this system.

@see http://lopica.sourceforge.net/os.html

LOOK WTF ?? Set the machine type for this system .


public Key findKey(String name) {
    if (keys == null) {
      return null;
    }
    // search rows
    for (Key key : keys.kkrow) {
      if (key.name.equals(name)) {
        return key;
      }
    }
    // search columns
    for (Key key : keys.kkcol) {
      if (key.name.equals(name)) {
        return key;
      }
    }
    return null;

  }

public
Key
findKey
(
String
name
)
{
if
(
keys
==
)
{
return
;
}
// search rows
for
(
Key
key
:
keys
.
kkrow
)
{
if
(
key
.
name
.
equals
(
name
)
)
{
return
key
;
}
}
// search columns
for
(
Key
key
:
keys
.
kkcol
)
{
if
(
key
.
name
.
equals
(
name
)
)
{
return
key
;
}
}
return
;
}

Find a key with the given name

@param name the name of the key
@return the key or null;


public DMFileHeaderInfo findFileHeader(String name) {
    if ((fileHeaderInfo == null) || fileHeaderInfo.isEmpty()) {
      return null;
    }
    for (DMFileHeaderInfo fhi : fileHeaderInfo) {
      if (name.equals(fhi.kfhnam)) {
        return fhi;
      }
    }
    return null;
  }

public DMFileHeaderInfo findFileHeader ( String name ) { if ( ( fileHeaderInfo == null ) || fileHeaderInfo . isEmpty ( ) ) { return null ; } for ( DMFileHeaderInfo fhi : fileHeaderInfo ) { if ( name . equals ( fhi . kfhnam ) ) { return fhi ; } } return null ; }

Find the file header with this name

@param name name of header
@return headerinfo or null if not found


public float[] getFileHeader(String name) throws IOException {
    DMFileHeaderInfo fh = findFileHeader(name);
    if ((fh == null) || (fh.kfhtyp != MDREAL)) {
      return null;
    }
    int knt = fileHeaderInfo.indexOf(fh);  // 0 based
    int iread = dmLabel.kpfile + 3 * dmLabel.kfhdrs;
    for (int i = 0; i < knt; i++) {
      DMFileHeaderInfo fhi = fileHeaderInfo.get(i);
      iread = iread + fhi.kfhlen + 1;
    }
    int nword = DM_RINT(iread);
    if (nword <= 0) {
      logError("Invalid header length for " + name);
      return null;
    }
    iread++;
    float[] rheader = new float[nword];
    if (name.equals("NAVB") && needToSwap) {
      DM_RFLT(iread, 1, rheader, 0);
      needToSwap = false;
      iread++;
      DM_RFLT(iread, 1, rheader, 1);
      needToSwap = true;
      iread++;
      DM_RFLT(iread, nword - 2, rheader, 2);

    } else {
      DM_RFLT(iread, rheader);
    }
    return rheader;
  }

public
float
[
]
getFileHeader
(
String
name
)
throws
IOException
{
DMFileHeaderInfo
fh
=
findFileHeader
(
name
)
;
if
(
(
fh
==
)
||
(
fh
.
kfhtyp
!=
MDREAL
)
)
{
return
;
}
int
knt
=
fileHeaderInfo
.
indexOf
(
fh
)
;
// 0 based
int
iread
=
dmLabel
.
kpfile
+
3
*
dmLabel
.
kfhdrs
;
for
(
int
i
=
0
;
i
<
knt
;
i
++
)
{
DMFileHeaderInfo
fhi
=
fileHeaderInfo
.
get
(
i
)
;
iread
=
iread
+
fhi
.
kfhlen
+
1
;
}
int
nword
=
DM_RINT
(
iread
)
;
if
(
nword
<=
0
)
{
logError
(
"Invalid header length for "
+
name
)
;
return
;
}
iread
++
;
float
[
]
rheader
=
new
float
[
nword
]
;
if
(
name
.
equals
(
"NAVB"
)
&&
needToSwap
)
{
DM_RFLT
(
iread
,
1
,
rheader
,
0
)
;
needToSwap
=
false
;
iread
++
;
DM_RFLT
(
iread
,
1
,
rheader
,
1
)
;
needToSwap
=
true
;
iread
++
;
DM_RFLT
(
iread
,
nword
2
,
rheader
,
2
)
;
}
else
{
DM_RFLT
(
iread
,
rheader
)
;
}
return
rheader
;
}

Read in the values for the file header

@param name name of header
@return values or null if not found
@throws IOException problem reading file


public void printParts() {
    if (parts == null) {
      return;
    }
    for (int i = 0; i < parts.size(); i++) {
      System.out.println("\nParts[" + i + "]:");
      System.out.println(parts.get(i));
    }
  }

public void printParts ( ) { if ( parts == null ) { return ; } for ( int i = 0 ; i < parts . size ( ) ; i ++ ) { System . out . println ( "\nParts[" + i + "]:" ) ; System . out . println ( parts . get ( i ) ) ; } }


public int getDataPointer(int irow, int icol, String partName) {
    int ipoint = -1;
    if ((irow < 1) || (irow > dmLabel.krow) || (icol < 1)
            || (icol > dmLabel.kcol)) {
      System.out.println("bad row or column number: " + irow + "/"
              + icol);
      return ipoint;
    }
    int iprt = getPartNumber(partName);
    if (iprt == 0) {
      System.out.println("couldn't find part");
      return ipoint;
    }
    // gotta subtract 1 because parts are 1 but List is 0 based
    DMPart part = parts.get(iprt - 1);
    // check for valid data type
    if ((part.ktyprt != MDREAL) && (part.ktyprt != MDGRID)
            && (part.ktyprt != MDRPCK)) {
      System.out.println("Not a valid type");
      return ipoint;
    }
    int ilenhd = part.klnhdr;
    ipoint = dmLabel.kpdata + (irow - 1) * dmLabel.kcol * dmLabel.kprt
            + (icol - 1) * dmLabel.kprt + (iprt - 1);
    return ipoint;
  }

Get the pointer to the data.  Taken from DM_RDTR

@param irow     row number
@param icol     column number
@param partName name of the part
@return word (1 based) of start of data.

Get the pointer to the data . Taken from DM_RDTR


public float DM_RFLT(int word) throws IOException {
    if (rf == null) {
      throw new IOException("DM_RFLT: no file to read from");
    }
    if (dmLabel == null) {
      throw new IOException("DM_RFLT: reader not initialized");
    }
    rf.seek(getOffset(word));
    if (needToSwap) {
      // set the order
      //if ((dmLabel.kmachn != MTMACH) &&
      //   ((dmLabel.kvmst && ! mvmst) ||
      //   (mvmst && !dmLabel.kvmst))) {
      rf.order(RandomAccessFile.LITTLE_ENDIAN);  // swap
    } else {
      rf.order(RandomAccessFile.BIG_ENDIAN);
    }
    float rdata = rf.readFloat();
    if (RMISSD != dmLabel.smissd) {
      if (Math.abs(rdata - dmLabel.smissd) < RDIFFD) {
        rdata = RMISSD;
      }
    }
    // reset to read normally
    rf.order(RandomAccessFile.BIG_ENDIAN);
    return rdata;
  }

public
float
DM_RFLT
(
int
word
)
throws
IOException
{
if
(
rf
==
)
{
throw
new
IOException
(
"DM_RFLT: no file to read from"
)
;
}
if
(
dmLabel
==
)
{
throw
new
IOException
(
"DM_RFLT: reader not initialized"
)
;
}
rf
.
seek
(
getOffset
(
word
)
)
;
if
(
needToSwap
)
{
// set the order
//if ((dmLabel.kmachn != MTMACH) &&
//   ((dmLabel.kvmst && ! mvmst) ||
//   (mvmst && !dmLabel.kvmst))) {
rf
.
order
(
RandomAccessFile
.
LITTLE_ENDIAN
)
;
// swap
}
else
{
rf
.
order
(
RandomAccessFile
.
BIG_ENDIAN
)
;
}
float
rdata
=
rf
.
readFloat
(
)
;
if
(
RMISSD
!=
dmLabel
.
smissd
)
{
if
(
Math
.
abs
(
rdata
dmLabel
.
smissd
)
<
RDIFFD
)
{
rdata
=
RMISSD
;
}
}
// reset to read normally
rf
.
order
(
RandomAccessFile
.
BIG_ENDIAN
)
;
return
rdata
;
}

Read a float

@param word word in file (1 based) to read
@return float read
@throws IOException problem reading file


public String DM_RSTR(int isword, int nchar) throws IOException {
    if (rf == null) {
      throw new IOException("DM_RSTR: no file to read from");
    }
    rf.seek(getOffset(isword));
    return rf.readString(nchar);
  }

public
String
DM_RSTR
(
int
isword
,
int
nchar
)
throws
IOException
{
if
(
rf
==
)
{
throw
new
IOException
(
"DM_RSTR: no file to read from"
)
;
}
rf
.
seek
(
getOffset
(
isword
)
)
;
return
rf
.
readString
(
nchar
)
;
}

Read a String

@param isword offset in file (1 based FORTRAN word)
@param nchar  number of characters to read
@return String read
@throws IOException problem reading file


public float[] DM_UNPK(DMPart part, int[] ibitst) {
    int nparms = part.kparms;
    int nwordp = part.kwordp;
    int npack = (ibitst.length - 1) / nwordp + 1;
    if (npack * nwordp != ibitst.length) {
      //logError("number of packed records not correct");
      // System.out.println("number of packed records not correct: "
      //                   + npack * nwordp + " vs. " + ibitst.length);
      return null;
    }
    float[] data = new float[nparms * npack];
    PackingInfo pkinf = part.packInfo;
    int ir = 0;
    int ii = 0;
    for (int pack = 0; pack < npack; pack++) {
      //
      //  Move bitstring into internal words.  TODO: necessary?
      //
      int[] jdata = new int[nwordp];
      System.arraycopy(ibitst, ii, jdata, 0, nwordp);

      //
      //  Extract each data value.
      //
      for (int idata = 0; idata < nparms; idata++) {

        //
        //  Extract correct bits from words using shift and mask
        //  operations.
        //
        int jbit = pkinf.nbitsc[idata];
        int jsbit = pkinf.isbitc[idata];
        int jshift = 1 - jsbit;
        int jsword = pkinf.iswrdc[idata];
        int jword = jdata[jsword];
        // use >>> to shift avoid carrying sign along
        int mask = mskpat >>> (32 - jbit);
        int ifield = jword >>> Math.abs(jshift);
        ifield = ifield & mask;
        if ((jsbit + jbit - 1) > 32) {
          jword = jdata[jsword + 1];
          jshift = jshift + 32;
          int iword = jword << jshift;
          iword = iword & mask;
          ifield = ifield | iword;
        }
        //
        //  The integer data is now in ifield.  Use the scaling and
        //  offset terms to convert to REAL data.
        //
        if (ifield == pkinf.imissc[idata]) {
          data[ir + idata] = RMISSD;
        } else {
          data[ir + idata] = (ifield + pkinf.koffst[idata])
                  * (float) pkinf.scalec[idata];
        }
      }
      ir += nparms;
      ii += nwordp;
    }
    return data;

  }

Unpack an array of packed integers.

@param part   the part with packing info
@param ibitst packed integer bit string
@return unpacked ints as floats


protected static String getBits(int b) {
    Formatter s = new Formatter();
    for (int i = 31; i >= 0; i--) {
      if ((b & (1 << i)) != 0) {
        s.format("1");
      } else {
        s.format("0");
      }
      if (i % 8 == 0) {
        s.format("|");
      }
    }
    return s.toString();
  }

protected static String getBits ( int b ) { Formatter s = new Formatter ( ) ; for ( int i = 31 ; i >= 0 ; i -- ) { if ( ( b & ( 1 << i ) ) != 0 ) { s . format ( "1" ) ; } else { s . format ( "0" ) ; } if ( i % 8 == 0 ) { s . format ( "|" ) ; } } return s . toString ( ) ; }

Get a bit string for an integer

@param b the integer
@return a bit string (e.g.: 01100001|11000000|10011010|10110100|)


public static void writeToChannel(NetcdfFile ncfile, WritableByteChannel wbc) throws IOException, InvalidRangeException {
    DataOutputStream stream = new DataOutputStream(new BufferedOutputStream( Channels.newOutputStream(wbc), 8000));
    //DataOutputStream stream = new DataOutputStream(Channels.newOutputStream(wbc));  // buffering seems to improve by 5%
    N3channelWriter writer = new N3channelWriter(ncfile);
    int numrec = ncfile.getUnlimitedDimension() == null ? 0 : ncfile.getUnlimitedDimension().getLength();
    writer.writeHeader(stream, numrec);
    stream.flush();
    writer.writeDataAll(wbc);
  }

Write ncfile to a WritableByteChannel.

@param ncfile the file to write
@param wbc write to this WritableByteChannel.
If its a Socket, must have been opened through a call to java.nio.channels.SocketChannel.open()
@throws IOException on IO error
@throws InvalidRangeException range error