cdm/src/main/java/ucar/nc2/iosp/grads/GradsDataDescriptorFile.java
private void parseDDF(int maxLines) throws IOException {

    //long start2 = System.currentTimeMillis();

    variableList = new ArrayList<>();
    dimList = new ArrayList<>();
    attrList = new ArrayList<>();

    // LOOK not using raf - opened file again
    int count = 0;
    try (BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(ddFile), CDM.utf8Charset))) {
      boolean inVarSection = false;
      boolean inEnsSection = false;
      String line;
      String original;
      GradsDimension curDim = null;

      while ((original = r.readLine()) != null) {
        count++;
        if (count > maxLines) {
          error = true;
          return;
        }

        original = original.trim();
        if (original.isEmpty()) {
          continue;
        }
        line = original.toLowerCase();

        if (line.startsWith("@ ")) {
          attrList.add(GradsAttribute.parseAttribute(original));
          continue;
        }

        // ignore attribute metadata and comments
        if (line.startsWith("*")) {
          continue;
        }

        if (inEnsSection) {
          if (line.startsWith(ENDEDEF.toLowerCase())) {
            inEnsSection = false;
            continue;  // done skipping ensemble definitions
          }
          // parse the ensemble info
        }
        if (inVarSection) {
          if (line.startsWith(ENDVARS.toLowerCase())) {
            inVarSection = false;
            continue;  // done parsing variables
          }
          GradsVariable var = new GradsVariable(original);
          int numLevels = var.getNumLevels();
          if (numLevels == 0) {
            numLevels = 1;
          }
          gridsPerTimeStep += numLevels;

          // parse a variable
          variableList.add(var);

        } else {
          // not in var section or edef section, look for general metadata
          StringTokenizer st = new StringTokenizer(original);

          String label = st.nextToken();

          // TODO: Handle other options
          if (label.equalsIgnoreCase(OPTIONS)) {
            curDim = null;
            while (st.hasMoreTokens()) {
              String token = st.nextToken();
              if (token.equalsIgnoreCase(BIG_ENDIAN)) {
                bigEndian = true;
              } else if (token.equalsIgnoreCase(LITTLE_ENDIAN)) {
                bigEndian = false;
              } else if (token.equalsIgnoreCase(BYTESWAPPED)) {
                swapByteOrder();
              } else if (token.equalsIgnoreCase(YREV)) {
                yReversed = true;
              } else if (token.equalsIgnoreCase(TEMPLATE)) {
                isTemplate = true;
              } else if (token.equalsIgnoreCase(SEQUENTIAL)) {
                isSequential = true;
              }
            }
          } else if (label.equalsIgnoreCase(CHSUB)) {
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            String sub = st.nextToken();
            addChsub(new Chsub(start, end, sub));

          } else if (label.equalsIgnoreCase(DSET)) {
            curDim = null;
            dataFile = st.nextToken();

          } else if (label.equalsIgnoreCase(UNDEF)) {
            curDim = null;
            missingData = Double.parseDouble(st.nextToken());

          } else if (label.equalsIgnoreCase(XYHEADER)) {
            curDim = null;
            xyHeaderBytes = Integer.parseInt(st.nextToken());

          } else if (label.equalsIgnoreCase(FILEHEADER)) {
            curDim = null;
            fileHeaderBytes = Integer.parseInt(st.nextToken());

          } else if (label.equalsIgnoreCase(XDEF)) {
            int xSize = Integer.valueOf(st.nextToken());
            String xMapping = st.nextToken();
            xDim = new GradsDimension(label, xSize, xMapping);
            curDim = xDim;
            dimList.add(xDim);

          } else if (label.equalsIgnoreCase(YDEF)) {
            int ySize = Integer.valueOf(st.nextToken());
            String yMapping = st.nextToken();
            yDim = new GradsDimension(label, ySize, yMapping);
            curDim = yDim;
            dimList.add(yDim);

          } else if (label.equalsIgnoreCase(ZDEF)) {
            int zSize = Integer.valueOf(st.nextToken());
            String zMapping = st.nextToken();
            zDim = new GradsDimension(label, zSize, zMapping);
            curDim = zDim;
            dimList.add(zDim);

          } else if (label.equalsIgnoreCase(TDEF)) {
            int tSize = Integer.valueOf(st.nextToken());
            // we can read the following directly
            // since tdef never uses "levels"
            String tMapping = st.nextToken();
            tDim = new GradsTimeDimension(label, tSize, tMapping);
            curDim = tDim;
            dimList.add(tDim);

          } else if (label.equalsIgnoreCase(EDEF)) {
            int eSize = Integer.valueOf(st.nextToken());
            // Check if EDEF entry is the short or extended version
            if (st.nextToken().equalsIgnoreCase(GradsEnsembleDimension.NAMES)) {
              inEnsSection = false;
              String eMapping = GradsEnsembleDimension.NAMES;
              eDim = new GradsEnsembleDimension(label, eSize, eMapping);
              curDim = eDim;
              dimList.add(curDim);

            } else {
              // TODO: handle list of ensembles
              curDim = null;
              inEnsSection = true;
            }

          } else if (label.equalsIgnoreCase(PDEF)) {
            curDim = null;
            hasProjection = true;

          } else if (label.equalsIgnoreCase(VARS)) {
            curDim = null;
            inVarSection = true;

          } else if (label.equalsIgnoreCase(DTYPE)) {
            curDim = null;
            dataType = st.nextToken();

          } else if (label.equalsIgnoreCase(TITLE)) {
            curDim = null;
            title = original.substring(original.indexOf(" ")).trim();

          } else if (curDim != null) {
            curDim.addLevel(label);
          }
          // get the rest of the tokens
          if (curDim != null) {
            while (st.hasMoreTokens()) {
              curDim.addLevel(st.nextToken());
            }
          }
        }

      }  // end parsing loop
      //System.out.println("Time to parse file = "
      //                   + (System.currentTimeMillis() - start2));

      // update the units for the zDimension if they are specified as
      // an attribute
      if (zDim != null) {
        for (GradsAttribute attr : attrList) {
          if (attr.getVariable().equalsIgnoreCase(ZDEF) &&
                  attr.getType().equalsIgnoreCase(GradsAttribute.STRING) &&
                  attr.getName().equalsIgnoreCase("units")) {
            zDim.setUnit(attr.getValue());
            break;
          }
        }
      }

    } catch (IOException ioe) {
      log.error("Error parsing metadata for " + ddFile);
      throw new IOException("error parsing metadata for " + ddFile);
    }
  }
private void parseDDF(int maxLines) throws IOException {

    //long start2 = System.currentTimeMillis();

    variableList = new ArrayList<>();
    dimList = new ArrayList<>();
    attrList = new ArrayList<>();

    // LOOK not using raf - opened file again
    int count = 0;
    try (BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(ddFile), CDM.utf8Charset))) {
      boolean inVarSection = false;
      boolean inEnsSection = false;
      String line;
      String original;
      GradsDimension curDim = null;

      while ((original = r.readLine()) != null) {
        count++;
        if (count > maxLines) {
          error = true;
          return;
        }

        original = original.trim();
        if (original.isEmpty()) {
          continue;
        }
        line = original.toLowerCase();

        if (line.startsWith("@ ")) {
          attrList.add(GradsAttribute.parseAttribute(original));
          continue;
        }

        // ignore attribute metadata and comments
        if (line.startsWith("*")) {
          continue;
        }

        if (inEnsSection) {
          if (line.startsWith(ENDEDEF.toLowerCase())) {
            inEnsSection = false;
            continue;  // done skipping ensemble definitions
          }
          // parse the ensemble info
        }
        if (inVarSection) {
          if (line.startsWith(ENDVARS.toLowerCase())) {
            inVarSection = false;
            continue;  // done parsing variables
          }
          GradsVariable var = new GradsVariable(original);
          int numLevels = var.getNumLevels();
          if (numLevels == 0) {
            numLevels = 1;
          }
          gridsPerTimeStep += numLevels;

          // parse a variable
          variableList.add(var);

        } else {
          // not in var section or edef section, look for general metadata
          StringTokenizer st = new StringTokenizer(original);

          String label = st.nextToken();

          // TODO: Handle other options
          if (label.equalsIgnoreCase(OPTIONS)) {
            curDim = null;
            while (st.hasMoreTokens()) {
              String token = st.nextToken();
              if (token.equalsIgnoreCase(BIG_ENDIAN)) {
                bigEndian = true;
              } else if (token.equalsIgnoreCase(LITTLE_ENDIAN)) {
                bigEndian = false;
              } else if (token.equalsIgnoreCase(BYTESWAPPED)) {
                swapByteOrder();
              } else if (token.equalsIgnoreCase(YREV)) {
                yReversed = true;
              } else if (token.equalsIgnoreCase(TEMPLATE)) {
                isTemplate = true;
              } else if (token.equalsIgnoreCase(SEQUENTIAL)) {
                isSequential = true;
              }
            }
          } else if (label.equalsIgnoreCase(CHSUB)) {
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            String sub = st.nextToken();
            addChsub(new Chsub(start, end, sub));

          } else if (label.equalsIgnoreCase(DSET)) {
            curDim = null;
            dataFile = st.nextToken();

          } else if (label.equalsIgnoreCase(UNDEF)) {
            curDim = null;
            missingData = Double.parseDouble(st.nextToken());

          } else if (label.equalsIgnoreCase(XYHEADER)) {
            curDim = null;
            xyHeaderBytes = Integer.parseInt(st.nextToken());

          } else if (label.equalsIgnoreCase(FILEHEADER)) {
            curDim = null;
            fileHeaderBytes = Integer.parseInt(st.nextToken());

          } else if (label.equalsIgnoreCase(XDEF)) {
            int xSize = Integer.valueOf(st.nextToken());
            String xMapping = st.nextToken();
            xDim = new GradsDimension(label, xSize, xMapping);
            curDim = xDim;
            dimList.add(xDim);

          } else if (label.equalsIgnoreCase(YDEF)) {
            int ySize = Integer.valueOf(st.nextToken());
            String yMapping = st.nextToken();
            yDim = new GradsDimension(label, ySize, yMapping);
            curDim = yDim;
            dimList.add(yDim);

          } else if (label.equalsIgnoreCase(ZDEF)) {
            int zSize = Integer.valueOf(st.nextToken());
            String zMapping = st.nextToken();
            zDim = new GradsDimension(label, zSize, zMapping);
            curDim = zDim;
            dimList.add(zDim);

          } else if (label.equalsIgnoreCase(TDEF)) {
            int tSize = Integer.valueOf(st.nextToken());
            // we can read the following directly
            // since tdef never uses "levels"
            String tMapping = st.nextToken();
            tDim = new GradsTimeDimension(label, tSize, tMapping);
            curDim = tDim;
            dimList.add(tDim);

          } else if (label.equalsIgnoreCase(EDEF)) {
            int eSize = Integer.valueOf(st.nextToken());
            // Check if EDEF entry is the short or extended version
            if (st.nextToken().equalsIgnoreCase(GradsEnsembleDimension.NAMES)) {
              inEnsSection = false;
              String eMapping = GradsEnsembleDimension.NAMES;
              eDim = new GradsEnsembleDimension(label, eSize, eMapping);
              curDim = eDim;
              dimList.add(curDim);

            } else {
              // TODO: handle list of ensembles
              curDim = null;
              inEnsSection = true;
            }

          } else if (label.equalsIgnoreCase(PDEF)) {
            curDim = null;
            hasProjection = true;

          } else if (label.equalsIgnoreCase(VARS)) {
            curDim = null;
            inVarSection = true;

          } else if (label.equalsIgnoreCase(DTYPE)) {
            curDim = null;
            dataType = st.nextToken();

          } else if (label.equalsIgnoreCase(TITLE)) {
            curDim = null;
            title = original.substring(original.indexOf(" ")).trim();

          } else if (curDim != null) {
            curDim.addLevel(label);
          }
          // get the rest of the tokens
          if (curDim != null) {
            while (st.hasMoreTokens()) {
              curDim.addLevel(st.nextToken());
            }
          }
        }

      }  // end parsing loop
      //System.out.println("Time to parse file = "
      //                   + (System.currentTimeMillis() - start2));

      // update the units for the zDimension if they are specified as
      // an attribute
      if (zDim != null) {
        for (GradsAttribute attr : attrList) {
          if (attr.getVariable().equalsIgnoreCase(ZDEF) &&
                  attr.getType().equalsIgnoreCase(GradsAttribute.STRING) &&
                  attr.getName().equalsIgnoreCase("units")) {
            zDim.setUnit(attr.getValue());
            break;
          }
        }
      }

    } catch (IOException ioe) {
      log.error("Error parsing metadata for " + ddFile);
      throw new IOException("error parsing metadata for " + ddFile);
    }
  }
private void parseDDF ( int maxLines ) throws IOException { //long start2 = System.currentTimeMillis();
 variableList = new ArrayList <> ( ) ; dimList = new ArrayList <> ( ) ; attrList = new ArrayList <> ( ) ; // LOOK not using raf - opened file again
 int count = 0 ; try ( BufferedReader r = new BufferedReader ( new InputStreamReader ( new FileInputStream ( ddFile ) , CDM . utf8Charset ) ) ) { boolean inVarSection = false ; boolean inEnsSection = false ; String line ; String original ; GradsDimension curDim = null ; while ( ( original = r . readLine ( ) ) != null ) { count ++ ; if ( count > maxLines ) { error = true ; return ; } original = original . trim ( ) ; if ( original . isEmpty ( ) ) { continue ; } line = original . toLowerCase ( ) ; if ( line . startsWith ( "@ " ) ) { attrList . add ( GradsAttribute . parseAttribute ( original ) ) ; continue ; } // ignore attribute metadata and comments
 if ( line . startsWith ( "*" ) ) { continue ; } if ( inEnsSection ) { if ( line . startsWith ( ENDEDEF . toLowerCase ( ) ) ) { inEnsSection = false ; continue ; // done skipping ensemble definitions
 } // parse the ensemble info
 } if ( inVarSection ) { if ( line . startsWith ( ENDVARS . toLowerCase ( ) ) ) { inVarSection = false ; continue ; // done parsing variables
 } GradsVariable var = new GradsVariable ( original ) ; int numLevels = var . getNumLevels ( ) ; if ( numLevels == 0 ) { numLevels = 1 ; } gridsPerTimeStep += numLevels ; // parse a variable
 variableList . add ( var ) ; } else { // not in var section or edef section, look for general metadata
 StringTokenizer st = new StringTokenizer ( original ) ; String label = st . nextToken ( ) ; // TODO: Handle other options
 if ( label . equalsIgnoreCase ( OPTIONS ) ) { curDim = null ; while ( st . hasMoreTokens ( ) ) { String token = st . nextToken ( ) ; if ( token . equalsIgnoreCase ( BIG_ENDIAN ) ) { bigEndian = true ; } else if ( token . equalsIgnoreCase ( LITTLE_ENDIAN ) ) { bigEndian = false ; } else if ( token . equalsIgnoreCase ( BYTESWAPPED ) ) { swapByteOrder ( ) ; } else if ( token . equalsIgnoreCase ( YREV ) ) { yReversed = true ; } else if ( token . equalsIgnoreCase ( TEMPLATE ) ) { isTemplate = true ; } else if ( token . equalsIgnoreCase ( SEQUENTIAL ) ) { isSequential = true ; } } } else if ( label . equalsIgnoreCase ( CHSUB ) ) { int start = Integer . parseInt ( st . nextToken ( ) ) ; int end = Integer . parseInt ( st . nextToken ( ) ) ; String sub = st . nextToken ( ) ; addChsub ( new Chsub ( start , end , sub ) ) ; } else if ( label . equalsIgnoreCase ( DSET ) ) { curDim = null ; dataFile = st . nextToken ( ) ; } else if ( label . equalsIgnoreCase ( UNDEF ) ) { curDim = null ; missingData = Double . parseDouble ( st . nextToken ( ) ) ; } else if ( label . equalsIgnoreCase ( XYHEADER ) ) { curDim = null ; xyHeaderBytes = Integer . parseInt ( st . nextToken ( ) ) ; } else if ( label . equalsIgnoreCase ( FILEHEADER ) ) { curDim = null ; fileHeaderBytes = Integer . parseInt ( st . nextToken ( ) ) ; } else if ( label . equalsIgnoreCase ( XDEF ) ) { int xSize = Integer . valueOf ( st . nextToken ( ) ) ; String xMapping = st . nextToken ( ) ; xDim = new GradsDimension ( label , xSize , xMapping ) ; curDim = xDim ; dimList . add ( xDim ) ; } else if ( label . equalsIgnoreCase ( YDEF ) ) { int ySize = Integer . valueOf ( st . nextToken ( ) ) ; String yMapping = st . nextToken ( ) ; yDim = new GradsDimension ( label , ySize , yMapping ) ; curDim = yDim ; dimList . add ( yDim ) ; } else if ( label . equalsIgnoreCase ( ZDEF ) ) { int zSize = Integer . valueOf ( st . nextToken ( ) ) ; String zMapping = st . nextToken ( ) ; zDim = new GradsDimension ( label , zSize , zMapping ) ; curDim = zDim ; dimList . add ( zDim ) ; } else if ( label . equalsIgnoreCase ( TDEF ) ) { int tSize = Integer . valueOf ( st . nextToken ( ) ) ; // we can read the following directly
 // since tdef never uses "levels"
 String tMapping = st . nextToken ( ) ; tDim = new GradsTimeDimension ( label , tSize , tMapping ) ; curDim = tDim ; dimList . add ( tDim ) ; } else if ( label . equalsIgnoreCase ( EDEF ) ) { int eSize = Integer . valueOf ( st . nextToken ( ) ) ; // Check if EDEF entry is the short or extended version
 if ( st . nextToken ( ) . equalsIgnoreCase ( GradsEnsembleDimension . NAMES ) ) { inEnsSection = false ; String eMapping = GradsEnsembleDimension . NAMES ; eDim = new GradsEnsembleDimension ( label , eSize , eMapping ) ; curDim = eDim ; dimList . add ( curDim ) ; } else { // TODO: handle list of ensembles
 curDim = null ; inEnsSection = true ; } } else if ( label . equalsIgnoreCase ( PDEF ) ) { curDim = null ; hasProjection = true ; } else if ( label . equalsIgnoreCase ( VARS ) ) { curDim = null ; inVarSection = true ; } else if ( label . equalsIgnoreCase ( DTYPE ) ) { curDim = null ; dataType = st . nextToken ( ) ; } else if ( label . equalsIgnoreCase ( TITLE ) ) { curDim = null ; title = original . substring ( original . indexOf ( " " ) ) . trim ( ) ; } else if ( curDim != null ) { curDim . addLevel ( label ) ; } // get the rest of the tokens
 if ( curDim != null ) { while ( st . hasMoreTokens ( ) ) { curDim . addLevel ( st . nextToken ( ) ) ; } } } } // end parsing loop
 //System.out.println("Time to parse file = "
 //                   + (System.currentTimeMillis() - start2));
 // update the units for the zDimension if they are specified as
 // an attribute
 if ( zDim != null ) { for ( GradsAttribute attr : attrList ) { if ( attr . getVariable ( ) . equalsIgnoreCase ( ZDEF ) && attr . getType ( ) . equalsIgnoreCase ( GradsAttribute . STRING ) && attr . getName ( ) . equalsIgnoreCase ( "units" ) ) { zDim . setUnit ( attr . getValue ( ) ) ; break ; } } } } catch ( IOException ioe ) { log . error ( "Error parsing metadata for " + ddFile ) ; throw new IOException ( "error parsing metadata for " + ddFile ) ; } }
Parse the ctl file

@throws IOException problem reading the file
Parse the ctl file