private void parseBase(Element e, String indent)
            throws DASException, NoSuchTypeException, BadSemanticsException {

        parseLevel++;

        String type = e.getName();

        if (type.equals("Attribute")) {
            // Do nothing here, the Attributes get parsed when the BaseType's
            // get built. This conditional basically serves as a "trap" to
            // ignore the <Attribute> tag.
        } else if (type.equals("Alias")) {
            // Do nothing here, the Aliases get parsed when the BaseType's
            // get built. This conditional basically serves as a "trap" to
            // ignore the <Alias> tag.

        } else if (type.equals("dataBLOB")) {

            // dataBLOB?
            // The schema says that the href attribute is
            // required for the dataBLOB element.
            org.jdom2.Attribute hrefAttr = e.getAttribute("href");

            // Since it's required we know that the getAttribute()
            // method is not going to return null.
            String contentID = hrefAttr.getValue();

            if (_Debug) System.out.println("Found dataBLOB element. contentID=\"" + contentID + "\"");

            dds.setBlobContentID(contentID);

        } else {

            // What's left must be a OPeNDAP BaseType

            if (_Debug) System.out.println("Parsing new BaseType element. Parse level: " + parseLevel);
            if (_Debug) showXMLElement(e, indent);

            // Go get a new BaseType formed from this element
            BaseType bt = newBaseType(e);

            // Set it's parent.
            // bt.setParent(parentDC);

            // Add it to it's parent (container)
            parentDC.addVariable(bt);

            // Now we need to make sure this particular BaseType
            // derived element isn't some special type that needs
            // additional parsing:

            // Is it a container?
            if (bt instanceof DConstructor) {
                // Up date the parsers state, (cache my parent)
                DConstructor myParentDC = parentDC;
                parentDC = (DConstructor) bt;
                try {
                // Grids are special containers, handle them
                if (bt instanceof DGrid) {
                    parseGrid(e, indent);
                } else {
                    // Otherwise, recurse on the children
                  for (Element child : e.getChildren()) {
                    parseBase(child, indent + "    ");
                  }
                }
                } finally {
                // restore my parent
                parentDC = myParentDC;
                }
            } else if (bt instanceof DArray) {
                // Array's are special, better build it if it is one

                if (_Debug) System.out.println("Parsing Array instance.  Array name: '" + bt.getClearName() + "'");

                parseArray(e, (DArray) bt, indent);

            }

        }

        parseLevel--;

    }

"Parsing Array instance.  Array name: '"

This method recursively travels through the DOM tree, locating
BaseType derived nodes and placing them in the DDS. The structure
of the BaseType derived elements in the XML instance document
is captured in the DOM object that is being parsed. This structure
again reflected in the resulting DDS.

This method recursively travels through the DOM tree locating BaseType derived nodes and placing them in the DDS . The structure of the BaseType derived elements in the XML instance document is captured in the DOM object that is being parsed . This structure again reflected in the resulting DDS .


private void parseGrid(Element gridElement, String indent)
            throws DASException, NoSuchTypeException, BadSemanticsException {

        parseLevel++;

        // Grab the parent object (which better be a Grid!)
        // just to elminate the hassle of casting everytime...
        DGrid myGrid = (DGrid) parentDC;

        if (_Debug) {
            System.out.println("Parsing Grid Element: " + gridElement);
            System.out.println("Grid Elements: ");
            //showXMLElement(gridElement, indent);
          for (Element element : gridElement.getChildren()) System.out.println(element);
        }

        // Get and parse the grid's Array element.
        String eName = "Array";
        if (_Debug) {
            System.out.println("Parsing Array element.");
            System.out.println("Asking for element: '" + eName + "' in namespace: '" + opendapNameSpace + "'");
        }
        Element arrayElement = gridElement.getChild(eName, opendapNameSpace);
        if (_Debug) System.out.println("Got Array element: " + arrayElement);
        DArray gridArray = (DArray) newBaseType(arrayElement);
        parseArray(arrayElement, gridArray, indent + "    ");

        // Add it to the Grid
        myGrid.addVariable(gridArray, DGrid.ARRAY);

        // Get the Map elements
        eName = "Map";
        if (_Debug) {
            System.out.println("Parsing Map elements.");
            System.out.println("Asking for element: '" + eName + "' in namespace: '" + opendapNameSpace + "'");
        }
        List<Element> mapElements = gridElement.getChildren("Map", opendapNameSpace);

        // Make sure the number of Map elements matches the dimension of the Grid Array.
        if (mapElements.size() != gridArray.numDimensions())
            throw new BadSemanticsException("Error in Grid syntax: " +
                    "The number of Map arrays must " +
                    "equal the number of dimensions " +
                    "of the data array.");

        // Parse each Map element and poke it into the Grid.
      for (Element mapElement : mapElements) {
        DArray thisMap = (DArray) newBaseType(mapElement);
        parseArray(mapElement, thisMap, indent + "    ");

        if (thisMap.numDimensions() != 1)
          throw new BadSemanticsException("Error in Grid syntax: " +
                  "Maps may have only one dimension.");

        myGrid.addVariable(thisMap, DGrid.MAPS);

      }

        parseLevel--;

    }

Grids are unusual examples of DConstructor and require special
handling when parsing.

Grids are unusual examples of DConstructor and require special handling when parsing .


private void parseAliases(Element e, String indent) throws DASException {

        parseLevel++;

        String subIndent = indent + "    ";
        if (_Debug) System.out.println(indent + "Parsing Aliases: ");

        if (_Debug)
            System.out.println(subIndent + "currentBT: " + currentBT.getTypeName() + " " + currentBT.getClearName());

        // Get the Alias elements
      for (Element aliasElement : e.getChildren("Alias", opendapNameSpace)) {
        String name = null;
        Attribute nameAttr = aliasElement.getAttribute("name");
        // no need to check that the getAttribute call worked because the Schema enforces
        // the presence of the "name" attribute for the <Alias> tag in the OPeNDAP namespace
        name = nameAttr.getValue();

        String attributeName = null;
        Attribute attributeAttr = aliasElement.getAttribute("Attribute");
        // no need to check that the getAttribute call worked because the Schema enforces
        // the presence of the "Attribute" attribute for the <Alias> tag in the OPeNDAP namespace
        attributeName = attributeAttr.getValue();

        if (_Debug) {
          System.out.println(subIndent + "The name '" + name +
                  "' is aliased to dds attribute: '" + attributeName + "'");
        }

        // Add the Alias to the appropriate container.
        if (currentAT == null)
          currentBT.addAttributeAlias(name, attributeName);
        else
          currentAT.addAlias(name, attributeName);

      }

        parseLevel--;
    }

Parse all of the Alias tags in this element of the XML document.
Add each one to the correct Attribute Table.

Parse all of the Alias tags in this element of the XML document . Add each one to the correct Attribute Table .


private List<DataDescriptor> decode(List<Short> keyDesc, BufrTableLookup lookup) {
    if (keyDesc == null) return null;

    List<DataDescriptor> keys = new ArrayList<DataDescriptor>();
    for (short id : keyDesc) {
      DataDescriptor dd = new DataDescriptor(id, lookup);
      keys.add( dd);
      if (dd.f == 3) {
        TableD.Descriptor tdd = lookup.getDescriptorTableD(dd.fxy);
        if (tdd == null || tdd.getSequence() == null) {
          dd.bad = true;
        } else {
          dd.name = tdd.getName();
          dd.subKeys = decode(tdd.getSequence(), lookup);
        }
      }
    }
    return keys;
  }

private List < DataDescriptor > decode ( List < Short > keyDesc , BufrTableLookup lookup ) { if ( keyDesc == null ) return null ; List < DataDescriptor > keys = new ArrayList < DataDescriptor > ( ) ; for ( short id : keyDesc ) { DataDescriptor dd = new DataDescriptor ( id , lookup ) ; keys . add ( dd ) ; if ( dd . f == 3 ) { TableD . Descriptor tdd = lookup . getDescriptorTableD ( dd . fxy ) ; if ( tdd == null || tdd . getSequence ( ) == null ) { dd . bad = true ; } else { dd . name = tdd . getName ( ) ; dd . subKeys = decode ( tdd . getSequence ( ) , lookup ) ; } } } return keys ; }

convert ids to DataDescriptors, expand table D

convert ids to DataDescriptors expand table D


private List<DataDescriptor> replicate(List<DataDescriptor> keys) {
    List<DataDescriptor> tree = new ArrayList<DataDescriptor>();
    Iterator<DataDescriptor> dkIter = keys.iterator();
    while (dkIter.hasNext()) {
      DataDescriptor dk = dkIter.next();
      if (dk.f == 1) {
        dk.subKeys = new ArrayList<DataDescriptor>();
        dk.replication = dk.y; // replication count

        if (dk.replication == 0) { // delayed replication
          root.isVarLength = true; // variable sized data == deferred replication == sequence data

          // the next one is the replication count size : does not count in field count (x)
          DataDescriptor replication = dkIter.next();
          if (replication.y == 0)
            dk.replicationCountSize = 1; // ??
          else if (replication.y == 1)
            dk.replicationCountSize = 8;
          else if (replication.y == 2)
            dk.replicationCountSize = 16;
          else if (replication.y == 11)
            dk.repetitionCountSize = 8;
          else if (replication.y == 12)
            dk.repetitionCountSize = 16;
          else
            log.error("Unknown replication type= "+replication);
        }

        // transfer to the subKey list
        for (int j = 0; j < dk.x && dkIter.hasNext(); j++) {
          dk.subKeys.add( dkIter.next());
        }

        // recurse
        dk.subKeys = replicate(dk.subKeys);

      } else if ((dk.f == 3) && (dk.subKeys != null)) {
        dk.subKeys = replicate( dk.subKeys); // do at all levels
      }

      tree.add(dk);
    }

    return tree;
  }

look for replication, move replicated items into subtree

look for replication move replicated items into subtree


public String getDatasetFilename() {
        String s = getEncodedName();
        System.out.println(s);
        return (s);
    }

public String getDatasetFilename ( ) { String s = getEncodedName ( ) ; System . out . println ( s ) ; return ( s ) ; }

Get the dataset filename.

@return The filename of the dataset.
@see #setDatasetFilename(String)


public String getCFFeatureType() {
    if (gemreader.getFileSubType().equals(GempakSurfaceFileReader.SHIP)) {
      return CF.FeatureType.point.toString();
    }
    return CF.FeatureType.timeSeries.toString();
  }

public String getCFFeatureType ( ) { if ( gemreader . getFileSubType ( ) . equals ( GempakSurfaceFileReader . SHIP ) ) { return CF . FeatureType . point . toString ( ) ; } return CF . FeatureType . timeSeries . toString ( ) ; }

Get the CF feature type

@return the feature type


public static boolean nearlyEqualsAbs(float a, float b, float maxAbsDiff) {
    return absoluteDifference(a, b) <= Math.abs(maxAbsDiff);
  }

public static boolean nearlyEqualsAbs ( float a , float b , float maxAbsDiff ) { return absoluteDifference ( a , b ) <= Math . abs ( maxAbsDiff ) ; }

Check if two numbers are nearly equal with given absolute tolerance.

@param a  first number.
@param b  second number.
@param maxAbsDiff  the maximum {@link #absoluteDifference absolute difference} the two numbers may have.
@return true if within tolerance.

Check if two numbers are nearly equal with given absolute tolerance .


@Override
    public boolean references(DapNode node)
    {
        switch (node.getSort()) {
        case DIMENSION:
        case ENUMERATION:
        case VARIABLE:
        case GROUP:
        case DATASET:
            return true;
        default:
            break;
        }
        return false;
    }

@ Override public boolean references ( DapNode node ) { switch ( node . getSort ( ) ) { case DIMENSION : case ENUMERATION : case VARIABLE : case GROUP : case DATASET : return true ; default : break ; } return false ; }

Selected consult or iterator overrides for efficiency


public final Unit parse(final String spec) throws NoSuchUnitException,
			UnitParseException, SpecificationException, UnitDBException,
			PrefixDBException, UnitSystemException {
		synchronized (MUTEX) {
			return parse(spec, UnitDBManager.instance());
		}
	}

public final Unit parse ( final String spec ) throws NoSuchUnitException , UnitParseException , SpecificationException , UnitDBException , PrefixDBException , UnitSystemException { synchronized ( MUTEX ) { return parse ( spec , UnitDBManager . instance ( ) ) ; } }

Parses a unit specification.  This method is thread-safe.

@param spec
The unit specification (e.g. "m/s");
@return The unit corresponding to the specification.
@throws NoSuchUnitException
A unit in the specification couldn't be found (e.g. the "m"
in the example).
@throws UnitParseException
The specification is grammatically incorrect.
@throws SpecificationException
The specification is incorrect somehow.
@throws UnitDBException
Problem with the unit database.
@throws PrefixDBException
Problem with the unit-prefix database.
@throws UnitSystemException
Problem with the system of units.

Parses a unit specification . This method is thread - safe .


public static void probeObject(Object o) {

        Class c = o.getClass();

        Class interfaces[] = c.getInterfaces();
        Class parent = c.getSuperclass();
        Method m[] = c.getMethods();

        System.out.println("********* OBJECT PROBE *********");
        System.out.println("Class Name:  " + c.getName());
        System.out.println("Super Class: " + parent.getName());
        System.out.println("Interfaces: ");
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println("    " + interfaces[i].getName());
        }

        System.out.println("Methods:");
        for (int i = 0; i < m.length; i++) {

            Class params[] = m[i].getParameterTypes();
            Class excepts[] = m[i].getExceptionTypes();
            Class ret = m[i].getReturnType();

            System.out.print("    " + ret.getName() + "  " + m[i].getName() + "(");

            for (int j = 0; j < params.length; j++) {
                if (j > 0)
                    System.out.print(", ");
                System.out.print(params[j].getName());
            }
            System.out.print(")  throws ");
            for (int j = 0; j < excepts.length; j++) {
                if (j > 0)
                    System.out.print(", ");
                System.out.print(excepts[j].getName());
            }
            System.out.println("");
        }
        System.out.println("******************");

    }

public
static
void
probeObject
(
Object
o
)
{
Class
c
=
o
.
getClass
(
)
;
Class
interfaces
[
]
=
c
.
getInterfaces
(
)
;
Class
parent
=
c
.
getSuperclass
(
)
;
Method
m
[
]
=
c
.
getMethods
(
)
;
System
.
out
.
println
(
"********* OBJECT PROBE *********"
)
;
System
.
out
.
println
(
"Class Name:  "
+
c
.
getName
(
)
)
;
System
.
out
.
println
(
"Super Class: "
+
parent
.
getName
(
)
)
;
System
.
out
.
println
(
"Interfaces: "
)
;
for
(
int
i
=
0
;
i
<
interfaces
.
length
;
i
++
)
{
System
.
out
.
println
(
"    "
+
interfaces
[
i
]
.
getName
(
)
)
;
}
System
.
out
.
println
(
"Methods:"
)
;
for
(
int
i
=
0
;
i
<
m
.
length
;
i
++
)
{
Class
params
[
]
=
m
[
i
]
.
getParameterTypes
(
)
;
Class
excepts
[
]
=
m
[
i
]
.
getExceptionTypes
(
)
;
Class
ret
=
m
[
i
]
.
getReturnType
(
)
;
System
.
out
.
print
(
"    "
+
ret
.
getName
(
)
+
"  "
+
m
[
i
]
.
getName
(
)
+
"("
)
;
for
(
int
j
=
0
;
j
<
params
.
length
;
j
++
)
{
if
(
j
>
0
)
System
.
out
.
print
(
", "
)
;
System
.
out
.
print
(
params
[
j
]
.
getName
(
)
)
;
}
System
.
out
.
print
(
")  throws "
)
;
for
(
int
j
=
0
;
j
<
excepts
.
length
;
j
++
)
{
if
(
j
>
0
)
System
.
out
.
print
(
", "
)
;
System
.
out
.
print
(
excepts
[
j
]
.
getName
(
)
)
;
}
System
.
out
.
println
(
""
)
;
}
System
.
out
.
println
(
"******************"
)
;
}

Show me lots of stuff about the passed in object


private boolean isTiled(Variable v) {
    for (Dimension d : v.getDimensions()) {
      for (Range r : section.getRanges()) {
        if (d.getShortName().equals(r.getName()))
          return true;
      }
    }
    return false;
  }

private boolean isTiled ( Variable v ) { for ( Dimension d : v . getDimensions ( ) ) { for ( Range r : section . getRanges ( ) ) { if ( d . getShortName ( ) . equals ( r . getName ( ) ) ) return true ; } } return false ; }

a variable is tiled if any of its dimensions are tiled


public CoordinateTimeAbstract makeBestFromComplete() {
    int[] best = new int[time2runtime.length];
    int last = -1;
    int count = 0;
    for (int i=0; i<time2runtime.length; i++) {
      int time = time2runtime[i];
      if (time >= last) {
        last = time;
        best[i] = time;
        count++;
      } else {
        best[i] = -1;
      }
    }
    return makeBestFromComplete(best, count);
  }

public CoordinateTimeAbstract makeBestFromComplete ( ) { int [ ] best = new int [ time2runtime . length ] ; int last = - 1 ; int count = 0 ; for ( int i = 0 ; i < time2runtime . length ; i ++ ) { int time = time2runtime [ i ] ; if ( time >= last ) { last = time ; best [ i ] = time ; count ++ ; } else { best [ i ] = - 1 ; } } return makeBestFromComplete ( best , count ) ; }

Implements coverting a "complete best" to a "monotonic best".
The reftime is not allowed to decrease
@return "monotonic best" CoordinateTimeAbstract, based on this one, which is a "complete best"

Implements coverting a complete best to a monotonic best . The reftime is not allowed to decrease


public ProjectionRect[] latLonToProjRect(LatLonRect latlonR) {

    double lat0 = latlonR.getLowerLeftPoint().getLatitude();
    double height = Math.abs(latlonR.getUpperRightPoint().getLatitude() - lat0);
    double width = latlonR.getWidth();
    double lon0 = LatLonPointImpl.lonNormal(
        latlonR.getLowerLeftPoint().getLongitude(),
        centerLon);
    double lon1 = LatLonPointImpl.lonNormal(
        latlonR.getUpperRightPoint().getLongitude(),
        centerLon);

    ProjectionRect[] rects = new ProjectionRect[] {new ProjectionRect(), new ProjectionRect()};
    if (lon0 < lon1) {
      rects[0].setRect(lon0, lat0, width, height);
      rects[1] = null;

    } else {
      double y = centerLon + 180 - lon0;
      rects[0].setRect(lon0, lat0, y, height);
      rects[1].setRect(lon1 - width + y, lat0, width - y, height);
    }

    return rects;
  }

public ProjectionRect [ ] latLonToProjRect ( LatLonRect latlonR ) { double lat0 = latlonR . getLowerLeftPoint ( ) . getLatitude ( ) ; double height = Math . abs ( latlonR . getUpperRightPoint ( ) . getLatitude ( ) - lat0 ) ; double width = latlonR . getWidth ( ) ; double lon0 = LatLonPointImpl . lonNormal ( latlonR . getLowerLeftPoint ( ) . getLongitude ( ) , centerLon ) ; double lon1 = LatLonPointImpl . lonNormal ( latlonR . getUpperRightPoint ( ) . getLongitude ( ) , centerLon ) ; ProjectionRect [ ] rects = new ProjectionRect [ ] { new ProjectionRect ( ) , new ProjectionRect ( ) } ; if ( lon0 < lon1 ) { rects [ 0 ] . setRect ( lon0 , lat0 , width , height ) ; rects [ 1 ] = null ; } else { double y = centerLon + 180 - lon0 ; rects [ 0 ] . setRect ( lon0 , lat0 , y , height ) ; rects [ 1 ] . setRect ( lon1 - width + y , lat0 , width - y , height ) ; } return rects ; }

Split a latlon rectangle to the equivalent ProjectionRect
using this LatLonProjection to split it at the seam if needed.

@param latlonR the latlon rectangle to transform
@return 1 or 2 ProjectionRect. If it doesnt cross the seam,
the second rectangle is null.

Split a latlon rectangle to the equivalent ProjectionRect using this LatLonProjection to split it at the seam if needed .


private void showTimeSeriesAll(java.util.List<LogReader.Log> logs) {
    TimeSeries bytesSentData = new TimeSeries("Bytes Sent", Minute.class);
    TimeSeries timeTookData = new TimeSeries("Average Latency", Minute.class);
    TimeSeries nreqData = new TimeSeries("Number of Requests", Minute.class);

    String intervalS = "5 minute"; // interval.getText().trim();
    // if (intervalS.length() == 0) intervalS = "5 minute";
    long period = 1000 * 60 * 5;
    try {
      TimeDuration tu = new TimeDuration(intervalS);
      period = (long) (1000 * tu.getValueInSeconds());
    } catch (Exception e) {
      System.out.printf("Illegal Time interval=%s %n", intervalS);
    }

    long current = 0;
    long bytes = 0;
    long timeTook = 0;
    long total_count = 0;
    long count = 0;
    for (LogReader.Log log : logs) {
      long msecs = log.date;
      if (msecs - current > period) {
        if (current > 0) {
          total_count += count;
          addPoint(bytesSentData, timeTookData, nreqData, new Date(current), bytes, count, timeTook);
        }
        bytes = 0;
        count = 0;
        timeTook = 0;
        current = msecs;
      }
      bytes += log.getBytes();
      timeTook += log.getMsecs();
      count++;
    }
    if (count > 0)
        addPoint(bytesSentData, timeTookData, nreqData, new Date(current), bytes, count, timeTook);
    total_count += count;
    System.out.printf("showTimeSeriesAll: total_count = %d logs = %d%n", total_count, logs.size());

    MultipleAxisChart mc = new MultipleAxisChart("Access Logs", intervalS + " average", "Mbytes Sent", bytesSentData);
    mc.addSeries("Number of Requests", nreqData);
    mc.addSeries("Average Latency (secs)", timeTookData);
    mc.finish(new java.awt.Dimension(1000, 1000));

    //MultipleAxisChart mc = new MultipleAxisChart("Bytes Sent", "5 min average", "Mbytes/sec", bytesSentData);
    //Chart c2 = new Chart("Average Latency", "5 min average", "Millisecs", timeTookData);
    //Chart c3 = new Chart("Number of Requests/sec", "5 min average", "", nreqData);

    timeSeriesPanel.removeAll();
    timeSeriesPanel.add(mc);
  }

construct the TImeSeries plot for the list of logs passed in


static public Map<String, Attribute> makeMap(List<Attribute> atts)
  {
    int size = (atts == null) ? 1 : atts.size();
    Map<String, Attribute> result = new HashMap<>(size);
    if(atts == null) return result;
    for(Attribute att : atts) result.put(att.getShortName(), att);
    return result;
  }

static public Map < String , Attribute > makeMap ( List < Attribute > atts ) { int size = ( atts == null ) ? 1 : atts . size ( ) ; Map < String , Attribute > result = new HashMap <> ( size ) ; if ( atts == null ) return result ; for ( Attribute att : atts ) result . put ( att . getShortName ( ) , att ) ; return result ; }

Turn a list into a map

@param atts list of attributes
@return map of attributes by name


public Array getValues() {
    if (values == null && svalue != null) {
      values = Array.factory(DataType.STRING, new int[]{1});
      values.setObject(values.getIndex(), svalue);
    }

    return values;
  }

public Array getValues ( ) { if ( values == null && svalue != null ) { values = Array . factory ( DataType . STRING , new int [ ] { 1 } ) ; values . setObject ( values . getIndex ( ) , svalue ) ; } return values ; }

Get the value as an Array.

@return Array of values.


public Number getNumericValue(int index) {
    if ((index < 0) || (index >= nelems))
      return null;

    // LOOK can attributes be enum valued? for now, no
    switch (dataType) {
      case STRING:
        try {
          return new Double(getStringValue(index));
        } catch (NumberFormatException e) {
          return null;
        }
      case BYTE:
      case UBYTE:
        return values.getByte(index);
      case SHORT:
      case USHORT:
        return values.getShort(index);
      case INT:
      case UINT:
        return values.getInt(index);
      case FLOAT:
        return values.getFloat(index);
      case DOUBLE:
        return values.getDouble(index);
      case LONG:
      case ULONG:
        return values.getLong(index);
    }
    return null;
  }

Retrieve a numeric value by index. If it's a String, it will try to parse it as a double.

@param index the index into the value array.
@return Number value[index], or null if its a non-parseable String or
the index is out of range.

Retrieve a numeric value by index . If it s a String it will try to parse it as a double .


protected void writeCDL(Formatter f, boolean strict, String parentname) {
    if(strict && (isString() || this.getEnumType() != null))
      // Force type explicitly for string.
      f.format("string "); //note lower case and trailing blank
    if(strict && parentname != null) f.format(NetcdfFile.makeValidCDLName(parentname));
    f.format(":");
    f.format("%s", strict ? NetcdfFile.makeValidCDLName(getShortName()) : getShortName());
    if (isString()) {
      f.format(" = ");
      for(int i = 0; i < getLength(); i++) {
        if(i != 0) f.format(", ");
        String val = getStringValue(i);
        if(val != null)
          f.format("\"%s\"", encodeString(val));
      }
    } else if(getEnumType() != null) {
      f.format(" = ");
      for (int i = 0; i < getLength(); i++) {
        if(i != 0) f.format(", ");
        EnumTypedef en = getEnumType();
        String econst = getStringValue(i);
        Integer ecint = en.lookupEnumInt(econst);
        if(ecint == null)
           throw new ForbiddenConversionException("Illegal enum constant: "+econst);
        f.format("\"%s\"", encodeString(econst));
      }
    } else {
      f.format(" = ");
      for (int i = 0; i < getLength(); i++) {
        if (i != 0) f.format(", ");

        Number number = getNumericValue(i);
        if (dataType.isUnsigned()) {
          // 'number' is unsigned, but will be treated as signed when we print it below, because Java only has signed
          // types. If it is large enough ( >= 2^(BIT_WIDTH-1) ), its most-significant bit will be interpreted as the
          // sign bit, which will result in an invalid (negative) value being printed. To prevent that, we're going
          // to widen the number before printing it.
          number = DataType.widenNumber(number);
        }
        f.format("%s", number);

        if (dataType.isUnsigned()) {
          f.format("U");
        }

        if (dataType == DataType.FLOAT)
          f.format("f");
        else if (dataType == DataType.SHORT || dataType == DataType.USHORT) {
          f.format("S");
        } else if (dataType == DataType.BYTE || dataType == DataType.UBYTE) {
          f.format("B");
        } else if (dataType == DataType.LONG || dataType == DataType.ULONG) {
          f.format("L");
        }
      }
    }
  }

Write CDL representation into f

@param f      write into this
@param strict if true, create strict CDL, escaping names


private void setStringValue(String val) {
    if (val == null)
      throw new IllegalArgumentException("Attribute value cannot be null");

    // get rid of trailing nul characters
    int len = val.length();
    while ((len > 0) && (val.charAt(len - 1) == 0))
      len--;
    if (len != val.length())
      val = val.substring(0, len);

    this.svalue = val;
    this.nelems = 1;
    this.dataType = DataType.STRING;

    //values = Array.factory(String.class, new int[]{1});
    //values.setObject(values.getIndex(), val);
    //setValues(values);
  }

set the value as a String, trimming trailing zeroes

@param val value of Attribute

set the value as a String trimming trailing zeroes


public void setValues(List values)
  {
    if(values == null || values.size() == 0)
	throw new IllegalArgumentException("Cannot determine attribute's type");
    int n = values.size();
    Class c = values.get(0).getClass();
    Object pa;

    if (c == String.class) {
      String[] va = new String[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (String) values.get(i);
    } else if (c == Integer.class) {
      int[] va = new int[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (Integer) values.get(i);
    } else if (c == Double.class) {
      double[] va = new double[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (Double) values.get(i);
    } else if (c == Float.class) {
      float[] va = new float[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (Float) values.get(i);
    } else if (c == Short.class) {
      short[] va = new short[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (Short) values.get(i);
    } else if (c == Byte.class) {
      byte[] va = new byte[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (Byte) values.get(i);
    } else if (c == Long.class) {
      long[] va = new long[n];
      pa = va;
      for (int i = 0; i < n; i++) va[i] = (Long) values.get(i);
    } else {
      throw new IllegalArgumentException("Unknown type for Attribute = " + c.getName());
    }
    setValues(Array.factory(this.dataType, new int[]{n}, pa));
  }

public
void
setValues
(
List
values
)
{
if
(
values
==
||
values
.
size
(
)
==
0
)
throw
new
IllegalArgumentException
(
"Cannot determine attribute's type"
)
;
int
n
=
values
.
size
(
)
;
Class
c
=
values
.
get
(
0
)
.
getClass
(
)
;
Object
pa
;
if
(
c
==
String
.
class
)
{
String
[
]
va
=
new
String
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
String
)
values
.
get
(
i
)
;
}
else
if
(
c
==
Integer
.
class
)
{
int
[
]
va
=
new
int
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
Integer
)
values
.
get
(
i
)
;
}
else
if
(
c
==
Double
.
class
)
{
double
[
]
va
=
new
double
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
Double
)
values
.
get
(
i
)
;
}
else
if
(
c
==
Float
.
class
)
{
float
[
]
va
=
new
float
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
Float
)
values
.
get
(
i
)
;
}
else
if
(
c
==
Short
.
class
)
{
short
[
]
va
=
new
short
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
Short
)
values
.
get
(
i
)
;
}
else
if
(
c
==
Byte
.
class
)
{
byte
[
]
va
=
new
byte
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
Byte
)
values
.
get
(
i
)
;
}
else
if
(
c
==
Long
.
class
)
{
long
[
]
va
=
new
long
[
n
]
;
pa
=
va
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
va
[
i
]
=
(
Long
)
values
.
get
(
i
)
;
}
else
{
throw
new
IllegalArgumentException
(
"Unknown type for Attribute = "
+
c
.
getName
(
)
)
;
}
setValues
(
Array
.
factory
(
this
.
dataType
,
new
int
[
]
{
n
}
,
pa
)
)
;
}

set the values from a list

@param values


public void setValues(Array arr) {
    if (immutable) throw new IllegalStateException("Cant modify");

    if (arr == null) {
      dataType = DataType.STRING;
      return;
    }

    if (arr.getElementType() == char.class) { // turn CHAR into STRING
      ArrayChar carr = (ArrayChar) arr;
      if (carr.getRank() == 1) { // common case
        svalue = carr.getString();
        this.nelems = 1;
        this.dataType = DataType.STRING;
        return;
      }
      // otherwise its an array of Strings
      arr = carr.make1DStringArray();
    }

    // this should be a utility somewhere
    if (arr.getElementType() == ByteBuffer.class) { // turn OPAQUE into BYTE
      int totalLen = 0;
      arr.resetLocalIterator();
      while (arr.hasNext()) {
        ByteBuffer bb = (ByteBuffer) arr.next();
        totalLen += bb.limit();
      }
      byte[] ba = new byte[totalLen];
      int pos = 0;
      arr.resetLocalIterator();
      while (arr.hasNext()) {
        ByteBuffer bb = (ByteBuffer) arr.next();
        System.arraycopy(bb.array(), 0, ba, pos, bb.limit());
        pos += bb.limit();
      }
      arr = Array.factory(DataType.BYTE, new int[]{totalLen}, ba);
    }

    if (DataType.getType(arr) == DataType.OBJECT)
      throw new IllegalArgumentException("Cant set Attribute with type " + arr.getElementType());

    if (arr.getRank() > 1)
      arr = arr.reshape(new int[]{(int) arr.getSize()}); // make sure 1D

    this.values = arr;
    this.nelems = (int) arr.getSize();
    this.dataType = DataType.getType(arr);
  }

public
void
setValues
(
Array
arr
)
{
if
(
immutable
)
throw
new
IllegalStateException
(
"Cant modify"
)
;
if
(
arr
==
)
{
dataType
=
DataType
.
STRING
;
return
;
}
if
(
arr
.
getElementType
(
)
==
char
.
class
)
{
// turn CHAR into STRING
ArrayChar
carr
=
(
ArrayChar
)
arr
;
if
(
carr
.
getRank
(
)
==
1
)
{
// common case
svalue
=
carr
.
getString
(
)
;
this
.
nelems
=
1
;
this
.
dataType
=
DataType
.
STRING
;
return
;
}
// otherwise its an array of Strings
arr
=
carr
.
make1DStringArray
(
)
;
}
// this should be a utility somewhere
if
(
arr
.
getElementType
(
)
==
ByteBuffer
.
class
)
{
// turn OPAQUE into BYTE
int
totalLen
=
0
;
arr
.
resetLocalIterator
(
)
;
while
(
arr
.
hasNext
(
)
)
{
ByteBuffer
bb
=
(
ByteBuffer
)
arr
.
next
(
)
;
totalLen
+=
bb
.
limit
(
)
;
}
byte
[
]
ba
=
new
byte
[
totalLen
]
;
int
pos
=
0
;
arr
.
resetLocalIterator
(
)
;
while
(
arr
.
hasNext
(
)
)
{
ByteBuffer
bb
=
(
ByteBuffer
)
arr
.
next
(
)
;
System
.
arraycopy
(
bb
.
array
(
)
,
0
,
ba
,
pos
,
bb
.
limit
(
)
)
;
pos
+=
bb
.
limit
(
)
;
}
arr
=
Array
.
factory
(
DataType
.
BYTE
,
new
int
[
]
{
totalLen
}
,
ba
)
;
}
if
(
DataType
.
getType
(
arr
)
==
DataType
.
OBJECT
)
throw
new
IllegalArgumentException
(
"Cant set Attribute with type "
+
arr
.
getElementType
(
)
)
;
if
(
arr
.
getRank
(
)
>
1
)
arr
=
arr
.
reshape
(
new
int
[
]
{
(
int
)
arr
.
getSize
(
)
}
)
;
// make sure 1D
this
.
values
=
arr
;
this
.
nelems
=
(
int
)
arr
.
getSize
(
)
;
this
.
dataType
=
DataType
.
getType
(
arr
)
;
}

set the values from an Array

@param arr value of Attribute


public void scan() throws IOException
  {
    if ( state == 1 ) throw new IllegalStateException( "Scan already underway." );
    if ( state >= 2 ) throw new IllegalStateException( "Scan has already been generated." );
    state = 1;

    // Make sure proxyDsHandlers Map is not null.
    if ( proxyDsHandlers == null ) proxyDsHandlers = Collections.EMPTY_MAP;

    // Create a skeleton catalog.
    genCatalog = createSkeletonCatalog( currentLevel );
    InvDatasetImpl topInvDs = (InvDatasetImpl) genCatalog.getDatasets().get( 0 );

    // Get the datasets in this collection.
    List crDsList = currentLevel.listDatasets( this.filter );

    // Sort the datasets in this collection.
    // @todo Should we move sort to end of this method? As is, we can't use naming or enhancements to determine sort order.
    if ( sorter != null ) sorter.sort( crDsList );

    // Add the datasets to the catalog.
    for ( int i = 0; i < crDsList.size(); i++ )
    //for ( Iterator it = crDsList.iterator(); it.hasNext(); )
    {
      CrawlableDataset curCrDs = (CrawlableDataset) crDsList.get( i );

      InvDatasetImpl curInvDs = (InvDatasetImpl) createInvDatasetFromCrawlableDataset( curCrDs, topInvDs, null );

      // Add dataset info to appropriate lists.
      InvCrawlablePair dsInfo = new InvCrawlablePair( curCrDs, curInvDs );
      //allDsInfo.add( dsInfo );
      if ( curCrDs.isCollection() )
        catRefInfo.add( dsInfo );
      else
        atomicDsInfo.add( dsInfo );

      // Add current InvDataset to top dataset.
      topInvDs.addDataset( curInvDs );
    }

    // Tie up any loose ends in catalog with finish().
    ( (InvCatalogImpl) genCatalog ).finish();

    // Add proxy datasets to list (only if some atomic datasets in this collection).
    if ( atomicDsInfo.size() > 0 )
    {
      boolean anyProxiesAdded = false;
      for ( Iterator it = proxyDsHandlers.values().iterator(); it.hasNext(); )
      {
        // Get current
        ProxyDatasetHandler curProxy = (ProxyDatasetHandler) it.next();

        InvService proxyService = curProxy.getProxyDatasetService( currentLevel );
        if ( proxyService != null )
        {
          // Create proxy CrawlableDataset and corresponding InvDataset
          CrawlableDataset crDsToAdd = curProxy.createProxyDataset( currentLevel );
          InvDatasetImpl invDsToAdd = createInvDatasetFromCrawlableDataset( crDsToAdd, topInvDs, proxyService );

          // Add dataset info to appropriate lists.
          InvCrawlablePair dsInfo = new InvCrawlablePair( crDsToAdd, invDsToAdd );
          proxyDsInfo.add( dsInfo );

          // Add dataset to catalog
          int index = curProxy.getProxyDatasetLocation( currentLevel, topInvDs.getDatasets().size() );
          topInvDs.addDataset( index, (InvDatasetImpl) invDsToAdd );

          genCatalog.addService( proxyService );
          anyProxiesAdded = true;
        }
      }

      // Tie up any proxy dataset loose ends.
      if ( anyProxiesAdded ) ( (InvCatalogImpl) genCatalog ).finish();
    }

    // Add any top-level metadata.
    this.addTopLevelMetadata( genCatalog, true );

    state = 2;
    return;
  }

Scan the collection and gather information on contained datasets.

@throws IOException if an I/O error occurs while locating the contained datasets.

Scan the collection and gather information on contained datasets .


public InvCatalogImpl generateProxyDsResolverCatalog( ProxyDatasetHandler pdh )
  {
    if ( state != 2 ) throw new IllegalStateException( "Scan has not been performed." );
    if ( ! proxyDsHandlers.containsValue( pdh )) throw new IllegalArgumentException( "Unknown ProxyDatasetHandler.");

    // Create a skeleton catalog.
    InvCatalogImpl catalog = createSkeletonCatalog( currentLevel );
    InvDatasetImpl topDs = (InvDatasetImpl) catalog.getDatasets().get( 0 );

    // Find actual dataset in the list of atomic dataset InvCrawlablePairs.
    InvCrawlablePair actualDsInfo = pdh.getActualDataset( atomicDsInfo );
    if ( actualDsInfo == null )
      return catalog; // TODO Test this case in TestDataRootHandler.
    InvDatasetImpl actualInvDs = (InvDatasetImpl) actualDsInfo.getInvDataset();

    actualInvDs.setName( pdh.getActualDatasetName( actualDsInfo, topDs.getName() ) );

    // Add current InvDataset to top dataset.
    catalog.removeDataset( topDs );
    catalog.addDataset( actualInvDs );
    // topDs.addDataset( actualInvDs );

    // Finish catalog.
    catalog.finish();

    // Add any top-level metadata.
    this.addTopLevelMetadata( catalog, false );

    return catalog;
  }

Generate the catalog for a resolver request of the given ProxyDatasetHandler.

@param pdh the ProxyDatasetHandler corresponding to the resolver request.
@return the catalog for a resolver request of the given proxy dataset.
@throws IllegalStateException if this collection has not yet been scanned.
@throws IllegalArgumentException if the given ProxyDatasetHandler is not known by this CollectionLevelScanner.

Generate the catalog for a resolver request of the given ProxyDatasetHandler .


void scheduleWrite(Message m) {
    q.add(m);
    if (!isScheduled.getAndSet(true)) {
      executor.submit( this);
    }
  }

void scheduleWrite ( Message m ) { q . add ( m ) ; if ( ! isScheduled . getAndSet ( true ) ) { executor . submit ( this ) ; } }

put a message on the queue, schedule writing if not already scheduled.

put a message on the queue schedule writing if not already scheduled .


private void setThreddsDatatype(thredds.client.catalog.Dataset invDataset, String wants) {
    if (invDataset == null) return;

    boolean wantsViewer = wants.equals("File");
    boolean wantsCoordSys = wants.equals("CoordSys");

    try {
      // just open as a NetcdfDataset
      if (wantsViewer) {
        openNetcdfFile(threddsDataFactory.openDataset(invDataset, true, null, null));
        return;
      }

      if (wantsCoordSys) {
        NetcdfDataset ncd = threddsDataFactory.openDataset(invDataset, true, null, null);
        ncd.enhance(); // make sure its enhanced
        openCoordSystems(ncd);
        return;
      }

      // otherwise do the datatype thing
      DataFactory.Result threddsData = threddsDataFactory.openFeatureDataset(invDataset, null);
      if (threddsData.fatalError) {
        JOptionPane.showMessageDialog(null, "Failed to open err="+threddsData.errLog);
        return;
      }
      jumptoThreddsDatatype(threddsData);

    }
    catch (IOException ioe) {
      JOptionPane.showMessageDialog(null, "Error on setThreddsDatatype = " + ioe.getMessage());
      ioe.printStackTrace();
    }

  }

private
void
setThreddsDatatype
(
thredds
.
client
.
catalog
.
Dataset
invDataset
,
String
wants
)
{
if
(
invDataset
==
)
return
;
boolean
wantsViewer
=
wants
.
equals
(
"File"
)
;
boolean
wantsCoordSys
=
wants
.
equals
(
"CoordSys"
)
;
try
{
// just open as a NetcdfDataset
if
(
wantsViewer
)
{
openNetcdfFile
(
threddsDataFactory
.
openDataset
(
invDataset
,
true
,
,
)
)
;
return
;
}
if
(
wantsCoordSys
)
{
NetcdfDataset
ncd
=
threddsDataFactory
.
openDataset
(
invDataset
,
true
,
,
)
;
ncd
.
enhance
(
)
;
// make sure its enhanced
openCoordSystems
(
ncd
)
;
return
;
}
// otherwise do the datatype thing
DataFactory
.
Result
threddsData
=
threddsDataFactory
.
openFeatureDataset
(
invDataset
,
)
;
if
(
threddsData
.
fatalError
)
{
JOptionPane
.
showMessageDialog
(
,
"Failed to open err="
+
threddsData
.
errLog
)
;
return
;
}
jumptoThreddsDatatype
(
threddsData
)
;
}
catch
(
IOException
ioe
)
{
JOptionPane
.
showMessageDialog
(
,
"Error on setThreddsDatatype = "
+
ioe
.
getMessage
(
)
)
;
ioe
.
printStackTrace
(
)
;
}
}

Jump to the appropriate tab based on datatype of InvDataset


private void jumptoThreddsDatatype(thredds.client.catalog.Access invAccess) {
    if (invAccess == null) {
      return;
    }

    thredds.client.catalog.Service s = invAccess.getService();
    if (s.getType() == ServiceType.HTTPServer) {
      downloadFile(invAccess.getStandardUrlName());
      return;
    }

    if (s.getType() == ServiceType.WMS) {
      openWMSDataset(invAccess.getStandardUrlName());
      return;
    }

    if (s.getType() == ServiceType.CdmrFeature) {
      openCoverageDataset(invAccess.getWrappedUrlName());
      return;
    }

    thredds.client.catalog.Dataset ds = invAccess.getDataset();
    if (ds.getFeatureType() == null) {
      // if no feature type, just open as a NetcdfDataset
      try {
        openNetcdfFile(threddsDataFactory.openDataset(invAccess, true, null, null));
      }
      catch (IOException ioe) {
        JOptionPane.showMessageDialog(null, "Error on setThreddsDatatype = " + ioe.getMessage());
      }
      return;
    }

    DataFactory.Result threddsData = null;
    try {
      threddsData = threddsDataFactory.openFeatureDataset(invAccess, null);
      if (threddsData.fatalError) {
        JOptionPane.showMessageDialog(null, "Failed to open err="+threddsData.errLog);
        return;
      }
      jumptoThreddsDatatype(threddsData);
    }
    catch (IOException ioe) {
      ioe.printStackTrace();
      JOptionPane.showMessageDialog(null, "Error on setThreddsDatatype = " + ioe.getMessage());
      if (threddsData != null) {
        try {
          threddsData.close();
        }
        catch (IOException ioe2) {
          // Okay to fall through?
        }
      }
    }

  }

jump to the appropriate tab based on datatype of InvAccess


private void jumptoThreddsDatatype(DataFactory.Result threddsData) {

    if (threddsData.fatalError) {
      JOptionPane.showMessageDialog(this, "Cant open dataset=" + threddsData.errLog);
      try {
        threddsData.close();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
      return;
    }

    if (threddsData.featureType.isCoverageFeatureType()) {
      if (threddsData.featureDataset instanceof FeatureDatasetCoverage) {
        makeComponent(ftTabPane, "Coverages");
        coveragePanel.setDataset(threddsData.featureDataset);
        tabbedPane.setSelectedComponent(ftTabPane);
        ftTabPane.setSelectedComponent(coveragePanel);
      }
      else if (threddsData.featureDataset instanceof GridDataset) {
        makeComponent(ftTabPane, "Grids");
        gridPanel.setDataset((GridDataset) threddsData.featureDataset);
        tabbedPane.setSelectedComponent(ftTabPane);
        ftTabPane.setSelectedComponent(gridPanel);
      }
    }
    else if (threddsData.featureType == FeatureType.IMAGE) {
      makeComponent(ftTabPane, "Images");
      imagePanel.setImageLocation(threddsData.imageURL);
      tabbedPane.setSelectedComponent(ftTabPane);
      ftTabPane.setSelectedComponent(imagePanel);
    }
    else if (threddsData.featureType == FeatureType.RADIAL) {
      makeComponent(ftTabPane, "Radial");
      radialPanel.setDataset((RadialDatasetSweep) threddsData.featureDataset);
      tabbedPane.setSelectedComponent(ftTabPane);
      ftTabPane.setSelectedComponent(radialPanel);
    }
    else if (threddsData.featureType.isPointFeatureType()) {
      makeComponent(ftTabPane, "PointFeature");
      pointFeaturePanel.setPointFeatureDataset((PointDatasetImpl) threddsData.featureDataset);
      tabbedPane.setSelectedComponent(ftTabPane);
      ftTabPane.setSelectedComponent(pointFeaturePanel);
    }
    else if (threddsData.featureType == FeatureType.STATION_RADIAL) {
      makeComponent(ftTabPane, "StationRadial");
      stationRadialPanel.setStationRadialDataset(threddsData.featureDataset);
      tabbedPane.setSelectedComponent(ftTabPane);
      ftTabPane.setSelectedComponent(stationRadialPanel);
    }
  }

private
void
jumptoThreddsDatatype
(
DataFactory
.
Result
threddsData
)
{
if
(
threddsData
.
fatalError
)
{
JOptionPane
.
showMessageDialog
(
this
,
"Cant open dataset="
+
threddsData
.
errLog
)
;
try
{
threddsData
.
close
(
)
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
(
)
;
}
return
;
}
if
(
threddsData
.
featureType
.
isCoverageFeatureType
(
)
)
{
if
(
threddsData
.
featureDataset
instanceof
FeatureDatasetCoverage
)
{
makeComponent
(
ftTabPane
,
"Coverages"
)
;
coveragePanel
.
setDataset
(
threddsData
.
featureDataset
)
;
tabbedPane
.
setSelectedComponent
(
ftTabPane
)
;
ftTabPane
.
setSelectedComponent
(
coveragePanel
)
;
}
else
if
(
threddsData
.
featureDataset
instanceof
GridDataset
)
{
makeComponent
(
ftTabPane
,
"Grids"
)
;
gridPanel
.
setDataset
(
(
GridDataset
)
threddsData
.
featureDataset
)
;
tabbedPane
.
setSelectedComponent
(
ftTabPane
)
;
ftTabPane
.
setSelectedComponent
(
gridPanel
)
;
}
}
else
if
(
threddsData
.
featureType
==
FeatureType
.
IMAGE
)
{
makeComponent
(
ftTabPane
,
"Images"
)
;
imagePanel
.
setImageLocation
(
threddsData
.
imageURL
)
;
tabbedPane
.
setSelectedComponent
(
ftTabPane
)
;
ftTabPane
.
setSelectedComponent
(
imagePanel
)
;
}
else
if
(
threddsData
.
featureType
==
FeatureType
.
RADIAL
)
{
makeComponent
(
ftTabPane
,
"Radial"
)
;
radialPanel
.
setDataset
(
(
RadialDatasetSweep
)
threddsData
.
featureDataset
)
;
tabbedPane
.
setSelectedComponent
(
ftTabPane
)
;
ftTabPane
.
setSelectedComponent
(
radialPanel
)
;
}
else
if
(
threddsData
.
featureType
.
isPointFeatureType
(
)
)
{
makeComponent
(
ftTabPane
,
"PointFeature"
)
;
pointFeaturePanel
.
setPointFeatureDataset
(
(
PointDatasetImpl
)
threddsData
.
featureDataset
)
;
tabbedPane
.
setSelectedComponent
(
ftTabPane
)
;
ftTabPane
.
setSelectedComponent
(
pointFeaturePanel
)
;
}
else
if
(
threddsData
.
featureType
==
FeatureType
.
STATION_RADIAL
)
{
makeComponent
(
ftTabPane
,
"StationRadial"
)
;
stationRadialPanel
.
setStationRadialDataset
(
threddsData
.
featureDataset
)
;
tabbedPane
.
setSelectedComponent
(
ftTabPane
)
;
ftTabPane
.
setSelectedComponent
(
stationRadialPanel
)
;
}
}

Jump to the appropriate tab based on datatype of threddsData


private static void setDataset() {
        // do it in the swing event thread
        SwingUtilities.invokeLater(( ) -> {
            int pos = wantDataset.indexOf('#');
            if (pos > 0) {
                final String catName = wantDataset.substring(0, pos); // {catalog}#{dataset}
                if (catName.endsWith(".xml")) {
                    ui.makeComponent(null, "THREDDS");
                    ui.threddsUI.setDataset(wantDataset);
                    ui.tabbedPane.setSelectedComponent(ui.threddsUI);
                }
                return;
            }

            // default
            ui.openNetcdfFile(wantDataset);
        });
    }

private
static
void
setDataset
(
)
{
// do it in the swing event thread
SwingUtilities
.
invokeLater
(
(
)
->
{
int
pos
=
wantDataset
.
indexOf
(
'
'
)
;
if
(
pos
>
0
)
{
final
String
catName
=
wantDataset
.
substring
(
0
,
pos
)
;
// {catalog}#{dataset}
if
(
catName
.
endsWith
(
".xml"
)
)
{
ui
.
makeComponent
(
,
"THREDDS"
)
;
ui
.
threddsUI
.
setDataset
(
wantDataset
)
;
ui
.
tabbedPane
.
setSelectedComponent
(
ui
.
threddsUI
)
;
}
return
;
}
// default
ui
.
openNetcdfFile
(
wantDataset
)
;
}
)
;
}


private static void prepareGui() {

        final String osName = System.getProperty("os.name").toLowerCase();
        final boolean isMacOs = osName.startsWith("mac os x");

        if (isMacOs) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");

            // fixes the case on macOS where users use the system menu option to quit rather than
            // closing a window using the 'x' button.
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    doSavePrefsAndUI();
                }
            });
        }
        else {
            // Not macOS, so try applying Nimbus L&F, if available.
            try {
                for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            }
            catch (Exception exc) {
                log.warn("Unable to apply Nimbus look-and-feel due to {}", exc.toString());

                if (log.isTraceEnabled()) {
                    exc.printStackTrace();
                }
            }
        }

        // misc Gui initialization(s)
        BAMutil.setResourcePath("/resources/nj22/ui/icons/");

        // Setting up a font metrics object triggers one of the most time-wasting steps of GUI set up.
        // We do it now before trying to create the splash or tools interface.
        SwingUtilities.invokeLater(( ) -> {
            final Toolkit tk = Toolkit.getDefaultToolkit ( );
            final Font f = new Font ("SansSerif", Font.PLAIN, 12);

            @SuppressWarnings("deprecation")
            final FontMetrics fm = tk.getFontMetrics (f);
        });
    }


private static void createToolsFrame() {
        // put UI in a JFrame
        frame = new JFrame("NetCDF (" + DIALOG_VERSION + ") Tools");

        ui = new ToolsUI(prefs, frame);

        frame.setIconImage(BAMutil.getImage("netcdfUI"));

        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowActivated(final WindowEvent e) {
                ToolsSplashScreen.getSharedInstance().setVisible(false);
            }

            @Override
            public void windowClosing(final WindowEvent e) {
                if (! done) {
                    exit();
                }
            }
        });

        frame.getContentPane().add(ui);

        final Rectangle have = frame.getGraphicsConfiguration().getBounds();
        final Rectangle def = new Rectangle(50, 50, 800, 800);

        Rectangle want = (Rectangle) prefs.getBean(FRAME_SIZE, def);

        if (want.getX() > have.getWidth() - 25) {
            // may be off screen when switcing between 2 monitor system
            want = def;
        }

        frame.setBounds(want);

        frame.pack();
        frame.setBounds(want);

        // in case a dataset was on the command line
        if (wantDataset != null) {
            setDataset();
        }
    }

Must call this method on the event thread.

Must call this method on the event thread .


static public String makeName( List<CoordinateAxis> axes) {
    List<CoordinateAxis> axesSorted = new ArrayList<>( axes);
    Collections.sort( axesSorted, new CoordinateAxis.AxisComparator());
    StringBuilder buff = new StringBuilder();
    for (int i=0; i<axesSorted.size(); i++) {
      CoordinateAxis axis = axesSorted.get(i);
      if (i>0) buff.append(" ");
      buff.append( axis.getFullNameEscaped());
    }
    return buff.toString();
  }

static
public
String
makeName
(
List
<
CoordinateAxis
>
axes
)
{
List
<
CoordinateAxis
>
axesSorted
=
new
ArrayList
<>
(
axes
)
;
Collections
.
sort
(
axesSorted
,
new
CoordinateAxis
.
AxisComparator
(
)
)
;
StringBuilder
buff
=
new
StringBuilder
(
)
;
for
(
int
i
=
0
;
i
<
axesSorted
.
size
(
)
;
i
++
)
{
CoordinateAxis
axis
=
axesSorted
.
get
(
i
)
;
if
(
i
>
0
)
buff
.
append
(
" "
)
;
buff
.
append
(
axis
.
getFullNameEscaped
(
)
)
;
}
return
buff
.
toString
(
)
;
}

Create standard name from list of axes. Sort the axes first
@param axes list of CoordinateAxis
@return CoordinateSystem name, created from axes names

Create standard name from list of axes . Sort the axes first


private CoordinateAxis lesserRank( CoordinateAxis a1, CoordinateAxis a2) {
    if (a1 == null) return a2;
    return (a1.getRank() <= a2.getRank()) ? a1 : a2;
  }

private CoordinateAxis lesserRank ( CoordinateAxis a1 , CoordinateAxis a2 ) { if ( a1 == null ) return a2 ; return ( a1 . getRank ( ) <= a2 . getRank ( ) ) ? a1 : a2 ; }

prefer smaller ranks, in case more than one

prefer smaller ranks in case more than one


public CoordinateAxis findAxis( AxisType type) {
    CoordinateAxis result = null;
    for (CoordinateAxis axis : coordAxes) {
      AxisType axisType = axis.getAxisType();
      if ((axisType != null) && (axisType == type))
        result = lesserRank(result, axis);
    }
    return result;
  }

public CoordinateAxis findAxis ( AxisType type ) { CoordinateAxis result = null ; for ( CoordinateAxis axis : coordAxes ) { AxisType axisType = axis . getAxisType ( ) ; if ( ( axisType != null ) && ( axisType == type ) ) result = lesserRank ( result , axis ) ; } return result ; }

Find the CoordinateAxis that has the given AxisType.
If more than one, return the one with lesser rank.
@param type look for this axisType
@return  CoordinateAxis of the given AxisType, else null.

Find the CoordinateAxis that has the given AxisType . If more than one return the one with lesser rank .


public ProjectionCT getProjectionCT() {
    for (CoordinateTransform ct : coordTrans) {
      if (ct instanceof ProjectionCT)
        return (ProjectionCT) ct;
    }
    return null;
  }

public ProjectionCT getProjectionCT ( ) { for ( CoordinateTransform ct : coordTrans ) { if ( ct instanceof ProjectionCT ) return ( ProjectionCT ) ct ; } return null ; }

Find the first ProjectionCT from the list of CoordinateTransforms.
@return ProjectionCT or null if none.

Find the first ProjectionCT from the list of CoordinateTransforms .


public boolean isGeoXY() {
    if ((xAxis == null) || (yAxis == null)) return false;
    return null != getProjection() && !(projection instanceof LatLonProjection);
  }

public boolean isGeoXY ( ) { if ( ( xAxis == null ) || ( yAxis == null ) ) return false ; return null != getProjection ( ) && ! ( projection instanceof LatLonProjection ) ; }

true if it has X and Y CoordinateAxis, and a CoordTransform Projection
@return true if it has X and Y CoordinateAxis, and a CoordTransform Projection

true if it has X and Y CoordinateAxis and a CoordTransform Projection


public boolean isRegular() {
    for (CoordinateAxis axis : coordAxes) {
      if (!(axis instanceof CoordinateAxis1D)) return false;
      if (!((CoordinateAxis1D) axis).isRegular()) return false;
    }
    return true;
  }

public boolean isRegular ( ) { for ( CoordinateAxis axis : coordAxes ) { if ( ! ( axis instanceof CoordinateAxis1D ) ) return false ; if ( ! ( ( CoordinateAxis1D ) axis ) . isRegular ( ) ) return false ; } return true ; }

true if all axes are CoordinateAxis1D and are regular

@return true if all axes are CoordinateAxis1D and are regular


public static boolean isSubset(Collection<Dimension> subset, Collection<Dimension> set) {
    for (Dimension d : subset) {
      if (!(set.contains(d)))
        return false;
    }
    return true;
  }

public static boolean isSubset ( Collection < Dimension > subset , Collection < Dimension > set ) { for ( Dimension d : subset ) { if ( ! ( set . contains ( d ) ) ) return false ; } return true ; }

Test if all the Dimensions in subset are in set
@param subset is this a subset
@param set of this?
@return true if all the Dimensions in subset are in set


public boolean containsAxes(List<CoordinateAxis> wantAxes) {
    for (CoordinateAxis ca : wantAxes) {
      if (!containsAxis(ca.getFullName()))
        return false;
    }
    return true;
   }

public boolean containsAxes ( List < CoordinateAxis > wantAxes ) { for ( CoordinateAxis ca : wantAxes ) { if ( ! containsAxis ( ca . getFullName ( ) ) ) return false ; } return true ; }

Do we have all the axes in the list?
@param wantAxes List of CoordinateAxis
@return true if all in our list.


public boolean containsAxis(String axisName) {
    for (CoordinateAxis ca : coordAxes) {
      if (ca.getFullName().equals(axisName))
        return true;
    }
    return false;
   }

public boolean containsAxis ( String axisName ) { for ( CoordinateAxis ca : coordAxes ) { if ( ca . getFullName ( ) . equals ( axisName ) ) return true ; } return false ; }

Do we have the named axis?
@param axisName (full unescaped) name of axis
@return true if we have an axis of that name


public boolean containsDomain(List<Dimension> wantDimensions) {
    for (Dimension d : wantDimensions) {
      if (!domain.contains(d))
        return false;
    }
    return true;
   }

public boolean containsDomain ( List < Dimension > wantDimensions ) { for ( Dimension d : wantDimensions ) { if ( ! domain . contains ( d ) ) return false ; } return true ; }

Do we have all the dimensions in the list?
@param wantDimensions List of Dimensions
@return true if all in our list.


public boolean containsAxisTypes(List<AxisType> wantAxes) {
    for (AxisType wantAxisType : wantAxes) {
      if (!containsAxisType(wantAxisType)) return false;
    }
    return true;
   }

public boolean containsAxisTypes ( List < AxisType > wantAxes ) { for ( AxisType wantAxisType : wantAxes ) { if ( ! containsAxisType ( wantAxisType ) ) return false ; } return true ; }

Do we have all the axes types in the list?
@param wantAxes List of AxisType
@return true if all in our list.


public boolean containsAxisType(AxisType wantAxisType) {
    for (CoordinateAxis ca : coordAxes) {
      if (ca.getAxisType() == wantAxisType) return true;
    }
    return false;
   }

public boolean containsAxisType ( AxisType wantAxisType ) { for ( CoordinateAxis ca : coordAxes ) { if ( ca . getAxisType ( ) == wantAxisType ) return true ; } return false ; }

Do we have an axes of the given type?
@param wantAxisType want this AxisType
@return true if we have at least one axis of that type.


public DAPNode cloneDAG(CloneMap map)
        throws CloneNotSupportedException
    {
        DAPNode node = (DAPNode)super.clone(); // Object.clone
	map.nodes.put(this,node);

        DAPNode tmp = map.nodes.get(_myParent);
        if(tmp != node)
            _myParent = tmp;
        return node;
    }

public
DAPNode
cloneDAG
(
CloneMap
map
)
throws
CloneNotSupportedException
{
DAPNode
node
=
(
DAPNode
)
super
.
clone
(
)
;
// Object.clone
map
.
nodes
.
put
(
this
,
node
)
;
DAPNode
tmp
=
map
.
nodes
.
get
(
_myParent
)
;
if
(
tmp
!=
node
)
_myParent
=
tmp
;
return
node
;
}

This procedure does the actual recursive clone.
@param map  list of previously cloned nodes
@return  clone of this node
@throws CloneNotSupportedException

This procedure does the actual recursive clone .


public Object getSelectedBean() {
    int viewRowIndex = jtable.getSelectedRow();
    if(viewRowIndex < 0)
      return null;
    int modelRowIndex = jtable.convertRowIndexToModel(viewRowIndex);
    return (modelRowIndex < 0) || (modelRowIndex >= beans.size()) ? null : beans.get(modelRowIndex);
  }

public Object getSelectedBean ( ) { int viewRowIndex = jtable . getSelectedRow ( ) ; if ( viewRowIndex < 0 ) return null ; int modelRowIndex = jtable . convertRowIndexToModel ( viewRowIndex ) ; return ( modelRowIndex < 0 ) || ( modelRowIndex >= beans . size ( ) ) ? null : beans . get ( modelRowIndex ) ; }

Get the currently selected bean, or null if none selected.

@return the currently selected bean, or null if none selected

Get the currently selected bean or null if none selected .


public List getSelectedBeans() {
    ArrayList<Object> list = new ArrayList<>();
    int[] viewRowIndices = jtable.getSelectedRows();
    for (int viewRowIndex : viewRowIndices) {
      int modelRowIndex = jtable.convertRowIndexToModel(viewRowIndex);
      list.add(beans.get(modelRowIndex));
      if (debugSelected) System.out.println(" bean selected= " + modelRowIndex + " " + beans.get(modelRowIndex));
    }
    return list;
  }

public
List
getSelectedBeans
(
)
{
ArrayList
<
Object
>
list
=
new
ArrayList
<>
(
)
;
int
[
]
viewRowIndices
=
jtable
.
getSelectedRows
(
)
;
for
(
int
viewRowIndex
:
viewRowIndices
)
{
int
modelRowIndex
=
jtable
.
convertRowIndexToModel
(
viewRowIndex
)
;
list
.
add
(
beans
.
get
(
modelRowIndex
)
)
;
if
(
debugSelected
)
System
.
out
.
println
(
" bean selected= "
+
modelRowIndex
+
" "
+
beans
.
get
(
modelRowIndex
)
)
;
}
return
list
;
}

Get the currently selected beans. Use this for multiple selection

@return ArrayList of currently selected beans (wont be null).
@see #setSelectionMode

Get the currently selected beans . Use this for multiple selection


public ArrayList<Object> getSelectedCells() {
    ArrayList<Object> list = new ArrayList<>();
    int[] viewRowIndices = jtable.getSelectedRows();
    int[] viewColumnIndices = jtable.getSelectedColumns();
    for (int i = 0; i < viewRowIndices.length; i++)
      for (int j = 0; i < viewColumnIndices.length; j++) {
        int modelRowIndex = jtable.convertRowIndexToModel(viewRowIndices[i]);
        int modelColumnIndex = jtable.convertColumnIndexToModel(viewColumnIndices[j]);
        list.add(model.getValueAt(modelRowIndex, modelColumnIndex));
      }

    return list;
  }

public ArrayList < Object > getSelectedCells ( ) { ArrayList < Object > list = new ArrayList <> ( ) ; int [ ] viewRowIndices = jtable . getSelectedRows ( ) ; int [ ] viewColumnIndices = jtable . getSelectedColumns ( ) ; for ( int i = 0 ; i < viewRowIndices . length ; i ++ ) for ( int j = 0 ; i < viewColumnIndices . length ; j ++ ) { int modelRowIndex = jtable . convertRowIndexToModel ( viewRowIndices [ i ] ) ; int modelColumnIndex = jtable . convertColumnIndexToModel ( viewColumnIndices [ j ] ) ; list . add ( model . getValueAt ( modelRowIndex , modelColumnIndex ) ) ; } return list ; }

Get the currently selected cells.
Use this for multiple row selection, when columnSelection is on

@return ArrayList of currently selected cells (wont be null).
@see BeanTable#setSelectionMode(int).

Get the currently selected cells . Use this for multiple row selection when columnSelection is on


public void setSelectedBean(Object bean) {
    if (bean == null) return;
    int modelRowIndex = beans.indexOf(bean);
    int viewRowIndex = jtable.convertRowIndexToView(modelRowIndex);

    if (viewRowIndex >= 0)
      jtable.getSelectionModel().setSelectionInterval(viewRowIndex, viewRowIndex);
    makeRowVisible(viewRowIndex);
  }

public void setSelectedBean ( Object bean ) { if ( bean == null ) return ; int modelRowIndex = beans . indexOf ( bean ) ; int viewRowIndex = jtable . convertRowIndexToView ( modelRowIndex ) ; if ( viewRowIndex >= 0 ) jtable . getSelectionModel ( ) . setSelectionInterval ( viewRowIndex , viewRowIndex ) ; makeRowVisible ( viewRowIndex ) ; }

Set which row is selected.

@param bean select this one; must be in the list.


protected void restoreState() {
    if (store == null) {
      return;
    }

    ArrayList propColObjs = (ArrayList) store.getBean("propertyCol", new ArrayList());
    HidableTableColumnModel tableColumnModel = (HidableTableColumnModel) jtable.getColumnModel();
    int newViewIndex = 0;

    for (Object propColObj : propColObjs) {
      PropertyCol propCol = (PropertyCol) propColObj;
      try {
        int currentViewIndex = tableColumnModel.getColumnIndex(propCol.getName());  // May throw IAE.

        TableColumn column = tableColumnModel.getColumn(currentViewIndex);
        column.setPreferredWidth(propCol.getWidth());

        tableColumnModel.moveColumn(currentViewIndex, newViewIndex);
        assert tableColumnModel.getColumn(newViewIndex) == column : "tableColumn wasn't successfully moved.";

        // We must do this last, since moveColumn() only works on visible columns.
        tableColumnModel.setColumnVisible(column, propCol.isVisible());
        if (propCol.isVisible()) {
          ++newViewIndex;  // Don't increment for hidden columns.
        }
      } catch (IllegalArgumentException e) {
        logger.debug(String.format(
                "Column named \"%s\" was present in the preferences file but not the dataset.", propCol.getName()), e);
      }
    }
  }


public static UnknownUnit create(String name) throws NameException {
    UnknownUnit unit;
    name = name.toLowerCase();
    synchronized (map) {
      unit = map.get(name);
      if (unit == null) {
        unit = new UnknownUnit(name);
        map.put(unit.getName(), unit);
        map.put(unit.getPlural(), unit);
      }
    }
    return unit;
  }

public static UnknownUnit create ( String name ) throws NameException { UnknownUnit unit ; name = name . toLowerCase ( ) ; synchronized ( map ) { unit = map . get ( name ) ; if ( unit == null ) { unit = new UnknownUnit ( name ) ; map . put ( unit . getName ( ) , unit ) ; map . put ( unit . getPlural ( ) , unit ) ; } } return unit ; }

Factory method for constructing an unknown unit from a name.

@param name The name of the unit.
@return The unknown unit.
@throws NameException name == null.

Factory method for constructing an unknown unit from a name .


@Override
    public void close() throws IOException
    {
        if(closed)
            return; /* Allow multiple close calls */
        closed = true;
        try {
            consume();
        } finally {
            super.close();
        }
        if(method != null) method.close();
    }

@
Override
public
void
close
(
)
throws
IOException
{
if
(
closed
)
return
;
/* Allow multiple close calls */
closed
=
true
;
try
{
consume
(
)
;
}
finally
{
super
.
close
(
)
;
}
if
(
method
!=
)
method
.
close
(
)
;
}

Closes this input stream and releases any system resources associated
with the stream; closes the method also.

@exception  IOException  if an I/O error occurs; but not if close
is called twice.

Closes this input stream and releases any system resources associated with the stream ; closes the method also .


private boolean isExtra(Variable v) {
    return v != null && extras != null && extras.contains(v);
  }

private boolean isExtra ( Variable v ) { return v != null && extras != null && extras . contains ( v ) ; }

Has v already been added to the set of extra variables?


private boolean isCoordinate(Variable v) {
    if (v == null) return false;
    String name = v.getShortName();
    return (latVE != null && latVE.axisName.equals(name)) ||
            (lonVE != null && lonVE.axisName.equals(name)) ||
            (altVE != null && altVE.axisName.equals(name)) ||
            (stnAltVE != null && stnAltVE.axisName.equals(name)) ||
            (timeVE != null && timeVE.axisName.equals(name)) ||
            (nomTimeVE != null && nomTimeVE.axisName.equals(name));
  }

private boolean isCoordinate ( Variable v ) { if ( v == null ) return false ; String name = v . getShortName ( ) ; return ( latVE != null && latVE . axisName . equals ( name ) ) || ( lonVE != null && lonVE . axisName . equals ( name ) ) || ( altVE != null && altVE . axisName . equals ( name ) ) || ( stnAltVE != null && stnAltVE . axisName . equals ( name ) ) || ( timeVE != null && timeVE . axisName . equals ( name ) ) || ( nomTimeVE != null && nomTimeVE . axisName . equals ( name ) ) ; }

Is v a coordinate axis for this feature type?


private CoordVarExtractor findCoordinateAxis(Table.CoordName coordName, Table t, int nestingLevel) {
    if (t == null) return null;

    String axisName = t.findCoordinateVariableName(coordName);

    if (axisName != null) {
      VariableDS v = t.findVariable(axisName);
      if (v != null)
        return new CoordVarExtractorVariable(v, axisName, nestingLevel);

      if (t.extraJoins != null) {
        for (Join j : t.extraJoins) {
          v = j.findVariable(axisName);
          if (v != null)
            return new CoordVarExtractorVariable(v, axisName, nestingLevel);
        }
      }

      // see if its in the StructureData
      if (t instanceof Table.TableSingleton) {
        Table.TableSingleton ts = (Table.TableSingleton) t;
        return new CoordVarStructureData(axisName, ts.sdata);
      }

      // see if its at the top level
      if (t instanceof Table.TableTop) {
        v = (VariableDS) ds.findVariable(axisName);

        if (v != null)
          return new CoordVarTop(v);
        else
          return new CoordVarConstant(coordName.toString(), "", axisName); // assume its the actual value
      }

      errlog.format("NestedTable: cant find variable '%s' for coordinate type %s %n", axisName, coordName);
    }

    // check the parent
    return findCoordinateAxis(coordName, t.parent, nestingLevel + 1);
  }

find a coord axis of the given type in the table and its parents


private void addDataVariables(List<VariableSimpleIF> list, Table t) {
    if (t.parent != null) addDataVariables(list, t.parent);
    for (VariableSimpleIF col : t.cols.values()) {
      if (t.nondataVars.contains(col.getFullName())) continue;
      if (t.nondataVars.contains(col.getShortName())) continue;  // fishy
      list.add(col);
    }
  }

private
void
addDataVariables
(
List
<
VariableSimpleIF
>
list
,
Table
t
)
{
if
(
t
.
parent
!=
)
addDataVariables
(
list
,
t
.
parent
)
;
for
(
VariableSimpleIF
col
:
t
.
cols
.
values
(
)
)
{
if
(
t
.
nondataVars
.
contains
(
col
.
getFullName
(
)
)
)
continue
;
if
(
t
.
nondataVars
.
contains
(
col
.
getShortName
(
)
)
)
continue
;
// fishy
list
.
add
(
col
)
;
}
}

use recursion so that parent variables come first


void addParentJoin(Cursor cursor) throws IOException {
    int level = cursor.currentIndex;
    Table t = getTable(level);
    if (t.extraJoins != null) {
      List<StructureData> sdata = new ArrayList<>(3);
      sdata.add(cursor.tableData[level]);
      for (Join j : t.extraJoins) {
        sdata.add(j.getJoinData(cursor));
      }
      cursor.tableData[level] = StructureDataFactory.make(sdata.toArray(new StructureData[sdata.size()]));  // LOOK should try to consolidate
    }
  }

void
addParentJoin
(
Cursor
cursor
)
throws
IOException
{
int
level
=
cursor
.
currentIndex
;
Table
t
=
getTable
(
level
)
;
if
(
t
.
extraJoins
!=
)
{
List
<
StructureData
>
sdata
=
new
ArrayList
<>
(
3
)
;
sdata
.
add
(
cursor
.
tableData
[
level
]
)
;
for
(
Join
j
:
t
.
extraJoins
)
{
sdata
.
add
(
j
.
getJoinData
(
cursor
)
)
;
}
cursor
.
tableData
[
level
]
=
StructureDataFactory
.
make
(
sdata
.
toArray
(
new
StructureData
[
sdata
.
size
(
)
]
)
)
;
// LOOK should try to consolidate
}
}


StationFeature makeStation(StructureData stationData) {
    if (stnVE.isMissing(stationData)) return null;
    String stationName = stnVE.getCoordValueAsString(stationData);

    String stationDesc = (stnDescVE == null) ? "" : stnDescVE.getCoordValueAsString(stationData);
    String stnWmoId = (wmoVE == null) ? "" : wmoVE.getCoordValueAsString(stationData);

    double lat = latVE.getCoordValue(stationData);
    double lon = lonVE.getCoordValue(stationData);
    double elev = (stnAltVE == null) ? Double.NaN : stnAltVE.getCoordValue(stationData);

    // missing lat, lon means skip this station
    if (Double.isNaN(lat) || Double.isNaN(lon)) return null;

    return new StationFeatureImpl(stationName, stationDesc, stnWmoId, lat, lon, elev, -1, stationData);
  }

also called from StandardPointFeatureIterator


public NodeMap<CDMNode,DapNode>
    create()
            throws DapException
    {
        // Netcdf Dataset will already have a root group
        Group cdmroot = ncfile.getRootGroup();
        this.nodemap.put(cdmroot,this.dmr);
        fillGroup(cdmroot, this.dmr, ncfile);
        return this.nodemap;
    }

Do the conversion and return a NodeMap
representing the conversion.

@throws DapException

Do the conversion and return a NodeMap representing the conversion .


static public SimpleUnit factory(String name) {
    try {
      return factoryWithExceptions(name);
    } catch (Exception e) {
      if (debugParse) System.out.println("Parse " + name + " got Exception " + e);
      return null;
    }
  }

static
public
SimpleUnit
factory
(
String
name
)
{
try
{
return
factoryWithExceptions
(
name
)
;
}
catch
(
Exception
e
)
{
if
(
debugParse
)
System
.
out
.
println
(
"Parse "
+
name
+
" got Exception "
+
e
)
;
return
;
}
}

Create a SimpleUnit from the given name, catch Exceptions.

@param name parse this name to create a unit.
@return SimpleUnit, DateUnit, TimeUnit, or null if failed
@see ucar.units.UnitFormat#parse

Create a SimpleUnit from the given name catch Exceptions .


static public SimpleUnit factoryWithExceptions(String name) throws UnitException {
    UnitFormat format = UnitFormatManager.instance();
    Unit uu = format.parse(name);
    //if (isDateUnit(uu)) return new DateUnit(name);
    if (isTimeUnit(uu)) return new TimeUnit(name);
    return new SimpleUnit(uu);
  }

Create a SimpleUnit from the given name, allow Exceptions.

@param name parse this name to create a unit.
@return SimpleUnit, DateUnit, or TimeUnit
@throws Exception when date parser fails
@see ucar.units.UnitFormat#parse

Create a SimpleUnit from the given name allow Exceptions .


static protected Unit makeUnit(String name) throws UnitException {
    UnitFormat format = UnitFormatManager.instance();
    return format.parse(name);
  }

static protected Unit makeUnit ( String name ) throws UnitException { UnitFormat format = UnitFormatManager . instance ( ) ; return format . parse ( name ) ; }


static public boolean isCompatibleWithExceptions(String unitString1, String unitString2) throws UnitException {
    UnitFormat format = UnitFormatManager.instance();
    Unit uu1 = format.parse(unitString1);
    Unit uu2 = format.parse(unitString2);
    return uu1.isCompatible(uu2);
  }

static public boolean isCompatibleWithExceptions ( String unitString1 , String unitString2 ) throws UnitException { UnitFormat format = UnitFormatManager . instance ( ) ; Unit uu1 = format . parse ( unitString1 ) ; Unit uu2 = format . parse ( unitString2 ) ; return uu1 . isCompatible ( uu2 ) ; }

Return true if  unitString1 is convertible to unitString2

@param unitString1 compare this unit
@param unitString2 compare this unit
@return true if the 2 units are compatible
@throws UnitException if units parsing fails


static public boolean isDateUnit(ucar.units.Unit uu) {
    boolean ok = uu.isCompatible(dateReferenceUnit);
    if (!ok) return false;
    try {
      uu.getConverterTo(dateReferenceUnit);
      return true;
    } catch (ConversionException e) {
      return false;
    }
  }

static public boolean isDateUnit ( ucar . units . Unit uu ) { boolean ok = uu . isCompatible ( dateReferenceUnit ) ; if ( ! ok ) return false ; try { uu . getConverterTo ( dateReferenceUnit ) ; return true ; } catch ( ConversionException e ) { return false ; } }

Return true if this ucar.units.Unit is a Date.

@param uu check this Unit
@return true if its a Date

Return true if this ucar . units . Unit is a Date .


static public boolean isTimeUnit(String unitString) {
    SimpleUnit su = factory(unitString);
    return su != null && isTimeUnit(su.getUnit());
  }

static public boolean isTimeUnit ( String unitString ) { SimpleUnit su = factory ( unitString ) ; return su != null && isTimeUnit ( su . getUnit ( ) ) ; }

Return true if the given unit is a time Unit, eg "seconds".

@param unitString check this unit string
@return true if its a Time

Return true if the given unit is a time Unit eg seconds .


static public double getConversionFactor(String inputUnitString, String outputUnitString) throws IllegalArgumentException {
    SimpleUnit inputUnit = SimpleUnit.factory(inputUnitString);
    SimpleUnit outputUnit = SimpleUnit.factory(outputUnitString);
    return inputUnit.convertTo(1.0, outputUnit);
  }

static public double getConversionFactor ( String inputUnitString , String outputUnitString ) throws IllegalArgumentException { SimpleUnit inputUnit = SimpleUnit . factory ( inputUnitString ) ; SimpleUnit outputUnit = SimpleUnit . factory ( outputUnitString ) ; return inputUnit . convertTo ( 1.0 , outputUnit ) ; }

Get the conversion factor to convert inputUnit to outputUnit.

@param inputUnitString  inputUnit in string form
@param outputUnitString outputUnit in string form
@return conversion factor
@throws IllegalArgumentException if not convertible

Get the conversion factor to convert inputUnit to outputUnit .


public double convertTo(double value, SimpleUnit outputUnit) throws IllegalArgumentException {
    try {
      return uu.convertTo(value, outputUnit.getUnit());
    } catch (ConversionException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }

public double convertTo ( double value , SimpleUnit outputUnit ) throws IllegalArgumentException { try { return uu . convertTo ( value , outputUnit . getUnit ( ) ) ; } catch ( ConversionException e ) { throw new IllegalArgumentException ( e . getMessage ( ) ) ; } }

Convert given value of this unit to the new unit.

@param value  value in this unit
@param outputUnit convert to this unit
@return  value in outputUnit
@throws IllegalArgumentException if outputUnit not convertible from this unit

Convert given value of this unit to the new unit .


public boolean isUnknownUnit() {
    ucar.units.Unit uu = getUnit();
    if (uu instanceof ucar.units.UnknownUnit)
      return true;
    if (uu instanceof ucar.units.DerivedUnit)
      return isUnknownUnit((ucar.units.DerivedUnit) uu);
    if (uu instanceof ucar.units.ScaledUnit) {
      ucar.units.ScaledUnit scu = (ucar.units.ScaledUnit) uu;
      Unit u = scu.getUnit();
      if (u instanceof ucar.units.UnknownUnit)
        return true;

      if (u instanceof ucar.units.DerivedUnit)
        return isUnknownUnit((ucar.units.DerivedUnit) u);
    }
    return false;
  }

public boolean isUnknownUnit ( ) { ucar . units . Unit uu = getUnit ( ) ; if ( uu instanceof ucar . units . UnknownUnit ) return true ; if ( uu instanceof ucar . units . DerivedUnit ) return isUnknownUnit ( ( ucar . units . DerivedUnit ) uu ) ; if ( uu instanceof ucar . units . ScaledUnit ) { ucar . units . ScaledUnit scu = ( ucar . units . ScaledUnit ) uu ; Unit u = scu . getUnit ( ) ; if ( u instanceof ucar . units . UnknownUnit ) return true ; if ( u instanceof ucar . units . DerivedUnit ) return isUnknownUnit ( ( ucar . units . DerivedUnit ) u ) ; } return false ; }

Is this an instance of an UnknownUnit?

@return true if an instance of an UnknownUnit


public double getValue() {
    if (!(uu instanceof ScaledUnit)) return Double.NaN;
    ScaledUnit offset = (ScaledUnit) uu;
    return offset.getScale();
  }

public double getValue ( ) { if ( ! ( uu instanceof ScaledUnit ) ) return Double . NaN ; ScaledUnit offset = ( ScaledUnit ) uu ; return offset . getScale ( ) ; }

Extract the value, can only be called for ScaledUnit.
@return value of this unit if ScaledUnit, else NaN

Extract the value can only be called for ScaledUnit .


public TopLevelClause newRelOpClause(int operator,
                                         SubClause lhs,
                                         List rhs)
            throws DAP2ServerSideException {

        return new RelOpClause(operator,
                lhs,
                rhs);
    }

public TopLevelClause newRelOpClause ( int operator , SubClause lhs , List rhs ) throws DAP2ServerSideException { return new RelOpClause ( operator , lhs , rhs ) ; }

Generates a clause which which compares subclauses, using one of the
relative operators supported by the Operator class.

Generates a clause which which compares subclauses using one of the relative operators supported by the Operator class .


public TopLevelClause newBoolFunctionClause(String functionName,
                                                List children)
            throws DAP2ServerSideException,
            NoSuchFunctionException {

        BoolFunction function =
                functionLibrary.getBoolFunction(functionName);
        if (function == null) {
            if (functionLibrary.getBTFunction(functionName) != null) {
                throw new NoSuchFunctionException
                        ("The function " + functionName +
                                "() does not return a " +
                                "boolean value, and must be used in a comparison or " +
                                "as an argument to another function.");
            } else {
                throw new NoSuchFunctionException
                        ("This server does not support a " +
                                functionName + "() function");
            }
        }
        return new BoolFunctionClause(function,
                children);
    }

Generates a clause which invokes a function that returns a
boolean value.

@see BoolFunctionClause

Generates a clause which invokes a function that returns a boolean value .


public SubClause newBTFunctionClause(String functionName,
                                         List children)
            throws DAP2ServerSideException,
            NoSuchFunctionException {

        BTFunction function =
                functionLibrary.getBTFunction(functionName);
        if (function == null) {
            if (functionLibrary.getBoolFunction(functionName) != null) {
                throw new NoSuchFunctionException
                        ("The function " + functionName +
                                "() cannot be used as a " +
                                "sub-expression in a constraint clause");
            } else {
                throw new NoSuchFunctionException
                        ("This server does not support a " +
                                functionName + "() function");
            }
        }
        return new BTFunctionClause(function,
                children);
    }

public
SubClause
newBTFunctionClause
(
String
functionName
,
List
children
)
throws
DAP2ServerSideException
,
NoSuchFunctionException
{
BTFunction
function
=
functionLibrary
.
getBTFunction
(
functionName
)
;
if
(
function
==
)
{
if
(
functionLibrary
.
getBoolFunction
(
functionName
)
!=
)
{
throw
new
NoSuchFunctionException
(
"The function "
+
functionName
+
"() cannot be used as a "
+
"sub-expression in a constraint clause"
)
;
}
else
{
throw
new
NoSuchFunctionException
(
"This server does not support a "
+
functionName
+
"() function"
)
;
}
}
return
new
BTFunctionClause
(
function
,
children
)
;
}

Generates a clause which invokes a function that returns a
BaseType.

@see BTFunctionClause

Generates a clause which invokes a function that returns a BaseType .


public static java.awt.image.BufferedImage makeGrayscaleImage( Array ma, IsMissingEvaluator missEval) {
    if (ma.getRank() < 2) return null;

    if (ma.getRank() == 3)
      ma = ma.reduce();

    if (ma.getRank() == 3)
      ma = ma.slice( 0, 0); // we need 2D

    int h = ma.getShape()[0];
    int w = ma.getShape()[1];
    DataBuffer dataBuffer = makeDataBuffer(ma, missEval);

    WritableRaster raster = WritableRaster.createInterleavedRaster(dataBuffer,
        w, h, //   int w, int h,
        w, //   int scanlineStride,
        1,      //    int pixelStride,
        new int[]{0}, //   int bandOffsets[],
        null);     //   Point location)

    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
    ComponentColorModel colorModel = new ComponentColorModel(cs,new int[] {8},
        false,false,Transparency.OPAQUE, DataBuffer.TYPE_BYTE);

    return new BufferedImage( colorModel, raster, false, null);
  }

public
static
java
.
awt
.
image
.
BufferedImage
makeGrayscaleImage
(
Array
ma
,
IsMissingEvaluator
missEval
)
{
if
(
ma
.
getRank
(
)
<
2
)
return
;
if
(
ma
.
getRank
(
)
==
3
)
ma
=
ma
.
reduce
(
)
;
if
(
ma
.
getRank
(
)
==
3
)
ma
=
ma
.
slice
(
0
,
0
)
;
// we need 2D
int
h
=
ma
.
getShape
(
)
[
0
]
;
int
w
=
ma
.
getShape
(
)
[
1
]
;
DataBuffer
dataBuffer
=
makeDataBuffer
(
ma
,
missEval
)
;
WritableRaster
raster
=
WritableRaster
.
createInterleavedRaster
(
dataBuffer
,
w
,
h
,
//   int w, int h,
w
,
//   int scanlineStride,
1
,
//    int pixelStride,
new
int
[
]
{
0
}
,
//   int bandOffsets[],
)
;
//   Point location)
ColorSpace
cs
=
ColorSpace
.
getInstance
(
ColorSpace
.
CS_GRAY
)
;
ComponentColorModel
colorModel
=
new
ComponentColorModel
(
cs
,
new
int
[
]
{
8
}
,
false
,
false
,
Transparency
.
OPAQUE
,
DataBuffer
.
TYPE_BYTE
)
;
return
new
BufferedImage
(
colorModel
,
raster
,
false
,
)
;
}

Adapt a rank 2 array into a java.awt.image.BufferedImage.
If passed a rank 3 array, take first 2D slice.
@param ma rank 2 or 3 array.
@return BufferedImage

Adapt a rank 2 array into a java . awt . image . BufferedImage . If passed a rank 3 array take first 2D slice .


public int crawl(InvCatalogImpl cat, CancelTask task, PrintWriter out, Object context) {

    if (out != null)
      out.println("***CATALOG " + cat.getCreateFrom());
    countCatrefs = 0;

    for (InvDataset ds : cat.getDatasets()) {
      if (type == Type.all)
        crawlDataset(ds, task, out, context, true);
      else
        crawlDirectDatasets(ds, task, out, context, true);
      if ((task != null) && task.isCancel()) break;
    }

    return 1 + countCatrefs;
  }

public
int
crawl
(
InvCatalogImpl
cat
,
CancelTask
task
,
PrintWriter
out
,
Object
context
)
{
if
(
out
!=
)
out
.
println
(
"***CATALOG "
+
cat
.
getCreateFrom
(
)
)
;
countCatrefs
=
0
;
for
(
InvDataset
ds
:
cat
.
getDatasets
(
)
)
{
if
(
type
==
Type
.
all
)
crawlDataset
(
ds
,
task
,
out
,
context
,
true
)
;
else
crawlDirectDatasets
(
ds
,
task
,
out
,
context
,
true
)
;
if
(
(
task
!=
)
&&
task
.
isCancel
(
)
)
break
;
}
return
1
+
countCatrefs
;
}

Crawl a catalog thats already been opened.
When you get to a dataset containing leaf datasets, do all, only the first, or a randomly chosen one.

@param cat  the catalog
@param task user can cancel the task (may be null)
@param out  send status messages to here (may be null)
@param context caller can pass this object in (used for thread safety)
@return number of catalog references opened and crawled

Crawl a catalog thats already been opened . When you get to a dataset containing leaf datasets do all only the first or a randomly chosen one .


public void crawlDataset(InvDataset ds, CancelTask task, PrintWriter out, Object context, boolean release) {
    boolean isCatRef = (ds instanceof InvCatalogRef);
    if (filter != null && filter.skipAll(ds)) {
      if (isCatRef && release) ((InvCatalogRef) ds).release();
      return;
    }

    boolean isDataScan = ds.findProperty("DatasetScan") != null;

    if (isCatRef) {
      InvCatalogRef catref = (InvCatalogRef) ds;
      if (out != null)
        out.println(" **CATREF " + catref.getURI() + " (" + ds.getName() + ") ");
      countCatrefs++;

      if (!listen.getCatalogRef( catref, context)) {
        if (release) catref.release();
        return;
      }
    }

    if (!isCatRef || isDataScan)
      listen.getDataset(ds, context);

    // recurse - depth first
      List<InvDataset> dlist = ds.getDatasets();
      if (isCatRef) {
        InvCatalogRef catref = (InvCatalogRef) ds;
        if (!isDataScan) {
          listen.getDataset(catref.getProxyDataset(), context); // wait till a catref is read, so all metadata is there !
        }
      }

      for (InvDataset dds : dlist) {
        crawlDataset(dds, task, out, context, release);
        if ((task != null) && task.isCancel())
          break;
      }

    if (isCatRef && release) {
      InvCatalogRef catref = (InvCatalogRef) ds;
      catref.release();
    }

  }

Crawl this dataset recursively, return all datasets

@param ds   the dataset
@param task user can cancel the task (may be null)
@param out  send status messages to here (may be null)
@param context caller can pass this object in (used for thread safety)

Crawl this dataset recursively return all datasets


public void crawlDirectDatasets(InvDataset ds, CancelTask task, PrintWriter out, Object context, boolean release) {
    boolean isCatRef = (ds instanceof InvCatalogRef);
    if (filter != null && filter.skipAll(ds)) {
      if (isCatRef && release) ((InvCatalogRef) ds).release();
      return;
    }

    if (isCatRef) {
      InvCatalogRef catref = (InvCatalogRef) ds;
      if (out != null)
        out.println(" **CATREF " + catref.getURI() + " (" + ds.getName() + ") ");
      countCatrefs++;

      if (!listen.getCatalogRef( catref, context)) {
        if (release) catref.release();
        return;
      }
    }

    // get datasets with data access ("leaves")
    List<InvDataset> dlist = ds.getDatasets();
    List<InvDataset> leaves = new ArrayList<InvDataset>();
    for (InvDataset dds : dlist) {
      if (dds.hasAccess())
        leaves.add(dds);
    }

    if (leaves.size() > 0) {
      if (type == Type.first_direct) {
        InvDataset dds = leaves.get(0);
        listen.getDataset(dds, context);

      } else if (type == Type.random_direct) {
        listen.getDataset(chooseRandom(leaves), context);

      } else if (type == Type.random_direct_middle) {
        listen.getDataset(chooseRandomNotFirstOrLast(leaves), context);

      } else { // do all of them
        for (InvDataset dds : leaves) {
          listen.getDataset(dds, context);
          if ((task != null) && task.isCancel()) break;
        }
      }
    }

    // recurse
      for (InvDataset dds : dlist) {
        if (dds.hasNestedDatasets())
          crawlDirectDatasets(dds, task, out, context, release);
        if ((task != null) && task.isCancel())
          break;
      }

    /* if (out != null) {
     int took = (int) (System.currentTimeMillis() - start);
     out.println(" ** " + ds.getName() + " took " + took + " msecs\n");
   } */

    if (ds instanceof InvCatalogRef && release) {
      InvCatalogRef catref = (InvCatalogRef) ds;
      catref.release();
    }

  }

Crawl this dataset recursively. Only send back direct datasets

@param ds   the dataset
@param task user can cancel the task (may be null)
@param out  send status messages to here (may be null)
@param context caller can pass this object in (used for thread safety)

Crawl this dataset recursively . Only send back direct datasets


public static File getFileOrCache(String fileLocation) {
    File result = getExistingFileOrCache(fileLocation);
    if (result != null) return result;
    return getDiskCache2().getFile(fileLocation);
  }

public static File getFileOrCache ( String fileLocation ) { File result = getExistingFileOrCache ( fileLocation ) ; if ( result != null ) return result ; return getDiskCache2 ( ) . getFile ( fileLocation ) ; }

Get index file, may be in cache directory, may not exist

@param fileLocation full path of original index filename
@return File, possibly in cache, may or may not exist

Get index file may be in cache directory may not exist


public static File getExistingFileOrCache(String fileLocation) {
    File result =  getDiskCache2().getExistingFileOrCache(fileLocation);
    if (result == null && Grib.debugGbxIndexOnly && fileLocation.endsWith(".gbx9.ncx4")) { // might create only from gbx9 for debugging
      int length = fileLocation.length();
      String maybeIndexAlreadyExists = fileLocation.substring(0, length-10)+".ncx4";
      result =  getDiskCache2().getExistingFileOrCache(maybeIndexAlreadyExists);
    }
    return result;
  }

Looking for an existing file, in cache or not

@param fileLocation full path of original index filename
@return existing file if you can find it, else null

Looking for an existing file in cache or not


static public void setDebugLeaks(boolean b) {
    if (b) {
      count_openFiles.set(0);
      maxOpenFiles.set(0);
      allFiles = new HashSet<>(1000);
    }
    debugLeaks = b;
  }

static public void setDebugLeaks ( boolean b ) { if ( b ) { count_openFiles . set ( 0 ) ; maxOpenFiles . set ( 0 ) ; allFiles = new HashSet <> ( 1000 ) ; } debugLeaks = b ; }

Debugging, do not use in production.
Set counters to zero, set debugging on
@param b set true to track java.io.RandomAccessFile

Debugging do not use in production . Set counters to zero set debugging on


static public List<String> getAllFiles() {
    if (null == allFiles) return null;
    List<String> result = new ArrayList<>();
    result.addAll(allFiles);
    Collections.sort(result);
    return result;
  }

static public List < String > getAllFiles ( ) { if ( null == allFiles ) return null ; List < String > result = new ArrayList <> ( ) ; result . addAll ( allFiles ) ; Collections . sort ( result ) ; return result ; }

Debugging, do not use.

@return list of all files used.


public synchronized void close() throws IOException {
    if (cache != null) {
      if (cacheState > 0) {
        if (cacheState == 1) {
          cacheState = 2;
          if (cache.release(this))  // return true if in the cache, otherwise was opened regular, so must be closed regular
            return;
          cacheState = 0; // release failed, bail out
        } else {
          return; // close has been called more than once - ok
        }
      }
    }

    if (debugLeaks) {
      openFiles.remove(location);
      if (showOpen) System.out.println("  close " + location);
    }

    if (file == null)
      return;

    // If we are writing and the buffer has been modified, flush the contents of the buffer.
    flush();

    // may need to extend file, in case no fill is being used
    // may need to truncate file in case overwriting a longer file
    // use only if minLength is set (by N3iosp)
    long fileSize = file.length();
    if (!readonly && (minLength != 0) && (minLength != fileSize)) {
      file.setLength(minLength);
      // System.out.println("TRUNCATE!!! minlength="+minLength);
    }

    // Close the underlying file object.
    file.close();
    file = null;  // help the gc
  }

Close the file, and release any associated system resources.

@throws IOException if an I/O error occurrs.

Close the file and release any associated system resources .


public void seek(long pos) throws IOException {
    if (pos < 0)
      throw new java.io.IOException("Negative seek offset");

    // If the seek is into the buffer, just update the file pointer.
    if ((pos >= bufferStart) && (pos < dataEnd)) {
      filePosition = pos;
      return;
    }

    // need new buffer, starting at pos
    readBuffer(pos);
  }

Set the position in the file for the next read or write.

@param pos the offset (in bytes) from the start of the file.
@throws IOException if an I/O error occurrs.

Set the position in the file for the next read or write .


public void flush() throws IOException {
    if (bufferModified) {
      file.seek(bufferStart);
      file.write(buffer, 0, dataSize);
      //System.out.println("--flush at "+bufferStart+" dataSize= "+dataSize+ " filePosition= "+filePosition);
      bufferModified = false;
    }

    /* check min length
    if (!readonly && (minLength != 0) && (minLength != file.length())) {
      file.setLength(minLength);
    } */
  }

Copy the contents of the buffer to the disk.

@throws IOException if an I/O error occurs.

Copy the contents of the buffer to the disk .


public int read() throws IOException {

    // If the file position is within the data, return the byte...
    if (filePosition < dataEnd) {
      int pos = (int) (filePosition - bufferStart);
      filePosition++;
      return (buffer[pos] & 0xff);

      // ...or should we indicate EOF...
    } else if (endOfFile) {
      return -1;

      // ...or seek to fill the buffer, and try again.
    } else {
      seek(filePosition);
      return read();
    }
  }

Read a byte of data from the file, blocking until data is
available.

@return the next byte of data, or -1 if the end of the file is
reached.
@throws IOException if an I/O error occurrs.

Read a byte of data from the file blocking until data is available .


public final void readShort(short[] pa, int start, int n) throws IOException {
    for (int i = 0; i < n; i++) {
      pa[start + i] = readShort();
    }
  }

public final void readShort ( short [ ] pa , int start , int n ) throws IOException { for ( int i = 0 ; i < n ; i ++ ) { pa [ start + i ] = readShort ( ) ; } }

Read an array of shorts

@param pa    read into this array
@param start starting at pa[start]
@param n     read this many elements
@throws IOException on read error


public final int readIntUnbuffered(long pos) throws IOException {
    byte[] bb = new byte[4];
    read_(pos, bb, 0, 4);
    int ch1 = bb[0] & 0xff;
    int ch2 = bb[1] & 0xff;
    int ch3 = bb[2] & 0xff;
    int ch4 = bb[3] & 0xff;
    if ((ch1 | ch2 | ch3 | ch4) < 0) {
      throw new EOFException();
    }

    if (bigEndian) {
      return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
    } else {
      return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1));
    }
  }

public final int readIntUnbuffered ( long pos ) throws IOException { byte [ ] bb = new byte [ 4 ] ; read_ ( pos , bb , 0 , 4 ) ; int ch1 = bb [ 0 ] & 0xff ; int ch2 = bb [ 1 ] & 0xff ; int ch3 = bb [ 2 ] & 0xff ; int ch4 = bb [ 3 ] & 0xff ; if ( ( ch1 | ch2 | ch3 | ch4 ) < 0 ) { throw new EOFException ( ) ; } if ( bigEndian ) { return ( ( ch1 << 24 ) + ( ch2 << 16 ) + ( ch3 << 8 ) + ( ch4 ) ) ; } else { return ( ( ch4 << 24 ) + ( ch3 << 16 ) + ( ch2 << 8 ) + ( ch1 ) ) ; } }

Read an integer at the given position, bypassing all buffering.

@param pos read a byte at this position
@return The int that was read
@throws IOException if an I/O error occurs.

Read an integer at the given position bypassing all buffering .


public final void readInt(int[] pa, int start, int n) throws IOException {
    for (int i = 0; i < n; i++) {
      pa[start + i] = readInt();
    }
  }

public final void readInt ( int [ ] pa , int start , int n ) throws IOException { for ( int i = 0 ; i < n ; i ++ ) { pa [ start + i ] = readInt ( ) ; } }

Read an array of ints

@param pa    read into this array
@param start starting at pa[start]
@param n     read this many elements
@throws IOException on read error