signature:
public class TableAnalyzer { /** * no TableConfig was passed in - gotta wing it */
private void makeTablesDefault ( boolean structAdded ) throws IOException { } }

implementation:
// 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 . add ( 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 ) ; }


signature:
public class TableAnalyzer { /** * / * public void showTables ( java . util . Formatter sf ) {
 * sf . format ( " % nTables % n " ) ;
 * for ( NestedTable . Table t : tableSet )
 * sf . format ( " % s % n " , t ) ;
 * sf . format ( " % nJoins % n " ) ;
 * for ( Join j : joins )
 * sf . format ( " % s % n " , j ) ; */
public void showNestedTables ( java . util . Formatter sf ) { } }

implementation: for ( NestedTable nt : leaves ) { nt . show ( sf ) ; }


signature:
public class TableAnalyzer { /** * Create an XML document from this info
 * @ return netcdfDatasetInfo XML document */
private Document makeDocument ( ) { } }

implementation: 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 ;


signature: public class TableAnalyzer { static void doit ( String filename ) throws IOException { } }

implementation: 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-----------------" ) ;


signature:
public class McIDASGridServiceProvider { /** * Is this a valid file ?
 * @ param raf RandomAccessFile to check
 * @ return true if a valid McIDAS grid file
 * @ throws IOException problem reading file */
public boolean isValidFile ( RandomAccessFile raf ) throws IOException { } }

implementation: mcGridReader = new McIDASGridReader ( ) ; return mcGridReader . init ( raf , false ) ;


signature:
public class McIDASGridServiceProvider { /** * Open the service provider for reading .
 * @ param raf file to read from
 * @ param ncfile netCDF file we are writing to ( memory )
 * @ param cancelTask task for cancelling
 * @ throws IOException problem reading file */
public void open ( RandomAccessFile raf , NetcdfFile ncfile , CancelTask cancelTask ) throws IOException { } }

implementation:
// 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 ) ) ; }


signature:
public class McIDASGridServiceProvider { /** * Open the index and create the netCDF file from that
 * @ param index GridIndex to use
 * @ param cancelTask cancel task
 * @ throws IOException problem reading the file */
protected void open ( GridIndex index , CancelTask cancelTask ) throws IOException { } }

implementation:
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 ( ) ;


signature:
public class McIDASGridServiceProvider { /** * Sync and extend
 * @ return false */
public boolean sync ( ) { } }

implementation:
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 ; }


signature:
public class ArrayShort { /** * package private . use Array . factory ( ) */
static ArrayShort factory ( Index index , boolean isUnsigned ) { } }

implementation: return ArrayShort . factory ( index , isUnsigned , null ) ;


signature:
public class ArrayShort { /** * copy from javaArray to storage using the iterator : used by factory ( Object ) ; */
protected void copyFrom1DJavaArray ( IndexIterator iter , Object javaArray ) { } }

implementation: short [ ] ja = ( short [ ] ) javaArray ; for ( short aJa : ja ) iter . setShortNext ( aJa ) ;


signature:
public class ArrayShort { /** * copy to javaArray from storage using the iterator : used by copyToNDJavaArray ; */
protected void copyTo1DJavaArray ( IndexIterator iter , Object javaArray ) { } }

implementation: short [ ] ja = ( short [ ] ) javaArray ; for ( int i = 0 ; i < ja . length ; i ++ ) ja [ i ] = iter . getShortNext ( ) ;


signature:
public class ArrayShort { /** * package private : mostly for iterators */
public double getDouble ( int index ) { } }

implementation: short val = storage [ index ] ; return ( double ) ( isUnsigned ( ) ? DataType . unsignedShortToInt ( val ) : val ) ;


signature:
public class AbstractServlet { /** * Sends a OPeNDAP DAP2 error to the client .
 * @ param de The OPeNDAP DAP2 exception that caused the problem .
 * @ param response The < code > HttpServletResponse < / code > for the client . */
public void dap2ExceptionHandler ( DAP2Exception de , HttpServletResponse response ) { } }

implementation:
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 ( ) ) ; }


signature:
public class AbstractServlet { /** * Sends an error to the client .
 * @ param e The exception that caused the problem .
 * @ param rs The < code > ReqState < / code > for the client . */
public void anyExceptionHandler ( Throwable e , ReqState rs ) { } }

implementation:
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 ( ) ) ; }


signature:
public class AbstractServlet { /** * Sends a OPeNDAP DAP2 error ( type UNKNOWN ERROR ) to the client and displays a
 * message on the server console .
 * @ param request The client ' s < code > HttpServletRequest < / code > request object .
 * @ param response The server ' s < code > HttpServletResponse < / code > response object .
 * @ param clientMsg Error message < code > String < / code > to send to the client .
 * @ param serverMsg Error message < code > String < / code > to display on the server console . */
public void sendDODSError ( HttpServletRequest request , HttpServletResponse response , String clientMsg , String serverMsg ) throws IOException , ServletException { } }

implementation:
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 ) ;


signature:
public class AbstractServlet { /** * 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 > Once the DAS has been parsed it is sent to the requesting client .
 * @ param rs The ReqState of this client request . Contains all kinds of
 * important stuff .
 * @ see ReqState */
public void doGetDAS ( ReqState rs ) throws Exception { } }

implementation:
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 ( ) ; }


signature:
public class AbstractServlet { /** * Sends an html document to the client explaining that they have used a
 * poorly formed URL and then the help page . . .
 * @ param rs The client ' s < code > ReqState < / code > */
public void badURL ( ReqState rs ) throws Exception { } }

implementation:
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 ) ;


signature:
public class AbstractServlet { /** * 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 . . .
 * Modified 2/8/07 jcaron to not make a DConnect2 call to itself
 * @ param rs the decoded Request State */
public void doGetASC ( ReqState rs ) throws Exception { } }

implementation:
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 ( ) ; }


signature:
public class AbstractServlet { /** * Default handler for debug requests ;
 * @ param rs The client ' s < code > ReqState < / code > object . */
public void doDebug ( ReqState rs ) throws IOException { } }

implementation:
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 ) ;


signature:
public class AbstractServlet { /** * 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 .
 * @ param ps The < code > PrintStream < / code > to send output .
 * @ param rs The < code > ReqState < / code > object to probe . */
public void probeRequest ( PrintWriter ps , ReqState rs ) { } }

implementation:
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 ( ) ) {
 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 ( "" ) ;


signature:
public class AbstractServlet { /** * Prints the OPeNDAP Server help page to the passed PrintWriter
 * @ param pw PrintWriter stream to which to dump the help page . */
private void printHelpPage ( PrintWriter pw ) { } }

implementation:
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." ) ;


signature:
public class SDString { /** * 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 .
 * @ param constrained a boolean value indicating whether to print
 * the declartion dependent on the projection information . < b > This
 * is only used by Server side code . < / b >
 * @ see DDS */
public void printXML ( PrintWriter pw , String pad , boolean constrained ) { } }

implementation:
// 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 ) ;


signature:
public class GradsUtil { /** * Get the latitude values for the given type .
 * @ param type gaussian type
 * @ param start starting index ( 1 based )
 * @ param num number of values
 * @ return the values
 * @ throws IllegalArgumentException invalid or unsupported type */
public static double [ ] getGaussianLatitudes ( String type , int start , int num ) throws IllegalArgumentException { } }

implementation:
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 ;


signature:
public class Swap { /** * Returns the long resulting from reversing 8 bytes at a specified
 * offset in a byte array .
 * @ param b the byte array
 * @ param offset the offset of the first byte
 * @ return the long represented by the bytes
 * < code > b [ offset + 7 ] , b [ offset + 6 ] , . . . , b [ offset ] < / code > */
static public long swapLong ( byte [ ] b , int offset ) { } }

implementation:
// 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 ;


signature:
public class Swap { /** * Returns the float resulting from reversing 4 bytes at a specified
 * offset in a byte array .
 * @ param b the byte array
 * @ param offset the offset of the first byte
 * @ return the float represented by the bytes
 * < code > b [ offset + 3 ] , b [ offset + 2 ] , . . . , b [ offset ] < / code > */
static public float swapFloat ( byte [ ] b , int offset ) { } }

implementation: int accum = 0 ; for ( int shiftBy = 0 , i = offset ; shiftBy < 32 ; shiftBy += 8 , i ++ ) accum |= ( b [ i ] & 0xff ) << shiftBy ; return Float . intBitsToFloat ( accum ) ;


signature:
public class Swap { /** * Returns the char resulting from swapping 2 bytes at a specified
 * offset in a byte array .
 * @ param b the byte array
 * @ param offset the offset of the first byte
 * @ return the char represented by the bytes
 * < code > b [ offset + 1 ] , b [ offset ] < / code > */
static public char swapChar ( byte [ ] b , int offset ) { } }

implementation:
// 2 bytes
int low = b [ offset ] & 0xff ; int high = b [ offset + 1 ] & 0xff ; return ( char ) ( high << 8 | low ) ;


signature:
public class CSMConvention { /** * The attribute " coordinates " is an alias for _ CoordinateAxes . */
protected void findCoordinateAxes ( NetcdfDataset ds ) { } }

implementation:
// 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 ) ;


signature:
public class CSMConvention { /** * Add a Parameter to a CoordinateTransform . The variable attribute points to a another variable that has the data in it .
 * Make sure that atrribute and variable exist . Id readData is true , read the data and use it as the value of the
 * parameter , otherwise use the name as the value of the parameter .
 * @ param rs the CoordinateTransform
 * @ param paramName the parameter name
 * @ param ds dataset
 * @ param v variable
 * @ param attName variable attribute name
 * @ param readData if true , read data and use a s parameter value
 * @ return true if success , false is failed */
protected boolean addParameter2 ( CoordinateTransform rs , String paramName , NetcdfFile ds , AttributeContainer v , String attName , boolean readData ) { } }

implementation: 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 ;


signature:
public class Group { /** * Find the Variable with the specified ( short ) name in this group .
 * @ param varShortName short name of Variable within this group .
 * @ return the Variable , or null if not found */
public Variable findVariable ( String varShortName ) { } }

implementation: if ( varShortName == null ) return null ; for ( Variable v : variables ) { if ( varShortName . equals ( v . getShortName ( ) ) ) return v ; } return null ;


signature:
public class Group { /** * Find the Variable with the specified ( short ) name in this group or a parent group .
 * @ param varShortName short name of Variable .
 * @ return the Variable , or null if not found */
public Variable findVariableOrInParent ( String varShortName ) { } }

implementation: if ( varShortName == null ) return null ; Variable v = findVariable ( varShortName ) ; Group parent = getParentGroup ( ) ; if ( ( v == null ) && ( parent != null ) ) v = parent . findVariableOrInParent ( varShortName ) ; return v ;


signature:
public class Group { /** * Retrieve the Group with the specified ( short ) name .
 * @ param groupShortName short name of the nested group you are looking for .
 * @ return the Group , or null if not found */
public Group findGroup ( String groupShortName ) { } }

implementation:
if ( groupShortName == null ) return null ; // groupShortName = NetcdfFile . makeNameUnescaped ( groupShortName ) ;
for ( Group group : groups ) { if ( groupShortName . equals ( group . getShortName ( ) ) ) return group ; } return null ;


signature:
public class Group { /** * Retrieve a Dimension using its ( short ) name . If it doesnt exist in this group ,
 * recursively look in parent groups .
 * @ param name Dimension name .
 * @ return the Dimension , or null if not found */
public Dimension findDimension ( String name ) { } }

implementation:
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 ;


signature:
public class Group { /** * Retrieve a Dimension using its ( short ) name , in this group only
 * @ param name Dimension name .
 * @ return the Dimension , or null if not found */
public Dimension findDimensionLocal ( String name ) { } }

implementation:
if ( name == null ) return null ; // name = NetcdfFile . makeNameUnescaped ( name ) ;
for ( Dimension d : dimensions ) { if ( name . equals ( d . getShortName ( ) ) ) return d ; } return null ;


signature:
public class Group { /** * AttributeHelper */
public java . util . List < Attribute > getAttributes ( ) { } }

implementation: return attributes . filter ( attributes , Attribute . SPECIALS ) . getAttributes ( ) ;


signature:
public class Group { /** * Find an Enumeration Typedef using its ( short ) name . If it doesnt exist in this group ,
 * recursively look in parent groups .
 * @ param name Enumeration name .
 * @ return the Enumeration , or null if not found */
public EnumTypedef findEnumeration ( String name ) { } }

implementation:
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 ;


signature:
public class Group { /** * Get the common parent of this and the other group .
 * Cant fail , since the root group is always a parent of any 2 groups .
 * @ param other the other group
 * @ return common parent of this and the other group */
public Group commonParent ( Group other ) { } }

implementation: if ( isParent ( other ) ) return this ; if ( other . isParent ( this ) ) return other ; while ( ! other . isParent ( this ) ) other = other . getParentGroup ( ) ; return other ;


signature:
public class Group { /** * Is this a parent of the other Group ?
 * @ param other another Group
 * @ return true is it is equal or a parent */
public boolean isParent ( Group other ) { } }

implementation: while ( ( other != this ) && ( other . getParentGroup ( ) != null ) ) other = other . getParentGroup ( ) ; return ( other == this ) ;


signature:
public class Group { /** * Get String with name and attributes . Used in short descriptions like tooltips .
 * @ return name and attributes String . */
public String getNameAndAttributes ( ) { } }

implementation: 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 ( ) ;


signature:
public class Group { /** * Set the Group ' s parent Group
 * @ param parent parent group . */
public void setParentGroup ( Group parent ) { } }

implementation: if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; super . setParentGroup ( parent == null ? ncfile . getRootGroup ( ) : parent ) ;


signature:
public class Group { /** * Adds the specified shared dimension to this group .
 * @ param dim the dimension to add .
 * @ throws IllegalStateException if this dimension is { @ link # setImmutable ( ) immutable } .
 * @ throws IllegalArgumentException if { @ code dim } isn ' t shared or a dimension with { @ code dim } ' s name already
 * exists within the group . */
public void addDimension ( Dimension dim ) { } }

implementation: 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 ) ;


signature:
public class Group { /** * Adds the specified shared dimension to this group , but only if another dimension with the same name doesn ' t
 * already exist .
 * @ param dim the dimension to add .
 * @ return { @ code true } if { @ code dim } was successfully added to the group . Otherwise , { @ code false } will be returned ,
 * meaning that a dimension with { @ code dim } ' s name already exists within the group .
 * @ throws IllegalStateException if this dimension is { @ link # setImmutable ( ) immutable } .
 * @ throws IllegalArgumentException if { @ code dim } isn ' t shared . */
public boolean addDimensionIfNotExists ( Dimension dim ) { } }

implementation: 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 ;


signature:
public class Group { /** * Add a nested Group
 * @ param g add this Group . */
public void addGroup ( Group g ) { } }

implementation: 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


signature:
public class Group { /** * Add an Enumeration
 * @ param e add this Enumeration . */
public void addEnumeration ( EnumTypedef e ) { } }

implementation: if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; if ( e == null ) return ; e . setParentGroup ( this ) ; enumTypedefs . add ( e ) ;


signature:
public class Group { /** * Add a Variable
 * @ param v add this Variable . */
public void addVariable ( Variable v ) { } }

implementation:
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


signature:
public class Group { /** * Remove an Dimension : uses the dimension hashCode to find it .
 * @ param d remove this Dimension .
 * @ return true if was found and removed */
public boolean remove ( Dimension d ) { } }

implementation: if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; return d != null && dimensions . remove ( d ) ;


signature:
public class Group { /** * Remove an Attribute : uses the Group hashCode to find it .
 * @ param g remove this Group .
 * @ return true if was found and removed */
public boolean remove ( Group g ) { } }

implementation: if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; return g != null && groups . remove ( g ) ;


signature:
public class Group { /** * Remove a Variable : uses the variable hashCode to find it .
 * @ param v remove this Variable .
 * @ return true if was found and removed */
public boolean remove ( Variable v ) { } }

implementation: if ( immutable ) throw new IllegalStateException ( "Cant modify" ) ; return v != null && variables . remove ( v ) ;


signature:
public class Group { /** * remove a Dimension using its name , in this group only
 * @ param dimName Dimension name .
 * @ return true if dimension found and removed */
public boolean removeDimension ( String dimName ) { } }

implementation: 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 ;


signature:
public class Group { /** * remove a Variable using its ( short ) name , in this group only
 * @ param shortName Variable name .
 * @ return true if Variable found and removed */
public boolean removeVariable ( String shortName ) { } }

implementation: 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 ;


signature:
public class Group { /** * Make this immutable .
 * @ return this */
public Group setImmutable ( ) { } }

implementation: super . setImmutable ( ) ; variables = Collections . unmodifiableList ( variables ) ; dimensions = Collections . unmodifiableList ( dimensions ) ; groups = Collections . unmodifiableList ( groups ) ; attributes . setImmutable ( ) ; return this ;


signature:
public class Group { /** * Create groups to ensure path is defined
 * @ param ncf the containing netcdf file object
 * @ param path the path to the desired group
 * @ param ignorelast true = > ignore last element in the path
 * @ return the Group , or null if not found */
public Group makeRelativeGroup ( NetcdfFile ncf , String path , boolean ignorelast ) { } }

implementation:
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 ;


signature:
public class DDS { /** * 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 .
 * @ return A correctly formed < code > DAS < / code > object for this DDS .
 * @ throws DASException
 * @ see DAS
 * @ see BaseType */
public DAS getDAS ( ) throws DASException { } }

implementation:
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 ) ;


signature:
public class DDS { /** * This method just makes sure that the attribute field in each Aliases resolves correctly
 * if there ends up being a " looseEnds " Attribute Table at the top level .
 * @ param attribute
 * @ return
 * @ throws MalformedAliasException */
private String convertDDSAliasFieldsToDASAliasFields ( String attribute ) throws MalformedAliasException { } }

implementation:
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 ) ;


signature:
public class DDS { /** * Make A helper function for < code > getLooseEndsTableName < / code >
 * insures that there are no naming conflicts when creating a looseEnds
 * < code > AttributeTable < / code >
 * @ param clearname
 * @ param attempt
 * @ return
 * @ see # getLooseEndsTableName
 * @ see # getDAS */
private String checkLooseEndsTableNameConflict ( String clearname , int attempt ) { } }

implementation:
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 ) ;


signature:
public class DDS { /** * A helper function for < code > checkLooseEndsTableNameConflict < / code >
 * insures that there are no naming conflicts when creating a looseEnds
 * < code > AttributeTable < / code >
 * @ param badName
 * @ param attempt
 * @ return
 * @ see # checkLooseEndsTableNameConflict
 * @ see # getLooseEndsTableName
 * @ see # getDAS */
private String repairLooseEndsTableConflict ( String badName , int attempt ) { } }

implementation: 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 ) ;


signature:
public class DDS { /** * Builds AttributeTables ( from BaseType variables ) for us in
 * a DAS created by getDAS ( )
 * @ param bt
 * @ param atbl
 * @ throws DASException
 * @ see # getDAS ( ) */
private void buildDASAttributeTable ( BaseType bt , AttributeTable atbl ) throws DASException { } }

implementation:
// 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 ) ; } }


signature:
public class DDS { /** * Builds AttributeTables ( from BaseType variables ) for us in
 * a DAS created by getDAS ( )
 * @ param atTable
 * @ param attr
 * @ throws DASException
 * @ see # buildDASAttributeTable ( BaseType , AttributeTable )
 * @ see # getDAS ( ) */
private void populateAttributeTable ( AttributeTable atTable , Attribute attr ) throws DASException { } }

implementation:
// 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 ) ; } }


signature:
public class DDS { /** * Print a DAS constructed from this DDS and it ' s BaseType variables .
 * @ param pw The < code > PrintWriter < / code > to print to . */
public void printDAS ( PrintWriter pw ) { } }

implementation: 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 ( ) ) ; }


signature:
public class DDS { /** * 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 .
 * @ param name the name of the variable to remove .
 * @ see DDS # checkSemantics ( boolean ) */
public void delVariable ( String name ) { } }

implementation: try { BaseType bt = getVariable ( name ) ; vars . removeElement ( bt ) ; } catch ( NoSuchVariableException e ) { }


signature:
public class DDS { /** * 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 >
 * Note that the List type modifier may only appear once . */
private DConstructor isVectorOfDConstructor ( BaseType var ) { } }

implementation:
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 ( ) ) ;


signature:
public class DDS { /** * Returns a reference to the named variable .
 * @ param name the name of the variable to return .
 * @ return the variable named < code > name < / code > .
 * @ throws NoSuchVariableException if the variable isn ' t found . */
public BaseType getVariable ( String name ) throws NoSuchVariableException { } }

implementation: Stack s = new Stack ( ) ; s = search ( name , s ) ; return ( BaseType ) s . pop ( ) ;


signature:
public class DDS { /** * 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 >
 * 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 .
 * @ param name Search for the named variable .
 * @ param compStack The component stack . This holds the BaseType variables
 * that match the each component of a specific variable ' s name . This
 * method starts its search using the element at the top of the stack and
 * adds to the stack . The order of BaseType variables on the stack is the
 * reverse of the tree - traverse order . That is , the top most element on
 * the stack is the BaseType for the named variable , < em > under < / em > that
 * is the named variable ' s parent and so on .
 * @ return A stack of BaseType variables which hold the path from the top
 * of the DDS to the named variable .
 * @ throws NoSuchVariableException */
public Stack search ( String name , Stack compStack ) throws NoSuchVariableException { } }

implementation: 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." ) ;


signature:
public class DDS { /** * 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 >
 * 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 .
 * @ param is the InputStream containing the < code > DDS < / code > to parse .
 * @ param validation Is a boolean indicating whether or not the parser should
 * validate the XML document using the Schema ( typically referenced in the
 * document itself ) . In general server side applications should always vaidate ,
 * while clients shouldn ' t bother ( since they are ostensibly receiving the
 * document from a server that has already done so . )
 * @ throws DDSException thrown on an error constructing the
 * < code > DDS < / code > .
 * @ opendap . ddx . experimental
 * @ see opendap . dap . parsers . DDSXMLParser
 * @ see # checkForAttributeNameConflict
 * @ see # resolveAliases */
public void parseXML ( InputStream is , boolean validation ) throws DAP2Exception { } }

implementation:
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 ( ) ;


signature:
public class DDS { /** * 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 >
 * 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 .
 * @ param ddxDoc A JDOM Document containing the < code > DDS < / code > to parse .
 * @ param validation Is a boolean indicating whether or not the parser should
 * validate the XML document using the Schema ( typically referenced in the
 * document itself ) . In general server side applications should always vaidate ,
 * while clients shouldn ' t bother ( since they are ostensibly receiving the
 * document from a server that has already done so . )
 * @ throws DDSException thrown on an error constructing the
 * < code > DDS < / code > .
 * @ opendap . ddx . experimental
 * @ see opendap . dap . parsers . DDSXMLParser
 * @ see # checkForAttributeNameConflict
 * @ see # resolveAliases */
public void parseXML ( Document ddxDoc , boolean validation ) throws DAP2Exception { } }

implementation:
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 ( ) ;


signature:
public class DDS { /** * Check the semantics of the < code > DDS < / code > . If
 * < code > all < / code > is true , check not only the semantics of the
 * < code > DDS < / code > itself , but also recursively check all variables
 * in the dataset .
 * @ param all this flag indicates whether to check the semantics of the
 * member variables , too .
 * @ throws BadSemanticsException if semantics are bad */
public void checkSemantics ( boolean all ) throws BadSemanticsException { } }

implementation: if ( getEncodedName ( ) == null ) { DAPNode . log . error ( "A dataset must have a name" ) ; throw new BadSemanticsException ( "DDS.checkSemantics(): A dataset must have a name" ) ; } Util . uniqueNames ( vars , getEncodedName ( ) , "Dataset" ) ; if ( all ) { for ( Enumeration e = vars . elements ( ) ; e . hasMoreElements ( ) ; ) { BaseType bt = ( BaseType ) e . nextElement ( ) ; bt . checkSemantics ( true ) ; } }


signature:
public class DDS { /** * Print the < code > DDS < / code > on the given < code > PrintWriter < / code > .
 * @ param os the < code > PrintWriter < / code > to use for output . */
public void print ( PrintWriter os ) { } }

implementation: os . println ( "Dataset {" ) ; for ( Enumeration e = vars . elements ( ) ; e . hasMoreElements ( ) ; ) { BaseType bt = ( BaseType ) e . nextElement ( ) ; bt . printDecl ( os ) ; } os . print ( "} " ) ; if ( getEncodedName ( ) != null ) os . print ( getEncodedName ( ) ) ; os . println ( ";" ) ;


signature:
public class DDS { /** * Before the DDS can be used all of the Aliases in the various
 * AttributeTables must be resolved . This means that it is necessary to verify that
 * each Alias references an Attribute that exists , and is not another Alias . This
 * is accomplished by searching the DDS ' s variable ' s attribute holdings for Aliases
 * Everytime an Alias is located , a new search begins to find the Attribute that the
 * Alias is attempting to reference .
 * This method recursively searchs through the passed < code > BaseType < / code > parameter
 * bt for Alias members of AttributeTables , and when they are found attempts to
 * resolve them to a specific Attribute .
 * This method gets called at the top level at the parser ONLY after the entire
 * DDS has been parsed and built . It ' s intial invocation get passed the DDS ( which
 * is in fact a < code > BaseType < / code > )
 * This method manipulates the global variable < code > currentBT < / code > .
 * @ param bt The < code > BaseType < / code > in which to search for and resolve Alias members */
private void resolveAliases ( BaseType bt ) throws MalformedAliasException , UnresolvedAliasException , NoSuchAttributeException { } }

implementation:
// cache the current / parent BaseType ( a container )
BaseType cacheBT = currentBT ; try { // Make the one we are about to search the current one .
currentBT = bt ; // Make the current AttributeTable null to indicate that we are at the top
// AttributeTable of a new current BaseType .
currentAT = null ; if ( Debug . isSet ( "DDS.resolveAliases" ) ) DAPNode . log . debug ( "Searching for Aliases in the Attributes of Variable: " + bt . getEncodedName ( ) ) ; // Process the Attributes of this BaseType .
resolveAliases ( bt . getAttributeTable ( ) ) ; // Now if this current BaseType is a container type , then we better
// search and resolve Aliases in it ' s children .
if ( bt instanceof DConstructor ) { if ( Debug . isSet ( "DDS.resolveAliases" ) ) DAPNode . log . debug ( "Searching for Aliases in the children of Variable: " + bt . getEncodedName ( ) ) ; Enumeration bte = ( ( DConstructor ) bt ) . getVariables ( ) ; while ( bte . hasMoreElements ( ) ) { BaseType thisBT = ( BaseType ) bte . nextElement ( ) ; // Recursive call . . .
resolveAliases ( thisBT ) ; } } } finally { // Restore the previous current BaseType state .
currentBT = cacheBT ; }


signature:
public class DDS { /** * This method recursively searchs through the passed < code > AttributeTable < / code > parameter
 * at for Alias members . When an Alias is found the method attempts to
 * resolve it to a specific Attribute .
 * This method is invoked by < code > resolveAliases ( BaseType bt ) < / code > , and is
 * used to search for Aliases in AttributeTables found in a BaseTypes Attributes .
 * This method manipulates the global variable < code > currentBT < / code > .
 * @ param at The < code > AttributeTable < / code > in which to search for and resolve Alias members */
private void resolveAliases ( AttributeTable at ) throws MalformedAliasException , UnresolvedAliasException , NoSuchAttributeException { } }

implementation:
// Cache the current ( parent ) Attribute table . This value is
// null if this method is call from resolveAliases ( BasetType bt )
AttributeTable cacheAT = currentAT ; try { // Set the current AttributeTable to the one that we are searching .
currentAT = at ; // getall of the Attributes from the table .
Enumeration aNames = currentAT . getNames ( ) ; while ( aNames . hasMoreElements ( ) ) { String aName = ( String ) aNames . nextElement ( ) ; opendap . dap . Attribute thisA = currentAT . getAttribute ( aName ) ; if ( thisA . isAlias ( ) ) { // Is Alias ? Resolve it !
resolveAlias ( ( Alias ) thisA ) ; if ( Debug . isSet ( "DDS.resolveAliases" ) ) { DAPNode . log . debug ( "Resolved Alias: '" + thisA . getEncodedName ( ) + "'\n" ) ; } } else if ( thisA . isContainer ( ) ) { // Is AttributeTable ( container ) ? Search it !
resolveAliases ( thisA . getContainer ( ) ) ; } } } finally { // Restore the previous currentAT state .
currentAT = cacheAT ; }


signature:
public class DDS { /** * This method attempts to resolve the past Alias to a specific Attribute in the DDS .
 * It does this by :
 * < ul >
 * < li > 1 ) Tokenizing the Alias ' s attribute field ( see < code > Alias < / code > ) < / li >
 * < li > 2 ) Evaluating the tokenized field to locate the longest
 * possible variable name represented as a consecutive set of tokens < / li >
 * < li > 2 ) Evaluating the the remaining tokenized field to locate the Attribute
 * that this Alias is attempting to reference < / li >
 * < li > 4 ) Setting the Aliases internal references for it ' s Variable and it ' s Attribute .
 * < / ul >
 * If an Attribute matching the definition of the Alias cannot be located ,
 * an Exception is thrown
 * @ param alias The < code > Alias < / code > which needs to be resolved */
private void resolveAlias ( Alias alias ) throws MalformedAliasException , UnresolvedAliasException { } }

implementation:
// Get the crucial stuff out of the Alias
String name = alias . getEncodedName ( ) ; String attribute = alias . getAliasedToAttributeFieldAsClearString ( ) ; if ( Debug . isSet ( "DDS.resolveAliases" ) ) { DAPNode . log . debug ( "\n\nFound: Alias " + name + "  " + attribute ) ; } // The Attribute field MAY NOT be empty .
if ( attribute . equals ( "" ) ) { throw new MalformedAliasException ( "The attribute 'attribute' in the Alias " + "element (name: '" + name + "') must have a value other than an empty string." ) ; } if ( Debug . isSet ( "DDS.resolveAliases" ) ) { DAPNode . log . debug ( "Attribute: `" + attribute + "'" ) ; } // Tokenize the attribute field .
Vector aNames = tokenizeAliasField ( attribute ) ; if ( Debug . isSet ( "DDS.resolveAliases" ) ) { DAPNode . log . debug ( "Attribute name tokenized to " + aNames . size ( ) + " elements" ) ; Enumeration e = aNames . elements ( ) ; while ( e . hasMoreElements ( ) ) { String aname = ( String ) e . nextElement ( ) ; DAPNode . log . debug ( "name: " + aname ) ; } } // The variable reference is the first part of the attribute field .
// Let ' s go find it . . .
BaseType targetBT = null ; // Absolute paths for attributes names must start with the dot character .
boolean isAbsolutePath = aNames . get ( 0 ) . equals ( "." ) ; if ( ! isAbsolutePath ) { // Is it not an absolute path ?
throw new MalformedAliasException ( "In the Alias '" + name + "'" + " the value of the attribute 'attribute' does not begin with the character dot (.). " + "The value of the 'attribute' field must always be an absolute path name from the " + "top level of the variable reference, and thus must always begin with the dot (.) character." ) ; } if ( aNames . size ( ) == 1 ) { // Is it only a dot ?
throw new MalformedAliasException ( "In the Alias '" + name + "'" + " the value of the attribute 'attribute' contains only the character dot (.). " + "The value of the 'attribute' field must always reference an Attribute using an absolute path name from the " + "top level of the DAS, and must reference an attribute within the DAS. A simple dot is not allowed." ) ; } aNames . remove ( 0 ) ; // Remove the first token , which by now we know is a single dot .
targetBT = getDeepestMatchingVariable ( this , aNames ) ; if ( targetBT == null ) { // No matching BaseType ?
// Then assume the attribute field references a
// top ( Dataset ) level Attribute .
targetBT = this ; } // LogStream . out . println ( " Alias references variable : . " + targetBT . getLongName ( ) ) ;
// Now that we have found a target BaseType variable that matches the reference in
// the variable field of the Alias ( b . t . w . that ' s a good thing ) let ' s go
// see if we can find an Attribute within that targetBT that matches the attribute field
// in the Alias decleration .
Attribute targetAT = null ; if ( aNames . size ( ) == 0 ) { // If there are no remaining tokens in the attribute field then
// we are referencing the attribute container of the targetBT .
targetAT = targetBT . getAttribute ( ) ; } else { // Go try to find the Attribute in the targetBT .
targetAT = getAttribute ( targetBT . getAttributeTable ( ) , aNames ) ; } alias . setMyVariable ( targetBT ) ; alias . setMyAttribute ( targetAT ) ;


signature:
public class DDS { /** * This method executes a ( recursive ) search of the < code > DConstructor < / code >
 * parameter < b > dcBT < / b > for a < code > BaseType < / code > variable whose name resolves to
 * the vector of names contained in the < code > Vector < / code > parameter
 * < b > vNames < / b > . A variable is considered a match if each of it ' s node
 * names in the hierarchy of containers in the
 * one passed as parameter < b > dcBT < / b > matches ( equals ) the corresponding name
 * in the Vector < b > vNames < / b > .
 * @ param dcBT The < code > DConstructor < / code > to search
 * @ param vNames The < code > Vector < / code > of names to match to the nodes of < b > at < / b > */
private BaseType getDeepestMatchingVariable ( DConstructor dcBT , Vector vNames ) { } }

implementation:
// Get the first name from the Vector
String vName = ( String ) vNames . get ( 0 ) ; // Get all of the child variables from the Dconstructor
Enumeration bte = dcBT . getVariables ( ) ; while ( bte . hasMoreElements ( ) ) { // Get this variable
BaseType bt = ( BaseType ) bte . nextElement ( ) ; // Get and normalize it ' s name .
String normName = normalize ( bt . getClearName ( ) ) ; // Compare the names
if ( normName . equals ( vName ) ) { // They match !
// Remove the name from the vector .
vNames . remove ( 0 ) ; if ( vNames . size ( ) == 0 ) { // are there more names ?
// Nope ! We Found it !
return bt ; } if ( bt instanceof DConstructor ) { // If there are more names then this thing better be a container
// recursively search it for the remaining names . . .
BaseType nextBT = getDeepestMatchingVariable ( ( DConstructor ) bt , vNames ) ; if ( nextBT != null ) return ( nextBT ) ; return ( bt ) ; } return ( bt ) ; } } return ( null ) ;


signature:
public class DDS { /** * The < code > normalize < / code > method is used to normalize variable and
 * attribute name strings prior
 * to their comparison with the normalized tokens extracted from the
 * variable and name fields in an Alias declaration .
 * The rule for this normalization is as follows :
 * < ul >
 * < li > The & quot ; ( double quote ) and the \ ( backslash , aka escape )
 * characters MUST be escaped ( using the \ character ) in the < b > variable < / b >
 * and < b > attribute < / b > fields . < / li >
 * < / ul >
 * @ param field The string to be normalized .
 * @ return The " normalized " string . */
public static String normalize ( String field ) { } }

implementation:
boolean Debug = false ; StringBuffer sb = new StringBuffer ( field ) ; for ( int offset = 0 ; offset < sb . length ( ) ; offset ++ ) { char c = sb . charAt ( offset ) ; // for every quote and slach in the string , add a slash in front of it .
if ( c == slash || c == quote ) { sb . insert ( offset , slash ) ; offset ++ ; } } // Coverity [ DEADCODE ]
if ( Debug ) { DAPNode . log . debug ( "String: `" + field + "` normalized to: `" + sb + "`" ) ; } return ( sb . toString ( ) ) ;


signature:
public class DDS { /** * The < code > tokenizeAliasFiled ( ) < / code > method is used to tokenize
 * the < b > variable < / b > and the < b > attribute < / b > fields in the alias
 * declaration . It is required that these fields be < b > normalized < / b >
 * in the XML instance document . The rules for this normalization
 * are as follows :
 * < ul >
 * < li > The & quot ; ( double quote ) and the \ ( backslash , aka escape )
 * characters MUST be escaped ( using the \ character ) in the < b > variable < / b >
 * and < b > attribute < / b > fields . < / li >
 * < li > The < b > variable < / b > and < b > attribute < / b > fields must be enclosed
 * in double quotes if their values contain the dot ( . ) character . < / li >
 * < li > Fully qualified < b > variable < / b > and < b > attribute < / b > names always
 * begin with the dot ( . ) character . < / li >
 * < / ul >
 * @ param field The string to be tokenized .
 * @ return The tokenized string .
 * @ throws MalformedAliasException */
public static Vector tokenizeAliasField ( String field ) throws MalformedAliasException { } }

implementation:
boolean Debug = false ; // find the index of the last element in the field .
int lastIndex = field . length ( ) - 1 ; // make a place to put the tokens .
Vector tokens = new Vector ( ) ; // Coverity [ DEADCODE ]
if ( Debug ) { DAPNode . log . debug ( "lastIndexOf(dot): " + field . lastIndexOf ( dot ) + "   lastIndex: " + lastIndex ) ; } // Does this thing start with a quote ?
if ( field . charAt ( 0 ) == quote ) { // find the closing quote .
// Because this token starts with a quote , it must be normalized
// ( see method description ) . The closing quote must exist ,
// and it cannont be escaped .
// The first character in the token is the one following the
// leadin quote .
int start = 1 ; // prepare to search for a closing quote .
int end = - 1 ; boolean done = false ; boolean escaped = false ; // search for the quote
for ( int i = 1 ; i <= lastIndex || ! done ; i ++ ) { char c = field . charAt ( i ) ; // LogStream . out . println ( " Checking for clear quote on char : " + c + " escaped = " + escaped + " done = " + done ) ;
// Was this character escaped ( with a slash ) ?
if ( escaped ) { // then ignore it and unset the escaped flag
// since the escape has been consumed .
escaped = false ; } else { // otherwise , is it an escape ( slash ) character
if ( c == slash ) { // the set the escaoed flag to true .
escaped = true ; } else if ( c == quote ) { // if it ' s not an escape ( slash ) then is it a quote ?
// LogStream . out . println ( " Found quote ! " ) ;
end = i ; done = true ; } } } // LogStream . out . println ( " start = " + start + " end = " + end + " lastIndex = " + lastIndex ) ;
// if the end is less than 0 then it didn ' t get set
// during the search for the quote , and thus the closing quote wasn ' t
// found . Throw an exception !
if ( end < 0 ) throw new MalformedAliasException ( "Alias fields that begin with the quote (\") sign " + "must have a closing quote." ) ; // If there is more stuff , and that stuff is not seperated from the
// closing quote by a dot character , then it ' s bad syntax .
if ( lastIndex > end && field . charAt ( end + 1 ) != dot ) throw new MalformedAliasException ( "Alias fields must be seperated by the dot (.) character." ) ; // The last caharcter in the field may not be an ( unquoted ) dot .
if ( field . charAt ( lastIndex ) == dot ) throw new MalformedAliasException ( "Alias fields may not end with the dot (.) character." ) ; // Looks like we found a complete token .
// Get it .
String firstToken = field . substring ( start , end ) ; // Add it to the tokens Vector .
tokens . add ( firstToken ) ; // if there is more stuff , then tokenize it .
if ( end < lastIndex ) { // get the rest of the stuff
String theRest = field . substring ( end + 2 ) ; // tokenize it and add each of the returned tokens to
// this tokens Vector .
// Recursive call .
Enumeration tkns = tokenizeAliasField ( theRest ) . elements ( ) ; while ( tkns . hasMoreElements ( ) ) tokens . add ( tkns . nextElement ( ) ) ; } return ( tokens ) ; } // Find the first dot . This simplistic search is appropriate because
// if this field contained a dot as part of it ' s name it should have
// been encased in quotes and handled by the previous logic .
int firstDot = field . indexOf ( dot ) ; if ( firstDot == 0 ) { // Does this thing start with dot ?
// Then it must be an absolute path .
// NOTE : This should be true ONLY for the first token
// in the list . By that I mean that a leading dot in
// the field string should only occur when the
// variable or alias field begins a dot . A secondary
// token may only start with a dot if the dot is
// actually part of the field , and thus it should be
// encased in quotes .
String thisToken = "." ; tokens . add ( thisToken ) ; // Check to see if there are more characters in the field to be tokenized .
// If there are , tokenize them .
if ( lastIndex > 0 ) { String theRest = field . substring ( 1 ) ; // Recursive call
Enumeration tkns = tokenizeAliasField ( theRest ) . elements ( ) ; // Take the tokens from the rest of the fields and
// add them to this token vector .
while ( tkns . hasMoreElements ( ) ) tokens . add ( tkns . nextElement ( ) ) ; } return ( tokens ) ; } if ( firstDot > 0 ) { // A secondary token may only contain a dot if the dot is
// actually part of the field , and thus the field should have been
// encased in quotes . Since we already check for a leading quote ,
// the first dor MUST be the end of the token .
String firstToken = field . substring ( 0 , firstDot ) ; tokens . add ( firstToken ) ; // A quick syntax check .
if ( lastIndex == firstDot ) throw new MalformedAliasException ( "Alias fields may not end with the dot (.) character." ) ; // Get the rest of the field string
String theRest = field . substring ( firstDot + 1 ) ; // tokenize it , and add it ' s tokens to this token Vector .
Enumeration tkns = tokenizeAliasField ( theRest ) . elements ( ) ; while ( tkns . hasMoreElements ( ) ) tokens . add ( tkns . nextElement ( ) ) ; return ( tokens ) ; } // This field string might be the final token , if we
// get here it must be so add it to the tokens vector
tokens . add ( field ) ; return ( tokens ) ;


signature:
public class DDS { /** * Prints the peristent representation of the < code > DDS < / code > as an XML document .
 * This XML document is know as a < b > DDX < / b > . The DDX can be parsed using the
 * < code > DDSXMLParser < / code >
 * @ param pw The < code > PrintWriter < / code > to print to .
 * @ param pad A < code > String < / code > to print at the begining of each line .
 * typically this is some white space .
 * @ param constrained A < code > boolean < / code > that indcates if the this call should
 * print the constrained version of the DDS . A value of < i > true < / i > will cause the
 * only the projected variables of the DDX to be printed .
 * @ opendap . ddx . experimental */
public void printXML ( PrintWriter pw , String pad , boolean constrained ) { } }

implementation: pw . println ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ) ; pw . print ( "<Dataset" ) ; if ( getEncodedName ( ) != null ) pw . print ( " name=\"" + DDSXMLParser . normalizeToXML ( getEncodedName ( ) ) + "\"" ) ; pw . println ( ) ; pw . println ( "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" ) ; pw . println ( "xmlns=\"" + opendapNameSpace + "\"" ) ; pw . print ( "xsi:schemaLocation=\"" ) ; pw . print ( opendapNameSpace + "  " ) ; pw . print ( schemaLocation ) ; pw . println ( "\" >" ) ; pw . println ( "" ) ; Enumeration e = getAttributeNames ( ) ; while ( e . hasMoreElements ( ) ) { String aName = ( String ) e . nextElement ( ) ; Attribute a = getAttribute ( aName ) ; if ( a != null ) a . printXML ( pw , pad + "\t" , constrained ) ; } pw . println ( "" ) ; Enumeration ve = getVariables ( ) ; while ( ve . hasMoreElements ( ) ) { BaseType bt = ( BaseType ) ve . nextElement ( ) ; bt . printXML ( pw , pad + "\t" , constrained ) ; } pw . println ( "" ) ; if ( _dataBlobID != null ) { pw . println ( pad + "\t" + "<dataBLOB href=\"" + DDSXMLParser . normalizeToXML ( _dataBlobID ) + "\"/>" ) ; } pw . println ( pad + "</Dataset>" ) ;


signature:
public class DDS { /** * Takes the passed parameter < code > das < / code > and attempts
 * to incorporate it ' s contents into the Attributes of the DDS
 * variables . If an < code > Attribute < / code > in the < code > DAS < / code >
 * can ' t be associated with a variable in a logical manner then
 * it is placed at the top level of the DDS . ( Basically it becomes
 * a toplevel attribute in the dataset )
 * @ param das The < code > DAS < / code > to ingest .
 * @ opendap . ddx . experimental */
public void ingestDAS ( DAS das ) { } }

implementation: try { ingestAttributeTable ( das , this ) ; resolveAliases ( ) ; } catch ( DASException de ) { DAPNode . log . error ( "DDS.ingestDAS(): " + de . getMessage ( ) ) ; }


signature:
public class DDS { /** * A helper methods for ingestDAS ( ) .
 * @ param a
 * @ param bt
 * @ throws DASException
 * @ see # ingestDAS ( DAS )
 * @ see # ingestAttribute ( Attribute , BaseType )
 * @ see # ingestAttributeTable ( AttributeTable , BaseType )
 * @ see # ingestAttributeTable ( AttributeTable , DConstructor ) */
private void ingestAttribute ( Attribute a , BaseType bt ) throws DASException { } }

implementation:
if ( a . isAlias ( ) ) { // copy an alias .
String name = a . getEncodedName ( ) ; String attribute = ( ( Alias ) a ) . getAliasedToAttributeFieldAsClearString ( ) ; bt . addAttributeAlias ( name , attribute ) ; } else if ( a . isContainer ( ) ) { AttributeTable at = a . getContainer ( ) ; ingestAttributeTable ( at , bt ) ; } else { // copy an Attribute and it ' s values . . .
String name = a . getEncodedName ( ) ; int type = a . getType ( ) ; Enumeration vals = a . getValues ( ) ; while ( vals . hasMoreElements ( ) ) { String value = ( String ) vals . nextElement ( ) ; bt . appendAttribute ( name , type , value , true ) ; } }


signature:
public class DDS { /** * A helper methods for ingestDAS ( ) .
 * @ param at
 * @ param dc
 * @ throws DASException
 * @ see # ingestDAS ( DAS )
 * @ see # ingestAttribute ( Attribute , BaseType )
 * @ see # ingestAttributeTable ( AttributeTable , BaseType ) */
private void ingestAttributeTable ( AttributeTable at , DConstructor dc ) throws DASException { } }

implementation: Enumeration ate = at . getNames ( ) ; while ( ate . hasMoreElements ( ) ) { String aName = ( String ) ate . nextElement ( ) ; Attribute a = at . getAttribute ( aName ) ; boolean foundIt = false ; Enumeration bte = dc . getVariables ( ) ; while ( bte . hasMoreElements ( ) ) { BaseType thisBT = ( BaseType ) bte . nextElement ( ) ; String bName = thisBT . getEncodedName ( ) ; if ( bName . equals ( aName ) ) { if ( a . isContainer ( ) && thisBT instanceof DConstructor ) { ingestAttributeTable ( a . getContainer ( ) , ( DConstructor ) thisBT ) ; } else { ingestAttribute ( a , thisBT ) ; } foundIt = true ; } } if ( ! foundIt ) { ingestAttribute ( a , dc ) ; } }


signature:
public class DDS { /** * A helper methods for ingestDAS ( ) .
 * @ see # ingestDAS ( DAS )
 * @ see # ingestAttribute ( Attribute , BaseType )
 * @ see # ingestAttributeTable ( AttributeTable , DConstructor ) */
private void ingestAttributeTable ( AttributeTable at , BaseType bt ) throws DASException { } }

implementation:
try { String atName = at . getEncodedName ( ) ; String bName = bt . getEncodedName ( ) ; // LogStream . out . println ( " ingestATTbl : atName : " + atName + " bName : " + bName ) ;
if ( bName . equals ( atName ) ) { // LogStream . out . println ( " adding each attribute ! " ) ;
Enumeration e = at . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String aName = ( String ) e . nextElement ( ) ; Attribute a = at . getAttribute ( aName ) ; ingestAttribute ( a , bt ) ; } } else { // LogStream . out . println ( " addingcontainer ! " ) ;
bt . addAttributeContainer ( at ) ; } } catch ( AttributeExistsException ase ) { Enumeration e = at . getNames ( ) ; while ( e . hasMoreElements ( ) ) { String aName = ( String ) e . nextElement ( ) ; Attribute a = at . getAttribute ( aName ) ; ingestAttribute ( a , bt ) ; } }


signature:
public class DDS { /** * 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 .
 * @ param dc The < code > DConstructor < / code > to search for name conflicts . */
private void checkForAttributeNameConflict ( DConstructor dc ) throws BadSemanticsException { } }

implementation:
if ( _Debug ) { DAPNode . log . debug ( "Checking " + dc . getTypeName ( ) + " " + dc . getClearName ( ) + " for name conflicts." ) ; } Enumeration bte = dc . getVariables ( ) ; while ( bte . hasMoreElements ( ) ) { BaseType bt = ( BaseType ) bte . nextElement ( ) ; // LogStream . out . println ( " member : " + bt . getTypeName ( ) + " " + bt . getName ( ) ) ;
Enumeration ate = dc . getAttributeNames ( ) ; while ( ate . hasMoreElements ( ) ) { String aName = ( String ) ate . nextElement ( ) ; // LogStream . out . println ( " attribute : " + aName ) ;
if ( aName . equals ( bt . getEncodedName ( ) ) ) { throw new BadSemanticsException ( "The variable '" + dc . getLongName ( ) + "' has an Attribute with the same name ('" + aName + "') as one of it's " + "member variables (" + bt . getTypeName ( ) + " " + bt . getEncodedName ( ) + ")\n" + "This is NOT allowed." ) ; } } if ( bt instanceof DConstructor ) { // LogStream . out . println ( " member ' " + bt . getName ( ) + " ' is a container . Better Check it ! " ) ;
// Recursive call ! !
checkForAttributeNameConflict ( ( DConstructor ) bt ) ; } }


signature:
public class DDS { /** * This a wrapper method for < code > DDS . print ( ) < / code > .
 * @ return The output of < code > DDS . print ( ) < / code > as
 * < code > String < / code >
 * @ see # print ( PrintWriter ) */
public String getDDSText ( ) { } }

implementation: StringWriter sw = new StringWriter ( ) ; this . print ( new PrintWriter ( sw ) ) ; return sw . toString ( ) ;


signature:
public class DDS { /** * This a wrapper method for < code > DDS . printXML ( ) < / code > .
 * @ return The output of < code > DDS . printXML ( ) < / code > as
 * < code > String < / code >
 * @ opendap . ddx . experimental
 * @ see # printXML ( PrintWriter ) */
public String getDDXText ( ) { } }

implementation: StringWriter sw = new StringWriter ( ) ; this . printXML ( new PrintWriter ( sw ) ) ; return sw . toString ( ) ;


signature:
public class DDS { /** * Returns a clone of this < code > DDS < / code > .
 * See DAPNode . cloneDag ( )
 * @ param map track previously cloned nodes
 * @ return a clone of this DDS . */
public DAPNode cloneDAG ( CloneMap map ) throws CloneNotSupportedException { } }

implementation:
DDS d = ( DDS ) super . cloneDAG ( map ) ; d . vars = new Vector ( ) ; for ( int i = 0 ; i < vars . size ( ) ; i ++ ) { BaseType element = ( BaseType ) vars . elementAt ( i ) ; d . vars . addElement ( cloneDAG ( map , element ) ) ; } d . setEncodedName ( this . getEncodedName ( ) ) ; // Question :
// What about copying the BaseTypeFactory ?
// Do we want a reference to the same one ? Or another / / Is there a difference ? Should we be building the clone
// using " new DDS ( getFactory ( ) ) " ? ?
// Answer :
// Yes . Use the same type factory !
d . factory = this . factory ; return d ;


signature:
public class Grib2Index { /** * LOOK what about extending an index ? ? */
public boolean makeIndex ( String filename , RandomAccessFile dataRaf ) throws IOException { } }

implementation:
String idxPath = filename ; if ( ! idxPath . endsWith ( GBX9_IDX ) ) idxPath += GBX9_IDX ; File idxFile = GribIndexCache . getFileOrCache ( idxPath ) ; File idxFileTmp = GribIndexCache . getFileOrCache ( idxPath + ".tmp" ) ; boolean ok = false ; RandomAccessFile raf = null ; try ( FileOutputStream fout = new FileOutputStream ( idxFileTmp ) ) { // / / header message
fout . write ( MAGIC_START . getBytes ( CDM . utf8Charset ) ) ; NcStream . writeVInt ( fout , version ) ; Map < Long , Integer > gdsMap = new HashMap < > ( ) ; gdsList = new ArrayList < > ( ) ; records = new ArrayList < > ( 200 ) ; Grib2IndexProto . Grib2Index . Builder rootBuilder = Grib2IndexProto . Grib2Index . newBuilder ( ) ; rootBuilder . setFilename ( filename ) ; if ( dataRaf == null ) { raf = RandomAccessFile . acquire ( filename ) ; dataRaf = raf ; } Grib2RecordScanner scan = new Grib2RecordScanner ( dataRaf ) ; while ( scan . hasNext ( ) ) { Grib2Record r = scan . next ( ) ; if ( r == null ) break ; // done
records . add ( r ) ; Grib2SectionGridDefinition gdss = r . getGDSsection ( ) ; Integer index = gdsMap . get ( gdss . calcCRC ( ) ) ; if ( index == null ) { gdsList . add ( gdss ) ; index = gdsList . size ( ) - 1 ; gdsMap . put ( gdss . calcCRC ( ) , index ) ; rootBuilder . addGdsList ( makeGdsProto ( gdss ) ) ; } rootBuilder . addRecords ( makeRecordProto ( r , index , r . getGDS ( ) . scanMode ) ) ; } if ( records . isEmpty ( ) ) throw new RuntimeException ( "No GRIB2 records found in " + dataRaf . getLocation ( ) ) ; Grib2IndexProto . Grib2Index index = rootBuilder . build ( ) ; byte [ ] b = index . toByteArray ( ) ; NcStream . writeVInt ( fout , b . length ) ; // message size
fout . write ( b ) ; // message - all in one gulp
logger . debug ( "  made gbx9 index for {} size={}" , filename , b . length ) ; ok = true ; return true ; } finally { if ( raf != null ) raf . close ( ) ; // only close if we opened it
// now switch ; fout has been closed
if ( ok ) { RandomAccessFile . eject ( idxFile . getPath ( ) ) ; boolean deleteOk = ! idxFile . exists ( ) || idxFile . delete ( ) ; boolean renameOk = idxFileTmp . renameTo ( idxFile ) ; if ( ! deleteOk ) logger . error ( "  could not delete Grib2Index= {}" , idxFile . getPath ( ) ) ; if ( ! renameOk ) logger . error ( "  could not rename Grib2Index= {}" , idxFile . getPath ( ) ) ; } }