protected void
    builddimrefs(DapVariable dapvar, List<Dimension> cdmdims)
            throws DapException
    {
        if (cdmdims == null || cdmdims.size() == 0)
            return;
        // It is unfortunately the case that the dimensions
        // associated with the variable are not
        // necessarily the same object as those dimensions
        // as declared, so we need to use a non-trivial
        // matching algorithm.
        for (Dimension cdmdim : cdmdims) {
            DapDimension dapdim = null;
            if (cdmdim.isShared()) {
                Dimension declareddim = finddimdecl(cdmdim);
                if (declareddim == null)
                    throw new DapException("Unprocessed cdm dimension: " + cdmdim);
                dapdim = (DapDimension) this.nodemap.get(declareddim);
                assert dapdim != null;
            } else if (cdmdim.isVariableLength()) {// ignore
                continue;
            } else {//anonymous
                dapdim = builddim(cdmdim);
            }
            assert (dapdim != null) : "Internal error";
            dapvar.addDimension(dapdim);
        }
    }

Assign dimensions to a variable

@param dapvar  The variable to which we wish to assign dimensions
@param cdmdims The cdm dimensions from which we will find the dimension info


protected EnumTypedef
    findMatchingEnum(EnumTypedef varenum)
            throws DapException
    {
        List<EnumTypedef> candidates = new ArrayList<>();
        for (Map.Entry<DapNode, CDMNode> entry : this.nodemap.getCDMMap().entrySet()) {
            CDMNode cdmnode = entry.getValue();
            if (cdmnode.getSort() != CDMSort.ENUMERATION)
                continue;
            // Compare the enumeration (note names will differ)
            EnumTypedef target = (EnumTypedef) cdmnode;
            /* Ideally, we should test the types of the enums,
               but, unfortunately, the var enum is always enum4.
            if(target.getBaseType() != varenum.getBaseType())
                continue;
            */
            Map<Integer, String> targetmap = target.getMap();
            Map<Integer, String> varmap = varenum.getMap();
            if (targetmap.size() != varmap.size())
                continue;
            boolean match = true; // until otherwise shown
            for (Map.Entry<Integer, String> tpair : targetmap.entrySet()) {
                String tname = tpair.getValue();
                int value = (int) tpair.getKey();
                boolean found = false;
                for (Map.Entry<Integer, String> vpair : varmap.entrySet()) {
                    if (tname.equals(vpair.getValue()) && value == (int) vpair.getKey()) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    match = false;
                    break;
                }
            }
            if (!match)
                continue;

            // Save it unless it is shadowed by a closer enum
            boolean shadowed = false;
            for (EnumTypedef etd : candidates) {
                if (shadows(etd.getGroup(), target.getGroup())) {
                    shadowed = true;
                    break;
                }
            }
            if (!shadowed)
                candidates.add(target);
        }

        switch (candidates.size()) {
            case 0:
                throw new DapException("CDMDSP: No matching enum type decl: " + varenum.getShortName());
            case 1:
                break;
            default:
                throw new DapException("CDMDSP: Multiple matching enum type decls: " + varenum.getShortName());
        }
        return candidates.get(0);
    }

Unfortunately, the CDM Iosp does not
actually use the declared enums. Rather,
for every enum type'd variable, a new
enum decl is defined. So, we need
to find the original enum decl that matches
the variable's enum.

Unfortunately the CDM Iosp does not actually use the declared enums . Rather for every enum type d variable a new enum decl is defined . So we need to find the original enum decl that matches the variable s enum .


static List<Dimension>
    getCoreDimset(List<Dimension> dimset)
            throws DapException
    {
        if (dimset == null) return null;
        List<Dimension> core = new ArrayList<>();
        int pos = -1;
        int count = 0;
        for (int i = 0; i < dimset.size(); i++) {
            if (dimset.get(i).isVariableLength()) {
                pos = i;
                count++;
            } else
                core.add(dimset.get(i));
        }
        if ((pos != dimset.size() - 1) || count > 1)
            throw new DapException("Unsupported use of (*) Dimension");
        return core;
    }

static
List
<
Dimension
>
getCoreDimset
(
List
<
Dimension
>
dimset
)
throws
DapException
{
if
(
dimset
==
)
return
;
List
<
Dimension
>
core
=
new
ArrayList
<>
(
)
;
int
pos
=
1
;
int
count
=
0
;
for
(
int
i
=
0
;
i
<
dimset
.
size
(
)
;
i
++
)
{
if
(
dimset
.
get
(
i
)
.
isVariableLength
(
)
)
{
pos
=
i
;
count
++
;
}
else
core
.
add
(
dimset
.
get
(
i
)
)
;
}
if
(
(
pos
!=
dimset
.
size
(
)
1
)
||
count
>
1
)
throw
new
DapException
(
"Unsupported use of (*) Dimension"
)
;
return
core
;
}

Strip vlen dimensions from a set of dimensions

@param dimset
@return subset of dimset with (trailing) vlen removed
@throws DapException


public int scanBufrFile(String filename, Counter total) throws Exception {
    int count = 0;
    try (RandomAccessFile raf = new RandomAccessFile(filename, "r")) {

      MessageScanner scan = new MessageScanner(raf);
      while (scan.hasNext()) {
        Message m = scan.next();
        if (m == null) continue;
        try {
          if (showMess) out.format("%sMessage %d header=%s%n", indent, count, m.getHeader());
          count++;
          Counter counter = new Counter();
          processBufrMessageAsDataset(scan, m, counter);
          if (showMess) out.format("%scount=%d miss=%d%n", indent, counter.nvals, counter.nmiss);
          total.add(counter);

        } catch (Exception e) {
          System.out.printf("  BARF:%s on %s%n", e.getMessage(), m.getHeader());
          indent.setIndentLevel(0);
        }
      }
    }
    return count;
  }

public
int
scanBufrFile
(
String
filename
,
Counter
total
)
throws
Exception
{
int
count
=
0
;
try
(
RandomAccessFile
raf
=
new
RandomAccessFile
(
filename
,
"r"
)
)
{
MessageScanner
scan
=
new
MessageScanner
(
raf
)
;
while
(
scan
.
hasNext
(
)
)
{
Message
m
=
scan
.
next
(
)
;
if
(
m
==
)
continue
;
try
{
if
(
showMess
)
out
.
format
(
"%sMessage %d header=%s%n"
,
indent
,
count
,
m
.
getHeader
(
)
)
;
count
++
;
Counter
counter
=
new
Counter
(
)
;
processBufrMessageAsDataset
(
scan
,
m
,
counter
)
;
if
(
showMess
)
out
.
format
(
"%scount=%d miss=%d%n"
,
indent
,
counter
.
nvals
,
counter
.
nmiss
)
;
total
.
add
(
counter
)
;
}
catch
(
Exception
e
)
{
System
.
out
.
printf
(
"  BARF:%s on %s%n"
,
e
.
getMessage
(
)
,
m
.
getHeader
(
)
)
;
indent
.
setIndentLevel
(
0
)
;
}
}
}
return
count
;
}


private void processBufrMessageAsDataset(MessageScanner scan, Message m, Counter counter) throws Exception {
    byte[] mbytes = scan.getMessageBytes(m);
    NetcdfFile ncfile = NetcdfFile.openInMemory("test", mbytes, "ucar.nc2.iosp.bufr.BufrIosp");
    Sequence obs = (Sequence) ncfile.findVariable(BufrIosp2.obsRecord);
    StructureDataIterator sdataIter = obs.getStructureIterator(-1);
    processSequence(obs, sdataIter, counter);
  }

private void processBufrMessageAsDataset ( MessageScanner scan , Message m , Counter counter ) throws Exception { byte [ ] mbytes = scan . getMessageBytes ( m ) ; NetcdfFile ncfile = NetcdfFile . openInMemory ( "test" , mbytes , "ucar.nc2.iosp.bufr.BufrIosp" ) ; Sequence obs = ( Sequence ) ncfile . findVariable ( BufrIosp2 . obsRecord ) ; StructureDataIterator sdataIter = obs . getStructureIterator ( - 1 ) ; processSequence ( obs , sdataIter , counter ) ; }

convert one message ino a NetcdfDataset and print data


public void doPost(HttpServletRequest req, HttpServletResponse res)
          throws ServletException, IOException {

    log.info("doPost(): " + UsageLog.setupRequestContext(req));

    // Check that we have a file upload request
    boolean isMultipart = ServletFileUpload.isMultipartContent(req);
    if (!isMultipart) {
      log.info("doPost(): " + UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_BAD_REQUEST, 0));
      res.sendError(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }

    //Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload(this.cdmValidatorContext.getFileuploadFileItemFactory());
    upload.setSizeMax(this.cdmValidatorContext.getMaxFileUploadSize());  // maximum bytes before a FileUploadException will be thrown

    List<FileItem> fileItems;
    try {
      fileItems = (List<FileItem>) upload.parseRequest(req);
    } catch (FileUploadException e) {
      log.info("doPost(): Validator FileUploadException", e);
      log.info("doPost(): " + UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_BAD_REQUEST, 0));
      if (!res.isCommitted()) res.sendError(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }

    //Process the uploaded items
    String username = null;
    boolean wantXml = false;
    for (FileItem item : fileItems) {
      if (item.isFormField()) {
        if ("username".equals(item.getFieldName()))
          username = item.getString();
        if ("xml".equals(item.getFieldName()))
          wantXml = item.getString().equals("true");
      }
    }

    for (FileItem item : fileItems) {
      if (!item.isFormField()) {
        try {
          processUploadedFile(req, res, (DiskFileItem) item, username, wantXml);
          return;
        } catch (Exception e) {
          log.info("doPost(): Validator processUploadedFile", e);
          log.info("doPost(): " + UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_BAD_REQUEST, 0));
          res.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
        }
      }
    }

  }

POST handles uploaded files

@param req request
@param res response
@throws ServletException
@throws IOException


public AffineTransform getTransform() {
    at.setTransform( pix_per_world, 0.0, 0.0, -pix_per_world, pix_x0, pix_y0);

    if (debug) {
      System.out.println("Navigation getTransform = "+ pix_per_world +" "+ pix_x0+" "+ pix_y0);
      System.out.println("  transform = "+ at);
    }
    return at;
  }

public
AffineTransform
getTransform
(
)
{
at
.
setTransform
(
pix_per_world
,
0.0
,
0.0
,
pix_per_world
,
pix_x0
,
pix_y0
)
;
if
(
debug
)
{
System
.
out
.
println
(
"Navigation getTransform = "
+
pix_per_world
+
" "
+
pix_x0
+
" "
+
pix_y0
)
;
System
.
out
.
println
(
"  transform = "
+
at
)
;
}
return
at
;
}

Get the affine transform based on screen size and world bounding box


public boolean wantRotate(double displayWidth, double displayHeight) {
    getMapArea( bb); // current world bounding box
    boolean aspectDisplay = displayHeight < displayWidth;
    boolean aspectWorldBB = bb.getHeight() < bb.getWidth();
    return (aspectDisplay ^ aspectWorldBB); // aspects are different
 }

public
boolean
wantRotate
(
double
displayWidth
,
double
displayHeight
)
{
getMapArea
(
bb
)
;
// current world bounding box
boolean
aspectDisplay
=
displayHeight
<
displayWidth
;
boolean
aspectWorldBB
=
bb
.
getHeight
(
)
<
bb
.
getWidth
(
)
;
return
(
aspectDisplay
^
aspectWorldBB
)
;
// aspects are different
}

calculate if we want to rotate based on aspect ratio


public ProjectionRect getMapArea(ProjectionRect rect) {
    if (rect == null)
      rect = new ProjectionRect();

    double width = pwidth/pix_per_world;
    double height = pheight/pix_per_world;

        // center point
    double wx0 = (pwidth/2-pix_x0)/pix_per_world;
    double wy0 = (pix_y0-pheight/2)/pix_per_world;

    rect.setRect(wx0-width/2, wy0-height/2,             // minx, miny
             width, height);                            // width, height

    return rect;
  }

public
ProjectionRect
getMapArea
(
ProjectionRect
rect
)
{
if
(
rect
==
)
rect
=
new
ProjectionRect
(
)
;
double
width
=
pwidth
/
pix_per_world
;
double
height
=
pheight
/
pix_per_world
;
// center point
double
wx0
=
(
pwidth
/
2
pix_x0
)
/
pix_per_world
;
double
wy0
=
(
pix_y0
pheight
/
2
)
/
pix_per_world
;
rect
.
setRect
(
wx0
width
/
2
,
wy0
height
/
2
,
// minx, miny
width
,
height
)
;
// width, height
return
rect
;
}

Get current MapArea .
@param rect : place results here, or null to create new Object


public Point2D worldToScreen(ProjectionPointImpl w, Point2D p) {
    p.setLocation( pix_per_world*w.getX() + pix_x0,
                   -pix_per_world*w.getY() + pix_y0);
    return p;
  }

public Point2D worldToScreen ( ProjectionPointImpl w , Point2D p ) { p . setLocation ( pix_per_world * w . getX ( ) + pix_x0 , - pix_per_world * w . getY ( ) + pix_y0 ) ; return p ; }

convert a world coordinate to a display point


public void pan( double deltax, double deltay) {
    zoom.push();

    pix_x0 -= deltax;
    pix_y0 -= deltay;
    fireMapAreaEvent();
  }

public void pan ( double deltax , double deltay ) { zoom . push ( ) ; pix_x0 -= deltax ; pix_y0 -= deltay ; fireMapAreaEvent ( ) ; }

call this to change the center of the screen's world coordinates.
deltax, deltay in display coordinates

call this to change the center of the screen s world coordinates . deltax deltay in display coordinates


public void zoom(double startx, double starty, double width, double height) {
    if (debugZoom)
      System.out.println("zoom "+ startx+ " "+starty+ " "+width+ " "+height+ " ");

    if ((width < 5) || (height < 5))
      return;
    zoom.push();

    pix_x0 -= startx+width/2 - pwidth/2;
    pix_y0 -= starty+height/2 - pheight/2;
    zoom(pwidth / width);
  }

public
void
zoom
(
double
startx
,
double
starty
,
double
width
,
double
height
)
{
if
(
debugZoom
)
System
.
out
.
println
(
"zoom "
+
startx
+
" "
+
starty
+
" "
+
width
+
" "
+
height
+
" "
)
;
if
(
(
width
<
5
)
||
(
height
<
5
)
)
return
;
zoom
.
push
(
)
;
pix_x0
-=
startx
+
width
/
2
pwidth
/
2
;
pix_y0
-=
starty
+
height
/
2
pheight
/
2
;
zoom
(
pwidth
/
width
)
;
}

call this to zoom into a subset of the screen.
startx, starty are the upper left corner of the box in display coords
width, height the size of the box in display coords

call this to zoom into a subset of the screen . startx starty are the upper left corner of the box in display coords width height the size of the box in display coords


private void recalcFromBoundingBox() {
    if (debugRecalc) {
      System.out.println("Navigation recalcFromBoundingBox= "+ bb);
      System.out.println("  "+ pwidth +" "+ pheight);
    }

      // decide which dimension is limiting
    double pixx_per_wx = (bb.getWidth() == 0.0) ? 1 : pwidth / bb.getWidth();
    double pixy_per_wy = (bb.getHeight() == 0.0) ? 1 : pheight / bb.getHeight();
    pix_per_world = Math.min(pixx_per_wx, pixy_per_wy);

      // calc the center point
    double wx0 = bb.getX() + bb.getWidth()/2;
    double wy0 = bb.getY() + bb.getHeight()/2;

      // calc offset based on center point
    pix_x0 = pwidth/2 - pix_per_world * wx0;
    pix_y0 = pheight/2 + pix_per_world * wy0;

    if (debugRecalc) {
      System.out.println("Navigation recalcFromBoundingBox done= "+ pix_per_world +" "+ pix_x0+" "+ pix_y0);
      System.out.println("  "+ pwidth +" "+ pheight+" "+ bb);
    }
  }

adjust bounding box to fit inside the screen size


public synchronized void addListener(Object l) {
    if (!listeners.contains(l)) {
      listeners.add(l);
      hasListeners = true;
    } else
      logger.warn("ListenerManager.addListener already has Listener " + l);
  }

Add a listener.

@param l listener must be of type "listener_class"


public synchronized void removeListener(Object l) {
    if (listeners.contains(l)) {
      listeners.remove(l);
      hasListeners = (listeners.size() > 0);
    } else
      logger.warn("ListenerManager.removeListener couldnt find Listener " + l);
  }

Remove a listener.
@param l listener must be of type "listener_class"


public synchronized void sendEvent(java.util.EventObject event) {
    if (!hasListeners || !enabled)
      return;

    Object[] args = new Object[1];
    args[0] = event;

    // send event to all listeners
    ListIterator iter = listeners.listIterator();
    while (iter.hasNext()) {
      Object client = iter.next();
      try {
        method.invoke(client, args);
      } catch (IllegalAccessException e) {
        logger.error("ListenerManager IllegalAccessException", e);
        iter.remove();
      } catch (IllegalArgumentException e) {
        logger.error("ListenerManager IllegalArgumentException", e);
        iter.remove();
      } catch (InvocationTargetException e) {
        // logger.error("ListenerManager InvocationTargetException on " + method+ " threw exception " + e.getTargetException(), e);
        throw new RuntimeException(e.getCause()); // pass exception to the caller of sendEvent()
      }
    }
  }

Send an event to all registered listeners. If an exception is thrown, remove
the Listener from the list

@param event the event to be sent: public void method_name( event_class event)

Send an event to all registered listeners . If an exception is thrown remove the Listener from the list


public synchronized void sendEventExcludeSource(java.util.EventObject event) {
    if (!hasListeners || !enabled)
      return;

    Object source = event.getSource();
    Object[] args = new Object[1];
    args[0] = event;

    // send event to all listeners except the source
    ListIterator iter = listeners.listIterator();
    while (iter.hasNext()) {
      Object client = iter.next();
      if (client == source)
        continue;

      try {
        method.invoke(client, args);
      } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException e) {
        e.printStackTrace();
        if (e.getCause() != null)
          e.getCause().printStackTrace();

        // iter.remove();
        logger.error("ListenerManager calling " + method + " threw exception ", e);
      }
    }
  }

Send an event to all registered listeners, except the named one.

@param event the event to be sent: public void method_name( event_class event)

Send an event to all registered listeners except the named one .


public static boolean print(String command, Writer out, ucar.nc2.util.CancelTask ct) throws IOException {
    // pull out the filename from the command
    String filename;
    StringTokenizer stoke = new StringTokenizer(command);
    if (stoke.hasMoreTokens())
      filename = stoke.nextToken();
    else {
      out.write(usage);
      return false;
    }

    try (NetcdfFile nc = NetcdfDataset.openFile(filename, ct)) {
      // the rest of the command
      int pos = command.indexOf(filename);
      command = command.substring(pos + filename.length());
      return print(nc, command, out, ct);

    } catch (java.io.FileNotFoundException e) {
      out.write("file not found= ");
      out.write(filename);
      return false;

    } finally {
      out.close();
    }
  }

ncdump that parses a command string.

@param command command string
@param out     send output here
@param ct      allow task to be cancelled; may be null.
@return true if successful
@throws IOException on write error


public static boolean print(NetcdfFile nc, String command, Writer out, ucar.nc2.util.CancelTask ct)
          throws IOException {
    WantValues showValues = WantValues.none;
    boolean ncml = false;
    boolean strict = false;
    String varNames = null;
    String trueDataset = null;
    String fakeDataset = null;

    if (command != null) {
      StringTokenizer stoke = new StringTokenizer(command);

      while (stoke.hasMoreTokens()) {
        String toke = stoke.nextToken();
        if (toke.equalsIgnoreCase("-help")) {
          out.write(usage);
          out.write('\n');
          return true;
        }
        if (toke.equalsIgnoreCase("-vall"))
          showValues = WantValues.all;
        if (toke.equalsIgnoreCase("-c") && (showValues == WantValues.none))
          showValues = WantValues.coordsOnly;
        if (toke.equalsIgnoreCase("-ncml"))
          ncml = true;
        if (toke.equalsIgnoreCase("-cdl") || toke.equalsIgnoreCase("-strict"))
          strict = true;
        if(toke.equalsIgnoreCase("-v") && stoke.hasMoreTokens())
          varNames = stoke.nextToken();
        if (toke.equalsIgnoreCase("-datasetname") && stoke.hasMoreTokens()) {
          fakeDataset = stoke.nextToken();
          if(fakeDataset.length() == 0) fakeDataset = null;
          if(fakeDataset != null) {
            trueDataset = nc.getLocation();
            nc.setLocation(fakeDataset);
          }
        }
      }
    }

    boolean ok = print(nc, out, showValues, ncml, strict, varNames, ct);
    if(trueDataset != null && fakeDataset != null)
      nc.setLocation(trueDataset);
    return ok;
  }

public static boolean print ( NetcdfFile nc , String command , Writer out , ucar . nc2 . util . CancelTask ct ) throws IOException { WantValues showValues = WantValues . none ; boolean ncml = false ; boolean strict = false ; String varNames = null ; String trueDataset = null ; String fakeDataset = null ; if ( command != null ) { StringTokenizer stoke = new StringTokenizer ( command ) ; while ( stoke . hasMoreTokens ( ) ) { String toke = stoke . nextToken ( ) ; if ( toke . equalsIgnoreCase ( "-help" ) ) { out . write ( usage ) ; out . write ( ' ' ) ; return true ; } if ( toke . equalsIgnoreCase ( "-vall" ) ) showValues = WantValues . all ; if ( toke . equalsIgnoreCase ( "-c" ) && ( showValues == WantValues . none ) ) showValues = WantValues . coordsOnly ; if ( toke . equalsIgnoreCase ( "-ncml" ) ) ncml = true ; if ( toke . equalsIgnoreCase ( "-cdl" ) || toke . equalsIgnoreCase ( "-strict" ) ) strict = true ; if ( toke . equalsIgnoreCase ( "-v" ) && stoke . hasMoreTokens ( ) ) varNames = stoke . nextToken ( ) ; if ( toke . equalsIgnoreCase ( "-datasetname" ) && stoke . hasMoreTokens ( ) ) { fakeDataset = stoke . nextToken ( ) ; if ( fakeDataset . length ( ) == 0 ) fakeDataset = null ; if ( fakeDataset != null ) { trueDataset = nc . getLocation ( ) ; nc . setLocation ( fakeDataset ) ; } } } } boolean ok = print ( nc , out , showValues , ncml , strict , varNames , ct ) ; if ( trueDataset != null && fakeDataset != null ) nc . setLocation ( trueDataset ) ; return ok ; }

ncdump, parsing command string, file already open.

@param nc      apply command to this file
@param command : command string
@param out     send output here
@param ct      allow task to be cancelled; may be null.
@return true if successful
@throws IOException on write error

ncdump parsing command string file already open .


static public String printVariableData(VariableIF v, ucar.nc2.util.CancelTask ct) throws IOException {
    Array data = v.read();
    /* try {
      data = v.isMemberOfStructure() ? v.readAllStructures(null, true) : v.read();
    }
    catch (InvalidRangeException ex) {
      return ex.getMessage();
    } */

    StringWriter writer = new StringWriter(10000);
    printArray(data, v.getFullName(), new PrintWriter(writer), new Indent(2), ct);
    return writer.toString();
  }

Print all the data of the given Variable.

@param v  variable to print
@param ct allow task to be cancelled; may be null.
@return String result
@throws IOException on write error

Print all the data of the given Variable .


static public String printVariableDataSection(Variable v, String sectionSpec, ucar.nc2.util.CancelTask ct) throws IOException, InvalidRangeException {
    Array data = v.read(sectionSpec);

    StringWriter writer = new StringWriter(20000);
    printArray(data, v.getFullName(), new PrintWriter(writer), new Indent(2), ct);
    return writer.toString();
  }

static public String printVariableDataSection ( Variable v , String sectionSpec , ucar . nc2 . util . CancelTask ct ) throws IOException , InvalidRangeException { Array data = v . read ( sectionSpec ) ; StringWriter writer = new StringWriter ( 20000 ) ; printArray ( data , v . getFullName ( ) , new PrintWriter ( writer ) , new Indent ( 2 ) , ct ) ; return writer . toString ( ) ; }

Print a section of the data of the given Variable.

@param v           variable to print
@param sectionSpec string specification
@param ct          allow task to be cancelled; may be null.
@return String result formatted data ouptut
@throws IOException           on write error
@throws InvalidRangeException is specified section doesnt match variable shape

Print a section of the data of the given Variable .


static public void printStructureData(PrintWriter out, StructureData sdata) throws IOException {
    printStructureData(out, sdata, new Indent(2), null);
    out.flush();
  }

static public void printStructureData ( PrintWriter out , StructureData sdata ) throws IOException { printStructureData ( out , sdata , new Indent ( 2 ) , null ) ; out . flush ( ) ; }

Print contents of a StructureData.

@param out   send output here.
@param sdata StructureData to print.
@throws IOException on read error


static public void printArrayPlain(Array ma, PrintWriter out) {
    ma.resetLocalIterator();
    while (ma.hasNext()) {
      out.print(ma.next());
      out.print(' ');
    }
  }

static public void printArrayPlain ( Array ma , PrintWriter out ) { ma . resetLocalIterator ( ) ; while ( ma . hasNext ( ) ) { out . print ( ma . next ( ) ) ; out . print ( ' ' ) ; } }

Print array as undifferentiated sequence of values.

@param ma  any Array except ArrayStructure
@param out print to here

Print array as undifferentiated sequence of values .


static public void printArray(Array array, PrintWriter pw) {
    printArray(array, null, null, pw, new Indent(2), null, true);
  }

static public void printArray ( Array array , PrintWriter pw ) { printArray ( array , null , null , pw , new Indent ( 2 ) , null , true ) ; }


static public void writeNcML(NetcdfFile ncfile, Writer writer, WantValues showValues, String url) throws IOException {
    Preconditions.checkNotNull(ncfile);
    Preconditions.checkNotNull(writer);
    Preconditions.checkNotNull(showValues);

    Predicate<Variable> writeVarsPred;
    switch (showValues) {
      case none:
        writeVarsPred = NcMLWriter.writeNoVariablesPredicate;
        break;
      case coordsOnly:
        writeVarsPred = NcMLWriter.writeCoordinateVariablesPredicate;
        break;
      case all:
        writeVarsPred = NcMLWriter.writeAllVariablesPredicate;
        break;
      default:
        String message = String.format(
            "CAN'T HAPPEN: showValues (%s) != null and checked all possible enum values.", showValues);
        throw new AssertionError(message);
    }

    NcMLWriter ncmlWriter = new NcMLWriter();
    ncmlWriter.setWriteVariablesPredicate(writeVarsPred);

    Element netcdfElement = ncmlWriter.makeNetcdfElement(ncfile, url);
    ncmlWriter.writeToWriter(netcdfElement, writer);
  }

Write the NcML representation for a file.
Note that ucar.nc2.dataset.NcMLWriter has a JDOM implementation, for complete NcML.
This method implements only the "core" NcML for plain ole netcdf files.

@param ncfile     write NcML for this file
@param writer     write to this Writer. Must be using UTF-8 encoding (where applicable)
@param showValues do you want the variable values printed?
@param url        use this for the url attribute; if null use getLocation(). // ??
@throws IOException on write error

Write the NcML representation for a file . Note that ucar . nc2 . dataset . NcMLWriter has a JDOM implementation for complete NcML . This method implements only the core NcML for plain ole netcdf files .


protected double readAttributeDouble(AttributeContainer v, String attname, double defValue) {
    Attribute att = v.findAttributeIgnoreCase(attname);
    if (att == null) return defValue;
    if (att.isString())
      return Double.parseDouble(att.getStringValue());
    else
      return att.getNumericValue().doubleValue();
  }

protected double readAttributeDouble ( AttributeContainer v , String attname , double defValue ) { Attribute att = v . findAttributeIgnoreCase ( attname ) ; if ( att == null ) return defValue ; if ( att . isString ( ) ) return Double . parseDouble ( att . getStringValue ( ) ) ; else return att . getNumericValue ( ) . doubleValue ( ) ; }

Read a variable attribute as a double.

@param v        the variable
@param attname  name of variable
@param defValue default value if attribute is not found
@return attribute value as a double, else NaN if not found


protected boolean addParameter(CoordinateTransform rs, String paramName, NetcdfFile ds, String varNameEscaped) {
    if (null == (ds.findVariable(varNameEscaped))) {
      if (null != errBuffer)
        errBuffer.format("CoordTransBuilder %s: no Variable named %s%n", getTransformName(), varNameEscaped);
      return false;
    }

    rs.addParameter(new Parameter(paramName, varNameEscaped));
    return true;
  }

Add a Parameter to a CoordinateTransform.
Make sure that the variable exists. If readData is true, read the data and use it as the value of the
parameter, otherwise use the variable name as the value of the parameter.

@param rs             the CoordinateTransform
@param paramName      the parameter name
@param ds             dataset
@param varNameEscaped escaped variable name
@return true if success, false is failed

Add a Parameter to a CoordinateTransform . Make sure that the variable exists . If readData is true read the data and use it as the value of the parameter otherwise use the variable name as the value of the parameter .


public static void main(String[] args) throws IOException {
    AccessLogParser p = new AccessLogParser();
    String line = "24.18.236.132 - - [04/Feb/2011:17:49:03 -0700] \"GET /thredds/fileServer//nexrad/level3/N0R/YUX/20110205/Level3_YUX_N0R_20110205_0011.nids \" 200 10409 \"-\" \"-\" 17";
    Matcher m = regPattern.matcher(line);
    System.out.printf("%s %s%n", m.matches(), m);
    for (int i=0; i<m.groupCount(); i++) {
      System.out.println(" "+i+ " "+m.group(i));
    }

    LogReader.Log log = p.parseLog(line);
    System.out.printf("%s%n", log);
  }


protected Object
    readAs(DapVariable atomvar, DapType basetype, List<Slice> slices)
            throws DapException
    {
        if(basetype.getTypeSort() == TypeSort.Enum) {// short circuit this case
            basetype = ((DapEnumeration) basetype).getBaseType();
            return readAs(atomvar, basetype, slices);
        }
        long count = DapUtil.sliceProduct(slices);
        Object result = LibTypeFcns.newVector(basetype, count);
        Odometer odom = Odometer.factory(slices);
        if(DapUtil.isContiguous(slices) && basetype.isFixedSize())
            readContig(slices, basetype, count, odom, result);
        else
            readOdom(slices, basetype, odom, result);
        return result;
    }

protected
Object
readAs
(
DapVariable
atomvar
,
DapType
basetype
,
List
<
Slice
>
slices
)
throws
DapException
{
if
(
basetype
.
getTypeSort
(
)
==
TypeSort
.
Enum
)
{
// short circuit this case
basetype
=
(
(
DapEnumeration
)
basetype
)
.
getBaseType
(
)
;
return
readAs
(
atomvar
,
basetype
,
slices
)
;
}
long
count
=
DapUtil
.
sliceProduct
(
slices
)
;
Object
result
=
LibTypeFcns
.
newVector
(
basetype
,
count
)
;
Odometer
odom
=
Odometer
.
factory
(
slices
)
;
if
(
DapUtil
.
isContiguous
(
slices
)
&&
basetype
.
isFixedSize
(
)
)
readContig
(
slices
,
basetype
,
count
,
odom
,
result
)
;
else
readOdom
(
slices
,
basetype
,
odom
,
result
)
;
return
result
;
}

Allow specification of basetype to use; used for enumerations

@param atomvar
@param basetype
@param slices
@return
@throws DapException

Allow specification of basetype to use ; used for enumerations


public final boolean isPositiveUp(GridRecord gr) {
    int type = gr.getLevelType1();
    if ((type == 1) || (type == 5)) {
      return false;
    }
    return true;
  }

public final boolean isPositiveUp ( GridRecord gr ) { int type = gr . getLevelType1 ( ) ; if ( ( type == 1 ) || ( type == 5 ) ) { return false ; } return true ; }

is this a PositiveUp VerticalCoordinate.

is this a PositiveUp VerticalCoordinate .


public boolean isCompatible(final Unit that) {
        // jeffm: for some reason just calling getDerivedUnit().equals(...)
        // with jikes 1.1.7 as the compiler causes the jvm to crash.
        // The Unit u1=... does not crash.
        final Unit u1 = getDerivedUnit();
        return u1.equals(that.getDerivedUnit());
        // return getDerivedUnit().equals(that.getDerivedUnit());
    }

Indicates if numeric values in this unit are convertible with another
unit.

@param that
The other unit.
@return true if and only if numeric values in this unit are
convertible the other unit.

Indicates if numeric values in this unit are convertible with another unit .


public String makeLabel(final String quantityID) {
        final StringBuilder buf = new StringBuilder(quantityID);
        if (quantityID.contains(" ")) {
            buf.insert(0, '(').append(')');
        }
        buf.append('/');
        final int start = buf.length();
        buf.append(toString());
        if (buf.substring(start).indexOf(' ') != -1) {
            buf.insert(start, '(').append(')');
        }
        return buf.toString();
    }

public
String
makeLabel
(
final
String
quantityID
)
{
final
StringBuilder
buf
=
new
StringBuilder
(
quantityID
)
;
if
(
quantityID
.
contains
(
" "
)
)
{
buf
.
insert
(
0
,
'
'
)
.
append
(
'
'
)
;
}
buf
.
append
(
'
'
)
;
final
int
start
=
buf
.
length
(
)
;
buf
.
append
(
toString
(
)
)
;
if
(
buf
.
substring
(
start
)
.
indexOf
(
'
'
)
!=
1
)
{
buf
.
insert
(
start
,
'
'
)
.
append
(
'
'
)
;
}
return
buf
.
toString
(
)
;
}

Returns a label for a quantity in this unit.

@param quantityID
The identifier for the quantity (e.g. "altitude").
@return The appropriate label (e.g. "altitude/m").

Returns a label for a quantity in this unit .


public void setBitOffset(int bitOffset) throws IOException {
    if (bitOffset % 8 == 0) {
      raf.seek(startPos + bitOffset / 8);
      bitPos = 0;
      bitBuf = 0;
    } else {
      raf.seek(startPos + bitOffset / 8);
      bitPos = 8 - (bitOffset % 8);
      bitBuf = (byte) raf.read();
      bitBuf &= 0xff >> (8 - bitPos);   // mask off consumed bits
    }
  }

public
void
setBitOffset
(
int
bitOffset
)
throws
IOException
{
if
(
bitOffset
%
8
==
0
)
{
raf
.
seek
(
startPos
+
bitOffset
/
8
)
;
bitPos
=
0
;
bitBuf
=
0
;
}
else
{
raf
.
seek
(
startPos
+
bitOffset
/
8
)
;
bitPos
=
8
(
bitOffset
%
8
)
;
bitBuf
=
(
byte
)
raf
.
read
(
)
;
bitBuf
&=
0xff
>>
(
8
bitPos
)
;
// mask off consumed bits
}
}

Position file at bitOffset from startPos

@param bitOffset bit offset from starting position
@throws IOException on io error


public long bits2UInt(int nb) throws IOException {
    assert nb <= 64;
    assert nb >= 0;

    long result = 0;
    int bitsLeft = nb;

    while (bitsLeft > 0) {

      // we ran out of bits - fetch the next byte...
      if (bitPos == 0) {
        bitBuf = nextByte();
        bitPos = BIT_LENGTH;
      }

      // -- retrieve bit from current byte ----------
      // how many bits to read from the current byte
      int size = Math.min(bitsLeft, bitPos);
      // move my part to start
      int myBits = bitBuf >> (bitPos - size);
      // mask-off sign-extending
      myBits &= BYTE_BITMASK;
      // mask-off bits of next value
      myBits &= ~(BYTE_BITMASK << size);

      // -- put bit to result ----------------------
      // where to place myBits inside of result
      int shift = bitsLeft - size;
      assert shift >= 0;

      // put it there
      result |= myBits << shift;

      // -- put bit to result ----------------------
      // update information on what we consumed
      bitsLeft -= size;
      bitPos -= size;
    }

    return result;
  }

Read the next nb bits and return an Unsigned Long .

@param nb the number of bits to convert to int, must be 0 <= nb <= 64.
@return result
@throws java.io.IOException on read error


public long bits2SInt(int nb) throws IOException {

    long result = bits2UInt(nb);

    // check if we're negative
    if (getBit(result, nb)) {
      // it's negative! reset leading bit
      result = setBit(result, nb, false);
      // build 2's-complement
      result = ~result & LONG_BITMASK;
      result = result + 1;
    }

    return result;

  }

public
long
bits2SInt
(
int
nb
)
throws
IOException
{
long
result
=
bits2UInt
(
nb
)
;
// check if we're negative
if
(
getBit
(
result
,
nb
)
)
{
// it's negative! reset leading bit
result
=
setBit
(
result
,
nb
,
false
)
;
// build 2's-complement
result
=
~
result
&
LONG_BITMASK
;
result
=
result
+
1
;
}
return
result
;
}

Read the next nb bits and return an Signed Long .

@param nb the number of bits to convert to int, must be <= 64.
@return result
@throws java.io.IOException on read error


private void openConnection(String urlString, Command command) throws IOException, DAP2Exception
    {
        InputStream is = null;

        try {
            try (HTTPMethod method = HTTPFactory.Get(_session, urlString)) {

                if(acceptCompress)
                    method.setCompression("deflate,gzip");

                // enable sessions
                if(allowSessions)
                    method.setUseSessions(true);
                int statusCode;
                for(; ; ) {
                    statusCode = method.execute();
                    if(statusCode != HttpStatus.SC_SERVICE_UNAVAILABLE)
                        break;
                    Thread.sleep(5000);
                    System.err.println("Service Unavailable");
                }

                // debug
                // if (debugHeaders) ucar.httpservices.HttpClientManager.showHttpRequestInfo(f, method);

                if(statusCode == HttpStatus.SC_NOT_FOUND) {
                    throw new DAP2Exception(DAP2Exception.NO_SUCH_FILE, method.getStatusText() + ": " + urlString);
                }

                if(statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) {
                    throw new InvalidCredentialsException(method.getStatusText());
                }

                if(statusCode != HttpStatus.SC_OK) {
                    throw new DAP2Exception("Method failed:" + method.getStatusText() + " on URL= " + urlString);
                }

                // Get the response body.
                is = method.getResponseAsStream();

                // check if its an error
                Header header = method.getResponseHeader("Content-Description");
                if(header != null && (header.getValue().equals("dods-error")
                        || header.getValue().equals("dods_error"))) {
                    // create server exception object
                    DAP2Exception ds = new DAP2Exception();
                    // parse the Error object from stream and throw it
                    ds.parse(is);
                    throw ds;
                }

                ver = new ServerVersion(method);

                checkHeaders(method);

                // check for deflator
                Header h = method.getResponseHeader("content-encoding");
                String encoding = (h == null) ? null : h.getValue();
                //if (encoding != null) LogStream.out.println("encoding= " + encoding);

                if(encoding != null && encoding.equals("deflate")) {
                    is = new BufferedInputStream(new InflaterInputStream(is), 1000);
                    if(showCompress) System.out.printf("deflate %s%n", urlString);

                } else if(encoding != null && encoding.equals("gzip")) {
                    is = new BufferedInputStream(new GZIPInputStream(is), 1000);
                    if(showCompress) System.out.printf("gzip %s%n", urlString);
                } else {
                    if(showCompress) System.out.printf("none %s%n", urlString);
                }

                command.process(is);
            }

        } catch (IOException | DAP2Exception e) {
            throw e;

        } catch (Exception e) {
            Util.check(e);
            //e.printStackTrace();
            throw new DAP2Exception(e);
        }
    }

Open a connection to the DODS server.

@param urlString the URL to open; assume already properly encoded
@param command   execute this command on the input stream
@throws IOException   if an IO exception occurred.
@throws DAP2Exception if the DODS server returned an error.


public DAS getDAS() throws IOException, DAP2Exception
    {
        DASCommand command = new DASCommand();
        if(filePath != null) { // url was file:
            File daspath = new File(filePath + ".das");
            // See if the das file exists
            if(daspath.canRead()) {
                try (FileInputStream is = new FileInputStream(daspath)) {
                    command.process(is);
                }
            }
        } else if(stream != null) {
            command.process(stream);
        } else { // assume url is remote
            try {
                openConnection(urlString + ".das" + getCompleteCE(projString,selString), command);
            } catch (DAP2Exception de) {
                //if(de.getErrorCode() != DAP2Exception.NO_SUCH_FILE)
                //throw de;  // rethrow
            }
        }
        return command.das;
    }

Returns the DAS object from the dataset referenced by this object's URL.
The DAS object is referred to by appending `.das' to the end of a DODS
URL.

@return the DAS associated with the referenced dataset.
@throws MalformedURLException if the URL given to the
constructor has an error
@throws IOException           if an error connecting to the remote server
@throws DASException          on an error constructing the DAS
@throws DAP2Exception         if an error returned by the remote server

Returns the DAS object from the dataset referenced by this object s URL . The DAS object is referred to by appending . das to the end of a DODS URL .


public DDS getDDS(String CE) throws IOException, ParseException, DAP2Exception
    {
        DDSCommand command = new DDSCommand();
        command.setURL(CE == null || CE.length() == 0 ? urlString : urlString + "?" + CE);
        if(filePath != null) {
            try (FileInputStream is = new FileInputStream(filePath + ".dds")) {
                command.process(is);
            }
        } else if(stream != null) {
            command.process(stream);
        } else { // must be a remote url
            openConnection(urlString + ".dds" + (getCompleteCE(CE)), command);
        }
        return command.dds;
    }

public
DDS
getDDS
(
String
CE
)
throws
IOException
,
ParseException
,
DAP2Exception
{
DDSCommand
command
=
new
DDSCommand
(
)
;
command
.
setURL
(
CE
==
||
CE
.
length
(
)
==
0
urlString
:
urlString
+
"?"
+
CE
)
;
if
(
filePath
!=
)
{
try
(
FileInputStream
is
=
new
FileInputStream
(
filePath
+
".dds"
)
)
{
command
.
process
(
is
)
;
}
}
else
if
(
stream
!=
)
{
command
.
process
(
stream
)
;
}
else
{
// must be a remote url
openConnection
(
urlString
+
".dds"
+
(
getCompleteCE
(
CE
)
)
,
command
)
;
}
return
command
.
dds
;
}

Returns the DDS object from the dataset referenced by this object's URL.
The DDS object is referred to by appending `.dds' to the end of a OPeNDAP
URL.

@param CE The constraint expression to be applied to this request by the
server.  This is combined with any CE given in the constructor.
@return the DDS associated with the referenced dataset.
@throws MalformedURLException if the URL given to the constructor
has an error
@throws IOException           if an error connecting to the remote server
@throws ParseException        if the DDS parser returned an error
@throws DDSException          on an error constructing the DDS
@throws DAP2Exception         if an error returned by the remote server

Returns the DDS object from the dataset referenced by this object s URL . The DDS object is referred to by appending . dds to the end of a OPeNDAP URL .


private String getCompleteCE(String CE)
    {
        String localProjString = null;
        String localSelString = null;
        if(CE == null)
            return "";
        //remove any leading '?'
        if(CE.startsWith("?")) CE = CE.substring(1);
        int selIndex = CE.indexOf('&');
        if(selIndex == 0) {
            localProjString = "";
            localSelString = CE;
        } else if(selIndex > 0) {
            localSelString = CE.substring(selIndex);
            localProjString = CE.substring(0, selIndex);
        } else {// selIndex < 0
            localProjString = CE;
            localSelString = "";
        }

        String ce = projString;

        if(!localProjString.equals("")) {
            if(!ce.equals("") && localProjString.indexOf(',') != 0)
                ce += ",";
            ce += localProjString;
        }

        if(!selString.equals("")) {
            if(selString.indexOf('&') != 0)
                ce += "&";
            ce += selString;
        }

        if(!localSelString.equals("")) {
            if(localSelString.indexOf('&') != 0)
                ce += "&";
            ce += localSelString;
        }

        if(ce.length() > 0) ce = "?" + ce;

        if(false) {
            DAPNode.log.debug("projString: '" + projString + "'");
            DAPNode.log.debug("localProjString: '" + localProjString + "'");
            DAPNode.log.debug("selString: '" + selString + "'");
            DAPNode.log.debug("localSelString: '" + localSelString + "'");
            DAPNode.log.debug("Complete CE: " + ce);
        }
        return ce;   // escaping will happen elsewhere
    }

private
String
getCompleteCE
(
String
CE
)
{
String
localProjString
=
;
String
localSelString
=
;
if
(
CE
==
)
return
""
;
//remove any leading '?'
if
(
CE
.
startsWith
(
"?"
)
)
CE
=
CE
.
substring
(
1
)
;
int
selIndex
=
CE
.
indexOf
(
'
'
)
;
if
(
selIndex
==
0
)
{
localProjString
=
""
;
localSelString
=
CE
;
}
else
if
(
selIndex
>
0
)
{
localSelString
=
CE
.
substring
(
selIndex
)
;
localProjString
=
CE
.
substring
(
0
,
selIndex
)
;
}
else
{
// selIndex < 0
localProjString
=
CE
;
localSelString
=
""
;
}
String
ce
=
projString
;
if
(
!
localProjString
.
equals
(
""
)
)
{
if
(
!
ce
.
equals
(
""
)
&&
localProjString
.
indexOf
(
'
'
)
!=
0
)
ce
+=
","
;
ce
+=
localProjString
;
}
if
(
!
selString
.
equals
(
""
)
)
{
if
(
selString
.
indexOf
(
'
'
)
!=
0
)
ce
+=
"&"
;
ce
+=
selString
;
}
if
(
!
localSelString
.
equals
(
""
)
)
{
if
(
localSelString
.
indexOf
(
'
'
)
!=
0
)
ce
+=
"&"
;
ce
+=
localSelString
;
}
if
(
ce
.
length
(
)
>
0
)
ce
=
"?"
+
ce
;
if
(
false
)
{
DAPNode
.
log
.
debug
(
"projString: '"
+
projString
+
"'"
)
;
DAPNode
.
log
.
debug
(
"localProjString: '"
+
localProjString
+
"'"
)
;
DAPNode
.
log
.
debug
(
"selString: '"
+
selString
+
"'"
)
;
DAPNode
.
log
.
debug
(
"localSelString: '"
+
localSelString
+
"'"
)
;
DAPNode
.
log
.
debug
(
"Complete CE: "
+
ce
)
;
}
return
ce
;
// escaping will happen elsewhere
}

Use some sense when assembling the CE. Since this DConnect
object may have constructed using a CE, any new CE will
have to be integrated into it for subsequent requests.
Try to do this in a sensible manner!

@param CE The new CE from the client.
@return The complete CE (the one this object was built
with integrated with the clients)

Use some sense when assembling the CE . Since this DConnect object may have constructed using a CE any new CE will have to be integrated into it for subsequent requests . Try to do this in a sensible manner!


@Override
    public LatLonPoint projToLatLon(ProjectionPoint world, LatLonPointImpl result) {
        double fromX = world.getX() - falseEasting;
        double fromY = world.getY() - falseNorthing;

        double toLat_r = fromY / earthRadius;
        double toLon_r;

        if (Misc.nearlyEquals(Math.abs(toLat_r), PI_OVER_2, 1e-10)) {
            toLat_r = toLat_r < 0 ? -PI_OVER_2 : +PI_OVER_2;
            toLon_r = Math.toRadians(centMeridian);  // if lat == +- pi/2, set lon = centMeridian (Snyder 248)
        } else if (Math.abs(toLat_r) < PI_OVER_2) {
            toLon_r = Math.toRadians(centMeridian) + fromX / (earthRadius * Math.cos(toLat_r));
        } else {
            return INVALID;  // Projection point is off the map.
        }

        if (Misc.nearlyEquals(Math.abs(toLon_r), PI, 1e-10)) {
            toLon_r = toLon_r < 0 ? -PI : +PI;
        } else if (Math.abs(toLon_r) > PI) {
            return INVALID;  // Projection point is off the map.
        }

        result.setLatitude(Math.toDegrees(toLat_r));
        result.setLongitude(Math.toDegrees(toLon_r));
        return result;
    }

Convert projection coordinates to a LatLonPoint

@param world  convert from these projection coordinates
@param result the object to write to
@return LatLonPoint the lat/lon coordinates


private String idvDatasetCatalog(String xml)
    {
        String ret = xml.replace("variables", "Variables");
        ret = ret.replace("timeCoverage", "TimeSpan");
        StringBuilder sub = new StringBuilder(ret.substring(0,
                ret.indexOf("<geospatialCoverage>")));
        sub.append("<LatLonBox>\n\t<north>90.0</north>\n\t<south>-90.0</south>");
        sub.append("\n\t<east>180.0</east>\n\t<west>-180.0</west></LatLonBox>");
        String endCoverage = "</geospatialCoverage>";
        sub.append(ret.substring(ret.indexOf(endCoverage) + endCoverage.length()));
        return sub.toString();
    }

This code tweaks our catalog output to match.

This code tweaks our catalog output to match .


private DateRange idvCompatibleRange(DateRange range)
    {
        CalendarDate start = range.getStart().getCalendarDate();
        CalendarDate end = range.getEnd().getCalendarDate();
        return new DateRange(start.toDate(), end.toDate());
    }

private DateRange idvCompatibleRange ( DateRange range ) { CalendarDate start = range . getStart ( ) . getCalendarDate ( ) ; CalendarDate end = range . getEnd ( ) . getCalendarDate ( ) ; return new DateRange ( start . toDate ( ) , end . toDate ( ) ) ; }


boolean isValidFile( ucar.unidata.io.RandomAccessFile raFile )
  {
    // @todo This method should not be called if read() has or will be called on this instance.
    this.raFile = raFile;
    try
    {
      this.actualSize = raFile.length();
    }
    catch ( IOException e )
    {
      return( false );
    }
    try
    {
      this.readHeaderFromFile( raFile );

      this.handleFileInformation();
      this.handleProcessingInformation();
      this.handleSatelliteInformation();
      this.handleSensorInformation();
    }
    catch ( IOException e )
    {
      return( false );
    }
    return( true );
  }

Check basic DMSP file validity of given random access file.

Check basic DMSP file validity of given random access file .


private void handleSatelliteInformation()
  {
    spacecraftIdAtt = new Attribute(
            this.spacecraftIdAttName,
            headerInfo.get(HeaderInfoTitle.SPACECRAFT_ID.toString()));
    noradIdAtt = new Attribute(
            this.noradIdAttName,
            headerInfo.get(HeaderInfoTitle.NORAD_ID.toString()));
  }

private void handleSatelliteInformation ( ) { spacecraftIdAtt = new Attribute ( this . spacecraftIdAttName , headerInfo . get ( HeaderInfoTitle . SPACECRAFT_ID . toString ( ) ) ) ; noradIdAtt = new Attribute ( this . noradIdAttName , headerInfo . get ( HeaderInfoTitle . NORAD_ID . toString ( ) ) ) ; }

Parse the satellite information from the header.

Parse the satellite information from the header .


private void handleSensorInformation()
  {
    numSamplesPerBand = Integer.parseInt( headerInfo.get( HeaderInfoTitle.SAMPLES_PER_BAND.toString()) );
    numSamplesPerBandDim = new Dimension(
            this.numSamplesPerBandDimName,
            numSamplesPerBand);

    // Read nominal resolution information
    nominalResolutionAtt = new Attribute( nominalResolutionAttName, headerInfo.get(HeaderInfoTitle.NOMINAL_RESOLUTION.toString()));

    // Read bands per scanlin information.
    bandsPerScanlineAtt = new Attribute( bandsPerScanlineAttName, Integer.valueOf(headerInfo.get(HeaderInfoTitle.BANDS_PER_SCANLINE.toString())));

    // Read bytes per smaple information
    bytesPerSampleAtt = new Attribute( bytesPerSampleAttName, Integer.valueOf(headerInfo.get(HeaderInfoTitle.BYTES_PER_SAMPLE.toString())));

    // Read byte offset for band 1 information.
    byteOffsetBand1Att = new Attribute( byteOffsetBand1AttName, Integer.valueOf(headerInfo.get(HeaderInfoTitle.BYTE_OFFSET_BAND_1.toString())));

    // Read byte offset for band 2 information.
    byteOffsetBand2Att = new Attribute( byteOffsetBand2AttName, Integer.valueOf(headerInfo.get(HeaderInfoTitle.BYTE_OFFSET_BAND_2.toString())));

    // Band 1 description
    band1Att = new Attribute( band1AttName, headerInfo.get( HeaderInfoTitle.BAND_1.toString()));

    // Band 2 description
    band2Att = new Attribute( band2AttName, headerInfo.get( HeaderInfoTitle.BAND_2.toString()));

    // Band organization
    bandOrganizationAtt = new Attribute( bandOrganizationAttName, headerInfo.get(HeaderInfoTitle.ORGANIZATION.toString()));

    // thermal offset
    thermalOffsetAtt = new Attribute( thermalOffsetAttName, headerInfo.get(HeaderInfoTitle.THERMAL_OFFSET.toString()));

    // thermal scale
    thermalScaleAtt = new Attribute( thermalScaleAttName, headerInfo.get(HeaderInfoTitle.THERMAL_SCALE.toString()));

    // percent daylight
    percentDaylightAtt = new Attribute( percentDaylightAttName, Double.valueOf(headerInfo.get(HeaderInfoTitle.PERCENT_DAYLIGHT.toString())));

    // percent full moon
    percentFullMoonAtt = new Attribute( percentFullMoonAttName, Double.valueOf(headerInfo.get(HeaderInfoTitle.PERCENT_FULL_MOON.toString())));

    // percent terminator evident
    percentTerminatorEvidentAtt = new Attribute( percentTerminatorEvidentAttName, Double.valueOf(headerInfo.get(HeaderInfoTitle.PERCENT_TERMINATOR_EVIDENT.toString())));
  }

Parse the sensor information from the header.

Parse the sensor information from the header .


static public Element readRootElement(String location) throws IOException {
    org.jdom2.Document doc;
    try {
      SAXBuilder builder = new SAXBuilder();
      doc = builder.build(location);
    } catch (JDOMException e) {
      throw new IOException(e.getMessage());
    }

    return doc.getRootElement();
  }

static public Element readRootElement ( String location ) throws IOException { org . jdom2 . Document doc ; try { SAXBuilder builder = new SAXBuilder ( ) ; doc = builder . build ( location ) ; } catch ( JDOMException e ) { throw new IOException ( e . getMessage ( ) ) ; } return doc . getRootElement ( ) ; }

Read an XML Document from a URL and return the root element.

@param location the URL location
@return the root element of the Document
@throws java.io.IOException on read error

Read an XML Document from a URL and return the root element .


static public String cleanCharacterData(String text) {
    if (text == null) return null;

    boolean bad = false;
    for (int i = 0, len = text.length(); i < len; i++) {
      int ch = text.charAt(i);
      if (!org.jdom2.Verifier.isXMLCharacter(ch)) {
        bad = true;
        break;
      }
    }

    if (!bad) return text;

    StringBuilder sbuff = new StringBuilder(text.length());
    for (int i = 0, len = text.length(); i < len; i++) {
      int ch = text.charAt(i);
      if (org.jdom2.Verifier.isXMLCharacter(ch))
        sbuff.append((char) ch);
    }
    return sbuff.toString();
  }

static public String cleanCharacterData ( String text ) { if ( text == null ) return null ; boolean bad = false ; for ( int i = 0 , len = text . length ( ) ; i < len ; i ++ ) { int ch = text . charAt ( i ) ; if ( ! org . jdom2 . Verifier . isXMLCharacter ( ch ) ) { bad = true ; break ; } } if ( ! bad ) return text ; StringBuilder sbuff = new StringBuilder ( text . length ( ) ) ; for ( int i = 0 , len = text . length ( ) ; i < len ; i ++ ) { int ch = text . charAt ( i ) ; if ( org . jdom2 . Verifier . isXMLCharacter ( ch ) ) sbuff . append ( ( char ) ch ) ; } return sbuff . toString ( ) ; }

Make sure that text is XML safe
@param text check this
@return original text if ok, else with bad characters removed


private static String xunescapeString(String in, char escape, boolean spaceplus)
    {
        try {
            if(in == null) return null;

            byte[] utf8 = in.getBytes(utf8Charset);
            byte escape8 = (byte) escape;
            byte[] out = new byte[utf8.length]; // Should be max we need

            int index8 = 0;
            for(int i = 0; i < utf8.length; ) {
                byte b = utf8[i++];
                if(b == plus && spaceplus) {
                    out[index8++] = blank;
                } else if(b == escape8) {
                    // check to see if there are enough characters left
                    if(i + 2 <= utf8.length) {
                        b = (byte) (fromHex(utf8[i]) << 4 | fromHex(utf8[i + 1]));
                        i += 2;
                    }
                }
                out[index8++] = b;
            }
            return new String(out, 0, index8, utf8Charset);
        } catch (Exception e) {
            return in;
        }

    }

Given a string that contains WWW escape sequences, translate those escape
sequences back into ASCII characters. Return the modified string.

@param in        The string to modify.
@param escape    The character used to signal the begining of an escape sequence.
param except If there is some escape code that should not be removed by
this call (e.g., you might not want to remove spaces, %20) use this
parameter to specify that code. The function will then transform all
escapes except that one.
@param spaceplus True if spaces should be replaced by '+'.
@return The modified string.

Given a string that contains WWW escape sequences translate those escape sequences back into ASCII characters . Return the modified string .


public static String escapeURLQuery(String ce)
    {
        try {
            ce = escapeString(ce, _allowableInUrlQuery);
        } catch (Exception e) {
            ce = null;
        }
        return ce;
    }

public static String escapeURLQuery ( String ce ) { try { ce = escapeString ( ce , _allowableInUrlQuery ) ; } catch ( Exception e ) { ce = null ; } return ce ; }

Define the DEFINITIVE URL constraint expression escape function.

@param ce The expression to modify.
@return The escaped expression.

Define the DEFINITIVE URL constraint expression escape function .


public static String unescapeURLQuery(String ce)
    {
        try {
            ce = unescapeString(ce);
        } catch (Exception e) {
            ce = null;
        }
        return ce;
    }

public static String unescapeURLQuery ( String ce ) { try { ce = unescapeString ( ce ) ; } catch ( Exception e ) { ce = null ; } return ce ; }

Define the DEFINITIVE URL constraint expression unescape function.

@param ce The expression to unescape.
@return The unescaped expression.

Define the DEFINITIVE URL constraint expression unescape function .


public static String backslashDecode(String s)
    {
        StringBuilder buf = new StringBuilder(s);
        int i = 0;
        while(i < buf.length()) {
            if(buf.charAt(i) == '\\') {
                buf.deleteCharAt(i);
            }
            i++;
        }
        return buf.toString();
    }

public static String backslashDecode ( String s ) { StringBuilder buf = new StringBuilder ( s ) ; int i = 0 ; while ( i < buf . length ( ) ) { if ( buf . charAt ( i ) == ' ' ) { buf . deleteCharAt ( i ) ; } i ++ ; } return buf . toString ( ) ; }

Define the DEFINITIVE URL BACKSLASH unescape function.

@param s The string to unescape.
@return The unescaped expression.

Define the DEFINITIVE URL BACKSLASH unescape function .


public static String backslashEncode(String s)
    {
        StringBuilder buf = new StringBuilder();
        for(int i = 0; i < s.length(); i++) {
            int c = buf.charAt(i);
            if(_MustBackslashEscape.indexOf(c) >= 0)
                buf.append(_BACKSLASHEscape);
            buf.append((char) c);
        }
        return buf.toString();
    }

public static String backslashEncode ( String s ) { StringBuilder buf = new StringBuilder ( ) ; for ( int i = 0 ; i < s . length ( ) ; i ++ ) { int c = buf . charAt ( i ) ; if ( _MustBackslashEscape . indexOf ( c ) >= 0 ) buf . append ( _BACKSLASHEscape ) ; buf . append ( ( char ) c ) ; } return buf . toString ( ) ; }

Define the DEFINITIVE URL BACKSLASH escape function.

@param s The string to escape.
@return The escaped expression.

Define the DEFINITIVE URL BACKSLASH escape function .


protected void addLightningGlobalAttributes(NetcdfFile ncfile) {
        ncfile.addAttribute(null, new Attribute(CF.FEATURE_TYPE, CF.FeatureType.point.toString()));
        ncfile.addAttribute( null, new Attribute(CDM.HISTORY, "Read directly by Netcdf Java IOSP"));
    }

protected
void
addLightningGlobalAttributes
(
NetcdfFile
ncfile
)
{
ncfile
.
addAttribute
(
,
new
Attribute
(
CF
.
FEATURE_TYPE
,
CF
.
FeatureType
.
point
.
toString
(
)
)
)
;
ncfile
.
addAttribute
(
,
new
Attribute
(
CDM
.
HISTORY
,
"Read directly by Netcdf Java IOSP"
)
)
;
}

Add the global attributes.  Specific implementations should call super
and then add their own.
@param ncfile  the file to add to

Add the global attributes . Specific implementations should call super and then add their own .


static public short swapShort(byte[] b, int offset) {
        // 2 bytes
        int low  = b[offset] & 0xff;
        int high = b[offset + 1] & 0xff;
        return (short) (high << 8 | low);
    }

static
public
short
swapShort
(
byte
[
]
b
,
int
offset
)
{
// 2 bytes
int
low
=
b
[
offset
]
&
0xff
;
int
high
=
b
[
offset
+
1
]
&
0xff
;
return
(
short
)
(
high
<<
8
|
low
)
;
}

Returns the short 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 short represented by the bytes
b[offset+1], b[offset]

Returns the short resulting from swapping 2 bytes at a specified offset in a byte array .


static public int swapInt(byte[] b, int offset) {
        // 4 bytes
        int accum = 0;
        for (int shiftBy = 0, i = offset; shiftBy < 32; shiftBy += 8, i++) {
            accum |= (b[i] & 0xff) << shiftBy;
        }
        return accum;
    }

static
public
int
swapInt
(
byte
[
]
b
,
int
offset
)
{
// 4 bytes
int
accum
=
0
;
for
(
int
shiftBy
=
0
,
i
=
offset
;
shiftBy
<
32
;
shiftBy
+=
8
,
i
++
)
{
accum
|=
(
b
[
i
]
&
0xff
)
<<
shiftBy
;
}
return
accum
;
}

Returns the int 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 int represented by the bytes
b[offset+3], b[offset+2], ..., b[offset]

Returns the int resulting from reversing 4 bytes at a specified offset in a byte array .


static public double swapDouble(byte[] b, int offset) {
        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 Double.longBitsToDouble(accum);
    }

static public double swapDouble ( byte [ ] b , int offset ) { 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 Double . longBitsToDouble ( accum ) ; }

Returns the double 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 double represented by the bytes
b[offset+7], b[offset+6], ..., b[offset]

Returns the double resulting from reversing 8 bytes at a specified offset in a byte array .


static public float swapFloat(float v) {
        int l = swapInt(Float.floatToIntBits(v));
        return (Float.intBitsToFloat(l));
    }

static public float swapFloat ( float v ) { int l = swapInt ( Float . floatToIntBits ( v ) ) ; return ( Float . intBitsToFloat ( l ) ) ; }

Returns the float resulting from reversing 4 bytes of a specified
float.

@param  v       input value for which byte reversal is desired
@return         the value represented by the bytes of v
reversed

Returns the float resulting from reversing 4 bytes of a specified float .


static public double swapDouble(double v) {
        long l = swapLong(Double.doubleToLongBits(v));
        return (Double.longBitsToDouble(l));
    }

static public double swapDouble ( double v ) { long l = swapLong ( Double . doubleToLongBits ( v ) ) ; return ( Double . longBitsToDouble ( l ) ) ; }

Returns the double resulting from reversing 8 bytes of a specified
double.

@param  v       input value for which byte reversal is desired
@return         the value represented by the bytes of v
reversed

Returns the double resulting from reversing 8 bytes of a specified double .


static public byte[] shortToBytes(short v) {
        byte[] b       = new byte[2];
        int    allbits = 255;
        for (int i = 0; i < 2; i++) {
            b[1 - i] = (byte) ((v & (allbits << i * 8)) >> i * 8);
        }
        return b;
    }

static public byte [ ] shortToBytes ( short v ) { byte [ ] b = new byte [ 2 ] ; int allbits = 255 ; for ( int i = 0 ; i < 2 ; i ++ ) { b [ 1 - i ] = ( byte ) ( ( v & ( allbits << i * 8 ) ) >> i * 8 ) ; } return b ; }

Convert a short to an array of 2 bytes.

@param  v       input value
@return         the corresponding array of bytes

Convert a short to an array of 2 bytes .


static public byte[] intToBytes(int v) {
        byte[] b       = new byte[4];
        int    allbits = 255;
        for (int i = 0; i < 4; i++) {
            b[3 - i] = (byte) ((v & (allbits << i * 8)) >> i * 8);
        }
        return b;
    }

static public byte [ ] intToBytes ( int v ) { byte [ ] b = new byte [ 4 ] ; int allbits = 255 ; for ( int i = 0 ; i < 4 ; i ++ ) { b [ 3 - i ] = ( byte ) ( ( v & ( allbits << i * 8 ) ) >> i * 8 ) ; } return b ; }

Convert an int to an array of 4 bytes.

@param  v       input value
@return         the corresponding array of bytes


static public byte[] longToBytes(long v) {
        byte[] b       = new byte[8];
        long   allbits = 255;
        for (int i = 0; i < 8; i++) {
            b[7 - i] = (byte) ((v & (allbits << i * 8)) >> i * 8);
        }
        return b;
    }

static public byte [ ] longToBytes ( long v ) { byte [ ] b = new byte [ 8 ] ; long allbits = 255 ; for ( int i = 0 ; i < 8 ; i ++ ) { b [ 7 - i ] = ( byte ) ( ( v & ( allbits << i * 8 ) ) >> i * 8 ) ; } return b ; }

Convert a long to an array of 8 bytes.

@param  v       input value
@return         the corresponding array of bytes


public VerticalTransform subset(Range t_range, Range z_range,
                                    Range y_range, Range x_range)
            throws ucar.ma2.InvalidRangeException {
        return new VerticalTransformSubset(this, t_range, z_range, y_range, x_range);
    }

public VerticalTransform subset ( Range t_range , Range z_range , Range y_range , Range x_range ) throws ucar . ma2 . InvalidRangeException { return new VerticalTransformSubset ( this , t_range , z_range , y_range , x_range ) ; }

Create a subset of this VerticalTransform.

@param t_range subset the time dimension, or null if you want all of it
@param z_range subset the vertical dimension, or null if you want all of it
@param y_range subset the y dimension, or null if you want all of it
@param x_range subset the x dimension, or null if you want all of it

@return the subsetted VerticalTransform

@throws ucar.ma2.InvalidRangeException if any of the range parameters are illegal

Create a subset of this VerticalTransform .


public String writeXML(Date lastModified) {
    XMLOutputter fmt = new XMLOutputter(Format.getPrettyFormat());
    return fmt.outputString(writeDocument(lastModified));
  }

public String writeXML ( Date lastModified ) { XMLOutputter fmt = new XMLOutputter ( Format . getPrettyFormat ( ) ) ; return fmt . outputString ( writeDocument ( lastModified ) ) ; }

Write the XML representation to a String.

@return the XML representation to a String.

Write the XML representation to a String .


private Array makeC(Array s, double a, double b) {
    int nz = (int) s.getSize();
    Index sIndex = s.getIndex();
    if (a == 0) return s;  // per R. Signell, USGS

    ArrayDouble.D1 c = new ArrayDouble.D1(nz);

    double fac1 = 1.0 - b;
    double denom1 = 1.0 / Math.sinh(a);
    double denom2 = 1.0 / (2.0 * Math.tanh(0.5 * a));

    for (int i = 0; i < nz; i++) {
      double sz = s.getDouble(sIndex.set(i));
      double term1 = fac1 * Math.sinh(a * sz) * denom1;
      double term2 = b * (Math.tanh(a * (sz + 0.5))
          * denom2 - 0.5);
      c.set(i, term1 + term2);
    }

    return c;
  }

private
Array
makeC
(
Array
s
,
double
a
,
double
b
)
{
int
nz
=
(
int
)
s
.
getSize
(
)
;
Index
sIndex
=
s
.
getIndex
(
)
;
if
(
a
==
0
)
return
s
;
// per R. Signell, USGS
ArrayDouble
.
D1
c
=
new
ArrayDouble
.
D1
(
nz
)
;
double
fac1
=
1.0
b
;
double
denom1
=
1.0
/
Math
.
sinh
(
a
)
;
double
denom2
=
1.0
/
(
2.0
*
Math
.
tanh
(
0.5
*
a
)
)
;
for
(
int
i
=
0
;
i
<
nz
;
i
++
)
{
double
sz
=
s
.
getDouble
(
sIndex
.
set
(
i
)
)
;
double
term1
=
fac1
*
Math
.
sinh
(
a
*
sz
)
*
denom1
;
double
term2
=
b
*
(
Math
.
tanh
(
a
*
(
sz
+
0.5
)
)
*
denom2
0.5
)
;
c
.
set
(
i
,
term1
+
term2
)
;
}
return
c
;
}

Make the C array

@param s s Array
@param a "a" value
@param b "b" value
@return the C array


public void startXML() {
        fileOutput += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

        fileOutput += "<schema " + "xmlns:" + WFSController.TDSNAMESPACE + "="  + WFSXMLHelper.encQuotes(namespace) + " " +
                "xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
                "xmlns=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml\" " +
                "targetNamespace=\"" + server + "\" elementFormDefault=\"qualified\" " +
                "version=\"0.1\">";
        fileOutput += "<xsd:import namespace=\"http://www.opengis.net/gml\" " +
                "schemaLocation=\"http://schemas.opengis.net/gml/2.1.2/feature.xsd\"/>";
    }

Initiate the response with an XML file with an XML header


public void writeFeatures() {

        for (WFSFeature feat : featureList) {
            fileOutput += "<xsd:complexType name=\"" + feat.getTitle() + "\">";
            fileOutput += "<xsd:complexContent>";
            fileOutput += "<xsd:extension base=\"gml:" + feat.getType() + "\">";
            fileOutput += "<xsd:sequence>";

            for (WFSFeatureAttribute attribute : feat.getAttributes()) {
                fileOutput += "<xsd:element name =\"" + attribute.getName() + "\" type=\"" + attribute.getType() + "\"/>";
            }

            fileOutput += "</xsd:sequence>";
            fileOutput += "</xsd:extension>";
            fileOutput += "</xsd:complexContent>";
            fileOutput += "</xsd:complexType>";
            fileOutput += "<xsd:element name =\"" + feat.getName() + "\" type=\"tds:" + feat.getTitle() + "\"/>";

        }
    }

public
void
writeFeatures
(
)
{
for
(
WFSFeature
feat
:
featureList
)
{
fileOutput
+=
"<xsd:complexType name=\""
+
feat
.
getTitle
(
)
+
"\">"
;
fileOutput
+=
"<xsd:complexContent>"
;
fileOutput
+=
"<xsd:extension base=\"gml:"
+
feat
.
getType
(
)
+
"\">"
;
fileOutput
+=
"<xsd:sequence>"
;
for
(
WFSFeatureAttribute
attribute
:
feat
.
getAttributes
(
)
)
{
fileOutput
+=
"<xsd:element name =\""
+
attribute
.
getName
(
)
+
"\" type=\""
+
attribute
.
getType
(
)
+
"\"/>"
;
}
fileOutput
+=
"</xsd:sequence>"
;
fileOutput
+=
"</xsd:extension>"
;
fileOutput
+=
"</xsd:complexContent>"
;
fileOutput
+=
"</xsd:complexType>"
;
fileOutput
+=
"<xsd:element name =\""
+
feat
.
getName
(
)
+
"\" type=\"tds:"
+
feat
.
getTitle
(
)
+
"\"/>"
;
}
}

Write the features from the featureList. For each feature, write its attributes

Write the features from the featureList . For each feature write its attributes


void addLevels(List<GridRecord> records) {
    for (GridRecord record : records) {
      Double d = new Double(record.getLevel1());
      if (!levels.contains(d)) {
        levels.add(d);
      }
      if (dontUseVertical && (levels.size() > 1)) {
        if (GridServiceProvider.debugVert) {
          System.out.println(
                  "GribCoordSys: unused level coordinate has > 1 levels = "
                          + verticalName + " " + record.getLevelType1() + " "
                          + levels.size());
        }
      }
    }
    Collections.sort(levels);
    if (positive.equals("down")) {
      Collections.reverse(levels);
      // TODO: delete
      /* for( int i = 0; i < (levels.size()/2); i++ ){
        Double tmp = (Double) levels.get( i );
        levels.set( i, levels.get(levels.size() -i -1));
        levels.set(levels.size() -i -1, tmp );
     } */
    }
  }

Add levels from the GridRecords

@param records the records


void addDimensionsToNetcdfFile(NetcdfFile ncfile, Group g) {
    if (dontUseVertical) {
      return;
    }
    int nlevs = levels.size();
    ncfile.addDimension(g, new Dimension(verticalName, nlevs, true));
  }

void addDimensionsToNetcdfFile ( NetcdfFile ncfile , Group g ) { if ( dontUseVertical ) { return ; } int nlevs = levels . size ( ) ; ncfile . addDimension ( g , new Dimension ( verticalName , nlevs , true ) ) ; }

Add dimensions to the netcdf file

@param ncfile the netCDF file
@param g      the group to add to


void addToNetcdfFile(NetcdfFile ncfile, Group g) {
    if (dontUseVertical) {
      return;
    }

    if (g == null) {
      g = ncfile.getRootGroup();
    }

    String dims = "time";
    if (!dontUseVertical) {
      dims = dims + " " + verticalName;
    }
    if (hcs.isLatLon()) {
      dims = dims + " lat lon";
    } else {
      dims = dims + " y x";
    }

    //Collections.sort( levels);
    int nlevs = levels.size();
    // ncfile.addDimension(g, new Dimension(verticalName, nlevs, true));

    // coordinate axis and coordinate system Variable
    Variable v = new Variable(ncfile, g, null, verticalName);
    v.setDataType(DataType.DOUBLE);

    v.addAttribute(new Attribute("long_name",
            lookup.getLevelDescription(record)));
    v.addAttribute(new Attribute("units", lookup.getLevelUnit(record)));

    // positive attribute needed for CF-1 Height and Pressure
    if (positive != null) {
      v.addAttribute(new Attribute("positive", positive));
    }

    if (units != null) {
      AxisType axisType;
      if (SimpleUnit.isCompatible("millibar", units)) {
        axisType = AxisType.Pressure;
      } else if (SimpleUnit.isCompatible("m", units)) {
        axisType = AxisType.Height;
      } else {
        axisType = AxisType.GeoZ;
      }

      v.addAttribute(
              new Attribute(
                      "grid_level_type",
                      Integer.toString(record.getLevelType1())));

      v.addAttribute(new Attribute(_Coordinate.AxisType,
              axisType.toString()));
      v.addAttribute(new Attribute(_Coordinate.Axes, dims));
      if (!hcs.isLatLon()) {
        v.addAttribute(new Attribute(_Coordinate.Transforms,
                hcs.getGridName()));
      }
    }

    double[] data = new double[nlevs];
    for (int i = 0; i < levels.size(); i++) {
      Double d = (Double) levels.get(i);
      data[i] = d.doubleValue();
    }
    Array dataArray = Array.factory(DataType.DOUBLE, new int[]{nlevs}, data);

    v.setDimensions(verticalName);
    v.setCachedData(dataArray, false);

    ncfile.addVariable(g, v);

    // look for vertical transforms
    if (record.getLevelType1() == 109) {
      findCoordinateTransform(g, "Pressure", record.getLevelType1());
    }
  }

Add this coordinate system to the netCDF file

@param ncfile the netCDF file
@param g      the group to add to


void findCoordinateTransform(Group g, String nameStartsWith, int levelType) {
    // look for variable that uses this coordinate
    List<Variable> vars = g.getVariables();
    for (Variable v : vars) {
      if (v.getShortName().equals(nameStartsWith)) {
        Attribute att = v.findAttribute("grid_level_type");
        if ((att == null) || (att.getNumericValue().intValue() != levelType)) {
          continue;
        }

        v.addAttribute(new Attribute(_Coordinate.TransformType, "Vertical"));
        v.addAttribute(new Attribute("transform_name", "Existing3DField"));
      }
    }
  }

Find the coordinate transform

@param g              group to check
@param nameStartsWith beginning of name
@param levelType      type of level


int getIndex(GridRecord record) {
    Double d = new Double(record.getLevel1());
    return levels.indexOf(d);
  }

int getIndex ( GridRecord record ) { Double d = new Double ( record . getLevel1 ( ) ) ; return levels . indexOf ( d ) ; }

Get the index of a particular  GridRecord

@param record record to find
@return the index or -1


static public void exit() {
    if (timer != null) {
      timer.cancel();
      System.out.printf("DiskCache2.exit()%n");
    }
    timer = null;
  }

static public void exit ( ) { if ( timer != null ) { timer . cancel ( ) ; System . out . printf ( "DiskCache2.exit()%n" ) ; } timer = null ; }

Be sure to call this when your application exits, otherwise your process may not exit without being killed.

Be sure to call this when your application exits otherwise your process may not exit without being killed .


public File getFile(String fileLocation) {
    if (!alwaysUseCache) {
      File f = new File(fileLocation);
      if (f.exists()) return f;
      if (canWrite(f)) return f;
    }

    if (neverUseCache) {
      throw new IllegalStateException("neverUseCache=true, but file does not exist and directory is not writeable ="+fileLocation);
    }

    File f = new File(makeCachePath(fileLocation));
    if (cachePathPolicy == CachePathPolicy.NestedDirectory) {
      File dir = f.getParentFile();
      if (!dir.exists() && !dir.mkdirs())
        cacheLog.warn("Cant create directories for file "+dir.getPath());
    }

    return f;
  }

Get the named File.
If exists or isWritable, return it.
Otherwise get corresponding file in the cache directory.

If fileLocation has "/" in it, and cachePathPolicy == NestedDirectory, the
nested directories will be created.

@param fileLocation logical file location
@return physical File as named, or in the cache.

Get the named File . If exists or isWritable return it . Otherwise get corresponding file in the cache directory .


public File getExistingFileOrCache(String fileLocation) {
    File f = new File(fileLocation);
    if (f.exists()) return f;

    if (neverUseCache) return null;

    File fc = new File(makeCachePath(fileLocation));
    if (fc.exists()) return fc;

    return null;
  }

public File getExistingFileOrCache ( String fileLocation ) { File f = new File ( fileLocation ) ; if ( f . exists ( ) ) return f ; if ( neverUseCache ) return null ; File fc = new File ( makeCachePath ( fileLocation ) ) ; if ( fc . exists ( ) ) return fc ; return null ; }

Looking for an existing file, in cache or no
@param fileLocation the original name
@return existing file if you can find it

Looking for an existing file in cache or no


public void showCache(PrintStream pw) {
    pw.println("Cache files");
    pw.println("Size   LastModified       Filename");
    File dir = new File(root);
    File[] files = dir.listFiles();
    if (files != null)
      for (File file : files) {
        String org = null;
        try {
          org = URLDecoder.decode(file.getName(), "UTF8");
        } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
        }

        pw.println(" " + file.length() + " " + new Date(file.lastModified()) + " " + org);
      }
  }

public
void
showCache
(
PrintStream
pw
)
{
pw
.
println
(
"Cache files"
)
;
pw
.
println
(
"Size   LastModified       Filename"
)
;
File
dir
=
new
File
(
root
)
;
File
[
]
files
=
dir
.
listFiles
(
)
;
if
(
files
!=
)
for
(
File
file
:
files
)
{
String
org
=
;
try
{
org
=
URLDecoder
.
decode
(
file
.
getName
(
)
,
"UTF8"
)
;
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
(
)
;
}
pw
.
println
(
" "
+
file
.
length
(
)
+
" "
+
new
Date
(
file
.
lastModified
(
)
)
+
" "
+
org
)
;
}
}

Show cache contents, for debugging.
@param pw write to this PrintStream.


public void cleanCache(File dir, Formatter sbuff, boolean isRoot) {
    long now = System.currentTimeMillis();
    File[] files = dir.listFiles();
    if (files == null) {
      throw new IllegalStateException( "DiskCache2: not a directory or I/O error on dir="+dir.getAbsolutePath());
    }

    // check for empty directory
    if (!isRoot && (files.length == 0)) {
      long duration = now - dir.lastModified();
      duration /= 1000 * 60; // minutes
      if (duration > persistMinutes) {
        boolean ok = dir.delete();
        if (!ok)
          cacheLog.error("Unable to delete file " + dir.getAbsolutePath());
        if (sbuff != null)
          sbuff.format(" deleted %s %s lastModified= %s%n", ok, dir.getPath(), CalendarDate.of(dir.lastModified()));
      }
      return;
    }

    // check for expired files
    for (File file : files) {
      if (file.isDirectory()) {
        cleanCache(file, sbuff, false);
      } else {
        long duration = now - file.lastModified();
        duration /= 1000 * 60; // minutes
        if (duration > persistMinutes) {
          boolean ok = file.delete();
          if (!ok)
            cacheLog.error("Unable to delete file " + file.getAbsolutePath());
          if (sbuff != null)
            sbuff.format(" deleted %s %s lastModified= %s%n", ok, file.getPath(), CalendarDate.of(file.lastModified()));
        }
      }
    }
  }

Remove any files or directories whose last modified time greater than persistMinutes
@param dir clean starting here
@param sbuff status messages here, may be null
@param isRoot delete empty directories, bit not root directory


public static Bearing calculateBearing(Earth e, LatLonPoint pt1,
                                           LatLonPoint pt2, Bearing result) {

        return calculateBearing(e, pt1.getLatitude(), pt1.getLongitude(),
                                pt2.getLatitude(), pt2.getLongitude(),
                                result);
    }

public static Bearing calculateBearing ( Earth e , LatLonPoint pt1 , LatLonPoint pt2 , Bearing result ) { return calculateBearing ( e , pt1 . getLatitude ( ) , pt1 . getLongitude ( ) , pt2 . getLatitude ( ) , pt2 . getLongitude ( ) , result ) ; }

Calculate the bearing between the 2 points.
See calculateBearing below.

@param e      Earth object (defines radius & flattening)
@param pt1    Point 1
@param pt2    Point 2
@param result Object to use if non-null
@return The bearing

Calculate the bearing between the 2 points . See calculateBearing below .


public static Bearing calculateBearing(LatLonPoint pt1, LatLonPoint pt2,
                                           Bearing result) {

        return calculateBearing(defaultEarth, pt1.getLatitude(),
                                pt1.getLongitude(), pt2.getLatitude(),
                                pt2.getLongitude(), result);
    }

public static Bearing calculateBearing ( LatLonPoint pt1 , LatLonPoint pt2 , Bearing result ) { return calculateBearing ( defaultEarth , pt1 . getLatitude ( ) , pt1 . getLongitude ( ) , pt2 . getLatitude ( ) , pt2 . getLongitude ( ) , result ) ; }

Calculate the bearing between the 2 points.
See calculateBearing below.  Uses default Earth object.

@param pt1    Point 1
@param pt2    Point 2
@param result Object to use if non-null
@return The bearing

Calculate the bearing between the 2 points . See calculateBearing below . Uses default Earth object .


public static void main(String[] args) {
        //Bearing         workBearing = new Bearing();
        LatLonPointImpl pt1 = new LatLonPointImpl(40, -105);
        LatLonPointImpl pt2 = new LatLonPointImpl(37.4, -118.4);
        Bearing         b   = calculateBearing(pt1, pt2, null);
        System.out.println("Bearing from " + pt1 + " to " + pt2 + " = \n\t"
                           + b);
        LatLonPointImpl pt3 = new LatLonPointImpl();
        pt3 = findPoint(pt1, b.getAngle(), b.getDistance(), pt3);
        System.out.println(
            "using first point, angle and distance, found second point at "
            + pt3);
        pt3 = findPoint(pt2, b.getBackAzimuth(), b.getDistance(), pt3);
        System.out.println(
            "using second point, backazimuth and distance, found first point at "
            + pt3);
        /*  uncomment for timing tests
        for(int j=0;j<10;j++) {
            long t1 = System.currentTimeMillis();
            for(int i=0;i<30000;i++) {
                workBearing = Bearing.calculateBearing(42.5,-93.0,
                                                       48.9,-117.09,workBearing);
            }
            long t2 = System.currentTimeMillis();
            System.err.println ("time:" + (t2-t1));
        }
        */
    }

//Bearing         workBearing = new Bearing();

Test the calculations - forward and back

@param args non used


public static LatLonPointImpl findPoint(Earth e, LatLonPoint pt1,
                                            double az, double dist,
                                            LatLonPointImpl result) {
        return findPoint(e, pt1.getLatitude(), pt1.getLongitude(), az, dist,
                         result);
    }

public static LatLonPointImpl findPoint ( Earth e , LatLonPoint pt1 , double az , double dist , LatLonPointImpl result ) { return findPoint ( e , pt1 . getLatitude ( ) , pt1 . getLongitude ( ) , az , dist , result ) ; }

Calculate a position given an azimuth and distance from
another point.

@param e      Earth object (defines radius and flattening)
@param pt1    Point 1
@param az     azimuth (degrees)
@param dist   distance from the point (km)
@param result Object to use if non-null
@return The LatLonPoint
@see #findPoint(double,double,double,double,LatLonPointImpl)

Calculate a position given an azimuth and distance from another point .


public static LatLonPointImpl findPoint(LatLonPoint pt1, double az,
                                            double dist,
                                            LatLonPointImpl result) {
        return findPoint(defaultEarth, pt1.getLatitude(), pt1.getLongitude(),
                         az, dist, result);
    }

public static LatLonPointImpl findPoint ( LatLonPoint pt1 , double az , double dist , LatLonPointImpl result ) { return findPoint ( defaultEarth , pt1 . getLatitude ( ) , pt1 . getLongitude ( ) , az , dist , result ) ; }

Calculate a position given an azimuth and distance from
another point.  Uses default Earth.

@param pt1    Point 1
@param az     azimuth (degrees)
@param dist   distance from the point (km)
@param result Object to use if non-null
@return The LatLonPoint
@see #findPoint(double,double,double,double,LatLonPointImpl)

Calculate a position given an azimuth and distance from another point . Uses default Earth .


public static LatLonPointImpl findPoint(double lat1, double lon1,
                                            double az, double dist,
                                            LatLonPointImpl result) {
        return findPoint(defaultEarth, lat1, lon1, az, dist, result);
    }

public static LatLonPointImpl findPoint ( double lat1 , double lon1 , double az , double dist , LatLonPointImpl result ) { return findPoint ( defaultEarth , lat1 , lon1 , az , dist , result ) ; }

Calculate a position given an azimuth and distance from
another point.  See details, below.  Uses default Earth.

@param lat1   latitude of starting point
@param lon1   longitude of starting point
@param az     forward azimuth (degrees)
@param dist   distance from the point (km)
@param result Object to use if non-null
@return the position as a LatLonPointImpl

Calculate a position given an azimuth and distance from another point . See details below . Uses default Earth .


public void loadPictureInThread( URL imageUrl, int priority, double rotation ) {
		if ( pictureStatusCode == LOADING ) {
			stopLoadingExcept( imageUrl );
		}

		this.imageUrl = imageUrl;
		this.rotation = rotation;
		LoadThread t = new LoadThread( this );
		t.setPriority( priority );
		t.start();
	}

public void loadPictureInThread ( URL imageUrl , int priority , double rotation ) { if ( pictureStatusCode == LOADING ) { stopLoadingExcept ( imageUrl ) ; } this . imageUrl = imageUrl ; this . rotation = rotation ; LoadThread t = new LoadThread ( this ) ; t . setPriority ( priority ) ; t . start ( ) ; }

method to invoke with a filename or URL of a picture that is to be loaded
a new thread. This is handy to update the screen while the loading chuggs along in the background.

@param	imageUrl	The URL of the image to be loaded
@param	priority	The Thread priority for this thread.
@param	rotation	The rotation 0-360 to be used on this picture

method to invoke with a filename or URL of a picture that is to be loaded a new thread . This is handy to update the screen while the loading chuggs along in the background .


public void loadPicture( URL imageUrl, double rotation ) {
		if ( pictureStatusCode == LOADING ) {
			stopLoadingExcept( imageUrl );
		}
		this.imageUrl = imageUrl;
		this.rotation = rotation;
		loadPicture();

	}

public void loadPicture ( URL imageUrl , double rotation ) { if ( pictureStatusCode == LOADING ) { stopLoadingExcept ( imageUrl ) ; } this . imageUrl = imageUrl ; this . rotation = rotation ; loadPicture ( ) ; }

method to invoke with a filename or URL of a picture that is to be loaded in
the main thread.

method to invoke with a filename or URL of a picture that is to be loaded in the main thread .


public void loadPicture() {
		Tools.log("SourcePicture.loadPicture: " + imageUrl.toString() + " loaded into SourcePicture object: " + Integer.toString(this.hashCode()) );
		//Tools.freeMem();

		setStatus( LOADING, "Loading: " + imageUrl.toString() );
		abortFlag = false;

		try {

			// Java 1.4 way with a Listener
			ImageInputStream iis = ImageIO.createImageInputStream( imageUrl.openStream() );
			Iterator i = ImageIO.getImageReaders( iis );
			if ( ! i.hasNext() ) { throw new IOException ("No Readers Available!"); }
			reader = (ImageReader) i.next();  // grab the first one

			reader.addIIOReadProgressListener( imageProgressListener );
			reader.setInput( iis );
			sourcePictureBufferedImage = null;
			// try {
				sourcePictureBufferedImage = reader.read( 0 ); // just get the first image
			/* } catch ( OutOfMemoryError e ) {
				Tools.log("SourcePicture caught an OutOfMemoryError while loading an image." );

				iis.close();
				reader.removeIIOReadProgressListener( imageProgressListener );
				reader.dispose();

				setStatus(ERROR, "Out of Memory Error while reading " + imageUrl.toString());
				sourcePictureBufferedImage = null;
				// PictureCache.clear();

				JOptionPane.showMessageDialog( null,  //deliberately null or it swaps the window
					"outOfMemoryError",
					"genericError",
					JOptionPane.ERROR_MESSAGE);

				System.gc();
				System.runFinalization();

				Tools.log("JPO has now run a garbage collection and finalization.");
				return;
			} */

			iis.close();
			reader.removeIIOReadProgressListener( imageProgressListener );
			//Tools.log("!!dispose being called!!");
			reader.dispose();

			if ( ! abortFlag ) {

				if ( rotation != 0 ) {
					setStatus( ROTATING, "Rotating: " + imageUrl.toString() );
					int xRot = sourcePictureBufferedImage.getWidth() / 2;
					int yRot = sourcePictureBufferedImage.getHeight() / 2;
					AffineTransform rotateAf = AffineTransform.getRotateInstance( Math.toRadians( rotation ), xRot, yRot );
					AffineTransformOp op = new AffineTransformOp( rotateAf, AffineTransformOp.TYPE_BILINEAR );
					Rectangle2D newBounds = op.getBounds2D( sourcePictureBufferedImage );
					// a simple AffineTransform would give negative top left coordinates -->
					// do another transform to get 0,0 as top coordinates again.
					double minX = newBounds.getMinX();
					double minY = newBounds.getMinY();

					AffineTransform translateAf = AffineTransform.getTranslateInstance( minX * (-1), minY * (-1) );
					rotateAf.preConcatenate( translateAf );
					op = new AffineTransformOp( rotateAf, AffineTransformOp.TYPE_BILINEAR );
					newBounds = op.getBounds2D( sourcePictureBufferedImage );

					// this piece of code is so essential!!! Otherwise the internal image format
					// is totally altered and either the AffineTransformOp decides it doesn't
					// want to rotate the image or web browsers can't read the resulting image.
					BufferedImage targetImage = new BufferedImage(
						(int) newBounds.getWidth(),
						(int) newBounds.getHeight(),
						BufferedImage.TYPE_3BYTE_BGR );

					sourcePictureBufferedImage = op.filter( sourcePictureBufferedImage, targetImage );
				}

				setStatus( READY, "Loaded: " + imageUrl.toString() );
				PictureCache.add( imageUrl, (SourcePicture) this.clone() );
			} else {
				setStatus( ERROR, "Aborted: " + imageUrl.toString() );
				sourcePictureBufferedImage = null;
			}
		} catch ( IOException e ) {
			setStatus(ERROR, "Error while reading " + imageUrl.toString());
			sourcePictureBufferedImage = null;
		}

	}

loads a picture from the URL in the imageUrl object into the sourcePictureBufferedImage
object and updates the status when done or failed.

loads a picture from the URL in the imageUrl object into the sourcePictureBufferedImage object and updates the status when done or failed .


public void stopLoading() {
		if ( imageUrl == null )
			return; // SourcePicture has never been used yet

		Tools.log("SourcePicture.stopLoading: called on " + imageUrl );
		if ( pictureStatusCode == LOADING ) {
			reader.abort();
			abortFlag = true;
			//reader.dispose();
			//setStatus( ERROR, "Cache Loading was stopped " + imageUrl.toString() );
			//sourcePictureBufferedImage = null;
			// actually the thread reading the image continues
		}
	}

this method can be invoked to stop the current reader


public boolean stopLoadingExcept( URL exemptionURL ) {
		if ( imageUrl == null )
			return false; // has never been used yet

		if ( pictureStatusCode != LOADING ) {
			Tools.log( "SourcePicture.stopLoadingExcept: called but pointless since image is not LOADING: " + imageUrl.toString());
			return false;
		}

		if ( ! exemptionURL.toString().equals( imageUrl.toString() ) ) {
			Tools.log ("SourcePicture.stopLoadingExcept: called with Url " + exemptionURL.toString() + " --> stopping loading of " + imageUrl.toString() );
			stopLoading();
			return true;
		} else
			return false;
	}

this method can be invoked to stop the current reader except if it
is reading the desired file. It returns true is the desired file
is being loaded. Otherwise it returns false.

this method can be invoked to stop the current reader except if it is reading the desired file . It returns true is the desired file is being loaded . Otherwise it returns false .


public Dimension getSize() {
		if ( sourcePictureBufferedImage != null )
			return new Dimension( sourcePictureBufferedImage.getWidth(), sourcePictureBufferedImage.getHeight());
		else
			return new Dimension(0,0);

	}

public Dimension getSize ( ) { if ( sourcePictureBufferedImage != null ) return new Dimension ( sourcePictureBufferedImage . getWidth ( ) , sourcePictureBufferedImage . getHeight ( ) ) ; else return new Dimension ( 0 , 0 ) ; }

return the size of the image or Zero if there is none


public void setSourceBufferedImage( BufferedImage img, String statusMessage ) {
		sourcePictureBufferedImage = img;
		setStatus( READY, statusMessage );
	}

public void setSourceBufferedImage ( BufferedImage img , String statusMessage ) { sourcePictureBufferedImage = img ; setStatus ( READY , statusMessage ) ; }

sets the buffered image. Unusual method use with care.

sets the buffered image . Unusual method use with care .


public URI getStandardUri() {
    try {
      Catalog cat = dataset.getParentCatalog();
      if (cat == null)
        return new URI(getUnresolvedUrlName());
      return cat.resolveUri(getUnresolvedUrlName());

    } catch (java.net.URISyntaxException e) {
      throw new RuntimeException("Error parsing URL= " + getUnresolvedUrlName());
    }
  }

public
URI
getStandardUri
(
)
{
try
{
Catalog
cat
=
dataset
.
getParentCatalog
(
)
;
if
(
cat
==
)
return
new
URI
(
getUnresolvedUrlName
(
)
)
;
return
cat
.
resolveUri
(
getUnresolvedUrlName
(
)
)
;
}
catch
(
java
.
net
.
URISyntaxException
e
)
{
throw
new
RuntimeException
(
"Error parsing URL= "
+
getUnresolvedUrlName
(
)
)
;
}
}

Construct the standard THREDDS access URI for this dataset access method,
resolved agaisnt the parent catalog if the URI is relative.

@return the standard fully resolved THREDDS access URI for this dataset access method, or null if error.

Construct the standard THREDDS access URI for this dataset access method resolved agaisnt the parent catalog if the URI is relative .


DataDescriptor makeAssociatedField(int bitWidth) {
    DataDescriptor assDD = new DataDescriptor();
    assDD.name = name + "_associated_field";
    assDD.units = "";
    assDD.refVal = 0;
    assDD.scale = 0;
    assDD.bitWidth = bitWidth;
    assDD.type = 0;

    assDD.f = 0;
    assDD.x = 31;
    assDD.y = 22;
    assDD.fxy =  (short) ((f << 14) + (x << 8) + (y));

    return assDD;
  }

DataDescriptor makeAssociatedField ( int bitWidth ) { DataDescriptor assDD = new DataDescriptor ( ) ; assDD . name = name + "_associated_field" ; assDD . units = "" ; assDD . refVal = 0 ; assDD . scale = 0 ; assDD . bitWidth = bitWidth ; assDD . type = 0 ; assDD . f = 0 ; assDD . x = 31 ; assDD . y = 22 ; assDD . fxy = ( short ) ( ( f << 14 ) + ( x << 8 ) + ( y ) ) ; return assDD ; }


static public void transferInfo(List<DataDescriptor> fromList, List<DataDescriptor> toList) { // get info from proto message
    if (fromList.size() != toList.size())
      throw new IllegalArgumentException("list sizes dont match "+fromList.size()+" != "+toList.size());

    for (int i=0; i<fromList.size(); i++) {
      DataDescriptor from = fromList.get(i);
      DataDescriptor to = toList.get(i);
      to.refersTo = from.refersTo;
      to.name = from.name;

      if (from.getSubKeys() != null)
        transferInfo(from.getSubKeys(), to.getSubKeys());
    }
  }

static
public
void
transferInfo
(
List
<
DataDescriptor
>
fromList
,
List
<
DataDescriptor
>
toList
)
{
// get info from proto message
if
(
fromList
.
size
(
)
!=
toList
.
size
(
)
)
throw
new
IllegalArgumentException
(
"list sizes dont match "
+
fromList
.
size
(
)
+
" != "
+
toList
.
size
(
)
)
;
for
(
int
i
=
0
;
i
<
fromList
.
size
(
)
;
i
++
)
{
DataDescriptor
from
=
fromList
.
get
(
i
)
;
DataDescriptor
to
=
toList
.
get
(
i
)
;
to
.
refersTo
=
from
.
refersTo
;
to
.
name
=
from
.
name
;
if
(
from
.
getSubKeys
(
)
!=
)
transferInfo
(
from
.
getSubKeys
(
)
,
to
.
getSubKeys
(
)
)
;
}
}

Transfer info from the "proto message" to another message with the exact same structure.
@param fromList transfer from here
@param toList to here

Transfer info from the proto message to another message with the exact same structure .