Input: / * LOOK public thredds . catalog . InvCatalog getParentCatalog () { return !useProxy ? super . getParentCatalog () : proxy . getParentCatalog () ; } [CODESPLIT] @ Override public java . util . List < ThreddsMetadata . Vocab > getProjects ( ) { return ! useProxy ? super . getProjects ( ) : proxy . getProjects ( ) ; }


Input: / * public void setLevels ( ucar . nc2 . dataset . grid . GridCoordSys gcs int current ) { this . zAxis = gcs . getVerticalAxis () ; if ( zAxis == null ) { slider . setEnabled ( false ) ; return ; } set up the slider and conversion slider . setEnabled ( true ) ; slider . setInverted ( !gcs . isZPositive () ) ; slider . setToolTipText ( zAxis . getUnitString () ) ; setSelectedIndex ( current ) ; [CODESPLIT] private int calcFracDigits ( String d ) { int pos = d . indexOf ( "." ) ; if ( pos < 0 ) return 0 ; return d . length ( ) - pos - 1 ; }


Input:
************************************************************************ Default handler for OPeNDAP info requests . Returns an html document describing the contents of the servers datasets .
 The INFOcache &lt ; init - param&gt ; element in the web . xml file specifies the designated location for :

 . info response override files .

 Server specific HTML * files .

 Dataset specific HTML * files .

 The server specific HTML * files must be named #servlet# . html where #servlet# is the name of the servlet that is running as the OPeNDAP server in question . This name is determined at run time by using the class called Class ( this . getClass () . getName () ) .

 In the C ++ code the analogy is the per - cgi file names .

 The dataset specific HTML * files are located by catenating . html to #name# where #name# is the name of the dataset . If the filename part of #name# is of the form [ A - Za - z ] + [ 0 - 9 ] * . * then this function also looks for a file whose name is [ A - Za - z ] . html For example if #name# is ... / data / fnoc1 . nc this function first looks for ... / data / fnoc1 . nc . html . However if that does not exist it will look for ... / data / fnoc . html . This allows one per - dataset file to be used for a collection of files with the same root name .

 NB : An HTML * file contains HTML without the   or  tags ( my own notation ) .

 Look for the user supplied Server - and dataset - specific HTML * documents .
 [CODESPLIT] public void sendINFO ( PrintWriter pw , GuardedDataset gds , ReqState rs ) throws DAP2Exception , ParseException { if ( _Debug ) System . out . println ( "opendap.servlet.GetInfoHandler.sendINFO() reached." ) ; String responseDoc = null ; ServerDDS myDDS = null ; DAS myDAS = null ; myDDS = gds . getDDS ( ) ; myDAS = gds . getDAS ( ) ; infoDir = rs . getINFOCache ( rs . getRootPath ( ) ) ; responseDoc = loadOverrideDoc ( infoDir , rs . getDataSet ( ) ) ; if ( responseDoc != null ) { if ( _Debug ) System . out . println ( "override document: " + responseDoc ) ; pw . print ( responseDoc ) ; } else { String user_html = get_user_supplied_docs ( rs . getServerClassName ( ) , rs . getDataSet ( ) ) ; String global_attrs = buildGlobalAttributes ( myDAS , myDDS ) ; String variable_sum = buildVariableSummaries ( myDAS , myDDS ) ; // Send the document back to the client. pw . println ( "<title>Dataset Information</title>" ) ; pw . println ( "" ) ; pw . println ( "" ) ; pw . println ( "" ) ; if ( global_attrs . length ( ) > 0 ) { pw . println ( global_attrs ) ; pw . println ( "
" ) ; } pw . println ( variable_sum ) ; pw . println ( "
" ) ; pw . println ( user_html ) ; pw . println ( "" ) ; // Flush the output buffer. pw . flush ( ) ; } }


Input:
************************************************************************ Checks the info directory for user supplied override documents for the passed dataset name . If there are overridedocuments present then the contents are read and returned to the caller as a string . [CODESPLIT] public String loadOverrideDoc ( String infoDir , String dataSet ) throws DAP2Exception { StringBuilder userDoc = new StringBuilder ( ) ; String overrideFile = dataSet + ".ovr" ; //Try to open and read the override file for this dataset. try { File fin = new File ( infoDir + overrideFile ) ; try ( BufferedReader svIn = new BufferedReader ( new InputStreamReader ( new FileInputStream ( fin ) , Util . UTF8 ) ) ; ) { boolean done = false ; while ( ! done ) { String line = svIn . readLine ( ) ; if ( line == null ) { done = true ; } else { userDoc . append ( line ) ; userDoc . append ( "\n" ) ; } } } } catch ( FileNotFoundException fnfe ) { userDoc . append ( "
No Could Not Open Override Document.

" ) ; return ( null ) ; } catch ( IOException ioe ) { throw ( new DAP2Exception ( opendap . dap . DAP2Exception . UNKNOWN_ERROR , ioe . getMessage ( ) ) ) ; } return ( userDoc . toString ( ) ) ; }


Input:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [CODESPLIT] private String buildGlobalAttributes ( DAS das , ServerDDS dds ) { boolean found = false ; StringBuilder ga = new StringBuilder ( ) ; ga . append ( "
Dataset Information
\n
\n" ) ; Enumeration edas = das . getNames ( ) ; while ( edas . hasMoreElements ( ) ) { String name = ( String ) edas . nextElement ( ) ; if ( ! dasTools . nameInKillFile ( name ) && ( dasTools . nameIsGlobal ( name ) || ! dasTools . nameInDDS ( name , dds ) ) ) { try { AttributeTable attr = das . getAttributeTable ( name ) ; if ( attr != null ) { Enumeration e = attr . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String aName = ( String ) e . nextElement ( ) ; Attribute a = attr . getAttribute ( aName ) ; found = true ; ga . append ( "\n
" ) ; ga . append ( aName + ":	\n" ) ; ga . append ( "" ) ; Enumeration es = a . getValues ( ) ; while ( es . hasMoreElements ( ) ) { String val = ( String ) es . nextElement ( ) ; ga . append ( val ) ; ga . append ( "
" ) ; } ga . append ( "
\n" ) ; } } } catch ( NoSuchAttributeException nsae ) { } } } ga . append ( "
\n
\n" ) ; if ( ! found ) ga . setLength ( 0 ) ; return ( ga . toString ( ) ) ; }


Input:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [CODESPLIT] private String buildVariableSummaries ( DAS das , ServerDDS dds ) { StringBuilder vs = new StringBuilder ( ) ; vs . append ( "
Variables in this Dataset
\n
\n" ) ; Enumeration e = dds . getVariables ( ) ; while ( e . hasMoreElements ( ) ) { BaseType bt = ( BaseType ) e . nextElement ( ) ; vs . append ( "
" ) ; vs . append ( summarizeVariable ( bt , das ) ) ; vs . append ( "
" ) ; } vs . append ( "
\n
\n" ) ; return ( vs . toString ( ) ) ; }


Input: Make deep copy from sdata to another StructureData object whose data is self contained [CODESPLIT] static public StructureDataDeep copy ( StructureData sdata , StructureMembers members ) { ArrayStructureBB abb = copyToArrayBB ( sdata , members , ByteOrder . BIG_ENDIAN ) ; return new StructureDataDeep ( abb ) ; }


Input: Make deep copy from an ArrayStructure to a ArrayStructureBB whose data is contained in a ByteBuffer [CODESPLIT] static public ArrayStructureBB copyToArrayBB ( ArrayStructure as , ByteOrder bo , boolean canonical ) throws IOException { if ( ! canonical && as . getClass ( ) . equals ( ArrayStructureBB . class ) ) { // no subclasses, LOOK detect already canonical later ArrayStructureBB abb = ( ArrayStructureBB ) as ; ByteBuffer bb = abb . getByteBuffer ( ) ; if ( bo == null || bo . equals ( bb . order ( ) ) ) return abb ; } StructureMembers smo = as . getStructureMembers ( ) ; StructureMembers sm = new StructureMembers ( smo ) ; ArrayStructureBB abb = new ArrayStructureBB ( sm , as . getShape ( ) ) ; ArrayStructureBB . setOffsets ( sm ) ; // this makes the packing canonical if ( bo != null ) { ByteBuffer bb = abb . getByteBuffer ( ) ; bb . order ( bo ) ; } try ( StructureDataIterator iter = as . getStructureDataIterator ( ) ) { while ( iter . hasNext ( ) ) copyToArrayBB ( iter . next ( ) , abb ) ; } return abb ; }


Input: Make deep copy to an ArrayStructureBB whose data is contained in a ByteBuffer . Use the order of the members in the given Structure ; skip copying any not in the Structure [CODESPLIT] static public ArrayStructureBB copyToArrayBB ( Structure s , ArrayStructure as , ByteOrder bo ) throws IOException { StructureMembers sm = s . makeStructureMembers ( ) ; ArrayStructureBB abb = new ArrayStructureBB ( sm , as . getShape ( ) ) ; ArrayStructureBB . setOffsets ( sm ) ; if ( bo != null ) { ByteBuffer bb = abb . getByteBuffer ( ) ; bb . order ( bo ) ; } try ( StructureDataIterator iter = as . getStructureDataIterator ( ) ) { while ( iter . hasNext ( ) ) copyToArrayBB ( iter . next ( ) , abb ) ; } return abb ; }


Input: Make deep copy from a StructureData to a ArrayStructureBB whose data is contained in a ByteBuffer . [CODESPLIT] static public ArrayStructureBB copyToArrayBB ( StructureData sdata ) { return copyToArrayBB ( sdata , new StructureMembers ( sdata . getStructureMembers ( ) ) , ByteOrder . BIG_ENDIAN ) ; }


Input: Make deep copy from a StructureData to a ArrayStructureBB whose data is contained in a ByteBuffer [CODESPLIT] static public ArrayStructureBB copyToArrayBB ( StructureData sdata , StructureMembers sm , ByteOrder bo ) { int size = sm . getStructureSize ( ) ; ByteBuffer bb = ByteBuffer . allocate ( size ) ; // default is big endian bb . order ( bo ) ; ArrayStructureBB abb = new ArrayStructureBB ( sm , new int [ ] { 1 } , bb , 0 ) ; ArrayStructureBB . setOffsets ( sm ) ; copyToArrayBB ( sdata , abb ) ; return abb ; }


Input:
Make deep copy from a StructureData into the given ArrayStructureBB [CODESPLIT] static public int copyToArrayBB ( StructureData sdata , ArrayStructureBB abb ) { //StructureMembers sm = sdata.getStructureMembers(); ByteBuffer bb = abb . getByteBuffer ( ) ; int start = bb . limit ( ) ; for ( StructureMembers . Member wantMember : abb . getMembers ( ) ) { StructureMembers . Member m = sdata . findMember ( wantMember . getName ( ) ) ; assert m != null ; assert m . getDataType ( ) == wantMember . getDataType ( ) ; DataType dtype = m . getDataType ( ) ; //System.out.printf("do %s (%s) = %d%n", m.getName(), m.getDataType(), bb.position()); if ( m . isScalar ( ) ) { switch ( dtype ) { case STRING : bb . putInt ( abb . addObjectToHeap ( sdata . getScalarString ( m ) ) ) ; break ; case FLOAT : bb . putFloat ( sdata . getScalarFloat ( m ) ) ; break ; case DOUBLE : bb . putDouble ( sdata . getScalarDouble ( m ) ) ; break ; case INT : case UINT : case ENUM4 : bb . putInt ( sdata . getScalarInt ( m ) ) ; break ; case SHORT : case USHORT : case ENUM2 : bb . putShort ( sdata . getScalarShort ( m ) ) ; break ; case BYTE : case UBYTE : case ENUM1 : bb . put ( sdata . getScalarByte ( m ) ) ; break ; case CHAR : bb . put ( ( byte ) sdata . getScalarChar ( m ) ) ; break ; case LONG : case ULONG : bb . putLong ( sdata . getScalarLong ( m ) ) ; break ; case STRUCTURE : StructureData sd = sdata . getScalarStructure ( m ) ; ArrayStructureBB out_abb = new ArrayStructureBB ( sd . getStructureMembers ( ) , new int [ ] { 1 } , bb , 0 ) ; copyToArrayBB ( sd , out_abb ) ; break ; default : throw new IllegalStateException ( "scalar " + dtype . toString ( ) ) ; /* case BOOLEAN:
           break;
         case SEQUENCE:
           break;
         case OPAQUE:
           break; */ } } else { int n = m . getSize ( ) ; switch ( dtype ) { case STRING : String [ ] ss = sdata . getJavaArrayString ( m ) ; bb . putInt ( abb . addObjectToHeap ( ss ) ) ; // stored as String[] on the heap break ; case FLOAT : float [ ] fdata = sdata . getJavaArrayFloat ( m ) ; for ( int i = 0 ; i < n ; i ++ ) bb . putFloat ( fdata [ i ] ) ; break ; case DOUBLE : double [ ] ddata = sdata . getJavaArrayDouble ( m ) ; for ( int i = 0 ; i < n ; i ++ ) bb . putDouble ( ddata [ i ] ) ; break ; case INT : case ENUM4 : int [ ] idata = sdata . getJavaArrayInt ( m ) ; for ( int i = 0 ; i < n ; i ++ ) bb . putInt ( idata [ i ] ) ; break ; case SHORT : case ENUM2 : short [ ] shdata = sdata . getJavaArrayShort ( m ) ; for ( int i = 0 ; i < n ; i ++ ) bb . putShort ( shdata [ i ] ) ; break ; case BYTE : case ENUM1 : byte [ ] bdata = sdata . getJavaArrayByte ( m ) ; for ( int i = 0 ; i < n ; i ++ ) bb . put ( bdata [ i ] ) ; break ; case CHAR : char [ ] cdata = sdata . getJavaArrayChar ( m ) ; bb . put ( IospHelper . convertCharToByte ( cdata ) ) ; break ; case LONG : long [ ] ldata = sdata . getJavaArrayLong ( m ) ; for ( int i = 0 ; i < n ; i ++ ) bb . putLong ( ldata [ i ] ) ; break ; default : throw new IllegalStateException ( "array " + dtype . toString ( ) ) ; /* case BOOLEAN:
          break;
         case OPAQUE:
          break;
        case STRUCTURE:
          break; // */ case SEQUENCE : break ; // skip } } } return bb . limit ( ) - start ; }


Input: Only use in GribVariable to decide on variable identity when intvMerge = false . By returning a constant we dont intvMerge = false . Problem is we cant reconstruct interval length without reference time which is not in the pds . [CODESPLIT] @ Override public double getForecastTimeIntervalSizeInHours ( Grib2Pds pds ) { Grib2Pds . PdsInterval pdsIntv = ( Grib2Pds . PdsInterval ) pds ; // override here only if timeRangeUnit = 255 boolean needOverride = false ; for ( Grib2Pds . TimeInterval ti : pdsIntv . getTimeIntervals ( ) ) { needOverride = ( ti . timeRangeUnit == 255 ) ; } if ( ! needOverride ) return super . getForecastTimeIntervalSizeInHours ( pds ) ; return 12.0 ; }


Input: Create a new CoordinateAxis1D as a section of this CoordinateAxis1D . [CODESPLIT] public CoordinateAxis1D section ( Range r ) throws InvalidRangeException { Section section = new Section ( ) . appendRange ( r ) ; CoordinateAxis1D result = ( CoordinateAxis1D ) section ( section ) ; int len = r . length ( ) ; // deal with the midpoints, bounds if ( isNumeric ( ) ) { double [ ] new_mids = new double [ len ] ; for ( int idx = 0 ; idx < len ; idx ++ ) { int old_idx = r . element ( idx ) ; new_mids [ idx ] = coords [ old_idx ] ; } result . coords = new_mids ; if ( isInterval ) { double [ ] new_bound1 = new double [ len ] ; double [ ] new_bound2 = new double [ len ] ; double [ ] new_edge = new double [ len + 1 ] ; for ( int idx = 0 ; idx < len ; idx ++ ) { int old_idx = r . element ( idx ) ; new_bound1 [ idx ] = bound1 [ old_idx ] ; new_bound2 [ idx ] = bound2 [ old_idx ] ; new_edge [ idx ] = bound1 [ old_idx ] ; new_edge [ idx + 1 ] = bound2 [ old_idx ] ; // all but last are overwritten } result . bound1 = new_bound1 ; result . bound2 = new_bound2 ; result . edge = new_edge ; } else { double [ ] new_edge = new double [ len + 1 ] ; for ( int idx = 0 ; idx < len ; idx ++ ) { int old_idx = r . element ( idx ) ; new_edge [ idx ] = edge [ old_idx ] ; new_edge [ idx + 1 ] = edge [ old_idx + 1 ] ; // all but last are overwritten } result . edge = new_edge ; } } if ( names != null ) { String [ ] new_names = new String [ len ] ; for ( int idx = 0 ; idx < len ; idx ++ ) { int old_idx = r . element ( idx ) ; new_names [ idx ] = names [ old_idx ] ; } result . names = new_names ; } result . wasCalcRegular = false ; result . calcIsRegular ( ) ; return result ; }


Input:
Get the list of names to be used for user selection . The ith one refers to the ith coordinate . [CODESPLIT] public List < NamedObject > getNames ( ) { int n = getDimension ( 0 ) . getLength ( ) ; List < NamedObject > names = new ArrayList <> ( n ) ; for ( int i = 0 ; i < n ; i ++ ) names . ( new ucar . nc2 . util . NamedAnything ( getCoordName ( i ) , getShortName ( ) + " " + getUnitsString ( ) ) ) ; return names ; } /**
   * The "name" of the ith coordinate. If nominal, this is all there is to a coordinate.
   * If numeric, this will return a String representation of the coordinate.
   *
   * @param index which one ?
   * @return the ith coordinate value as a String
   */ public String getCoordName ( int index ) { if ( ! wasRead ) doRead ( ) ; if ( isNumeric ( ) ) return Format . d ( getCoordValue ( index ) , 5 , 8 ) ; else return names [ index ] ; } /**
   * Get the ith coordinate value. This is the value of the coordinate axis at which
   * the data value is associated. These must be strictly monotonic.
   *
   * @param index which coordinate. Between 0 and getNumElements()-1 inclusive.
   * @return coordinate value.
   * @throws UnsupportedOperationException if !isNumeric()
   */ public double getCoordValue  ( int index ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordValue() on non-numeric" ) ; if ( ! wasRead ) doRead ( ) ; return coords [ index ] ; } @ Override public double getMinValue  ( ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordValue() on non-numeric" ) ; if ( ! wasRead ) doRead ( ) ; return Math . min ( coords [ 0 ] , coords [ coords . length - 1 ] ) ; } @ Override public double getMaxValue  ( ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordValue() on non-numeric" ) ; if ( ! wasRead ) doRead ( ) ; return Math . max ( coords [ 0 ] , coords [ coords . length - 1 ] ) ; } public double getMinEdgeValue  ( ) { if ( edge == null ) return getMinValue ( ) ; if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordValue() on non-numeric" ) ; if ( ! wasRead ) doRead ( ) ; return Math . min ( edge [ 0 ] , edge [ edge . length - 1 ] ) ; } public double getMaxEdgeValue  ( ) { if ( edge == null ) return getMaxValue ( ) ; if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordValue() on non-numeric" ) ; if ( ! wasRead ) doRead ( ) ; return Math . max ( edge [ 0 ] , edge [ edge . length - 1 ] ) ; } /**
   * Get the ith coordinate edge. Exact only if isContiguous() is true, otherwise use getBound1() and getBound2().
   * This is the value where the underlying grid element switches
   * from "belonging to" coordinate value i-1 to "belonging to" coordinate value i.
   * In some grids, this may not be well defined, and so should be considered an
   * approximation or a visualization hint.
   *

   *  Coordinate edges must be strictly monotonic:
   *    coordEdge(0) < coordValue(0) < coordEdge(1) < coordValue(1) ...
   *    ... coordEdge(i) < coordValue(i) < coordEdge(i+1) < coordValue(i+1) ...
   *    ... coordEdge(n-1) < coordValue(n-1) < coordEdge(n)
   *

   *
   * @param index which coordinate. Between 0 and getNumElements() inclusive.
   * @return coordinate edge.
   * @throws UnsupportedOperationException if !isNumeric()
   */ public double getCoordEdge  ( int index ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordEdge() on non-numeric" ) ; if ( ! wasBoundsDone ) makeBounds ( ) ; return edge [ index ] ; } /**
   * Get the coordinate values as a double array.
   *
   * @return coordinate value.
   * @throws UnsupportedOperationException if !isNumeric()
   */ public double [ ] getCoordValues  ( ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordValues() on non-numeric" ) ; if ( ! wasRead ) doRead ( ) ; return coords . clone ( ) ; } /**
   * Get the coordinate edges as a double array.
   * Exact only if isContiguous() is true, otherwise use getBound1() and getBound2().
   *
   * @return coordinate edges.
   * @throws UnsupportedOperationException if !isNumeric()
   */ public double [ ] getCoordEdges  ( ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getCoordEdges() on non-numeric" ) ; if ( ! wasBoundsDone ) makeBounds ( ) ; return edge . clone ( ) ; } @ Override public boolean isContiguous  ( ) { if ( ! wasBoundsDone ) makeBounds ( ) ; // this sets isContiguous return isContiguous ; } /////////////////////////////////////////////// /**
   * If this coordinate has interval values.
   * If so, then one should use getBound1, getBound2, and not getCoordEdges()
   *
   * @return true if coordinate has interval values
   */ public boolean isInterval  ( ) { if ( ! wasBoundsDone ) makeBounds ( ) ; // this sets isInterval return isInterval ; } /**
   * Get the coordinate bound1 as a double array.
   * bound1[i] # coordValue[i] # bound2[i], where # is < if increasing (bound1[i] < bound1[i+1])
   * else < if decreasing.
   *
   * @return coordinate bound1.
   * @throws UnsupportedOperationException if !isNumeric()
   */ public double [ ] getBound1  ( ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getBound1() on non-numeric" ) ; if ( ! wasBoundsDone ) makeBounds ( ) ; if ( bound1 == null ) makeBoundsFromEdges ( ) ; assert bound1 != null ; return bound1 . clone ( ) ; } /**
   * Get the coordinate bound1 as a double array.
   * bound1[i] # coordValue[i] # bound2[i],  where # is < if increasing (bound1[i] < bound1[i+1])
   * else < if decreasing.
   *
   * @return coordinate bound2.
   * @throws UnsupportedOperationException if !isNumeric()
   */ public double [ ] getBound2  ( ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis1D.getBound2() on non-numeric" ) ; if ( ! wasBoundsDone ) makeBounds ( ) ; if ( bound2 == null ) makeBoundsFromEdges ( ) ; assert bound2 != null ; return bound2 . clone ( ) ; } /**
   * Get the coordinate bounds for the ith coordinate.
   * Can use this for isContiguous() true or false.
   *
   * @param i coordinate index
   * @return double[2] edges for ith coordinate
   */ public double [ ] getCoordBounds  ( int i ) { if ( ! wasBoundsDone ) makeBounds ( ) ; double [ ] e = new double [ 2 ] ; if ( isContiguous ( ) ) { e [ 0 ] = getCoordEdge ( i ) ; e [ 1 ] = getCoordEdge ( i + 1 ) ; } else { e [ 0 ] = bound1 [ i ] ; e [ 1 ] = bound2 [ i ] ; } return e ; } public double getCoordBoundsMidpoint  ( int i ) { double [ ] bounds = getCoordBounds ( i ) ; return ( bounds [ 0 ] + bounds [ 1 ] ) / 2 ; } /**
   * Given a coordinate value, find what grid element contains it.
   * This means that
   *

   * edge[i] <= value < edge[i+1] (if values are ascending)
   * edge[i] > value >= edge[i+1] (if values are descending)
   *

   *
   * @param coordVal position in this coordinate system
   * @return index of grid point containing it, or -1 if outside grid area
   */ public int findCoordElement  ( double coordVal ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis.findCoordElement() on non-numeric" ) ; if ( isRegular ( ) ) return findCoordElementRegular ( coordVal , false ) ; if ( isContiguous ( ) ) return findCoordElementIrregular ( coordVal , false ) ; else return findCoordElementNonContiguous ( coordVal , false ) ; } /**
   * Given a coordinate position, find what grid element contains it, or is closest to it.
   *
   * @param coordVal position in this coordinate system
   * @return index of grid point containing it, or best estimate of closest grid interval.
   */ public int findCoordElementBounded  ( double coordVal ) { if ( ! isNumeric ( ) ) throw new UnsupportedOperationException ( "CoordinateAxis.findCoordElementBounded() on non-numeric" ) ; // the scalar or len-1 case: if ( this . getSize ( ) == 1 ) return 0 ; if ( isRegular ( ) ) return findCoordElementRegular ( coordVal , true ) ; if ( isContiguous ( ) ) return findCoordElementIrregular ( coordVal , true ) ; else return findCoordElementNonContiguous ( coordVal , true ) ; } /**
   * @deprecated use findCoordElement(coordVal)
   */ public int findCoordElement  ( double coordVal , int lastIndex ) { return findCoordElement ( coordVal ) ; } ////////////////////////////////////////////////////////////////// // following is from Jon Blower's ncWMS // faster routines for coordValue -> index search // significantly modified /**
   * Optimize the regular case
   * Gets the index of the given point. Uses index = (value - start) / stride,
   * hence this is faster than an exhaustive search.
   * from jon blower's ncWMS.
   *
   * @param coordValue The value along this coordinate axis
   * @param bounded    if false and not in range, return -1, else nearest index
   * @return the index that is nearest to this point, or -1 if the point is
   * out of range for the axis
   */ private int findCoordElementRegular  ( double coordValue , boolean bounded ) { int n = ( int ) this . getSize ( ) ; // the scalar or len-1 case: if ( this . getSize ( ) == 1 ) { return 0 ; } /*  if (axisType == AxisType.Lon) {
      double maxValue = this.start + this.increment * n;
      if (betweenLon(coordValue, this.start, maxValue)) {
        double distance = LatLonPointImpl.getClockwiseDistanceTo(this.start, coordValue);
        double exactNumSteps = distance / this.increment;
        // This axis might wrap, so we make sure that the returned index is within range
        return ((int) Math.round(exactNumSteps)) % (int) this.getSize();

      } else if (coordValue < this.start) {
        return bounded ? 0 : -1;
      } else {
        return bounded ? n - 1 : -1;
      }
    } */ double distance = coordValue - this . start ; double exactNumSteps = distance / this . increment ; int index = ( int ) Math . round ( exactNumSteps ) ; if ( index < 0 ) return bounded ? 0 : - 1 ; else if ( index >= n ) return bounded ? n - 1 : - 1 ; return index ; } private boolean betweenLon  ( double lon , double lonBeg , double lonEnd ) { while ( lon < lonBeg ) lon += 360 ; return ( lon >= lonBeg ) && ( lon <= lonEnd ) ; } /**
   * Performs a binary search to find the index of the element of the array
   * whose value is contained in the interval, so must be contiguous.
   *
   * @param target  The value to search for
   * @param bounded if false, and not in range, return -1, else nearest index
   * @return the index of the element in values whose value is closest to target,
   * or -1 if the target is out of range
   */ private int findCoordElementIrregular  ( double target , boolean bounded ) { int n = ( int ) this . getSize ( ) ; int low = 0 ; int high = n ; if ( isAscending ) { // Check that the point is within range if ( target < this . edge [ low ] ) return bounded ? 0 : - 1 ; else if ( target > this . edge [ high ] ) return bounded ? n - 1 : - 1 ; // do a binary search to find the nearest index int mid = low ; while ( high > low + 1 ) { mid = ( low + high ) / 2 ; double midVal = this . edge [ mid ] ; if ( midVal == target ) return mid ; else if ( midVal < target ) low = mid ; else high = mid ; } return low ; } else { // Check that the point is within range if ( target > this . edge [ low ] ) return bounded ? 0 : - 1 ; else if ( target < this . edge [ high ] ) return bounded ? n - 1 : - 1 ; // do a binary search to find the nearest index int mid = low ; while ( high > low + 1 ) { mid = ( low + high ) / 2 ; double midVal = this . edge [ mid ] ; if ( midVal == target ) return mid ; else if ( midVal < target ) high = mid ; else low = mid ; } return high - 1 ; } } /**
   * Given a coordinate position, find what grid element contains it.
   * Only use if isContiguous() == false
   * This algorithm does a linear search in the bound1[] amd bound2[] array.
   *

   * This means that
   *

   * edge[i] <= pos < edge[i+1] (if values are ascending)
   * edge[i] > pos >= edge[i+1] (if values are descending)
   *

   *
   * @param target  The value to search for
   * @param bounded if false, and not in range, return -1, else nearest index
   * @return the index of the element in values whose value is closest to target,
   * or -1 if the target is out of range
   */ private int findCoordElementNonContiguous  ( double target , boolean bounded ) { double [ ] bounds1 = getBound1 ( ) ; double [ ] bounds2 = getBound2 ( ) ; int n = bounds1 . length ; if ( isAscending ) { // Check that the point is within range if ( target < bounds1 [ 0 ] ) return bounded ? 0 : - 1 ; else if ( target > bounds2 [ n - 1 ] ) return bounded ? n - 1 : - 1 ; int [ ] idx = findSingleHit ( bounds1 , bounds2 , target ) ; if ( idx [ 0 ] == 0 && ! bounded ) return - 1 ; // no hits if ( idx [ 0 ] == 1 ) return idx [ 1 ] ; // one hit // multiple hits = choose closest to the midpoint i guess return findClosest ( coords , target ) ; } else { // Check that the point is within range if ( target > bounds1 [ 0 ] ) return bounded ? 0 : - 1 ; else if ( target < bounds2 [ n - 1 ] ) return bounded ? n - 1 : - 1 ; int [ ] idx = findSingleHit ( bounds2 , bounds1 , target ) ; if ( idx [ 0 ] == 0 && ! bounded ) return - 1 ; // no hits if ( idx [ 0 ] == 1 ) return idx [ 1 ] ; // multiple hits = choose closest to the midpoint i guess return findClosest ( getCoordValues ( ) , target ) ; } } // return index if only one match, else -1 private int [ ] findSingleHit  ( double [ ] low , double [ ] high , double target ) { int hits = 0 ; int idxFound = - 1 ; int n = low . length ; for ( int i = 0 ; i < n ; i ++ ) { if ( ( low [ i ] <= target ) && ( target <= high [ i ] ) ) { hits ++ ; idxFound = i ; } } return new int [ ] { hits , idxFound } ; } // return index of closest value to target private int findClosest  ( double [ ] values , double target ) { double minDiff = Double . MAX_VALUE ; int idxFound = - 1 ; int n = values . length ; for ( int i = 0 ; i < n ; i ++ ) { double diff = Math . abs ( values [ i ] - target ) ; if ( diff < minDiff ) { minDiff = diff ; idxFound = i ; } } return idxFound ; } /////////////////////////////////////////////////////////////////////////////// // check if Regular /**
   * Get starting value if isRegular()
   *
   * @return starting value if isRegular()
   */ public double getStart  ( ) { calcIsRegular ( ) ; return start ; } /**
   * Get increment value if isRegular()
   *
   * @return increment value if isRegular()
   */ public double getIncrement  ( ) { calcIsRegular ( ) ; return increment ; } /**
   * If true, then value(i) = getStart() + i * getIncrement().
   *
   * @return if evenly spaced.
   */ public boolean isRegular  ( ) { calcIsRegular ( ) ; return isRegular ; } private void calcIsRegular  ( ) { if ( wasCalcRegular ) return ; if ( ! wasRead ) doRead ( ) ; if ( ! isNumeric ( ) ) isRegular = false ; else if ( getSize ( ) < 2 ) isRegular = true ; else { start = getCoordValue ( 0 ) ; int n = ( int ) getSize ( ) ; increment = ( getCoordValue ( n - 1 ) - getCoordValue ( 0 ) ) / ( n - 1 ) ; isRegular = true ; for ( int i = 1 ; i < getSize ( ) ; i ++ ) if ( ! ucar . nc2 . util . Misc . nearlyEquals ( getCoordValue ( i ) - getCoordValue ( i - 1 ) , increment , 5.0e-3 ) ) { isRegular = false ; break ; } } wasCalcRegular = true ; } /////////////////////////////////////////////////////////////////////////////// private void doRead  ( ) { if ( isNumeric ( ) ) { readValues ( ) ; wasRead = true ; if ( getSize ( ) < 2 ) isAscending = true ; else isAscending = getCoordValue ( 0 ) < getCoordValue ( 1 ) ; //  calcIsRegular(); */ } else if ( getDataType ( ) == DataType . STRING ) { readStringValues ( ) ; wasRead = true ; } else { readCharValues ( ) ; wasRead = true ; } } // turns longitude coordinate into monotonic, dealing with possible wrap. public void correctLongitudeWrap  ( ) { // correct non-monotonic longitude coords if ( axisType != AxisType . Lon ) { return ; } if ( ! wasRead ) doRead ( ) ; if ( ! wasBoundsDone ) makeBounds ( ) ; boolean monotonic = true ; for ( int i = 0 ; i < coords . length - 1 ; i ++ ) monotonic &= isAscending ? coords [ i ] < coords [ i + 1 ] : coords [ i ] > coords [ i + 1 ] ; if ( ! monotonic ) { boolean cross = false ; if ( isAscending ) { for ( int i = 0 ; i < coords . length ; i ++ ) { if ( cross ) coords [ i ] += 360 ; if ( ! cross && ( i < coords . length - 1 ) && ( coords [ i ] > coords [ i + 1 ] ) ) cross = true ; } } else { for ( int i = 0 ; i < coords . length ; i ++ ) { if ( cross ) coords [ i ] -= 360 ; if ( ! cross && ( i < coords . length - 1 ) && ( coords [ i ] < coords [ i + 1 ] ) ) cross = true ; } } // LOOK - need to make sure we get stuff from the cache Array cachedData = Array . factory ( DataType . DOUBLE , getShape ( ) , coords ) ; if ( getDataType ( ) != DataType . DOUBLE ) cachedData = MAMath . convert ( cachedData , getDataType ( ) ) ; setCachedData ( cachedData ) ; if ( ! isInterval ) { makeEdges ( ) ; } } } // only used if String private void readStringValues  ( ) { int count = 0 ; Array data ; try { data = read ( ) ; } catch ( IOException ioe ) { log . error ( "Error reading string coordinate values " , ioe ) ; throw new IllegalStateException ( ioe ) ; } names = new String [ ( int ) data . getSize ( ) ] ; IndexIterator ii = data . getIndexIterator ( ) ; while ( ii . hasNext ( ) ) names [ count ++ ] = ( String ) ii . getObjectNext ( ) ; } private void readCharValues  ( ) { int count = 0 ; ArrayChar data ; try { data = ( ArrayChar ) read ( ) ; } catch ( IOException ioe ) { log . error ( "Error reading char coordinate values " , ioe ) ; throw new IllegalStateException ( ioe ) ; } ArrayChar . StringIterator iter = data . getStringIterator ( ) ; names = new String [ iter . getNumElems ( ) ] ; while ( iter . hasNext ( ) ) names [ count ++ ] = iter . next ( ) ; } private void readValues  ( ) { Array data ; try { // setUseNaNs(false); // missing values not allowed LOOK not true for point data !! data = read ( ) ; // if (!hasCachedData()) setCachedData(data, false); //cache data for subsequent reading } catch ( IOException ioe ) { log . error ( "Error reading coordinate values " , ioe ) ; throw new IllegalStateException ( ioe ) ; } coords = ( double [ ] ) data . get1DJavaArray ( DataType . DOUBLE ) ; //IndexIterator iter = data.getIndexIterator(); //while (iter.hasNext()) //  coords[count++] = iter.getDoubleNext(); } /**
   * Calculate bounds, set isInterval, isContiguous
   */ private void makeBounds  ( ) { if ( ! wasRead ) doRead ( ) ; if ( isNumeric ( ) ) { if ( ! makeBoundsFromAux ( ) ) { makeEdges ( ) ; } } wasBoundsDone = true ; } private boolean makeBoundsFromAux  ( ) { Attribute boundsAtt = findAttributeIgnoreCase ( CF . BOUNDS ) ; if ( ( null == boundsAtt ) || ! boundsAtt . isString ( ) ) return false ; String boundsVarName = boundsAtt . getStringValue ( ) ; VariableDS boundsVar = ( VariableDS ) ncd . findVariable ( getParentGroup ( ) , boundsVarName ) ; if ( null == boundsVar ) return false ; if ( 2 != boundsVar . getRank ( ) ) return false ; if ( getDimension ( 0 ) != boundsVar . getDimension ( 0 ) ) return false ; if ( 2 != boundsVar . getDimension ( 1 ) . getLength ( ) ) return false ; Array data ; try { boundsVar . removeEnhancement ( NetcdfDataset . Enhance . ConvertMissing ) ; // Don't convert missing values to NaN. data = boundsVar . read ( ) ; } catch ( IOException e ) { log . warn ( "CoordinateAxis1D.hasBounds read failed " , e ) ; return false ; } assert ( data . getRank ( ) == 2 ) && ( data . getShape ( ) [ 1 ] == 2 ) : "incorrect shape data for variable " + boundsVar ; // extract the bounds int n = shape [ 0 ] ; double [ ] value1 = new double [ n ] ; double [ ] value2 = new double [ n ] ; Index ima = data . getIndex ( ) ; for ( int i = 0 ; i < n ; i ++ ) { ima . set0 ( i ) ; value1 [ i ] = data . getDouble ( ima . set1 ( 0 ) ) ; value2 [ i ] = data . getDouble ( ima . set1 ( 1 ) ) ; } /* flip if needed
    boolean firstLower = true; // in the first interval, is lower < upper ?
    for (int i = 0; i < value1.length; i++) {
      if (Misc.nearlyEquals(value1[i], value2[i])) continue; // skip when lower == upper
      firstLower = value1[i] < value2[i];
      break;
    }
    // check first against last : lower, unless all lower equal then upper
    boolean goesUp = (n < 2) || value1[n - 1] > value1[0] || (Misc.nearlyEquals(value1[n - 1], value2[0]) && value2[n - 1] > value2[0]);
    if (goesUp != firstLower) {
      double[] temp = value1;
      value1 = value2;
      value2 = temp;
    } */ // decide if they are contiguous boolean contig = true ; for ( int i = 0 ; i < n - 1 ; i ++ ) { if ( ! ucar . nc2 . util . Misc . nearlyEquals ( value1 [ i + 1 ] , value2 [ i ] ) ) contig = false ; } if ( contig ) { edge = new double [ n + 1 ] ; edge [ 0 ] = value1 [ 0 ] ; for ( int i = 1 ; i < n + 1 ; i ++ ) edge [ i ] = value2 [ i - 1 ] ; } else { // what does edge mean when not contiguous ?? edge = new double [ n + 1 ] ; edge [ 0 ] = value1 [ 0 ] ; for ( int i = 1 ; i < n ; i ++ ) edge [ i ] = ( value1 [ i ] + value2 [ i - 1 ] ) / 2 ; edge [ n ] = value2 [ n - 1 ] ; isContiguous = false ; } bound1 = value1 ; bound2 = value2 ; isInterval = true ; return true ; } private void makeEdges  ( ) { int size = ( int ) getSize ( ) ; edge = new double [ size + 1 ] ; if ( size < 1 ) return ; for ( int i = 1 ; i < size ; i ++ ) edge [ i ] = ( coords [ i - 1 ] + coords [ i ] ) / 2 ; edge [ 0 ] = coords [ 0 ] - ( edge [ 1 ] - coords [ 0 ] ) ; edge [ size ] = coords [ size - 1 ] + ( coords [ size - 1 ] - edge [ size - 1 ] ) ; isContiguous = true ; } private void makeBoundsFromEdges  ( ) { int size = ( int ) getSize ( ) ; if ( size == 0 ) return ; bound1 = new double [ size ] ; bound2 = new double [ size ] ; for ( int i = 0 ; i < size ; i ++ ) { bound1 [ i ] = edge [ i ] ; bound2 [ i ] = edge [ i + 1 ] ; } // flip if needed if ( bound1 [ 0 ] > bound2 [ 0 ] ) { double [ ] temp = bound1 ; bound1 = bound2 ; bound2 = temp ; } } }


Input: ///////////////////////////////////////////////// JFileChooser /////////////////////////////////////////////////// [CODESPLIT] @ Override public int showDialog ( Component parent , String approveButtonText ) throws HeadlessException { int returnValue = super . showDialog ( parent , approveButtonText ) ; this . dialog = null ; // dialog was disposed in super-method. Null out so we don't try to use it. return returnValue ; }


Input:
Find a TableConfigurer for this dataset if there is one . [CODESPLIT] static public TableConfigurer getTableConfigurer ( FeatureType wantFeatureType , NetcdfDataset ds ) throws IOException { String convUsed = null ; // search for the Conventions attribute
 String convName = ds . findAttValueIgnoreCase ( null , CDM . CONVENTIONS , null ) ; if ( convName == null ) convName = ds . findAttValueIgnoreCase ( null , "Convention" , null ) ; // now search for TableConfigurer using that Convention
 Configurator anal = null ; if ( convName != null ) { convName = convName . trim ( ) ; // search for Convention parsing class
 anal = matchConfigurator ( convName ) ; if ( anal != null ) { convUsed = convName ; if ( debug ) System . out . println ( "  TableConfigurer found using convName " + convName ) ; } // now search for comma or semicolon or / delimited list
 if ( anal == null ) { List < String > names = new ArrayList <> ( ) ; if ( ( convName . indexOf ( ' ' ) > 0 ) || ( convName . indexOf ( ' ' ) > 0 ) ) { StringTokenizer stoke = new StringTokenizer ( convName , ",;" ) ; while ( stoke . hasMoreTokens ( ) ) { String name = stoke . nextToken ( ) ; names . add ( name . trim ( ) ) ; } } else if ( ( convName . indexOf ( ' ' ) > 0 ) ) { StringTokenizer stoke = new StringTokenizer ( convName , "/" ) ; while ( stoke . hasMoreTokens ( ) ) { String name = stoke . nextToken ( ) ; names . add ( name . trim ( ) ) ; } } if ( names . size ( ) > 0 ) { // search the registered conventions, in order
 for ( Configurator conv : conventionList ) { for ( String name : names ) { if ( name . equalsIgnoreCase ( conv . convName ) ) { anal = conv ; convUsed = name ; if ( debug ) System . out . println ( "  TableConfigurer found using convName " + convName ) ; } } if ( anal != null ) break ; } } } } // search for ones that dont use Convention attribute, in order added.
 // call method isMine() using reflection.
 if ( anal == null ) { for ( Configurator conv : conventionList ) { Class c = conv . confClass ; Method isMineMethod ; try { isMineMethod = c . getMethod ( "isMine" , new Class [ ] { FeatureType . class , NetcdfDataset . class } ) ; } catch ( NoSuchMethodException ex ) { continue ; } try { Boolean result = ( Boolean ) isMineMethod . invoke ( conv . confInstance , wantFeatureType , ds ) ; if ( debug ) System . out . println ( "  TableConfigurer.isMine " + c . getName ( ) + " result = " + result ) ; if ( result ) { anal = conv ; convUsed = conv . convName ; break ; } } catch ( Exception ex ) { System . out . println ( "ERROR: Class " + c . getName ( ) + " Exception invoking isMine method%n" + ex ) ; } } } // Instantiate a new TableConfigurer object
 TableConfigurer tc = null ; if ( anal != null ) { try { tc = ( TableConfigurer ) anal . confClass . newInstance ( ) ; tc . setConvName ( convName ) ; tc . setConvUsed ( convUsed ) ; } catch ( InstantiationException | IllegalAccessException e ) { log . error ( "TableConfigurer create failed" , e ) ; } } return tc ; }


Input:
Create a TableAnalyser for this dataset with the given TableConfigurer [CODESPLIT] static public TableAnalyzer factory ( TableConfigurer tc , FeatureType wantFeatureType , NetcdfDataset ds ) throws IOException { // Create a TableAnalyzer with this TableConfigurer (may be null)
 TableAnalyzer analyzer = new TableAnalyzer ( ds , tc ) ; if ( tc != null ) { if ( tc . getConvName ( ) == null ) analyzer . userAdvice . format ( " No 'Conventions' global attribute.%n" ) ; else analyzer . userAdvice . format ( " Conventions global attribute = %s %n" , tc . getConvName ( ) ) ; // add the convention name used
 if ( tc . getConvUsed ( ) != null ) { analyzer . setConventionUsed ( tc . getConvUsed ( ) ) ; if ( ! tc . getConvUsed ( ) . equals ( tc . getConvName ( ) ) ) analyzer . userAdvice . format ( " TableConfigurer used = " + tc . getConvUsed ( ) + ".%n" ) ; } } else { analyzer . userAdvice . format ( " No TableConfigurer found, using default analysis.%n" ) ; } // construct the nested table object
 analyzer . analyze ( wantFeatureType ) ; return analyzer ; }


Input: for debugging messages [CODESPLIT] public FeatureType getFirstFeatureType ( ) { for ( NestedTable nt : leaves ) { if ( nt . hasCoords ( ) ) return nt . getFeatureType ( ) ; } return null ; }


Input:
Make a NestedTable object for the dataset . [CODESPLIT] private void analyze ( FeatureType wantFeatureType ) throws IOException { // for netcdf-3 files, convert record dimension to structure
 // LOOK may be problems when served via opendap
 boolean structAdded = ( Boolean ) ds . sendIospMessage ( NetcdfFile . IOSP_MESSAGE_ADD_RECORD_STRUCTURE ) ; if ( tc == null ) { makeTablesDefault ( structAdded ) ; makeNestedTables ( ) ; } else { configResult = tc . getConfig ( wantFeatureType , ds , errlog ) ; if ( configResult != null ) addTableRecurse ( configResult ) ; // kinda stupid
 else { // use default
 makeTablesDefault ( structAdded ) ; makeNestedTables ( ) ; } } // find the leaves
 for ( TableConfig config : tableSet ) { if ( config . children == null ) { // its a leaf
 NestedTable flatTable = new NestedTable ( ds , config , errlog ) ; leaves . add ( flatTable ) ; } } if ( PointDatasetStandardFactory . showTables ) getDetailInfo ( new Formatter ( System . out ) ) ; }


Input:
no TableConfig was passed in - gotta wing it [CODESPLIT] private void makeTablesDefault ( boolean structAdded ) throws IOException { // make Structures into a table
 List < Variable > vars = new ArrayList <> ( ds . getVariables ( ) ) ; Iterator < Variable > iter = vars . iterator ( ) ; while ( iter . hasNext ( ) ) { Variable v = iter . next ( ) ; if ( v instanceof Structure ) { // handles Sequences too
 TableConfig st = new TableConfig ( Table . Type . Structure , v . getFullName ( ) ) ; CoordSysEvaluator . findCoords ( st , ds , null ) ; st . structName = v . getFullName ( ) ; st . nestedTableName = v . getShortName ( ) ; addTable ( st ) ; checkIfTrajectory ( st ) ; iter . remove ( ) ; findNestedStructures ( ( Structure ) v , st ) ; // look for nested structures
 } else if ( structAdded && v . isUnlimited ( ) ) { iter . remove ( ) ; } } if ( tableSet . size ( ) > 0 ) return ; // search at dimensions that lat, lon, time coordinates use
 Set < Dimension > dimSet = new HashSet <> ( 10 ) ; for ( CoordinateAxis axis : ds . getCoordinateAxes ( ) ) { if ( ( axis . getAxisType ( ) == AxisType . Lat ) || ( axis . getAxisType ( ) == AxisType . Lon ) || ( axis . getAxisType ( ) == AxisType . Time ) ) for ( Dimension dim : axis . getDimensions ( ) ) dimSet . ( dim ) ; } // lat, lon, time all use same dimension - use it
 if ( dimSet . size ( ) == 1 ) { final Dimension obsDim = ( Dimension ) dimSet . toArray ( ) [ 0 ] ; TableConfig st = new TableConfig ( Table . Type . Structure , obsDim . getShortName ( ) ) ; st . structureType = obsDim . isUnlimited ( ) ? TableConfig . StructureType . Structure : TableConfig . StructureType . PsuedoStructure ; st . structName = obsDim . isUnlimited ( ) ? "record" : obsDim . getShortName ( ) ; st . dimName = obsDim . getShortName ( ) ; CoordSysEvaluator . findCoords ( st , ds , new CoordSysEvaluator . Predicate ( ) { public boolean match ( CoordinateAxis axis ) { return obsDim . equals ( axis . getDimension ( 0 ) ) ; } } ) ; CoordinateAxis time = CoordSysEvaluator . findCoordByType ( ds , AxisType . Time ) ; if ( ( time != null ) && ( time . getRank ( ) == 0 ) ) { st . addJoin ( new JoinArray ( time , JoinArray . Type . scalar , 0 ) ) ; st . time = time . getShortName ( ) ; } addTable ( st ) ; checkIfTrajectory ( st ) ; } if ( tableSet . size ( ) > 0 ) return ; // try the time dimension
 CoordinateAxis time = null ; for ( CoordinateAxis axis : ds . getCoordinateAxes ( ) ) { if ( ( axis . getAxisType ( ) == AxisType . Time ) && axis . isIndependentCoordinate ( ) ) { time = axis ; break ; } } if ( time != null ) { Dimension obsDim = time . getDimension ( 0 ) ; TableConfig st = new TableConfig ( Table . Type . Structure , obsDim . getShortName ( ) ) ; st . structureType = TableConfig . StructureType . PsuedoStructure ; st . dimName = obsDim . getShortName ( ) ; CoordSysEvaluator . findCoords ( st , ds , null ) ; addTable ( st ) ; } }


Input: / * public void showTables ( java . util . Formatter sf ) { sf . format ( %nTables%n ) ; for ( NestedTable . Table t : tableSet ) sf . format ( %s%n t ) ; [CODESPLIT] public void showNestedTables ( java . util . Formatter sf ) { for ( NestedTable nt : leaves ) { nt . show ( sf ) ; } }


Input: Create an XML document from this info [CODESPLIT] private Document makeDocument ( ) { Element rootElem = new Element ( "featureDataset" ) ; Document doc = new Document ( rootElem ) ; rootElem . setAttribute ( "location" , ds . getLocation ( ) ) ; rootElem . addContent ( new Element ( "analyser" ) . setAttribute ( "class" , getName ( ) ) ) ; if ( ft != null ) rootElem . setAttribute ( "featureType" , ft . toString ( ) ) ; for ( NestedTable nt : leaves ) { writeTable ( rootElem , nt . getLeaf ( ) ) ; } return doc ; }


Input: ////////////////////////////////////////////////////////////////////////////// [CODESPLIT] static void doit ( String filename ) throws IOException { System . out . println ( filename ) ; NetcdfDataset ncd = ucar . nc2 . dataset . NetcdfDataset . openDataset ( filename ) ; TableAnalyzer csa = TableAnalyzer . factory ( null , null , ncd ) ; csa . getDetailInfo ( new Formatter ( System . out ) ) ; System . out . println ( "%n-----------------" ) ; }


Input: Is this a valid file? [CODESPLIT] public boolean isValidFile ( RandomAccessFile raf ) throws IOException { mcGridReader = new McIDASGridReader ( ) ; return mcGridReader . init ( raf , false ) ; }


Input: Open the service provider for reading . [CODESPLIT] public void open ( RandomAccessFile raf , NetcdfFile ncfile , CancelTask cancelTask ) throws IOException { //debugProj = true; super . open ( raf , ncfile , cancelTask ) ; long start = System . currentTimeMillis ( ) ; if ( mcGridReader == null ) { mcGridReader = new McIDASGridReader ( ) ; } mcGridReader . init ( raf ) ; GridIndex index = mcGridReader . getGridIndex ( ) ; open ( index , cancelTask ) ; if ( debugOpen ) { System . out . println ( " GridServiceProvider.open " + ncfile . getLocation ( ) + " took " + ( System . currentTimeMillis ( ) - start ) ) ; } }


Input: Open the index and create the netCDF file from that [CODESPLIT] protected void open ( GridIndex index , CancelTask cancelTask ) throws IOException { McIDASLookup lookup = new McIDASLookup ( ( McIDASGridRecord ) index . getGridRecords ( ) . get ( 0 ) ) ; GridIndexToNC delegate = new GridIndexToNC ( index . filename ) ; //delegate.setUseDescriptionForVariableName(false); delegate . open ( index , lookup , 4 , ncfile , cancelTask ) ; ncfile . finish ( ) ; }


Input: Sync and extend [CODESPLIT] public boolean sync ( ) { try { if ( ! mcGridReader . init ( ) ) { return false ; } GridIndex index = mcGridReader . getGridIndex ( ) ; // reconstruct the ncfile objects ncfile . empty ( ) ; open ( index , null ) ; return true ; } catch ( IOException ioe ) { return false ; } }


Input: package private . use Array . factory () [CODESPLIT] static ArrayShort factory ( Index index , boolean isUnsigned ) { return ArrayShort . factory ( index , isUnsigned , null ) ; }


Input: copy from javaArray to storage using the iterator : used by factory ( Object ) ; [CODESPLIT] protected void copyFrom1DJavaArray ( IndexIterator iter , Object javaArray ) { short [ ] ja = ( short [ ] ) javaArray ; for ( short aJa : ja ) iter . setShortNext ( aJa ) ; }


Input: copy to javaArray from storage using the iterator : used by copyToNDJavaArray ; [CODESPLIT] protected void copyTo1DJavaArray ( IndexIterator iter , Object javaArray ) { short [ ] ja = ( short [ ] ) javaArray ; for ( int i = 0 ; i < ja . length ; i ++ ) ja [ i ] = iter . getShortNext ( ) ; }


Input: package private : mostly for iterators [CODESPLIT] public double getDouble ( int index ) { short val = storage [ index ] ; return ( double ) ( isUnsigned ( ) ? DataType . unsignedShortToInt ( val ) : val ) ; }


Input: ************************************************************************ Sends a OPeNDAP DAP2 error to the client . [CODESPLIT] public void dap2ExceptionHandler ( DAP2Exception de , HttpServletResponse response ) { log . info ( "DODSServlet.dodsExceptionHandler (" + de . getErrorCode ( ) + ") " + de . getErrorMessage ( ) ) ; if ( Debug . isSet ( "showException" ) ) { de . print ( System . err ) ; de . printStackTrace ( System . err ) ; printDODSException ( de ) ; } try { BufferedOutputStream eOut = new BufferedOutputStream ( response . getOutputStream ( ) ) ; response . setHeader ( "Content-Description" , "dods-error" ) ; // This should probably be set to "plain" but this works, the // C++ slients don't barf as they would if I sent "plain" AND // the C++ don't expect compressed data if I do this... response . setHeader ( "Content-Encoding" , "" ) ; de . print ( eOut ) ; } catch ( IOException ioe ) { log . error ( "Cannot respond to client! IO Error: " + ioe . getMessage ( ) ) ; } }


Input: ************************************************************************ Sends an error to the client . [CODESPLIT] public void anyExceptionHandler ( Throwable e , ReqState rs ) { log . error ( "DODServlet ERROR (anyExceptionHandler): " + e ) ; printThrowable ( e ) ; try { if ( rs == null ) throw new DAP2Exception ( "anyExceptionHandler: no request state provided" ) ; log . error ( rs . toString ( ) ) ; HttpServletResponse response = rs . getResponse ( ) ; log . error ( rs . toString ( ) ) ; if ( track ) { RequestDebug reqD = ( RequestDebug ) rs . getUserObject ( ) ; log . error ( "  request number: " + reqD . reqno + " thread: " + reqD . threadDesc ) ; } response . setHeader ( "Content-Description" , "dods-error" ) ; // This should probably be set to "plain" but this works, the // C++ slients don't barf as they would if I sent "plain" AND // the C++ don't expect compressed data if I do this... response . setHeader ( "Content-Encoding" , "" ) ; // Strip any double quotes out of the parser error message. // These get stuck in auto-magically by the javacc generated parser // code and they break our error parser (bummer!) String msg = e . getMessage ( ) ; if ( msg != null ) msg = msg . replace ( ' ' , ' ' ) ; DAP2Exception de2 = new DAP2Exception ( opendap . dap . DAP2Exception . UNDEFINED_ERROR , msg ) ; BufferedOutputStream eOut = new BufferedOutputStream ( response . getOutputStream ( ) ) ; de2 . print ( eOut ) ; } catch ( Exception ioe ) { log . error ( "Cannot respond to client! IO Error: " + ioe . getMessage ( ) ) ; } }


Input: ************************************************************************ Sends a OPeNDAP DAP2 error ( type UNKNOWN ERROR ) to the client and displays a message on the server console . [CODESPLIT] public void sendDODSError ( HttpServletRequest request , HttpServletResponse response , String clientMsg , String serverMsg ) throws IOException , ServletException { response . setContentType ( "text/plain" ) ; response . setHeader ( "XDODS-Server" , getServerVersion ( ) ) ; response . setHeader ( "Content-Description" , "dods-error" ) ; // Commented because of a bug in the OPeNDAP C++ stuff... //response.setHeader("Content-Encoding", "none"); ServletOutputStream Out = response . getOutputStream ( ) ; DAP2Exception de = new DAP2Exception ( opendap . dap . DAP2Exception . UNKNOWN_ERROR , clientMsg ) ; de . print ( Out ) ; response . setStatus ( HttpServletResponse . SC_OK ) ; log . error ( serverMsg ) ; }


Input: ************************************************************************ Default handler for the client s DAS request . Operates on the assumption that the DAS information is cached on a disk local to the server . If you don t like that then you better override it in your server : ) <p / > <p > Once the DAS has been parsed it is sent to the requesting client . [CODESPLIT] public void doGetDAS ( ReqState rs ) throws Exception { if ( Debug . isSet ( "showResponse" ) ) { log . debug ( "doGetDAS for dataset: " + rs . getDataSet ( ) ) ; } GuardedDataset ds = null ; try { ds = getDataset ( rs ) ; if ( ds == null ) return ; rs . getResponse ( ) . setContentType ( "text/plain" ) ; rs . getResponse ( ) . setHeader ( "XDODS-Server" , getServerVersion ( ) ) ; rs . getResponse ( ) . setHeader ( "Content-Description" , "dods-das" ) ; // Commented because of a bug in the OPeNDAP C++ stuff... //rs.getResponse().setHeader("Content-Encoding", "plain"); OutputStream Out = new BufferedOutputStream ( rs . getResponse ( ) . getOutputStream ( ) ) ; DAS myDAS = ds . getDAS ( ) ; myDAS . print ( Out ) ; rs . getResponse ( ) . setStatus ( HttpServletResponse . SC_OK ) ; if ( Debug . isSet ( "showResponse" ) ) { //log.debug("DAS=\n"); //myDAS.print(LogStream.out); } } catch ( DAP2Exception de ) { dap2ExceptionHandler ( de , rs . getResponse ( ) ) ; } catch ( ParseException pe ) { parseExceptionHandler ( pe , rs . getResponse ( ) ) ; } catch ( Throwable t ) { anyExceptionHandler ( t , rs ) ; } finally { // release lock if needed if ( ds != null ) ds . release ( ) ; } }


Input: ************************************************************************ Sends an html document to the client explaining that they have used a poorly formed URL and then the help page ... [CODESPLIT] public void badURL ( ReqState rs ) throws Exception { if ( Debug . isSet ( "showResponse" ) ) { log . debug ( "Sending Bad URL Page." ) ; } //log.info("DODSServlet.badURL " + rs.getRequest().getRequestURI()); rs . getResponse ( ) . setContentType ( "text/html" ) ; rs . getResponse ( ) . setHeader ( "XDODS-Server" , getServerVersion ( ) ) ; rs . getResponse ( ) . setHeader ( "Content-Description" , "dods-error" ) ; // Commented because of a bug in the OPeNDAP C++ stuff... //rs.getResponse().setHeader("Content-Encoding", "plain"); PrintWriter pw = new PrintWriter ( new OutputStreamWriter ( rs . getResponse ( ) . getOutputStream ( ) , Util . UTF8 ) ) ; printBadURLPage ( pw ) ; printHelpPage ( pw ) ; pw . flush ( ) ; rs . getResponse ( ) . setStatus ( HttpServletResponse . SC_OK ) ; }


Input: ************************************************************************ Default handler for OPeNDAP ascii data requests . Returns the request data as a comma delimited ascii file . Note that this means that the more complex OPeNDAP structures such as Grids get flattened ... <p / > <p / > Modified 2 / 8 / 07 jcaron to not make a DConnect2 call to itself [CODESPLIT] public void doGetASC ( ReqState rs ) throws Exception { if ( Debug . isSet ( "showResponse" ) ) { log . debug ( "doGetASC For: " + rs . getDataSet ( ) ) ; } GuardedDataset ds = null ; try { ds = getDataset ( rs ) ; if ( ds == null ) return ; rs . getResponse ( ) . setHeader ( "XDODS-Server" , getServerVersion ( ) ) ; rs . getResponse ( ) . setContentType ( "text/plain" ) ; rs . getResponse ( ) . setHeader ( "Content-Description" , "dods-ascii" ) ; if ( debug ) log . debug ( "Sending OPeNDAP ASCII Data For: " + rs + "  CE: '" + rs . getConstraintExpression ( ) + "'" ) ; ServerDDS dds = ds . getDDS ( ) ; //dds = url.getData(ce, null, new asciiFactory());  previous way // Instantiate the CEEvaluator and parse the constraint expression CEEvaluator ce = new CEEvaluator ( dds ) ; // i think this makes the dds constrained ce . parseConstraint ( rs ) ; PrintWriter pw = new PrintWriter ( new OutputStreamWriter ( rs . getResponse ( ) . getOutputStream ( ) , Util . UTF8 ) ) ; dds . printConstrained ( pw ) ; pw . println ( "---------------------------------------------" ) ; AsciiWriter writer = new AsciiWriter ( ) ; // could be static writer . toASCII ( pw , dds , ds ) ; // the way that getDAP2Data works // DataOutputStream sink = new DataOutputStream(bOut); // ce.send(myDDS.getName(), sink, ds); pw . flush ( ) ; rs . getResponse ( ) . setStatus ( HttpServletResponse . SC_OK ) ; } catch ( ParseException pe ) { parseExceptionHandler ( pe , rs . getResponse ( ) ) ; } catch ( DAP2Exception de ) { dap2ExceptionHandler ( de , rs . getResponse ( ) ) ; } catch ( Throwable t ) { anyExceptionHandler ( t , rs ) ; } finally { // release lock if needed if ( ds != null ) ds . release ( ) ; } }


Input:
************************************************************************ Default handler for debug requests ; [CODESPLIT] public void doDebug ( ReqState rs ) throws IOException { rs . getResponse ( ) . setHeader ( "XDODS-Server" , getServerVersion ( ) ) ; rs . getResponse ( ) . setContentType ( "text/html" ) ; rs . getResponse ( ) . setHeader ( "Content-Description" , "dods_debug" ) ; PrintWriter pw = new PrintWriter ( new OutputStreamWriter ( rs . getResponse ( ) . getOutputStream ( ) , Util . UTF8 ) ) ; pw . println ( "<title>Debugging</title>" ) ; pw . println ( "
" ) ; StringTokenizer tz = new StringTokenizer ( rs . getConstraintExpression ( ) , "=;" ) ; while ( tz . hasMoreTokens ( ) ) { String cmd = tz . nextToken ( ) ; pw . println ( "Cmd= " + cmd ) ; if ( cmd . equals ( "help" ) ) { pw . println ( " help;log;logEnd;logShow" ) ; pw . println ( " showFlags;showInitParameters;showRequest" ) ; pw . println ( " on|off=(flagName)" ) ; doDebugCmd ( cmd , tz , pw ) ; // for subclasses } else if ( cmd . equals ( "on" ) ) Debug . set ( tz . nextToken ( ) , true ) ; else if ( cmd . equals ( "off" ) ) Debug . set ( tz . nextToken ( ) , false ) ; else if ( cmd . equals ( "showFlags" ) ) { Iterator iter = Debug . keySet ( ) . iterator ( ) ; while ( iter . hasNext ( ) ) { String key = ( String ) iter . next ( ) ; pw . println ( "  " + key + " " + Debug . isSet ( key ) ) ; } } else if ( cmd . equals ( "showInitParameters" ) ) pw . println ( rs . toString ( ) ) ; else if ( cmd . equals ( "showRequest" ) ) probeRequest ( pw , rs ) ; else if ( ! doDebugCmd ( cmd , tz , pw ) ) { // for subclasses pw . println ( "  unrecognized command" ) ; } } pw . println ( "--------------------------------------" ) ; pw . println ( "Logging is on" ) ; Iterator iter = Debug . keySet ( ) . iterator ( ) ; while ( iter . hasNext ( ) ) { String key = ( String ) iter . next ( ) ; boolean val = Debug . isSet ( key ) ; if ( val ) pw . println ( "  " + key + " " + Debug . isSet ( key ) ) ; } pw . println ( "
" ) ; pw . flush ( ) ; rs . getResponse ( ) . setStatus ( HttpServletResponse . SC_OK ) ; }


Input:
************************************************************************ This is a bit of instrumentation that I kept around to let me look at the state of the incoming <code > HttpServletRequest< / code > from the client . This method calls the <code > get * < / code > methods of the request and prints the results to standard out . [CODESPLIT] public void probeRequest ( PrintWriter ps , ReqState rs ) { Enumeration e ; int i ; ps . println ( "####################### PROBE ##################################" ) ; ps . println ( "The HttpServletRequest object is actually a: " + rs . getRequest ( ) . getClass ( ) . getName ( ) ) ; ps . println ( "" ) ; ps . println ( "HttpServletRequest Interface:" ) ; ps . println ( "    getAuthType:           " + rs . getRequest ( ) . getAuthType ( ) ) ; ps . println ( "    getMethod:             " + rs . getRequest ( ) . getMethod ( ) ) ; ps . println ( "    getPathInfo:           " + rs . getRequest ( ) . getPathInfo ( ) ) ; ps . println ( "    getPathTranslated:     " + rs . getRequest ( ) . getPathTranslated ( ) ) ; ps . println ( "    getRequestURL:         " + rs . getRequest ( ) . getRequestURL ( ) ) ; ps . println ( "    getQueryString:        " + rs . getRequest ( ) . getQueryString ( ) ) ; ps . println ( "    getRemoteUser:         " + rs . getRequest ( ) . getRemoteUser ( ) ) ; ps . println ( "    getRequestedSessionId: " + rs . getRequest ( ) . getRequestedSessionId ( ) ) ; ps . println ( "    getRequestURI:         " + rs . getRequest ( ) . getRequestURI ( ) ) ; ps . println ( "    getServletPath:        " + rs . getRequest ( ) . getServletPath ( ) ) ; ps . println ( "    isRequestedSessionIdFromCookie: " + rs . getRequest ( ) . isRequestedSessionIdFromCookie ( ) ) ; ps . println ( "    isRequestedSessionIdValid:      " + rs . getRequest ( ) . isRequestedSessionIdValid ( ) ) ; ps . println ( "    isRequestedSessionIdFromURL:    " + rs . getRequest ( ) . isRequestedSessionIdFromURL ( ) ) ; ps . println ( "" ) ; i = 0 ; e = rs . getRequest ( ) . getHeaderNames ( ) ; ps . println ( "    Header Names:" ) ; while ( e . hasMoreElements ( ) ) { i ++ ; String s = ( String ) e . nextElement ( ) ; ps . print ( "        Header[" + i + "]: " + s ) ; ps . println ( ": " + rs . getRequest ( ) . getHeader ( s ) ) ; } ps . println ( "" ) ; ps . println ( "ServletRequest Interface:" ) ; ps . println ( "    getCharacterEncoding:  " + rs . getRequest ( ) . getCharacterEncoding ( ) ) ; ps . println ( "    getContentType:        " + rs . getRequest ( ) . getContentType ( ) ) ; ps . println ( "    getContentLength:      " + rs . getRequest ( ) . getContentLength ( ) ) ; ps . println ( "    getProtocol:           " + rs . getRequest ( ) . getProtocol ( ) ) ; ps . println ( "    getScheme:             " + rs . getRequest ( ) . getScheme ( ) ) ; ps . println ( "    getServerName:         " + rs . getRequest ( ) . getServerName ( ) ) ; ps . println ( "    getServerPort:         " + rs . getRequest ( ) . getServerPort ( ) ) ; ps . println ( "    getRemoteAddr:         " + rs . getRequest ( ) . getRemoteAddr ( ) ) ; ps . println ( "    getRemoteHost:         " + rs . getRequest ( ) . getRemoteHost ( ) ) ; //ps.println("    getRealPath:           "+rs.getRequest().getRealPath()); ps . println ( "............................." ) ; ps . println ( "" ) ; i = 0 ; e = rs . getRequest ( ) . getAttributeNames ( ) ; ps . println ( "    Attribute Names:" ) ; while ( e . hasMoreElements ( ) ) { i ++ ; String s = ( String ) e . nextElement ( ) ; ps . print ( "        Attribute[" + i + "]: " + s ) ; ps . println ( " Type: " + rs . getRequest ( ) . getAttribute ( s ) ) ; } ps . println ( "............................." ) ; ps . println ( "" ) ; i = 0 ; e = rs . getRequest ( ) . getParameterNames ( ) ; ps . println ( "    Parameter Names:" ) ; while ( e . hasMoreElements ( ) ) { i ++ ; String s = ( String ) e . nextElement ( ) ; ps . print ( "        Parameter[" + i + "]: " + s ) ; ps . println ( " Value: " + rs . getRequest ( ) . getParameter ( s ) ) ; } ps . println ( "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" ) ; ps . println ( " . . . . . . . . . Servlet Infomation API  . . . . . . . . . . . . . ." ) ; ps . println ( "" ) ; ps . println ( "Servlet Context:" ) ; ps . println ( "" ) ; /* i = 0;
    e = servletContext.getAttributeNames();
    ps.println("    Attribute Names:");
    while (e.hasMoreElements()) {
      i++;
      String s = (String) e.nextElement();
      ps.print("        Attribute[" + i + "]: " + s);
      ps.println(" Type: " + servletContext.getAttribute(s));
    }

    ps.println("    ServletContext.getRealPath(\".\"): " + servletContext.getRealPath("."));
    ps.println("    ServletContext.getMajorVersion(): " + servletContext.getMajorVersion());
//        ps.println("ServletContext.getMimeType():     " + sc.getMimeType());
    ps.println("    ServletContext.getMinorVersion(): " + servletContext.getMinorVersion());
//        ps.println("ServletContext.getRealPath(): " + sc.getRealPath()); */ ps . println ( "............................." ) ; ps . println ( "Servlet Config:" ) ; ps . println ( "" ) ; ServletConfig scnfg = getServletConfig ( ) ; i = 0 ; e = scnfg . getInitParameterNames ( ) ; ps . println ( "    InitParameters:" ) ; while ( e . hasMoreElements ( ) ) { String p = ( String ) e . nextElement ( ) ; ps . print ( "        InitParameter[" + i + "]: " + p ) ; ps . println ( " Value: " + scnfg . getInitParameter ( p ) ) ; i ++ ; } ps . println ( "" ) ; ps . println ( "######################## END PROBE ###############################" ) ; ps . println ( "" ) ; }


Input:
************************************************************************ Prints the OPeNDAP Server help page to the passed PrintWriter [CODESPLIT] private void printHelpPage ( PrintWriter pw ) { pw . println ( "
OPeNDAP Server Help
" ) ; pw . println ( "To access most of the features of this OPeNDAP server, append" ) ; pw . println ( "one of the following a eight suffixes to a URL: .das, .dds, .dods, .ddx, .blob, .info," ) ; pw . println ( ".ver or .help. Using these suffixes, you can ask this server for:" ) ; pw . println ( "
" ) ; pw . println ( "
 das

 Dataset Attribute Structure (DAS)
" ) ; pw . println ( "
 dds

 Dataset Descriptor Structure (DDS)
" ) ; pw . println ( "
 dods

 DataDDS object (A constrained DDS populated with data)
" ) ; pw . println ( "
 ddx

 XML version of the DDS/DAS
" ) ; pw . println ( "
 blob

 Serialized binary data content for requested data set, " + "with the constraint expression applied.
" ) ; pw . println ( "
 info

 info object (attributes, types and other information)
" ) ; pw . println ( "
 html

 html form for this dataset
" ) ; pw . println ( "
 ver

 return the version number of the server
" ) ; pw . println ( "
 help

 help information (this text)
" ) ; pw . println ( "
" ) ; pw . println ( "For example, to request the DAS object from the FNOC1 dataset at URI/GSO (a" ) ; pw . println ( "test dataset) you would appand `.das' to the URL:" ) ; pw . println ( "http://opendap.gso.url.edu/cgi-bin/nph-nc/data/fnoc1.nc.das." ) ; pw . println ( "
Note: Many OPeNDAP clients supply these extensions for you so you don't" ) ; pw . println ( "need to append them (for example when using interfaces supplied by us or" ) ; pw . println ( "software re-linked with a OPeNDAP client-library). Generally, you only need to" ) ; pw . println ( "add these if you are typing a URL directly into a WWW browser." ) ; pw . println ( "
Note: If you would like version information for this server but" ) ; pw . println ( "don't know a specific data file or data set name, use `/version' for the" ) ; pw . println ( "filename. For example: http://opendap.gso.url.edu/cgi-bin/nph-nc/version will" ) ; pw . println ( "return the version number for the netCDF server used in the first example. " ) ; pw . println ( "
Suggestion: If you're typing this URL into a WWW browser and" ) ; pw . println ( "would like information about the dataset, use the `.info' extension." ) ; pw . println ( "<p>If you'd like to see a data values, use the `.html' extension and submit a" ) ; pw . println ( "query using the customized form." ) ; }


Input: Write the variable s declaration in XML . This function is used to create the XML representation of the Data Descriptor Structure ( DDS ) . See <em > The OPeNDAP User Manual< / em > for information about this structure . [CODESPLIT] public void printXML ( PrintWriter pw , String pad , boolean constrained ) { // BEWARE! Since printXML()is (multiple) overloaded in BaseType // and all of the different signatures of printXML() in BaseType // lead to one signature, we must be careful to override that // SAME signature here. That way all calls to printDecl() for // this object lead to this implementation. // Also, since printXML()is (multiple) overloaded in BaseType // and all of the different signatures of printXML() in BaseType // lead to the signature we are overriding here, we MUST call // the printXML with the SAME signature THROUGH the super class // reference (assuming we want the super class functionality). If // we do otherwise, we will create an infinte call loop. OOPS! // System.out.println("SDString.printXML(pw,pad,"+constrained+")  Project: "+Project); if ( constrained && ! isProject ( ) ) return ; super . printXML ( pw , pad , constrained ) ; }


Input: Get the latitude values for the given type . [CODESPLIT] public static double [ ] getGaussianLatitudes ( String type , int start , int num ) throws IllegalArgumentException { double [ ] baseArray = null ; start -- ; // it's one based if ( type . equalsIgnoreCase ( GAUST62 ) ) { baseArray = gltst62 ; } else if ( type . equalsIgnoreCase ( GAUSR15 ) ) { baseArray = glts15 ; } else if ( type . equalsIgnoreCase ( GAUSR20 ) ) { baseArray = glts20 ; } else if ( type . equalsIgnoreCase ( GAUSR30 ) ) { baseArray = glts30 ; } else if ( type . equalsIgnoreCase ( GAUSR40 ) ) { baseArray = glats ; } else { throw new IllegalArgumentException ( "Unsupported type: " + type ) ; } if ( start + num > baseArray . length ) { throw new IllegalArgumentException ( "Maximum " + baseArray . length + " latitudes exceeded" ) ; } double [ ] retVals = new double [ num ] ; for ( int i = 0 ; i < num ; i ++ ) { retVals [ i ] = baseArray [ start + i ] ; } return retVals ; }


Input: Returns the long resulting from reversing 8 bytes at a specified offset in a byte array . [CODESPLIT] static public long swapLong ( byte [ ] b , int offset ) { // 8 bytes long accum = 0 ; long shiftedval ; for ( int shiftBy = 0 , i = offset ; shiftBy < 64 ; shiftBy += 8 , i ++ ) { shiftedval = ( ( long ) ( b [ i ] & 0xff ) ) << shiftBy ; accum |= shiftedval ; } return accum ; }


Input: Returns the float resulting from reversing 4 bytes at a specified offset in a byte array . [CODESPLIT] static public float swapFloat ( byte [ ] b , int offset ) { int accum = 0 ; for ( int shiftBy = 0 , i = offset ; shiftBy < 32 ; shiftBy += 8 , i ++ ) accum |= ( [ i ] & 0xff ) << shiftBy ; return Float . intBitsToFloat ( accum ) ; }


Input: Returns the char resulting from swapping 2 bytes at a specified offset in a byte array . [CODESPLIT] static public char swapChar ( byte [ ] b , int offset ) { // 2 bytes int low = b [ offset ] & 0xff ; int high = b [ offset + 1 ] & 0xff ; return ( char ) ( high << 8 | low ) ; }


Input:
The attribute coordinates is an alias for _CoordinateAxes . [CODESPLIT] protected void findCoordinateAxes ( NetcdfDataset ds ) { // coordinates is an alias for _CoordinateAxes
 for ( VarProcess vp : varList ) { if ( vp . coordAxes == null ) { // dont override if already set
 String coordsString = ds . findAttValueIgnoreCase ( vp . v , CF . COORDINATES , null ) ; if ( coordsString != null ) { vp . coordinates = coordsString ; } } } super . findCoordinateAxes ( ds ) ; }


Input: Add a Parameter to a CoordinateTransform . The variable attribute points to a another variable that has the data in it . Make sure that atrribute and variable exist . Id readData is true read the data and use it as the value of the parameter otherwise use the name as the value of the parameter . [CODESPLIT] protected boolean addParameter2 ( CoordinateTransform rs , String paramName , NetcdfFile ds , AttributeContainer v , String attName , boolean readData ) { String varName ; if ( null == ( varName = v . findAttValueIgnoreCase ( attName , null ) ) ) { parseInfo . format ( "CSMConvention No Attribute named %s%n" , attName ) ; return false ; } varName = varName . trim ( ) ; Variable dataVar ; if ( null == ( dataVar = ds . findVariable ( varName ) ) ) { parseInfo . format ( "CSMConvention No Variable named %s%n" , varName ) ; return false ; } if ( readData ) { Array data ; try { data = dataVar . read ( ) ; } catch ( IOException e ) { parseInfo . format ( "CSMConvention failed on read of %s err= %s%n" , varName , e . getMessage ( ) ) ; return false ; } double [ ] vals = ( double [ ] ) data . get1DJavaArray ( DataType . DOUBLE ) ; rs . addParameter ( new Parameter ( paramName , vals ) ) ; } else rs . addParameter ( new Parameter ( paramName , varName ) ) ; return true ; }


Input: Find the Variable with the specified ( short ) name in this group . [CODESPLIT] public Variable findVariable ( String varShortName ) { if ( varShortName == null ) return null ; for ( Variable v : variables ) { if ( varShortName . equals ( v . getShortName ( ) ) ) return v ; } return null ; }


Input: Find the Variable with the specified ( short ) name in this group or a parent group . [CODESPLIT] public Variable findVariableOrInParent ( String varShortName ) { if ( varShortName == null ) return null ; Variable v = findVariable ( varShortName ) ; Group parent = getParentGroup ( ) ; if ( ( v == null ) && ( parent != null ) ) v = parent . findVariableOrInParent ( varShortName ) ; return v ; }


Input: Retrieve the Group with the specified ( short ) name . [CODESPLIT] public Group findGroup ( String groupShortName ) { if ( groupShortName == null ) return null ; // groupShortName = NetcdfFile.makeNameUnescaped(groupShortName); for ( Group group : groups ) { if ( groupShortName . equals ( group . getShortName ( ) ) ) return group ; } return null ; }


Input: Retrieve a Dimension using its ( short ) name . If it doesnt exist in this group recursively look in parent groups . [CODESPLIT] public Dimension findDimension ( String name ) { if ( name == null ) return null ; // name = NetcdfFile.makeNameUnescaped(name); Dimension d = findDimensionLocal ( name ) ; if ( d != null ) return d ; Group parent = getParentGroup ( ) ; if ( parent != null ) return parent . findDimension ( name ) ; return null ; }


Input: Retrieve a Dimension using its ( short ) name in this group only [CODESPLIT] public Dimension findDimensionLocal ( String name ) { if ( name == null ) return null ; // name =  NetcdfFile.makeNameUnescaped(name); for ( Dimension d : dimensions ) { if ( name . equals ( d . getShortName ( ) ) ) return d ; } return null ; }


Input: AttributeHelper [CODESPLIT] public java . util . List < Attribute > getAttributes ( ) { return attributes . filter ( attributes , Attribute . SPECIALS ) . getAttributes ( ) ; }


Input: Find an Enumeration Typedef using its ( short ) name . If it doesnt exist in this group recursively look in parent groups . [CODESPLIT] public EnumTypedef findEnumeration ( String name ) { if ( name == null ) return null ; // name =  NetcdfFile.makeNameUnescaped(name); for ( EnumTypedef d : enumTypedefs ) { if ( name . equals ( d . getShortName ( ) ) ) return d ; } Group parent = getParentGroup ( ) ; if ( parent != null ) return parent . findEnumeration ( name ) ; return null ; }


Input: Get the common parent of this and the other group . Cant fail since the root group is always a parent of any 2 groups . [CODESPLIT] public Group commonParent ( Group other ) { if ( isParent ( other ) ) return this ; if ( other . isParent ( this ) ) return other ; while ( ! other . isParent ( this ) ) other = other . getParentGroup ( ) ; return other ; }


Input: Is this a parent of the other Group? [CODESPLIT] public boolean isParent ( Group other ) { while ( ( other != this ) && ( other . getParentGroup ( ) != null ) ) other = other . getParentGroup ( ) ; return ( other == this ) ; }


Input: Get String with name and attributes . Used in short descriptions like tooltips . [CODESPLIT] public String getNameAndAttributes ( ) { StringBuilder sbuff = new StringBuilder ( ) ; sbuff . append ( "Group " ) ; sbuff . append ( getShortName ( ) ) ; sbuff . append ( "\n" ) ; for ( Attribute att : attributes . getAttributes ( ) ) { sbuff . append ( "  " ) . append ( getShortName ( ) ) . append ( ":" ) ; sbuff . append ( att . toString ( ) ) ; sbuff . append ( ";" ) ; sbuff . append ( "\n" ) ; } return sbuff . toString ( ) ; }


Input: Set the Group s parent Group [CODESPLIT] public void setParentGroup ( Group parent ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; super . setParentGroup ( parent == null ? ncfile . getRootGroup ( ) : parent ) ; }


Input: Adds the specified shared dimension to this group . [CODESPLIT] public void addDimension ( Dimension dim ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; if ( ! dim . isShared ( ) ) { throw new IllegalArgumentException ( "Dimensions added to a group must be shared." ) ; } if ( findDimensionLocal ( dim . getShortName ( ) ) != null ) throw new IllegalArgumentException ( "Dimension name (" + dim . getShortName ( ) + ") must be unique within Group " + getShortName ( ) ) ; dimensions . add ( dim ) ; dim . setGroup ( this ) ; }


Input: Adds the specified shared dimension to this group but only if another dimension with the same name doesn t already exist . [CODESPLIT] public boolean addDimensionIfNotExists ( Dimension dim ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; if ( ! dim . isShared ( ) ) { throw new IllegalArgumentException ( "Dimensions added to a group must be shared." ) ; } if ( findDimensionLocal ( dim . getShortName ( ) ) != null ) return false ; dimensions . add ( dim ) ; dim . setGroup ( this ) ; return true ; }


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


Input: Add an Enumeration [CODESPLIT] public void addEnumeration ( EnumTypedef e ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; if ( e == null ) return ; e . setParentGroup ( this ) ; enumTypedefs . add ( e ) ; }


Input: Add a Variable [CODESPLIT] public void addVariable ( Variable v ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; if ( v == null ) return ; if ( findVariable ( v . getShortName ( ) ) != null ) { //Variable other = findVariable(v.getShortName()); // debug throw new IllegalArgumentException ( "Variable name (" + v . getShortName ( ) + ") must be unique within Group " + getShortName ( ) ) ; } variables . add ( v ) ; v . setParentGroup ( this ) ; // variable can only be in one group }


Input: Remove an Dimension : uses the dimension hashCode to find it . [CODESPLIT] public boolean remove ( Dimension d ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; return d != null && dimensions . remove ( d ) ; }


Input: Remove an Attribute : uses the Group hashCode to find it . [CODESPLIT] public boolean remove ( Group g ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; return g != null && groups . remove ( g ) ; }


Input: Remove a Variable : uses the variable hashCode to find it . [CODESPLIT] public boolean remove ( Variable v ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; return v != null && variables . remove ( v ) ; }


Input: remove a Dimension using its name in this group only [CODESPLIT] public boolean removeDimension ( String dimName ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; for ( int i = 0 ; i < dimensions . size ( ) ; i ++ ) { Dimension d = dimensions . get ( i ) ; if ( dimName . equals ( d . getShortName ( ) ) ) { dimensions . remove ( d ) ; return true ; } } return false ; }


Input: remove a Variable using its ( short ) name in this group only [CODESPLIT] public boolean removeVariable ( String shortName ) { if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; for ( int i = 0 ; i < variables . size ( ) ; i ++ ) { Variable v = variables . get ( i ) ; if ( shortName . equals ( v . getShortName ( ) ) ) { variables . remove ( v ) ; return true ; } } return false ; }


Input: Make this immutable . [CODESPLIT] public Group setImmutable ( ) { super . setImmutable ( ) ; variables = Collections . unmodifiableList ( variables ) ; dimensions = Collections . unmodifiableList ( dimensions ) ; groups = Collections . unmodifiableList ( groups ) ; attributes . setImmutable ( ) ; return this ; }


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


Input: Creates a DAS object from the collection of <code > BaseType< / code > variables and their associated <code > Attributes< / code > . This DAS is correctly formed ( vis - a - vis the DAP specification ) for this DDS . [CODESPLIT] public DAS getDAS ( ) throws DASException { DAS myDAS = new DAS ( ) ; try { // Since the DDS can contain Attributes, in addtion to Attribute containers (AttributeTables) // at the top (dataset) level and the DAS cannot, it is required that these Attributes be // bundled into a container at the top level of the DAS. // In the code that follows this container is called "looseEnds" // Make the container. AttributeTable looseEnds = new AttributeTable ( getLooseEndsTableName ( ) ) ; // Carfully populate it from the one at our top-level. Since we are using the // API and also copying containers here in order to build a new version, // we must use a clone of this (the DDS's) AttributeTable. AttributeTable atTbl = ( AttributeTable ) getAttributeTable ( ) . clone ( ) ; int countLooseAttributes = 0 ; // Work on each Attribute in the container. Enumeration e = atTbl . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String aName = ( String ) e . nextElement ( ) ; Attribute a = atTbl . getAttribute ( aName ) ; String clearname = a . getClearName ( ) ; if ( a . isAlias ( ) ) { // copy an alias. String attribute = ( ( Alias ) a ) . getAliasedToAttributeFieldAsClearString ( ) ; looseEnds . addAlias ( clearname , convertDDSAliasFieldsToDASAliasFields ( attribute ) ) ; countLooseAttributes ++ ; } else if ( a . isContainer ( ) ) { // A reference copy. This is why we are working with a clone. myDAS . addAttributeTable ( clearname , a . getContainer ( ) ) ; } else { // copy an Attribute and it's values... int type = a . getType ( ) ; Enumeration vals = a . getValues ( ) ; while ( vals . hasMoreElements ( ) ) { String value = ( String ) vals . nextElement ( ) ; looseEnds . appendAttribute ( clearname , type , value , true ) ; } countLooseAttributes ++ ; } } if ( _Debug ) { DAPNode . log . debug ( "Found " + countLooseAttributes + " top level Attributes." ) ; } //if (_Debug) myDAS.print(LogStream.dbg); // Only add this AttributeTable if actually contains Attributes! if ( countLooseAttributes > 0 ) { if ( _Debug ) DAPNode . log . debug ( "Creating looseEnds table: " + looseEnds . getEncodedName ( ) ) ; myDAS . addAttributeTable ( looseEnds . getEncodedName ( ) , looseEnds ) ; } // Walk through the variables at the top level. e = getVariables ( ) ; while ( e . hasMoreElements ( ) ) { BaseType bt = ( BaseType ) e . nextElement ( ) ; // Build the correct AttributeTable for it at the Toplevel of the DAS buildDASAttributeTable ( bt , myDAS ) ; } //if (_Debug) myDAS.print(LogStream.dbg); // Make sure that the Aliases resolve correctly. Since we are moving from a // DDS/DDX space to a DFAS space the Aliases may not be resolvable. In that // case an exception will get thrown... myDAS . resolveAliases ( ) ; } catch ( Exception e ) { e . printStackTrace ( ) ; throw new DASException ( opendap . dap . DAP2Exception . UNKNOWN_ERROR , "Could not create a DAS from this DDX object.\n" + "Because of the structural differences between the DDX and the DAS it is " + "possible for the DDX to contain sets of Attributes that cannot be represented " + "in a DAS object.\n" + "The specific problem was an execption of type " + e . getClass ( ) . getName ( ) + " with an " + "error message of: \n" + e . getMessage ( ) ) ; } return ( myDAS ) ; }


Input: This method just makes sure that the attribute field in each Aliases resolves correctly if there ends up being a looseEnds Attribute Table at the top level . [CODESPLIT] private String convertDDSAliasFieldsToDASAliasFields ( String attribute ) throws MalformedAliasException { String prefix = "" ; Vector aNames = tokenizeAliasField ( attribute ) ; // We know that the first token should be a dot, we look at the // second token to see if it references a variable in the DDS. String topName = ( String ) aNames . get ( 1 ) ; boolean foundIt = false ; Enumeration e = getVariables ( ) ; while ( e . hasMoreElements ( ) ) { BaseType bt = ( BaseType ) e . nextElement ( ) ; String normName = normalize ( bt . getEncodedName ( ) ) ; if ( topName . equals ( normName ) ) foundIt = true ; } if ( ! foundIt ) { // The Attribute referenced is at the top level of the DDS itself. // The Attributes at the top level of the DDS get repackaged into // a special AttributeTable, this makes the Aliases that point to // any of these Attribute resolve correctly. prefix = "." + getLooseEndsTableName ( ) ; } return ( prefix + attribute ) ; }


Input: Make A helper function for <code > getLooseEndsTableName< / code > insures that there are no naming conflicts when creating a looseEnds <code > AttributeTable< / code > [CODESPLIT] private String checkLooseEndsTableNameConflict ( String clearname , int attempt ) { Enumeration e = getVariables ( ) ; while ( e . hasMoreElements ( ) ) { BaseType bt = ( BaseType ) e . nextElement ( ) ; String btName = bt . getEncodedName ( ) ; //LogStream.out.println("bt: '"+btName+"'  dataset: '"+name+"'"); if ( btName . equals ( clearname ) ) { clearname = repairLooseEndsTableConflict ( clearname , attempt ++ ) ; clearname = checkLooseEndsTableNameConflict ( clearname , attempt ) ; } } AttributeTable at = getAttributeTable ( ) ; e = at . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String aName = ( String ) e . nextElement ( ) ; if ( aName . equals ( clearname ) ) { clearname = repairLooseEndsTableConflict ( clearname , attempt ++ ) ; clearname = checkLooseEndsTableNameConflict ( clearname , attempt ) ; } } return ( clearname ) ; }


Input: A helper function for <code > checkLooseEndsTableNameConflict< / code > insures that there are no naming conflicts when creating a looseEnds <code > AttributeTable< / code > [CODESPLIT] private String repairLooseEndsTableConflict ( String badName , int attempt ) { DAPNode . log . debug ( "Repairing toplevel attribute table name conflict. Attempt: " + attempt ) ; String name = "" ; switch ( attempt ) { case 0 : name = badName + "_DatasetAttributes_0" ; break ; default : int last_ = badName . lastIndexOf ( "_" ) ; name = badName . substring ( 0 , last_ ) + "_" + attempt ; break ; } return ( name ) ; }


Input: Builds AttributeTables ( from BaseType variables ) for us in a DAS created by getDAS () [CODESPLIT] private void buildDASAttributeTable ( BaseType bt , AttributeTable atbl ) throws DASException { // Get this BaseType's AttributeTable. Since we are using the AttributeTable // interface to build the DAS (which will have a different structure than the // table we are getting anyway), we don't need a copy, only the reference. AttributeTable tBTAT = bt . getAttributeTable ( ) ; // if the table is empty, then do nothing if ( tBTAT == null || tBTAT . size ( ) == 0 ) return ; // Start a new (child) AttributeTable (using the name of the one we are // copying) in the (parent) AttributeTable we are working on. AttributeTable newAT = atbl . appendContainer ( tBTAT . getEncodedName ( ) ) ; if ( _Debug ) { DAPNode . log . debug ( "newAT.getName(): " + newAT . getEncodedName ( ) ) ; } // Get each Attribute in the AttributeTable that we are copying, // and then put it's values into our new AttributeTable; Enumeration e = tBTAT . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String attrName = ( String ) e . nextElement ( ) ; Attribute attr = tBTAT . getAttribute ( attrName ) ; populateAttributeTable ( newAT , attr ) ; } // If this BaseType is a "container" type (aka complex type, aka DConstructor) // Then we have to search it's children for Attributes and then  them // and put them in our new Attribute Table. if ( bt instanceof DConstructor ) { Enumeration v = ( ( DConstructor ) bt ) . getVariables ( ) ; while ( v . hasMoreElements ( ) ) { BaseType thisBT = ( BaseType ) v . nextElement ( ) ; buildDASAttributeTable ( thisBT , newAT ) ; } } }


Input: Builds AttributeTables ( from BaseType variables ) for us in a DAS created by getDAS () [CODESPLIT] private void populateAttributeTable ( AttributeTable atTable , Attribute attr ) throws DASException { // Always check for Aliases first! They return the values for their targets // when asked if they are containers! if ( attr . isAlias ( ) ) { String alias = attr . getEncodedName ( ) ; String attribute = ( ( Alias ) attr ) . getAliasedToAttributeFieldAsClearString ( ) ; if ( _Debug ) DAPNode . log . debug ( "Adding Alias name: " + alias ) ; atTable . addAlias ( alias , convertDDSAliasFieldsToDASAliasFields ( attribute ) ) ; } else if ( attr . isContainer ( ) ) { // If this Attribute is a container of other Attributes (an AttributeTable) // then we need to recurse to get it's children. // Get this Attribute's container (AttributeTable). // Since we are using the AttributeTable // interface to build the DAS (which will have a different structure than the // table we are getting anyway), we don't need a copy, only the reference. AttributeTable thisTable = attr . getContainer ( ) ; // Start a new (child) AttributeTable (using the name of the one we are // copying) in the (parent) AttributeTable we are working on. if ( _Debug ) DAPNode . log . debug ( "Appending AttributeTable name: " + thisTable . getEncodedName ( ) ) ; AttributeTable newTable = atTable . appendContainer ( thisTable . getEncodedName ( ) ) ; // Get each Attribute in the AttributeTable that we are copying, // and then put it's values into our new AttributeTable; Enumeration e = thisTable . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String attrName = ( String ) e . nextElement ( ) ; Attribute thisAttr = thisTable . getAttribute ( attrName ) ; populateAttributeTable ( newTable , thisAttr ) ; } } else { // Since the Attribute is a "leaf" and not a container we need to // push it's contents into the AttributeTable that we are building. int type = attr . getType ( ) ; String name = attr . getEncodedName ( ) ; Enumeration v = attr . getValues ( ) ; while ( v . hasMoreElements ( ) ) { String value = ( String ) v . nextElement ( ) ; if ( _Debug ) DAPNode . log . debug ( "AtributeTable: " + atTable . getEncodedName ( ) + " Appending Attribute name: " + name + "  type: " + type + " value: " + value ) ; atTable . appendAttribute ( name , type , value ) ; } } }


Input: Print a DAS constructed from this DDS and it s BaseType variables . [CODESPLIT] public void printDAS ( PrintWriter pw ) { DAS myDAS = null ; try { myDAS = this . getDAS ( ) ; myDAS . print ( pw ) ; } catch ( DASException dasE ) { pw . println ( "\n\nCould not get a DAS object to print!\n" + "DDS.getDAS() threw an Exception. Message: \n" + dasE . getMessage ( ) ) ; } }


Input: Removes a variable from the <code > DDS< / code > . Does nothing if the variable can t be found . If there are multiple variables with the same name only the first will be removed . To detect this call the <code > checkSemantics< / code > method to verify that each variable has a unique name . [CODESPLIT] public void delVariable ( String name ) { try { BaseType bt = getVariable ( name ) ; vars . removeElement ( bt ) ; } catch ( NoSuchVariableException e ) { } }


Input: Is the variable <code > var< / code > a vector of DConstructors? Return true if it is false otherwise . This mess will recurse into a DVector s template BaseType ( which is a BaseTypePrimivitiveVector ) and look to see if that is either a DConstructor or <em > contains< / em > a DConstructor . So the <code > List Strucutre { ... } g [ 10 ] ; < / code > should be handled correctly . <p > <p / > Note that the List type modifier may only appear once . [CODESPLIT] private DConstructor isVectorOfDConstructor ( BaseType var ) { if ( ! ( var instanceof DVector ) ) return null ; if ( ! ( ( ( DVector ) var ) . getPrimitiveVector ( ) instanceof BaseTypePrimitiveVector ) ) return null ; // OK. We have a DVector whose template is a BaseTypePrimitiveVector. BaseTypePrimitiveVector btpv = ( BaseTypePrimitiveVector ) ( ( DVector ) var ) . getPrimitiveVector ( ) ; // After that nasty cast, is the template a DConstructor? if ( btpv . getTemplate ( ) instanceof DConstructor ) return ( DConstructor ) btpv . getTemplate ( ) ; else return isVectorOfDConstructor ( btpv . getTemplate ( ) ) ; }


Input: Returns a reference to the named variable . [CODESPLIT] public BaseType getVariable ( String name ) throws NoSuchVariableException { Stack s = new Stack ( ) ; s = search ( name , s ) ; return ( BaseType ) s . pop ( ) ; }


Input: Look for <code > name< / code > in the DDS . Start the search using the ctor variable ( or array / list of ctors ) found on the top of the Stack <code > compStack< / code > ( for component stack ) . When the named variable is found return the stack compStack modified so that it now contains each ctor - type variable that on the path to the named variable . If the variable is not found after exhausting all possibilities throw NoSuchVariable . <p > <p / > Note : This method takes the stack as a parameter so that it can be used by a parser that is working through a list of identifiers that represents the path to a variable <em > as well as< / em > a shorthand notation for the identifier that is the equivalent to the leaf node name alone . In the form case the caller helps build the stack by repeatedly calling <code > search< / code > in the latter case this method must build the stack itself . This method is over kill for the first case . [CODESPLIT] public Stack search ( String name , Stack compStack ) throws NoSuchVariableException { DDSSearch ddsSearch = new DDSSearch ( compStack ) ; if ( ddsSearch . deepSearch ( name ) ) return ddsSearch . components ; else throw new NoSuchVariableException ( "The variable `" + name + "' was not found in the dataset." ) ; }


Input: Reads a <b > DDX< / b > from the named <code > InputStream< / code > . This method calls a generated parser to interpret an XML representation of a <code > DDS< / code > ( aka a <b > DDX< / b > ) and instantiate that <code > DDS< / code > in memory . This method does the following : <ul > <li > Gets a new <code > DDSXMLParser< / code > using the <code > BaseTypeFactory< / code > held in this ( the <code > DDS< / code > ) class . < / li > <li > Uses the <code > DDSXMLParser< / code > to parse the DDX waiting in the <code > InputStream< / code > <i > is< / i > . < / li > <li > Calls <code > DDS . checkForAttributeNameConflict () < / code > < / li > <li > Calls <code > DDS . resolveAliases () < / code > < / li > < / ul > <p / > The last two items should be called EVERY time a <code > DDS< / code > is populated with variables ( by a parser or through the <code > DDS< / code > API ) and prior to releasing it for use to any calling program . [CODESPLIT] public void parseXML ( InputStream is , boolean validation ) throws DAP2Exception { DDSXMLParser dp = new DDSXMLParser ( opendapNameSpace ) ; dp . parse ( is , this , factory , validation ) ; // Check for name conflicts. IN the XML representation // of the DDS it is syntactically possible for a // variable container (Dconstructor) to possess an // Attribute that has the same name as one of the container // variable's member variables. That's a NO-NO!. // Check for it here and throw a nice fat exception if we find it. checkForAttributeNameConflict ( ) ; // Resolve the aliases. Aliases are basically analagous // to softlinks in a UNIX filesystem. Since an alias // can point any Attribute in the dataset, the vailidity // of the alias cannot be checked until all of the // members of the Dataset (both variables and their // Attributes) have been built. Once that is done // we can check to make sure that every alias points // at a vaild Attribute (and not another alias, non-existent // Attribute, etc) resolveAliases ( ) ; }


Input: Reads a <b > DDX< / b > from the named <code > Document< / code > . This method calls a generated parser to interpret an XML representation of a <code > DDS< / code > ( aka a <b > DDX< / b > ) and instantiate that <code > DDS< / code > in memory . This method does the following : <ul > <li > Gets a new <code > DDSXMLParser< / code > using the <code > BaseTypeFactory< / code > held in this ( the <code > DDS< / code > ) class . < / li > <li > Uses the <code > DDSXMLParser< / code > to parse the DDX waiting in the <code > InputStream< / code > <i > is< / i > . < / li > <li > Calls <code > DDS . checkForAttributeNameConflict () < / code > < / li > <li > Calls <code > DDS . resolveAliases () < / code > < / li > < / ul > <p / > <p / > The last two items should be called EVERY time a <code > DDS< / code > is populated with variables ( by a parser or through the <code > DDS< / code > API ) and prior to releasing it for use to any calling program . [CODESPLIT] public void parseXML ( Document ddxDoc , boolean validation ) throws DAP2Exception { DDSXMLParser dp = new DDSXMLParser ( opendapNameSpace ) ; dp . parse ( ddxDoc , this , factory , validation ) ; // Check for name conflicts. IN the XML representation // of the DDS it is syntactically possible for a // variable container (Dconstructor) to possess an // Attribute that has the same name as one of the container // variable's member variables. That's a NO-NO!. // Check for it here and throw a nice fat exception if we find it. checkForAttributeNameConflict ( ) ; // Resolve the aliases. Aliases are basically analagous // to softlinks in a UNIX filesystem. Since an alias // can point any Attribute in the dataset, the vailidity // of the alias cannot be checked until all of the // members of the Dataset (both variables and their // Attributes) have been built. Once that is done // we can check to make sure that every alias points // at a vaild Attribute (and not another alias, non-existent // Attribute, etc) resolveAliases ( ) ; }