public float[] getParamValues(DoradeRDAT rdat,float[] workingArray)
            throws DescriptorException {

        if (! paramName.equals(rdat.getParamName()))
            throw new DescriptorException("parameter name mismatch");

        byte[] paramData = rdat.getRawData();

        int nCells = myRADD.getNCells();

        float[] values;
	if(workingArray!=null && workingArray.length == nCells) {
	    values = workingArray;
	} else {
	    values = new float[nCells];
	}

        short[] svalues = null;
        if (myRADD.getCompressionScheme() == DoradeRADD.COMPRESSION_HRD) {
            if (binaryFormat != DoradePARM.FORMAT_16BIT_INT) {
                throw new DescriptorException("Cannot unpack " +
                           "compressed data with binary format " +
                           binaryFormat);
            }
            svalues = uncompressHRD(paramData, nCells);
        }

        for (int cell = 0; cell < nCells; cell++) {
            switch (binaryFormat) {
                case DoradePARM.FORMAT_8BIT_INT:
                    byte bval = paramData[cell];
                    values[cell] = (bval == badDataFlag) ?
                                   BAD_VALUE : (bval - bias) / scale;
                    break;
                case DoradePARM.FORMAT_16BIT_INT:
                    short sval = (svalues != null) ?
                                 svalues[cell] : grabShort(paramData, 2 * cell);
                    values[cell] = (sval == badDataFlag) ?
                                   BAD_VALUE : (sval - bias) / scale;
                    break;
                case DoradePARM.FORMAT_32BIT_INT:
                    int ival = grabInt(paramData, 4 * cell);
                    values[cell] = (ival == badDataFlag) ?
                                   BAD_VALUE : (ival - bias) / scale;
                    break;
                case DoradePARM.FORMAT_32BIT_FLOAT:
                    float fval = grabFloat(paramData, 4 * cell);
                    values[cell] = (fval == badDataFlag) ?
                                   BAD_VALUE : (fval - bias) / scale;
                    break;
                case DoradePARM.FORMAT_16BIT_FLOAT:
                    throw new DescriptorException("can't unpack 16-bit " +
                                                        "float data yet");
                default:
                    throw new DescriptorException("bad binary format (" +
                                                        binaryFormat + ")");
            }
        }
        return values;
    }

public
float
[
]
getParamValues
(
DoradeRDAT
rdat
,
float
[
]
workingArray
)
throws
DescriptorException
{
if
(
!
paramName
.
equals
(
rdat
.
getParamName
(
)
)
)
throw
new
DescriptorException
(
"parameter name mismatch"
)
;
byte
[
]
paramData
=
rdat
.
getRawData
(
)
;
int
nCells
=
myRADD
.
getNCells
(
)
;
float
[
]
values
;
if
(
workingArray
!=
&&
workingArray
.
length
==
nCells
)
{
values
=
workingArray
;
}
else
{
values
=
new
float
[
nCells
]
;
}
short
[
]
svalues
=
;
if
(
myRADD
.
getCompressionScheme
(
)
==
DoradeRADD
.
COMPRESSION_HRD
)
{
if
(
binaryFormat
!=
DoradePARM
.
FORMAT_16BIT_INT
)
{
throw
new
DescriptorException
(
"Cannot unpack "
+
"compressed data with binary format "
+
binaryFormat
)
;
}
svalues
=
uncompressHRD
(
paramData
,
nCells
)
;
}
for
(
int
cell
=
0
;
cell
<
nCells
;
cell
++
)
{
switch
(
binaryFormat
)
{
case
DoradePARM
.
FORMAT_8BIT_INT
:
byte
bval
=
paramData
[
cell
]
;
values
[
cell
]
=
(
bval
==
badDataFlag
)
BAD_VALUE
:
(
bval
bias
)
/
scale
;
break
;
case
DoradePARM
.
FORMAT_16BIT_INT
:
short
sval
=
(
svalues
!=
)
svalues
[
cell
]
:
grabShort
(
paramData
,
2
*
cell
)
;
values
[
cell
]
=
(
sval
==
badDataFlag
)
BAD_VALUE
:
(
sval
bias
)
/
scale
;
break
;
case
DoradePARM
.
FORMAT_32BIT_INT
:
int
ival
=
grabInt
(
paramData
,
4
*
cell
)
;
values
[
cell
]
=
(
ival
==
badDataFlag
)
BAD_VALUE
:
(
ival
bias
)
/
scale
;
break
;
case
DoradePARM
.
FORMAT_32BIT_FLOAT
:
float
fval
=
grabFloat
(
paramData
,
4
*
cell
)
;
values
[
cell
]
=
(
fval
==
badDataFlag
)
BAD_VALUE
:
(
fval
bias
)
/
scale
;
break
;
case
DoradePARM
.
FORMAT_16BIT_FLOAT
:
throw
new
DescriptorException
(
"can't unpack 16-bit "
+
"float data yet"
)
;
default
:
throw
new
DescriptorException
(
"bad binary format ("
+
binaryFormat
+
")"
)
;
}
}
return
values
;
}

Get the unpacked data values for a selected parameter.
@param rdat the name of the desired parameter
@param workingArray If non-null and the same length as needed then use this.
@return the unpacked data values for all cells, using BAD_VALUE
for bad data cells
@throws DescriptorException

Get the unpacked data values for a selected parameter .


@Override
  public ProjectionImpl constructCopy() {
    ProjectionImpl result =  new VerticalPerspectiveView(getOriginLat(), getOriginLon(), R, getHeight(), false_east, false_north);
    result.setDefaultMapArea(defaultMapArea);
    result.setName(name);
    return result;
  }

@ Override public ProjectionImpl constructCopy ( ) { ProjectionImpl result = new VerticalPerspectiveView ( getOriginLat ( ) , getOriginLon ( ) , R , getHeight ( ) , false_east , false_north ) ; result . setDefaultMapArea ( defaultMapArea ) ; result . setName ( name ) ; return result ; }

"map limit" circle of this radius from the origin, p 173

map limit circle of this radius from the origin p 173


public ThreddsDataFactory.Result openFeatureDataset(InvDataset invDataset, ucar.nc2.util.CancelTask task) throws IOException {
    return openFeatureDataset(null, invDataset, task, new Result());
  }

public ThreddsDataFactory . Result openFeatureDataset ( InvDataset invDataset , ucar . nc2 . util . CancelTask task ) throws IOException { return openFeatureDataset ( null , invDataset , task , new Result ( ) ) ; }

Open a FeatureDataset from an InvDataset object, deciding on which InvAccess to use.

@param invDataset use this to figure out what type, how to open, etc
@param task       allow user to cancel; may be null
@return ThreddsDataFactory.Result check fatalError for validity
@throws IOException on read error

Open a FeatureDataset from an InvDataset object deciding on which InvAccess to use .


public ThreddsDataFactory.Result openFeatureDataset(InvAccess access, ucar.nc2.util.CancelTask task) throws IOException {
    InvDataset invDataset = access.getDataset();
    ThreddsDataFactory.Result result = new Result();
    if (invDataset.getDataType() == null) {
      result.errLog.format("InvDatasert must specify a FeatureType%n");
      result.fatalError = true;
      return result;
    }

    return openFeatureDataset(invDataset.getDataType(), access, task, result);
  }

Open a FeatureDataset from an InvAccess object.

@param access use this InvAccess.
@param task   may be null
@return ThreddsDataFactory.Result check fatalError for validity
@throws IOException on read error

Open a FeatureDataset from an InvAccess object .


public NetcdfDataset openDataset(InvDataset invDataset, boolean acquire, ucar.nc2.util.CancelTask task, Formatter log) throws IOException {
    Result result = new Result();
    NetcdfDataset ncd = openDataset(invDataset, acquire, task, result);
    if (log != null) log.format("%s", result.errLog);
    return (result.fatalError) ? null : ncd;
  }

public NetcdfDataset openDataset ( InvDataset invDataset , boolean acquire , ucar . nc2 . util . CancelTask task , Formatter log ) throws IOException { Result result = new Result ( ) ; NetcdfDataset ncd = openDataset ( invDataset , acquire , task , result ) ; if ( log != null ) log . format ( "%s" , result . errLog ) ; return ( result . fatalError ) ? null : ncd ; }

Try to open as a NetcdfDataset.

@param invDataset open this
@param acquire    if true, aquire the dataset, else open it
@param task       may be null
@param log        error message, may be null
@return NetcdfDataset or null if failure
@throws IOException on read error


public static void annotate(InvDataset ds, NetcdfDataset ncDataset) {
    ncDataset.setTitle(ds.getName());
    ncDataset.setId(ds.getID());

// add properties as global attributes
    for (InvProperty p : ds.getProperties()) {
      String name = p.getName();
      if (null == ncDataset.findGlobalAttribute(name)) {
        ncDataset.addAttribute(null, new Attribute(name, p.getValue()));
      }
    }

    /* ThreddsMetadata.GeospatialCoverage geoCoverage = ds.getGeospatialCoverage();
   if (geoCoverage != null) {
     if ( null != geoCoverage.getNorthSouthRange()) {
       ncDataset.addAttribute(null, new Attribute("geospatial_lat_min", new Double(geoCoverage.getLatSouth())));
       ncDataset.addAttribute(null, new Attribute("geospatial_lat_max", new Double(geoCoverage.getLatNorth())));
     }
     if ( null != geoCoverage.getEastWestRange()) {
       ncDataset.addAttribute(null, new Attribute("geospatial_lon_min", new Double(geoCoverage.getLonWest())));
       ncDataset.addAttribute(null, new Attribute("geospatial_lon_max", new Double(geoCoverage.getLonEast())));
     }
     if ( null != geoCoverage.getUpDownRange()) {
       ncDataset.addAttribute(null, new Attribute("geospatial_vertical_min", new Double(geoCoverage.getHeightStart())));
       ncDataset.addAttribute(null, new Attribute("geospatial_vertical_max", new Double(geoCoverage.getHeightStart() + geoCoverage.getHeightExtent())));
     }
   }

   DateRange timeCoverage = ds.getTimeCoverage();
   if (timeCoverage != null) {
     ncDataset.addAttribute(null, new Attribute("time_coverage_start", timeCoverage.getStart().toDateTimeStringISO()));
     ncDataset.addAttribute(null, new Attribute("time_coverage_end", timeCoverage.getEnd().toDateTimeStringISO()));
   } */

    ncDataset.finish();
  }

Add information from the InvDataset to the NetcdfDataset.

@param ds        get info from here
@param ncDataset add to here

Add information from the InvDataset to the NetcdfDataset .


public static List<Property> removeDups(List<Property> org) {
    List<Property> result = new ArrayList<>(org.size());
    for (Property p : org)
      if (!result.contains(p))  // O(n**2)
        result.add(p);
    return result;
  }

public
static
List
<
Property
>
removeDups
(
List
<
Property
>
org
)
{
List
<
Property
>
result
=
new
ArrayList
<>
(
org
.
size
(
)
)
;
for
(
Property
p
:
org
)
if
(
!
result
.
contains
(
p
)
)
// O(n**2)
result
.
add
(
p
)
;
return
result
;
}


void addPartition(int partno, int groupno, int varno, int ndups, int nrecords, int nmissing,
        GribCollectionMutable.VariableIndex vi) {
      if (partList == null) partList = new ArrayList<>(nparts);
      partList.add(new PartitionForVariable2D(partno, groupno, varno));
      this.ndups += ndups;
      this.nrecords += nrecords;
      this.nmissing += nmissing;
    }

void addPartition ( int partno , int groupno , int varno , int ndups , int nrecords , int nmissing , GribCollectionMutable . VariableIndex vi ) { if ( partList == null ) partList = new ArrayList <> ( nparts ) ; partList . add ( new PartitionForVariable2D ( partno , groupno , varno ) ) ; this . ndups += ndups ; this . nrecords += nrecords ; this . nmissing += nmissing ; }

only used by PartitionBuilder, not PartitionBuilderFromIndex

only used by PartitionBuilder not PartitionBuilderFromIndex


@Nullable
    public GribCollectionMutable makeGribCollection() {
      GribCollectionMutable result = GribCdmIndex.openMutableGCFromIndex(dcm.getIndexFilename(GribCdmIndex.NCX_SUFFIX), config, false, true, logger);
      if (result == null) {
        logger.error("Failed on openMutableGCFromIndex {}", dcm.getIndexFilename(GribCdmIndex.NCX_SUFFIX));
        return null;
      }
      lastModified = result.lastModified;
      fileSize = result.fileSize;
      if (result.masterRuntime != null)
        partitionDate = result.masterRuntime.getFirstDate();
      return result;
    }

@
Nullable
public
GribCollectionMutable
makeGribCollection
(
)
{
GribCollectionMutable
result
=
GribCdmIndex
.
openMutableGCFromIndex
(
dcm
.
getIndexFilename
(
GribCdmIndex
.
NCX_SUFFIX
)
,
config
,
false
,
true
,
logger
)
;
if
(
result
==
)
{
logger
.
error
(
"Failed on openMutableGCFromIndex {}"
,
dcm
.
getIndexFilename
(
GribCdmIndex
.
NCX_SUFFIX
)
)
;
return
;
}
lastModified
=
result
.
lastModified
;
fileSize
=
result
.
fileSize
;
if
(
result
.
masterRuntime
!=
)
partitionDate
=
result
.
masterRuntime
.
getFirstDate
(
)
;
return
result
;
}


public static
  RegExpAndDurationTimeCoverageEnhancer
  getInstanceToMatchOnDatasetName( String matchPattern,
                                   String substitutionPattern,
                                   String duration )
  {
    return new RegExpAndDurationTimeCoverageEnhancer(
            matchPattern, substitutionPattern,
            duration, MatchTarget.DATASET_NAME );
  }

public static RegExpAndDurationTimeCoverageEnhancer getInstanceToMatchOnDatasetName ( String matchPattern , String substitutionPattern , String duration ) { return new RegExpAndDurationTimeCoverageEnhancer ( matchPattern , substitutionPattern , duration , MatchTarget . DATASET_NAME ) ; }

Factory method that returns a RegExpAndDurationTimeCoverageEnhancer instance
that will apply the match pattern to the dataset name.

@param matchPattern a regular expression used to match against the CrawlableDataset name.
@param substitutionPattern the time coverage start time (which may contain regular expression capturing group substitution strings).
@param duration the time coverage duration string.

@return a RegExpAndDurationTimeCoverageEnhancer that will apply the match pattern to the dataset name.

Factory method that returns a RegExpAndDurationTimeCoverageEnhancer instance that will apply the match pattern to the dataset name .


public static RegExpAndDurationTimeCoverageEnhancer
  getInstanceToMatchOnDatasetPath( String matchPattern,
                                   String substitutionPattern,
                                   String duration )
  {
    return new RegExpAndDurationTimeCoverageEnhancer(
            matchPattern, substitutionPattern,
            duration, MatchTarget.DATASET_PATH );
  }

public static RegExpAndDurationTimeCoverageEnhancer getInstanceToMatchOnDatasetPath ( String matchPattern , String substitutionPattern , String duration ) { return new RegExpAndDurationTimeCoverageEnhancer ( matchPattern , substitutionPattern , duration , MatchTarget . DATASET_PATH ) ; }

Factory method that returns a RegExpAndDurationTimeCoverageEnhancer instance
that will apply the match pattern to the dataset path.

@param matchPattern a regular expression used to match against the CrawlableDataset path.
@param substitutionPattern the time coverage start time (which may contain regular expression capturing group substitution strings).
@param duration the time coverage duration string.

@return a RegExpAndDurationTimeCoverageEnhancer that will apply the match pattern to the dataset path.

Factory method that returns a RegExpAndDurationTimeCoverageEnhancer instance that will apply the match pattern to the dataset path .


public boolean writeXML(QueryCapability dqc, String filename) {
    try {
      BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(filename));
      writeXML(dqc, os);
      os.close();
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }

public boolean writeXML ( QueryCapability dqc , String filename ) { try { BufferedOutputStream os = new BufferedOutputStream ( new FileOutputStream ( filename ) ) ; writeXML ( dqc , os ) ; os . close ( ) ; } catch ( IOException e ) { e . printStackTrace ( ) ; return false ; } return true ; }

Write the catalog as an XML document to the specified filename.

@param dqc      : write this QueryCapability to an XML representation.
@param filename write to this filename
@return true if success

Write the catalog as an XML document to the specified filename .


private ucar.ma2.ArrayStructure readStructureData(ucar.nc2.Structure s, Section section) throws java.io.IOException, InvalidRangeException {
    H4header.Vinfo vinfo = (H4header.Vinfo) s.getSPobject();
    vinfo.setLayoutInfo();   // make sure needed info is present
    int recsize = vinfo.elemSize;

    // create the ArrayStructure
    StructureMembers members = s.makeStructureMembers();
    for (StructureMembers.Member m : members.getMembers()) {
      Variable v2 = s.findVariable(m.getName());
      H4header.Minfo minfo = (H4header.Minfo) v2.getSPobject();
      m.setDataParam(minfo.offset);
    }
    members.setStructureSize(recsize);
    ArrayStructureBB structureArray = new ArrayStructureBB(members, section.getShape());  // LOOK subset

    // loop over records
    byte[] result = structureArray.getByteBuffer().array();

    /*if (vinfo.isChunked) {
      InputStream is = getChunkedInputStream(vinfo);
      PositioningDataInputStream dataSource = new PositioningDataInputStream(is);
      Layout layout = new LayoutRegular(vinfo.start, recsize, s.getShape(), section);
      IospHelper.readData(dataSource, layout, DataType.STRUCTURE, result);  */

    if (!vinfo.isLinked && !vinfo.isCompressed) {
      Layout layout = new LayoutRegular(vinfo.start, recsize, s.getShape(), section);
      IospHelper.readData(raf, layout, DataType.STRUCTURE, result, -1, true);

      /* option 1
    } else if (vinfo.isLinked && !vinfo.isCompressed) {
      Layout layout = new LayoutSegmented(vinfo.segPos, vinfo.segSize, recsize, s.getShape(), section);
      IospHelper.readData(raf, layout, DataType.STRUCTURE, result, -1);  */

      // option 2
    } else if (vinfo.isLinked && !vinfo.isCompressed) {
      InputStream is = new LinkedInputStream(vinfo);
      PositioningDataInputStream dataSource = new PositioningDataInputStream(is);
      Layout layout = new LayoutRegular(0, recsize, s.getShape(), section);
      IospHelper.readData(dataSource, layout, DataType.STRUCTURE, result);

    } else if (!vinfo.isLinked && vinfo.isCompressed) {
      InputStream is = getCompressedInputStream(vinfo);
      PositioningDataInputStream dataSource = new PositioningDataInputStream(is);
      Layout layout = new LayoutRegular(0, recsize, s.getShape(), section);
      IospHelper.readData(dataSource, layout, DataType.STRUCTURE, result);

    } else if (vinfo.isLinked && vinfo.isCompressed) {
      InputStream is = getLinkedCompressedInputStream(vinfo);
      PositioningDataInputStream dataSource = new PositioningDataInputStream(is);
      Layout layout = new LayoutRegular(0, recsize, s.getShape(), section);
      IospHelper.readData(dataSource, layout, DataType.STRUCTURE, result);

    } else {
      throw new IllegalStateException();
    }

    return structureArray;
  }

Structures must be fixed sized

@param s       the record structure
@param section the record range to read
@return an ArrayStructure, with all the data read in.
@throws IOException                    on error
@throws ucar.ma2.InvalidRangeException if invalid section


public void setPicture( URL filenameURL, String legendParam, double rotation ) {
    legend = legendParam;
    centerWhenScaled = true;
    sclPic.setScaleSize(getSize());

    sclPic.stopLoadingExcept( filenameURL );
    sclPic.loadAndScalePictureInThread( filenameURL, Thread.MAX_PRIORITY, rotation );
  }

public void setPicture ( URL filenameURL , String legendParam , double rotation ) { legend = legendParam ; centerWhenScaled = true ; sclPic . setScaleSize ( getSize ( ) ) ; sclPic . stopLoadingExcept ( filenameURL ) ; sclPic . loadAndScalePictureInThread ( filenameURL , Thread . MAX_PRIORITY , rotation ) ; }

brings up the indicated picture on the display.
@param filenameURL  The URL of the picture to display
@param legendParam	The description of the picture
@param rotation  The rotation that should be applied

brings up the indicated picture on the display .


public void setBufferedImage( BufferedImage img, String statusMessage  ) {
    legend = statusMessage;
    centerWhenScaled = true;
    Dimension dim = getSize();
    sclPic.setScaleSize(dim);

    SourcePicture source = new SourcePicture();
    source.setSourceBufferedImage( img, statusMessage );

    sclPic.setSourcePicture( source);
    if (!scaleToFit)
      sclPic.setScaleFactor(1.0);
    sclPic.scalePicture();
    repaint();
  }

public void setBufferedImage ( BufferedImage img , String statusMessage ) { legend = statusMessage ; centerWhenScaled = true ; Dimension dim = getSize ( ) ; sclPic . setScaleSize ( dim ) ; SourcePicture source = new SourcePicture ( ) ; source . setSourceBufferedImage ( img , statusMessage ) ; sclPic . setSourcePicture ( source ) ; if ( ! scaleToFit ) sclPic . setScaleFactor ( 1.0 ) ; sclPic . scalePicture ( ) ; repaint ( ) ; }


public void zoomToFit() {
		//Tools.log("zoomToFit invoked");
		sclPic.setScaleSize( getSize() );
		// prevent useless rescale events when the picture is not ready
		if ( sclPic.getStatusCode() == sclPic.LOADED
		  || sclPic.getStatusCode() == sclPic.READY ) {
			sclPic.createScaledPictureInThread( Thread.MAX_PRIORITY );
		}
	}

this method sets the desired scaled size of the ScalablePicture
to the size of the JPanel and fires off a createScaledPictureInThread
request if the ScalablePicture has been loaded or is ready.

@see ScalablePicture#createScaledPictureInThread(int)

this method sets the desired scaled size of the ScalablePicture to the size of the JPanel and fires off a createScaledPictureInThread request if the ScalablePicture has been loaded or is ready .


public void paintComponent(Graphics g) {
		int WindowWidth = getSize().width;
		int WindowHeight = getSize().height;

    Tools.log ("paintComponent called");

		if (Dragging == false) {  //otherwise it's already a move Cursor
			setCursor(new Cursor(Cursor.WAIT_CURSOR));
		}

		if ( sclPic.getScaledPicture() != null ) {
			Graphics2D g2d = (Graphics2D)g;

			int X_Offset = (int) ((double) (WindowWidth / 2) - (focusPoint.x * sclPic.getScaleFactor()));
			int Y_Offset = (int) ((double) (WindowHeight / 2) - (focusPoint.y * sclPic.getScaleFactor()));

			// clear damaged component area
		 	Rectangle clipBounds = g2d.getClipBounds();
			g2d.setColor(Color.black); // getBackground());
			g2d.fillRect(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);

			g2d.drawRenderedImage(sclPic.getScaledPicture(), AffineTransform.getTranslateInstance( X_Offset, Y_Offset));
			//g2d.drawImage(sclPic.getScaledPicture(), null, 0, 0);

			if (showInfo) {
				g2d.setColor(Color.white);
				g2d.drawString(legend, infoPoint.x, infoPoint.y);
				g2d.drawString("Size: " + Integer.toString(sclPic.getOriginalWidth()) + " x " + Integer.toString(sclPic.getOriginalHeight())
						+ " Offset: " + X_Offset + " x " + Y_Offset
						+ " Mid: " + Integer.toString(focusPoint.x) + " x " + Integer.toString(focusPoint.y)
						+ " Scale: " + twoDecimalFormatter.format(sclPic.getScaleFactor()), infoPoint.x, infoPoint.y + lineSpacing);
				/* g2d.drawString("File: " + sclPic.getFilename()
						, infoPoint.x
						, infoPoint.y + (2 * lineSpacing) );
				g2d.drawString("Loaded in: "
						+ twoDecimalFormatter.format( sclPic.getSourcePicture().loadTime / 1000F )
						+ " Seconds"
						, infoPoint.x
						, infoPoint.y + (3 * lineSpacing) );
				g2d.drawString("Free memory: "
						+ Long.toString( Runtime.getRuntime().freeMemory( )/1024/1024, 0 )
						+ " MB"
						, infoPoint.x
						, infoPoint.y + (4 * lineSpacing) ); */
			}
		} else {
			// paint a black square
			g.setClip(0, 0, WindowWidth, WindowHeight);
			g.setColor(Color.black);
			g.fillRect(0,0,WindowWidth,WindowHeight);
		}

		if (Dragging == false) {  //otherwise a move Cursor and should remain
			setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		}
	}

we are overriding the default paintComponent method, grabbing the Graphics
handle and doing our own drawing here. Esentially this method draws a large
black rectangle. A drawRenderedImage is then painted doing an affine transformation
on the scaled image to position it so the the desired point is in the middle of the
Graphics object. The picture is not scaled here because this is a slow operation
and only needs to be done once, while moving the image is something the user is
likely to do more often.

we are overriding the default paintComponent method grabbing the Graphics handle and doing our own drawing here . Esentially this method draws a large black rectangle . A drawRenderedImage is then painted doing an affine transformation on the scaled image to position it so the the desired point is in the middle of the Graphics object . The picture is not scaled here because this is a slow operation and only needs to be done once while moving the image is something the user is likely to do more often .


public static int[] TG_FTOI(int[] iftime, int start) {

        int[] intdtf = new int[3];
        // If there is no forecast information, the string is stored as
        // date and time.

        if (iftime[start] < 100000000) {
            intdtf[0] = iftime[start];
            intdtf[1] = iftime[start + 1];
            intdtf[2] = 0;

            //  Otherwise, decode date/time and forecast info from the
            //  two integers.

        } else {

            //  The first word contains MMDDYYHHMM.  This must be turned
            //  into YYMMDD and HHMM.

            intdtf[0] = iftime[start] / 10000;
            intdtf[1] = iftime[start] - intdtf[0] * 10000;
            int mmdd = intdtf[0] / 100;
            int iyyy = intdtf[0] - mmdd * 100;
            intdtf[0] = iyyy * 10000 + mmdd;

            //  The forecast time remains the same.

            intdtf[2] = iftime[start + 1];
        }
        return intdtf;
    }

This subroutine converts the two integers stored in a grid file
into three integers containing the date, time and forecast time.
@param  iftime  input time array
@param  start offset into the array
@return  int[3] with date time and forecast time

This subroutine converts the two integers stored in a grid file into three integers containing the date time and forecast time .


public static String TG_ITOC(int[] intdtf) {
        String gdattim = "";

        //Check for the blank time which may be found.

        if ((intdtf[0] == 0) && (intdtf[1] == 0) && (intdtf[2] == 0)) {
            return gdattim;
        }

        //  Put the date and time into the character time.

        gdattim = TI_CDTM(intdtf[0], intdtf[1]);

        //  Decode the forecast information if there is any.

        if (intdtf[2] != 0) {
            String[] timeType = TG_CFTM(intdtf[2]);
            String   ftype    = timeType[0];
            String   ftime    = timeType[1];

            //      Combine two parts into string.

            gdattim = gdattim.substring(0, 11) + ftype + ftime;
        }

        return gdattim;
    }

This subroutine converts an integer time array containing the date,
time and forecast time into a GEMPAK grid time.

@param intdtf  integer array of date, time and forecast time

@return  formatted string

This subroutine converts an integer time array containing the date time and forecast time into a GEMPAK grid time .


public static String TI_ITOC(int[] idtarr) {
        String dattim;
        String date, time;

        //   Put array values into variables.

        int iyear  = idtarr[0];
        int imonth = idtarr[1];
        int iday   = idtarr[2];
        int ihour  = idtarr[3];
        int iminut = idtarr[4];

        //  Check for leap year.

        //int ndays = TI_DAYM(iyear, imonth);
        iyear = iyear % 100;

        //  Check that each of these values is valid.

        /*  TODO: Check these
            IF  ( iyear .lt. 0 )  iret = -7
            IF  ( ( imonth .lt. 1 ) .or. ( imonth .gt. 12 ) ) iret = -8
            IF  ( ( iday   .lt. 1 ) .or. ( iday   .gt. ndays ) )
         +                                                    iret = -9
            IF  ( ( ihour  .lt. 0 ) .or. ( ihour  .gt. 24 ) ) iret = -10
            IF  ( ( iminut .lt. 0 ) .or. ( iminut .gt. 60 ) ) iret = -11
            IF  ( iret .ne. 0 )  RETURN
        */

        //  Get the date and time.

        int idate = iyear * 10000 + imonth * 100 + iday;
        int itime = ihour * 100 + iminut;

        //  Convert date and time to character strings.
        //  Fill in blanks with zeroes.
        date   = StringUtil2.padZero(idate, 6);
        time   = StringUtil2.padZero(itime, 4);

        dattim = date + "/" + time;

        return dattim;
    }

This subroutine converts an integer time array into a standard
GEMPAK time.  The integers are checked for validity.
@param idtarr   Time array (YYYY,MM,DD,HH,MM)
@return time as a string

This subroutine converts an integer time array into a standard GEMPAK time . The integers are checked for validity .


public static int TI_DAYM(int iyear, int imon) {

        int iday = 0;

        if ((imon > 0) && (imon < 13)) {

            //  Pick the number of days for the given month.

            iday = month[imon - 1];
            if ((imon == 2) && LEAP(iyear)) {
                iday = iday + 1;
            }
        }
        return iday;
    }

This subroutine returns the number of days in the given month.
The year must be a full four-digit year.

@param iyear  integer year
@param imon  integer month

@return  number of days

This subroutine returns the number of days in the given month . The year must be a full four - digit year .


public static String LV_CCRD(int ivcord) {
        //Translate known vertical coordinates or look for parameter name.
        String vcoord = "";

        //Check for numeric vertical coordinates.

        if ((ivcord >= 0) && (ivcord < vertCoords.length)) {
            vcoord = vertCoords[ivcord];

        } else if (ivcord > 100) {
            //     Check for character name as vertical coordinate.  Check that
            //     each character is an alphanumeric character.

            vcoord = ST_ITOC(ivcord);
            /*
              Check for bad values

                DO  i = 1, 4
                    v = vcoord (i:i)
                    IF  ( ( ( v .lt. 'A' ) .or. ( v .gt. 'Z' ) ) .and.
     +                    ( ( v .lt. '0' ) .or. ( v .gt. '9' ) ) )  THEN
                        ier = -1
                    END IF
                END DO
            END IF
            */
        }
        return vcoord;
    }

This subroutine translates a numeric value for IVCORD into its
character value in VCOORD.
@param ivcord  integer coordinate value
@return  string coordinate name

This subroutine translates a numeric value for IVCORD into its character value in VCOORD .


public static int[] swp4(int[] values, int startIndex, int number) {
        for (int i = startIndex; i < startIndex + number; i++) {
            values[i] = Integer.reverseBytes(values[i]);
        }
        return values;
    }

public static int [ ] swp4 ( int [ ] values , int startIndex , int number ) { for ( int i = startIndex ; i < startIndex + number ; i ++ ) { values [ i ] = Integer . reverseBytes ( values [ i ] ) ; } return values ; }

Swap the order of the integers in place.
@param values  array of int values
@param startIndex  starting index of the array
@param number of bytes
@return input array with values swapped

Swap the order of the integers in place .


public static String getGridPackingName(int pktyp) {
        String packingType = "UNKNOWN";
        switch (pktyp) {

          case GempakConstants.MDGNON :
              packingType = "MDGNON";
              break;

          case GempakConstants.MDGGRB :
              packingType = "MDGGRB";
              break;

          case GempakConstants.MDGNMC :
              packingType = "MDGNMC";
              break;

          case GempakConstants.MDGDIF :
              packingType = "MDGDIF";
              break;

          case GempakConstants.MDGDEC :
              packingType = "MDGDEC";
              break;

          case GempakConstants.MDGRB2 :
              packingType = "MDGRB2";
              break;

          default :
              break;
        }
        return packingType;
    }

public static String getGridPackingName ( int pktyp ) { String packingType = "UNKNOWN" ; switch ( pktyp ) { case GempakConstants . MDGNON : packingType = "MDGNON" ; break ; case GempakConstants . MDGGRB : packingType = "MDGGRB" ; break ; case GempakConstants . MDGNMC : packingType = "MDGNMC" ; break ; case GempakConstants . MDGDIF : packingType = "MDGDIF" ; break ; case GempakConstants . MDGDEC : packingType = "MDGDEC" ; break ; case GempakConstants . MDGRB2 : packingType = "MDGRB2" ; break ; default : break ; } return packingType ; }

Get a name for the grid packing type

@param pktyp   packing type

@return  String version of packing type


public static String getDataType(int typrt) {
        String dataType = "" + typrt;
        switch (typrt) {

          case GempakConstants.MDREAL :
              dataType = "MDREAL";
              break;

          case GempakConstants.MDINTG :
              dataType = "MDINTG";
              break;

          case GempakConstants.MDCHAR :
              dataType = "MDCHAR";
              break;

          case GempakConstants.MDRPCK :
              dataType = "MDRPCK";
              break;

          case GempakConstants.MDGRID :
              dataType = "MDGRID";
              break;

          default :
              break;
        }
        return dataType;
    }

public static String getDataType ( int typrt ) { String dataType = "" + typrt ; switch ( typrt ) { case GempakConstants . MDREAL : dataType = "MDREAL" ; break ; case GempakConstants . MDINTG : dataType = "MDINTG" ; break ; case GempakConstants . MDCHAR : dataType = "MDCHAR" ; break ; case GempakConstants . MDRPCK : dataType = "MDRPCK" ; break ; case GempakConstants . MDGRID : dataType = "MDGRID" ; break ; default : break ; } return dataType ; }

Get a name for the data packing type

@param typrt   data type

@return  String version of data type


public void readData(InputStream is, StatusUI statusUI)
            throws IOException, EOFException, DAP2Exception {

      /* ByteArrayOutputStream bout = new ByteArrayOutputStream(50 * 1000);
      copy(is, bout);
      LogStream.dbg.printf(" readData size=%d %n",bout.size());
      LogStream.dbg.logflush();
      ByteArrayInputStream bufferedIS = new ByteArrayInputStream( bout.toByteArray());  */
      //statusUI = new Counter();

        // Buffer the input stream for better performance
        BufferedInputStream bufferedIS = new BufferedInputStream(is);
        // Use a DataInputStream for deserialize
        DataInputStream dataIS = new DataInputStream(bufferedIS);

        for (Enumeration e = getVariables(); e.hasMoreElements();) {
            if (statusUI != null && statusUI.userCancelled()) throw new DataReadException("User cancelled");
            ClientIO bt = (ClientIO) e.nextElement();

          /* if (true) {
            BaseType btt = (BaseType) bt;
            System.out.printf("Deserializing: %s (%s) %n", btt.getEncodedName(), ((BaseType) bt).getTypeName());
          } */
            bt.deserialize(dataIS, ver, statusUI);
        }
        //LogStream.out.printf("Deserializing: total size = %s %n", counter);

        // notify GUI of finished download
        if (statusUI != null)
            statusUI.finished();
    }

Read the data stream from the given InputStream.  In the C++ version,
this code was in Connect.

@param is       the InputStream to read from
@param statusUI the StatusUI object to use, or null
@throws EOFException      if EOF is found before the variable is completely
deserialized.
@throws IOException       thrown on any other InputStream exception.
@throws DataReadException when invalid data is read, or if the user
cancels the download.
@throws DAP2Exception     if the OPeNDAP server returned an error.

Read the data stream from the given InputStream . In the C ++ version this code was in Connect .


public final void externalize(OutputStream os, boolean compress, boolean headers)
            throws IOException {
        // First, print headers
        if (headers) {
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(os,Util.UTF8));
            pw.println("HTTP/1.0 200 OK");
            pw.println("XDAP: " + ServerVersion.DAP2_PROTOCOL_VERSION);
            pw.println("XDODS-Server: DODS/" + ServerVersion.DAP2_PROTOCOL_VERSION);
            pw.println("Content-type: application/octet-stream");
            pw.println("Content-Description: dods-data");
            if (compress) {
                pw.println("Content-Encoding: deflate");
            }
            pw.println();
            pw.flush();
        }

        // Buffer the output stream for better performance
        OutputStream bufferedOS;
        if (compress) {
            // need a BufferedOutputStream - 3X performance - LOOK: why ??
            bufferedOS = new BufferedOutputStream(new DeflaterOutputStream(os));
        } else {
            bufferedOS = new BufferedOutputStream(os);
        }

        // Redefine PrintWriter here, so the DDS is also compressed if necessary
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(bufferedOS,Util.UTF8));
        print(pw);
        // pw.println("Data:");  // JCARON CHANGED
        pw.flush();
        bufferedOS.write("\nData:\n".getBytes(CDM.utf8Charset)); // JCARON CHANGED
        bufferedOS.flush();

        // Use a DataOutputStream for serialize
        DataOutputStream dataOS = new DataOutputStream(bufferedOS);
        for (Enumeration e = getVariables(); e.hasMoreElements();) {
            ClientIO bt = (ClientIO) e.nextElement();
            bt.externalize(dataOS);
        }
        // Note: for DeflaterOutputStream, flush() is not sufficient to flush
        // all buffered data
        dataOS.close();
    }

Dump the dataset using externalize methods. This should create
a multipart Mime document with the binary representation of the
DDS that is currently in memory.

@param os       the OutputStream to use.
@param compress true if we should compress the output.
@param headers  true if we should print HTTP headers.
@throws IOException thrown on any OutputStream exception.

Dump the dataset using externalize methods . This should create a multipart Mime document with the binary representation of the DDS that is currently in memory .


public static TagEnum getTag(short code) {
    TagEnum te = hash.get(code);
    if (te == null) te = new TagEnum("UNKNOWN", "UNKNOWN", code);
    return te;
  }

public static TagEnum getTag ( short code ) { TagEnum te = hash . get ( code ) ; if ( te == null ) te = new TagEnum ( "UNKNOWN" , "UNKNOWN" , code ) ; return te ; }

Find the Tag that matches the code.

@param code find Tag with this code.
@return Tag or null if no match.


public BufferedImage getNextImage(boolean forward) {
    if (grid != null) {
      if (forward) {
        this.time++;
        if (this.time >= this.ntimes) this.time = 0;
      } else {
        this.time--;
        if (this.time < 0) this.time = this.ntimes-1;
      }

      Array data;
      try {
        data = grid.readDataSlice( this.time, 0, -1, -1);
        return ImageArrayAdapter.makeGrayscaleImage( data, grid);
      } catch (IOException e) {
        e.printStackTrace();
        return null;
      }
    }

    if (currentFile == null)
      return null;

    if (currentDir == null) {
      currentDirFileNo = 0;
      currentDir = currentFile.getParentFile();
      currentDirFileList = new ArrayList<>();
      addToList( currentDir, currentDirFileList);
      //Arrays.asList(currentDir.listFiles());
      //Collections.sort(currentDirFileList);
      for (int i = 0; i < currentDirFileList.size(); i++) {
        File file = currentDirFileList.get(i);
        if (file.equals(currentFile))
          currentDirFileNo = i;
      }
    }

    if (forward) {
      currentDirFileNo++;
      if (currentDirFileNo >= currentDirFileList.size())
        currentDirFileNo = 0;
    } else {
      currentDirFileNo--;
      if (currentDirFileNo < 0)
        currentDirFileNo = currentDirFileList.size()-1;
    }

    File nextFile = currentDirFileList.get(currentDirFileNo);
    try {
      System.out.println("Open image "+nextFile);
      return javax.imageio.ImageIO.read(nextFile);
    } catch (IOException e) {
      System.out.println("Failed to open image "+nextFile);
      return getNextImage( forward);
    }

  }

This assumes you have opened a file. looks in the parent directory.
@param forward if true got to next, else previous
@return  next file in the directory, as a BufferedImage.

This assumes you have opened a file . looks in the parent directory .


static public int
    size(DapType type)
    {
        switch (type.getTypeSort()) {
        case Char: // remember serial size is 1, not 2.
        case UInt8:
        case Int8:
            return 1;
        case Int16:
        case UInt16:
            return 2;
        case Int32:
        case UInt32:
        case Float32:
            return 4;
        case Int64:
        case UInt64:
        case Float64:
            return 8;
        case Enum:
            return size(((DapEnumeration)type).getBaseType());
        default:
            break;
        }
        return 0;
    }

static
public
int
size
(
DapType
type
)
{
switch
(
type
.
getTypeSort
(
)
)
{
case
Char
:
// remember serial size is 1, not 2.
case
UInt8
:
case
Int8
:
return
1
;
case
Int16
:
case
UInt16
:
return
2
;
case
Int32
:
case
UInt32
:
case
Float32
:
return
4
;
case
Int64
:
case
UInt64
:
case
Float64
:
return
8
;
case
Enum
:
return
size
(
(
(
DapEnumeration
)
type
)
.
getBaseType
(
)
)
;
default
:
break
;
}
return
0
;
}

Conmpute the size, in databuffer,
of the daptype wrt to a serialization;
0 if undefined.

@param type The type of interest
@return the size, in databuffer

Conmpute the size in databuffer of the daptype wrt to a serialization ; 0 if undefined .


private static int sumArray(int[] arr) {
        if (arr == null) throw new NullPointerException("null array");
        if (arr.length == 0) throw new IllegalArgumentException("Zero-length array");
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] <= 0) {
                throw new IllegalArgumentException("All array values must be > 0");
            }
            sum += arr[i];
        }
        return sum;
    }

private
static
int
sumArray
(
int
[
]
arr
)
{
if
(
arr
==
)
throw
new
NullPointerException
(
"null array"
)
;
if
(
arr
.
length
==
0
)
throw
new
IllegalArgumentException
(
"Zero-length array"
)
;
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
arr
.
length
;
i
++
)
{
if
(
arr
[
i
]
<=
0
)
{
throw
new
IllegalArgumentException
(
"All array values must be > 0"
)
;
}
sum
+=
arr
[
i
]
;
}
return
sum
;
}

Calculates the sum of the values in the given array.
@throws NullPointerException if arr is null
@throws IllegalArgumentException if arr is empty or contains
zero or negative values.

Calculates the sum of the values in the given array .


public void setGrid( Rectangle2D bbox, double width, double height) {
    offsetX = bbox.getX();
    offsetY = bbox.getY();

      // number of grid cells
    countX = Math.min( nx, (int) (bbox.getWidth() / (scaleOverlap * width)));
    countY = Math.min( ny, (int) (bbox.getHeight() / (scaleOverlap * height)));

    gridWidth = bbox.getWidth() / countX;
    gridHeight = bbox.getHeight() / countY;

    if (debug)
      System.out.println("SpatialGrid size "+ gridWidth+" "+ gridHeight+" = "+countX+" by "+countY+
        " scaleOverlap= "+ scaleOverlap);
  }

public
void
setGrid
(
Rectangle2D
bbox
,
double
width
,
double
height
)
{
offsetX
=
bbox
.
getX
(
)
;
offsetY
=
bbox
.
getY
(
)
;
// number of grid cells
countX
=
Math
.
min
(
nx
,
(
int
)
(
bbox
.
getWidth
(
)
/
(
scaleOverlap
*
width
)
)
)
;
countY
=
Math
.
min
(
ny
,
(
int
)
(
bbox
.
getHeight
(
)
/
(
scaleOverlap
*
height
)
)
)
;
gridWidth
=
bbox
.
getWidth
(
)
/
countX
;
gridHeight
=
bbox
.
getHeight
(
)
/
countY
;
if
(
debug
)
System
.
out
.
println
(
"SpatialGrid size "
+
gridWidth
+
" "
+
gridHeight
+
" = "
+
countX
+
" by "
+
countY
+
" scaleOverlap= "
+
scaleOverlap
)
;
}

Set the grid scale.
@param bbox bounding box: we are only interested in points inside of this
@param width : divide the bounding box into cells of this width.
@param height : divide the bounding box into cells of this height.
maximum number of grid cells is nx x ny


public void setOverlap(int overlap) {
    // overlap limited to [0, 50%]
    double dover = Math.max( 0.0, Math.min(.01*overlap, .50));
    scaleOverlap = 1.0 - dover;
  }

public
void
setOverlap
(
int
overlap
)
{
// overlap limited to [0, 50%]
double
dover
=
Math
.
max
(
0.0
,
Math
.
min
(
.01
*
overlap
,
.50
)
)
;
scaleOverlap
=
1.0
dover
;
}

Set how much the data may overlap.
@param overlap : percent overlap


public void clear() {
   for (int y=0; y<countY; y++)
     for (int x=0; x<countX; x++)
       gridArray[y][x].used = false;
  }

public void clear ( ) { for ( int y = 0 ; y < countY ; y ++ ) for ( int x = 0 ; x < countX ; x ++ ) gridArray [ y ] [ x ] . used = false ; }


public boolean markIfClear (Rectangle2D rect, Object o) {
    double centerX = rect.getX() + rect.getWidth()/2;
    double centerY = rect.getY() + rect.getHeight()/2;

    int indexX = (int) ((centerX-offsetX)/gridWidth);
    int indexY = (int) ((centerY-offsetY)/gridHeight);

    if (debugMark)
      System.out.println("markIfClear "+ rect+ " "+indexX+" "+indexY);

    if ((indexX < 0) || (indexX >= countX) || (indexY < 0) || (indexY >= countY)) // outside box
      return false;

    GridCell gwant = gridArray[indexY][indexX];
    if (gwant.used)  // already taken
      return false;

    if (null != findIntersection(rect))
      return false;

    // its ok to use
    gwant.used = true;
    gwant.objectBB = rect;
    gwant.o = o;
    return true;
  }

public
boolean
markIfClear
(
Rectangle2D
rect
,
Object
o
)
{
double
centerX
=
rect
.
getX
(
)
+
rect
.
getWidth
(
)
/
2
;
double
centerY
=
rect
.
getY
(
)
+
rect
.
getHeight
(
)
/
2
;
int
indexX
=
(
int
)
(
(
centerX
offsetX
)
/
gridWidth
)
;
int
indexY
=
(
int
)
(
(
centerY
offsetY
)
/
gridHeight
)
;
if
(
debugMark
)
System
.
out
.
println
(
"markIfClear "
+
rect
+
" "
+
indexX
+
" "
+
indexY
)
;
if
(
(
indexX
<
0
)
||
(
indexX
>=
countX
)
||
(
indexY
<
0
)
||
(
indexY
>=
countY
)
)
// outside box
return
false
;
GridCell
gwant
=
gridArray
[
indexY
]
[
indexX
]
;
if
(
gwant
.
used
)
// already taken
return
false
;
if
(
!=
findIntersection
(
rect
)
)
return
false
;
// its ok to use
gwant
.
used
=
true
;
gwant
.
objectBB
=
rect
;
gwant
.
o
=
o
;
return
true
;
}

Check if the given rect intersects an already drawn one.
If not, set the corresponding cell as marked, store object, return true,
meaning "ok to draw".
@param rect the bounding box of the thing we want to draw
@param o store this object
@return true if inside the bounding box and no intersection

Check if the given rect intersects an already drawn one . If not set the corresponding cell as marked store object return true meaning ok to draw .


public Object findIntersection (Rectangle2D rect) {
    double centerX = rect.getX() + rect.getWidth()/2;
    double centerY = rect.getY() + rect.getHeight()/2;

    int indexX = (int) ((centerX-offsetX)/gridWidth);
    int indexY = (int) ((centerY-offsetY)/gridHeight);

    // outside box
    if ((indexX < 0) || (indexX >= countX) || (indexY < 0) || (indexY >= countY))
      return null;

    // check the surrounding points
    for (int y=Math.max(0,indexY-1); y<=Math.min(countY-1,indexY+1); y++) {
      for (int x=Math.max(0,indexX-1); x<=Math.min(countX-1,indexX+1); x++) {
        GridCell gtest = gridArray[y][x];

        if (!gtest.used)
          continue;

        if (intersectsOverlap( rect, gtest.objectBB)) // hits an adjacent rectangle
          return gtest.o;
      }
    }

    return null;
  }

public
Object
findIntersection
(
Rectangle2D
rect
)
{
double
centerX
=
rect
.
getX
(
)
+
rect
.
getWidth
(
)
/
2
;
double
centerY
=
rect
.
getY
(
)
+
rect
.
getHeight
(
)
/
2
;
int
indexX
=
(
int
)
(
(
centerX
offsetX
)
/
gridWidth
)
;
int
indexY
=
(
int
)
(
(
centerY
offsetY
)
/
gridHeight
)
;
// outside box
if
(
(
indexX
<
0
)
||
(
indexX
>=
countX
)
||
(
indexY
<
0
)
||
(
indexY
>=
countY
)
)
return
;
// check the surrounding points
for
(
int
y
=
Math
.
max
(
0
,
indexY
1
)
;
y
<=
Math
.
min
(
countY
1
,
indexY
+
1
)
;
y
++
)
{
for
(
int
x
=
Math
.
max
(
0
,
indexX
1
)
;
x
<=
Math
.
min
(
countX
1
,
indexX
+
1
)
;
x
++
)
{
GridCell
gtest
=
gridArray
[
y
]
[
x
]
;
if
(
!
gtest
.
used
)
continue
;
if
(
intersectsOverlap
(
rect
,
gtest
.
objectBB
)
)
// hits an adjacent rectangle
return
gtest
.
o
;
}
}
return
;
}

Check if the given rect intersects an already drawn object
@param rect the bounding box of the thing we want to draw
@return object that intersects, or null if no intersection


public Object findIntersection (Point2D p) {
    int indexX = (int) ((p.getX()-offsetX)/gridWidth);
    int indexY = (int) ((p.getY()-offsetY)/gridHeight);

    // outside box
    if ((indexX < 0) || (indexX >= countX) || (indexY < 0) || (indexY >= countY))
      return null;

    // check the surrounding points
    for (int y=Math.max(0,indexY-1); y<=Math.min(countY-1,indexY+1); y++) {
      for (int x=Math.max(0,indexX-1); x<=Math.min(countX-1,indexX+1); x++) {
        GridCell gtest = gridArray[y][x];

        if (!gtest.used)
          continue;

        if (gtest.objectBB.contains( p.getX(), p.getY()))
          return gtest.o;
      }
    }

    return null;
  }

public
Object
findIntersection
(
Point2D
p
)
{
int
indexX
=
(
int
)
(
(
p
.
getX
(
)
offsetX
)
/
gridWidth
)
;
int
indexY
=
(
int
)
(
(
p
.
getY
(
)
offsetY
)
/
gridHeight
)
;
// outside box
if
(
(
indexX
<
0
)
||
(
indexX
>=
countX
)
||
(
indexY
<
0
)
||
(
indexY
>=
countY
)
)
return
;
// check the surrounding points
for
(
int
y
=
Math
.
max
(
0
,
indexY
1
)
;
y
<=
Math
.
min
(
countY
1
,
indexY
+
1
)
;
y
++
)
{
for
(
int
x
=
Math
.
max
(
0
,
indexX
1
)
;
x
<=
Math
.
min
(
countX
1
,
indexX
+
1
)
;
x
++
)
{
GridCell
gtest
=
gridArray
[
y
]
[
x
]
;
if
(
!
gtest
.
used
)
continue
;
if
(
gtest
.
objectBB
.
contains
(
p
.
getX
(
)
,
p
.
getY
(
)
)
)
return
gtest
.
o
;
}
}
return
;
}

Check if the given point is contained in already drawn object
@param p the point to check
@return object that intersects, or null if no intersection


public Object findClosest(Point2D pt) {
    Object o = null;
    int indexX = (int) ((pt.getX()-offsetX)/gridWidth);
    int indexY = (int) ((pt.getY()-offsetY)/gridHeight);

    if (debugClosest)
      System.out.println("findClosest "+ pt+ " "+indexX+" "+indexY);

    if ((indexX < 0) || (indexX >= countX) || (indexY < 0) || (indexY >= countY)) // outside box
      return null;

    GridCell gwant = gridArray[indexY][indexX];
    if (gwant.used)  // that was easy
      return gwant.o;

    // check the surrounding points along perimeter of increasing diameter
    for (int p=1; p<Math.max(countX-1, countY-1); p++)
      if (null != (o = findClosestAlongPerimeter(pt, indexX, indexY, p)))
        return o;

    return null; // nothing found
  }

Find the closest marked cell to the given point
@param pt  find the closest marked cell to this point
@return the object associated with the closest cell, or null if none


private double distanceSq( Point2D pt, int indexX, int indexY) {
    if ((indexX < 0) || (indexX >= countX) || (indexY < 0) || (indexY >= countY)) // outside bounding box
      return MAX_DOUBLE;

      GridCell gtest = gridArray[indexY][indexX];
      if (!gtest.used)    // nothing in this cell
        return MAX_DOUBLE;

        // get distance from center of cell
      Rectangle2D rect = gtest.objectBB;
      double dx = rect.getX()+rect.getWidth()/2 - pt.getX();
      double dy = rect.getY()+rect.getHeight()/2 - pt.getY();
      return (dx*dx + dy*dy);
    }

private
double
distanceSq
(
Point2D
pt
,
int
indexX
,
int
indexY
)
{
if
(
(
indexX
<
0
)
||
(
indexX
>=
countX
)
||
(
indexY
<
0
)
||
(
indexY
>=
countY
)
)
// outside bounding box
return
MAX_DOUBLE
;
GridCell
gtest
=
gridArray
[
indexY
]
[
indexX
]
;
if
(
!
gtest
.
used
)
// nothing in this cell
return
MAX_DOUBLE
;
// get distance from center of cell
Rectangle2D
rect
=
gtest
.
objectBB
;
double
dx
=
rect
.
getX
(
)
+
rect
.
getWidth
(
)
/
2
pt
.
getX
(
)
;
double
dy
=
rect
.
getY
(
)
+
rect
.
getHeight
(
)
/
2
pt
.
getY
(
)
;
return
(
dx
*
dx
+
dy
*
dy
)
;
}

if out of bbox or cell not marked, return MAX_DOUBLE

if out of bbox or cell not marked return MAX_DOUBLE


public static synchronized BaseUnit getOrCreate(final UnitName id,
            final BaseQuantity baseQuantity) throws NameException,
            UnitExistsException {
        BaseUnit baseUnit;
        final BaseUnit nameUnit = nameMap.get(id);
        final BaseUnit quantityUnit = quantityMap.get(baseQuantity);
        if (nameUnit != null || quantityUnit != null) {
            baseUnit = nameUnit != null
                    ? nameUnit
                    : quantityUnit;
            if ((nameUnit != null && !baseQuantity.equals(nameUnit
                    .getBaseQuantity()))
                    || (quantityUnit != null && !id.equals(quantityUnit
                            .getUnitName()))) {
                throw new UnitExistsException(
                        "Attempt to incompatibly redefine base unit \""
                                + baseUnit + '"');
            }
        }
        else {
            baseUnit = new BaseUnit(id, baseQuantity);
            quantityMap.put(baseQuantity, baseUnit);
            nameMap.put(id, baseUnit);
        }
        return baseUnit;
    }

Factory method for creating a new BaseUnit or obtaining a
previously-created one.

@param id
The identifier for the base unit.
id.getSymbol()
shall not return
null.
@param baseQuantity
The base quantity of the base unit.
@throws NameException
id.getSymbol() returned
null.
@throws UnitExistsException
Attempt to incompatibly redefine an existing base unit.

Factory method for creating a new BaseUnit or obtaining a previously - created one .


static private ServiceType searchFragment(String fragment) {
    if (fragment.length() == 0)
      return null;
    Map<String, String> map = parseFragment(fragment);
    if (map == null) return null;
    String protocol = map.get("protocol");
    if(protocol == null) {
      for(String p: FRAGPROTOCOLS) {
        if(map.get(p) != null) {protocol = p; break;}
      }
    }
    if (protocol != null) {
      if (protocol.equalsIgnoreCase("dap") || protocol.equalsIgnoreCase("dods"))
        return ServiceType.OPENDAP;
      if (protocol.equalsIgnoreCase("dap4"))
        return ServiceType.DAP4;
      if (protocol.equalsIgnoreCase("cdmremote"))
        return ServiceType.CdmRemote;
      if (protocol.equalsIgnoreCase("thredds"))
        return ServiceType.THREDDS;
      if (protocol.equalsIgnoreCase("ncml"))
        return ServiceType.NCML;
    }
    return null;
  }

static private ServiceType searchFragment ( String fragment ) { if ( fragment . length ( ) == 0 ) return null ; Map < String , String > map = parseFragment ( fragment ) ; if ( map == null ) return null ; String protocol = map . get ( "protocol" ) ; if ( protocol == null ) { for ( String p : FRAGPROTOCOLS ) { if ( map . get ( p ) != null ) { protocol = p ; break ; } } } if ( protocol != null ) { if ( protocol . equalsIgnoreCase ( "dap" ) || protocol . equalsIgnoreCase ( "dods" ) ) return ServiceType . OPENDAP ; if ( protocol . equalsIgnoreCase ( "dap4" ) ) return ServiceType . DAP4 ; if ( protocol . equalsIgnoreCase ( "cdmremote" ) ) return ServiceType . CdmRemote ; if ( protocol . equalsIgnoreCase ( "thredds" ) ) return ServiceType . THREDDS ; if ( protocol . equalsIgnoreCase ( "ncml" ) ) return ServiceType . NCML ; } return null ; }

Given a location, find markers indicated which protocol to use
LOOK what use case is this handling ?

@param fragment the fragment is to be examined
@return The discovered ServiceType, or null

Given a location find markers indicated which protocol to use LOOK what use case is this handling ?


static private ServiceType searchPath(String url) {
      if(false) { // Disable for now
      if(url == null || url.length() == 0)
        return null;
      url = url.toLowerCase(); // for matching purposes
      for(int i=0; i<FRAGPROTOCOLS.length;i++) {
        String p = FRAGPROTOCOLS[i];
        if(url.indexOf("/thredds/"+p.toLowerCase()+"/")>= 0) {
          return FRAGPROTOSVCTYPE[i];
        }
      }
      }
      return null;
    }

static
private
ServiceType
searchPath
(
String
url
)
{
if
(
false
)
{
// Disable for now
if
(
url
==
||
url
.
length
(
)
==
0
)
return
;
url
=
url
.
toLowerCase
(
)
;
// for matching purposes
for
(
int
i
=
0
;
i
<
FRAGPROTOCOLS
.
length
;
i
++
)
{
String
p
=
FRAGPROTOCOLS
[
i
]
;
if
(
url
.
indexOf
(
"/thredds/"
+
p
.
toLowerCase
(
)
+
"/"
)
>=
0
)
{
return
FRAGPROTOSVCTYPE
[
i
]
;
}
}
}
return
;
}

Given a url, search the path to look for protocol indicators

@param url the url is to be examined
@return The discovered ServiceType, or null

Given a url search the path to look for protocol indicators


static private ServiceType decodePathExtension(String path) {
    // Look at the path extensions
    if (path.endsWith(".dds") || path.endsWith(".das") || path.endsWith(".dods"))
      return ServiceType.OPENDAP;

    if (path.endsWith(".dmr") || path.endsWith(".dap") || path.endsWith(".dsr"))
      return ServiceType.DAP4;

    if (path.endsWith(".xml") || path.endsWith(".ncml"))
      return ServiceType.NCML;
    return null;
  }

static
private
ServiceType
decodePathExtension
(
String
path
)
{
// Look at the path extensions
if
(
path
.
endsWith
(
".dds"
)
||
path
.
endsWith
(
".das"
)
||
path
.
endsWith
(
".dods"
)
)
return
ServiceType
.
OPENDAP
;
if
(
path
.
endsWith
(
".dmr"
)
||
path
.
endsWith
(
".dap"
)
||
path
.
endsWith
(
".dsr"
)
)
return
ServiceType
.
DAP4
;
if
(
path
.
endsWith
(
".xml"
)
||
path
.
endsWith
(
".ncml"
)
)
return
ServiceType
.
NCML
;
return
;
}

Check path extension; assumes no query or fragment

@param path the path to examine for extension
@return ServiceType inferred from the extension or null

Check path extension ; assumes no query or fragment


static private ServiceType checkIfDods(String location) throws IOException {
    int len = location.length();
    // Strip off any trailing .dds, .das, or .dods
    if (location.endsWith(".dds"))
      location = location.substring(0, len - ".dds".length());
    if (location.endsWith(".das"))
      location = location.substring(0, len - ".das".length());
    if (location.endsWith(".dods"))
      location = location.substring(0, len - ".dods".length());

    // Opendap assumes that the caller has properly escaped the url
    try (
            // For some reason, the head method is not using credentials
            // method = session.newMethodHead(location + ".dds");
            HTTPMethod method = HTTPFactory.Get(location + ".dds")) {

      int status = method.execute();
      if (status == 200) {
        Header h = method.getResponseHeader("Content-Description");
        if ((h != null) && (h.getValue() != null)) {
          String v = h.getValue();
          if (v.equalsIgnoreCase("dods-dds") || v.equalsIgnoreCase("dods_dds"))
            return ServiceType.OPENDAP;
          else
            throw new IOException("OPeNDAP Server Error= " + method.getResponseAsString());
        }
      }
      if (status == HttpStatus.SC_UNAUTHORIZED || status == HttpStatus.SC_FORBIDDEN)
        throw new IOException("Unauthorized to open dataset " + location);

      // not dods
      return null;
    }
  }

not sure what other opendap servers do, so fall back on check for dds

not sure what other opendap servers do so fall back on check for dds


static private ServiceType checkIfDap4(String location) throws IOException {
    // Strip off any trailing DAP4 prefix
    if (location.endsWith(".dap"))
      location = location.substring(0, location.length() - ".dap".length());
    else if (location.endsWith(".dmr"))
      location = location.substring(0, location.length() - ".dmr".length());
    else if (location.endsWith(".dmr.xml"))
      location = location.substring(0, location.length() - ".dmr.xml".length());
    else if (location.endsWith(".dsr"))
      location = location.substring(0, location.length() - ".dsr".length());
    try (HTTPMethod method = HTTPFactory.Get(location + ".dmr.xml")) {
      int status = method.execute();
      if (status == 200) {
        Header h = method.getResponseHeader("Content-Type");
        if ((h != null) && (h.getValue() != null)) {
          String v = h.getValue();
          if (v.startsWith("application/vnd.opendap.org"))
            return ServiceType.DAP4;
        }
      }
      if (status == HttpStatus.SC_UNAUTHORIZED || status == HttpStatus.SC_FORBIDDEN)
        throw new IOException("Unauthorized to open dataset " + location);

      // not dods
      return null;
    }
  }

static
private
ServiceType
checkIfDap4
(
String
location
)
throws
IOException
{
// Strip off any trailing DAP4 prefix
if
(
location
.
endsWith
(
".dap"
)
)
location
=
location
.
substring
(
0
,
location
.
length
(
)
".dap"
.
length
(
)
)
;
else
if
(
location
.
endsWith
(
".dmr"
)
)
location
=
location
.
substring
(
0
,
location
.
length
(
)
".dmr"
.
length
(
)
)
;
else
if
(
location
.
endsWith
(
".dmr.xml"
)
)
location
=
location
.
substring
(
0
,
location
.
length
(
)
".dmr.xml"
.
length
(
)
)
;
else
if
(
location
.
endsWith
(
".dsr"
)
)
location
=
location
.
substring
(
0
,
location
.
length
(
)
".dsr"
.
length
(
)
)
;
try
(
HTTPMethod
method
=
HTTPFactory
.
Get
(
location
+
".dmr.xml"
)
)
{
int
status
=
method
.
execute
(
)
;
if
(
status
==
200
)
{
Header
h
=
method
.
getResponseHeader
(
"Content-Type"
)
;
if
(
(
h
!=
)
&&
(
h
.
getValue
(
)
!=
)
)
{
String
v
=
h
.
getValue
(
)
;
if
(
v
.
startsWith
(
"application/vnd.opendap.org"
)
)
return
ServiceType
.
DAP4
;
}
}
if
(
status
==
HttpStatus
.
SC_UNAUTHORIZED
||
status
==
HttpStatus
.
SC_FORBIDDEN
)
throw
new
IOException
(
"Unauthorized to open dataset "
+
location
)
;
// not dods
return
;
}
}


public long sendData2(Variable v, Section section, OutputStream out, NcStreamCompression compress) throws IOException, InvalidRangeException {
    if (show) System.out.printf(" %s section=%s%n", v.getFullName(), section);

    boolean isVlen = v.isVariableLength(); //  && v.getRank() > 1;
    if (isVlen)
      v.read(section);
    NcStreamDataCol encoder = new NcStreamDataCol();
    NcStreamProto.DataCol dataProto = encoder.encodeData2(v.getFullName(), isVlen, section, v.read(section));

    // LOOK trap error, write error message ??

    // dataProto.writeDelimitedTo(out);
    long size = 0;
    size += writeBytes(out, NcStream.MAGIC_DATA2); // data version 3

    byte[] datab = dataProto.toByteArray();
    size += NcStream.writeVInt(out, datab.length); // dataProto len
    size += writeBytes(out, datab); // dataProto
    return size;
  }


static public String fqnSuffix(String fqn)
    {
        int structindex = fqn.lastIndexOf('.');
        int groupindex = fqn.lastIndexOf('/');
        if(structindex >= 0)
            return fqn.substring(structindex + 1, fqn.length());
        else
            return fqn.substring(groupindex + 1, fqn.length());
    }

static public String fqnSuffix ( String fqn ) { int structindex = fqn . lastIndexOf ( ' ' ) ; int groupindex = fqn . lastIndexOf ( ' ' ) ; if ( structindex >= 0 ) return fqn . substring ( structindex + 1 , fqn . length ( ) ) ; else return fqn . substring ( groupindex + 1 , fqn . length ( ) ) ; }

return last name part of an fqn; result will be escaped.

return last name part of an fqn ; result will be escaped .


static public String fqnPrefix(String fqn)
    {
        int structindex = fqn.lastIndexOf('.');
        int groupindex = fqn.lastIndexOf('/');
        if(structindex >= 0)
            return fqn.substring(0, structindex);
        else
            return fqn.substring(0, groupindex);
    }

static public String fqnPrefix ( String fqn ) { int structindex = fqn . lastIndexOf ( ' ' ) ; int groupindex = fqn . lastIndexOf ( ' ' ) ; if ( structindex >= 0 ) return fqn . substring ( 0 , structindex ) ; else return fqn . substring ( 0 , groupindex ) ; }

return prefix name part of an fqn; result will be escaped.

return prefix name part of an fqn ; result will be escaped .


static public String
    locateFile(String filename, String abspath, boolean wantdir)
    {
        Deque<String> q = new ArrayDeque<String>();
        // clean up the path and filename
        filename = filename.trim().replace('\\', '/');
        abspath = abspath.trim().replace('\\', '/');
        if(filename.charAt(0) == '/') filename = filename.substring(1);
        if(filename.endsWith("/")) filename = filename.substring(0, filename.length() - 1);
        if(abspath.endsWith("/")) abspath = abspath.substring(0, abspath.length() - 1);
        q.addFirst(abspath);  // prime the search queue

        for(; ; ) {  // breadth first search
            String currentpath = q.poll();
            if(currentpath == null) break; // done searching
            File current = new File(currentpath);
            File[] contents = current.listFiles();
            if(contents != null) {
                for(File subfile : contents) {
                    if(!subfile.getName().equals(filename)) continue;
                    if((wantdir && subfile.isDirectory())
                            || (!wantdir && subfile.isFile())) {
                        // Assume this is it
                        return DapUtil.canonicalpath(subfile.getAbsolutePath());
                    }
                }
                for(File subfile : contents) {
                    if(subfile.isDirectory())
                        q.addFirst(currentpath + "/" + subfile.getName());
                }
            }
        }
        return null;
    }

static
public
String
locateFile
(
String
filename
,
String
abspath
,
boolean
wantdir
)
{
Deque
<
String
>
q
=
new
ArrayDeque
<
String
>
(
)
;
// clean up the path and filename
filename
=
filename
.
trim
(
)
.
replace
(
'
'
,
'
'
)
;
abspath
=
abspath
.
trim
(
)
.
replace
(
'
'
,
'
'
)
;
if
(
filename
.
charAt
(
0
)
==
'
'
)
filename
=
filename
.
substring
(
1
)
;
if
(
filename
.
endsWith
(
"/"
)
)
filename
=
filename
.
substring
(
0
,
filename
.
length
(
)
1
)
;
if
(
abspath
.
endsWith
(
"/"
)
)
abspath
=
abspath
.
substring
(
0
,
abspath
.
length
(
)
1
)
;
q
.
addFirst
(
abspath
)
;
// prime the search queue
for
(
;
;
)
{
// breadth first search
String
currentpath
=
q
.
poll
(
)
;
if
(
currentpath
==
)
break
;
// done searching
File
current
=
new
File
(
currentpath
)
;
File
[
]
contents
=
current
.
listFiles
(
)
;
if
(
contents
!=
)
{
for
(
File
subfile
:
contents
)
{
if
(
!
subfile
.
getName
(
)
.
equals
(
filename
)
)
continue
;
if
(
(
wantdir
&&
subfile
.
isDirectory
(
)
)
||
(
!
wantdir
&&
subfile
.
isFile
(
)
)
)
{
// Assume this is it
return
DapUtil
.
canonicalpath
(
subfile
.
getAbsolutePath
(
)
)
;
}
}
for
(
File
subfile
:
contents
)
{
if
(
subfile
.
isDirectory
(
)
)
q
.
addFirst
(
currentpath
+
"/"
+
subfile
.
getName
(
)
)
;
}
}
}
return
;
}

Walk the specified subtree dir tree to try to locate file|dir named filename.
Use breadth first search.

@param filename Name of the file|dir to locate
@param abspath  Absolute path from which to start search
@param wantdir  True if we are looking for a directory,
false if we are looking for a file
@return absolute path of the file or null

Walk the specified subtree dir tree to try to locate file|dir named filename . Use breadth first search .


static public String
    locateRelative(String relpath, String abspath, boolean wantdir)
    {
        // clean up the path and filename
        relpath = relpath.trim().replace('\\', '/');
        if(relpath.charAt(0) == '/') relpath = relpath.substring(1);
        if(relpath.endsWith("/")) relpath = relpath.substring(0, relpath.length() - 1);
        String[] pieces = relpath.split("[/]");
        String partial = abspath;
        for(int i = 0; i < pieces.length - 1; i++) {
            String nextdir = locateFile(pieces[i], abspath, true);
            if(nextdir == null) return null;
            partial = nextdir;
        }
        // See if the final file|dir exists in this dir
        String finalpath = locateFile(pieces[pieces.length - 1], partial, wantdir);
        return finalpath;
    }

Walk the specified dir tree to locate file specified by relative path.
Use breadth first search.

@param relpath Name of the file|dir to locate
@param abspath Absolute path from which to start search
@param wantdir True if we are looking for a directory,
false if we are looking for a file
@return absolute path of the file|dir wrt to abspath

Walk the specified dir tree to locate file specified by relative path . Use breadth first search .


static public byte[] extract(ByteBuffer buf)
    {
        int len = buf.limit();
        byte[] bytes = new byte[len];
        buf.rewind();
        buf.get(bytes);
        return bytes;
    }

static public byte [ ] extract ( ByteBuffer buf ) { int len = buf . limit ( ) ; byte [ ] bytes = new byte [ len ] ; buf . rewind ( ) ; buf . get ( bytes ) ; return bytes ; }

Properly extract the byte contents of a ByteBuffer

@param buf The buffer whose content is to be extracted
as defined by the buffer limit.
@return The byte array contents of the buffer


static public List<DapVariable>
    getStructurePath(DapVariable var)
    {
        List<DapNode> path = var.getPath();
        List<DapVariable> structpath = new ArrayList<DapVariable>();
        for(int i = 0; i < path.size(); i++) {
            DapNode node = path.get(i);
            switch (node.getSort()) {
            case DATASET:
            case GROUP:
                break;
            case VARIABLE:
                structpath.add((DapVariable) node);
                break;
            default:
                assert false : "Internal error";
            }
        }
        return structpath;
    }

static
public
List
<
DapVariable
>
getStructurePath
(
DapVariable
var
)
{
List
<
DapNode
>
path
=
var
.
getPath
(
)
;
List
<
DapVariable
>
structpath
=
new
ArrayList
<
DapVariable
>
(
)
;
for
(
int
i
=
0
;
i
<
path
.
size
(
)
;
i
++
)
{
DapNode
node
=
path
.
get
(
i
)
;
switch
(
node
.
getSort
(
)
)
{
case
DATASET
:
case
GROUP
:
break
;
case
VARIABLE
:
structpath
.
add
(
(
DapVariable
)
node
)
;
break
;
default
:
assert
false
:
"Internal error"
;
}
}
return
structpath
;
}

Given a dap variable, get the path  from the
top-level variable to and including the given variable
such that all but the last element is a structure.

Given a dap variable get the path from the top - level variable to and including the given variable such that all but the last element is a structure .


static public String
    nullify(String path)
    {
        return (path != null && path.length() == 0 ? null : path);
    }

static public String nullify ( String path ) { return ( path != null && path . length ( ) == 0 ? null : path ) ; }

Convert "" paths to null

@param path
@return path or null


static public String
    join(String[] array, String sep, int from, int upto)
    {
        if(sep == null) sep = "";
        if(from < 0 || upto > array.length)
            throw new IndexOutOfBoundsException();
        if(upto <= from)
            return "";
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for(int i = from; i < upto; i++, first = false) {
            if(!first) result.append(sep);
            result.append(array[i]);
        }
        return result.toString();
    }

static public String join ( String [ ] array , String sep , int from , int upto ) { if ( sep == null ) sep = "" ; if ( from < 0 || upto > array . length ) throw new IndexOutOfBoundsException ( ) ; if ( upto <= from ) return "" ; StringBuilder result = new StringBuilder ( ) ; boolean first = true ; for ( int i = from ; i < upto ; i ++ , first = false ) { if ( ! first ) result . append ( sep ) ; result . append ( array [ i ] ) ; } return result . toString ( ) ; }

Given an Array of Strings and a separator and a count,
concat the first count elements of an array with separator
between them. A null string is treated like "".

@param array the array to concat
@param sep   the separator
@param from  start point for join (inclusive)
@param upto  end point for join (exclusive)
@return the join

Given an Array of Strings and a separator and a count concat the first count elements of an array with separator between them . A null string is treated like .


static public boolean
    hasDriveLetter(String path)
    {
        boolean hasdr = false;
        if(path != null && path.length() >= 2) {
            hasdr = (DRIVELETTERS.indexOf(path.charAt(0)) >= 0 && path.charAt(1) == ':');
        }
        return hasdr;
    }

static public boolean hasDriveLetter ( String path ) { boolean hasdr = false ; if ( path != null && path . length ( ) >= 2 ) { hasdr = ( DRIVELETTERS . indexOf ( path . charAt ( 0 ) ) >= 0 && path . charAt ( 1 ) == ' ' ) ; } return hasdr ; }

return true if this path appears to start with a windows drive letter

@param path
@return


static public List<String>
    getProtocols(String url, int[] breakpoint)
    {
        // break off any leading protocols;
        // there may be more than one.
        // Watch out for Windows paths starting with a drive letter.
        // Each protocol has trailing ':'  removed

        List<String> allprotocols = new ArrayList<>(); // all leading protocols upto path or host

        // Note, we cannot use split because of the context sensitivity
        StringBuilder buf = new StringBuilder(url);
        int protosize = 0;
        for(; ; ) {
            int index = buf.indexOf(":");
            if(index < 0) break; // no more protocols
            String protocol = buf.substring(0, index);
            // Check for windows drive letter
            if(index == 1 //=>|protocol| == 1 => windows drive letter
                    && "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    .indexOf(buf.charAt(0)) >= 0) break;
            allprotocols.add(protocol);
            buf.delete(0, index + 1); // remove the leading protocol
            protosize += (index + 1);
            if(buf.indexOf("/") == 0)
                break; // anything after this is not a protocol
        }
        breakpoint[0] = protosize;
        return allprotocols;
    }

Return the set of leading protocols for a url; may be more than one.

@param url        the url whose protocols to return
@param breakpoint return the index past last protocol
@return list of leading protocols without the trailing :

Return the set of leading protocols for a url ; may be more than one .


static public List<Slice>
    indexToSlices(Index indices, DapVariable template)
            throws dap4.core.util.DapException
    {
        List<DapDimension> dims = template.getDimensions();
        List<Slice> slices = indexToSlices(indices, dims);
        return slices;
    }

static public List < Slice > indexToSlices ( Index indices , DapVariable template ) throws dap4 . core . util . DapException { List < DapDimension > dims = template . getDimensions ( ) ; List < Slice > slices = indexToSlices ( indices , dims ) ; return slices ; }

Provide a helper function to convert an Index object to
a slice list.

@param indices  indicate value to read
@param template variable template
@return corresponding List<Slice>
@throws DapException

Provide a helper function to convert an Index object to a slice list .


static public List<Slice>
    offsetToSlices(long offset, DapVariable template)
            throws DapException
    {
        List<DapDimension> dims = template.getDimensions();
        long[] dimsizes = DapUtil.getDimSizes(dims);
        return indexToSlices(offsetToIndex(offset, dimsizes), template);
    }

static public List < Slice > offsetToSlices ( long offset , DapVariable template ) throws DapException { List < DapDimension > dims = template . getDimensions ( ) ; long [ ] dimsizes = DapUtil . getDimSizes ( dims ) ; return indexToSlices ( offsetToIndex ( offset , dimsizes ) , template ) ; }

Provide a helper function to convert an offset  to
a slice list.

@param offset
@param template variable template
@return
@throws dap4.core.util.DapException

Provide a helper function to convert an offset to a slice list .


static public boolean
    isContiguous(List<Slice> slices)
    {
        for(Slice sl : slices) {
            if(sl.getStride() != 1) return false;
        }
        return true;
    }

static public boolean isContiguous ( List < Slice > slices ) { for ( Slice sl : slices ) { if ( sl . getStride ( ) != 1 ) return false ; } return true ; }

Test if a set of slices represent a contiguous region
This is equivalent to saying all strides are one

@param slices
@return


static public boolean
    isSinglePoint(List<Slice> slices)
    {
        for(Slice sl : slices) {
            if(sl.getCount() != 1) return false;
        }
        return true;
    }

static public boolean isSinglePoint ( List < Slice > slices ) { for ( Slice sl : slices ) { if ( sl . getCount ( ) != 1 ) return false ; } return true ; }

Test if a set of slices represent a single position

@param slices
@return


static public Index
    slicesToIndex(List<Slice> slices)
            throws DapException
    {
        long[] positions = new long[slices.size()];
        long[] dimsizes = new long[slices.size()];
        for(int i = 0; i < positions.length; i++) {
            Slice s = slices.get(i);
            if(s.getCount() != 1)
                throw new DapException("Attempt to convert non-singleton sliceset to index");
            positions[i] = s.getFirst();
            dimsizes[i] = s.getMax();
        }
        return new Index(positions, dimsizes);
    }

If a set of slices refers to a single position,
then return the corresponding Index. Otherwise,
throw Exception.

@param slices
@return Index corresponding to slices
@throws DapException

If a set of slices refers to a single position then return the corresponding Index . Otherwise throw Exception .


public DataResult readData(InputStream is, NetcdfFile ncfile, String location) throws IOException {
    byte[] b = new byte[4];
    int bytesRead = NcStream.readFully(is, b);
    if (bytesRead < b.length)
      throw new EOFException(location);

    if (NcStream.test(b,NcStream.MAGIC_DATA)) return readData1(is, ncfile);
    if (NcStream.test(b,NcStream.MAGIC_DATA2)) return readData2(is);

    throw new IOException("Data transfer corrupted on " + location);
  }

public
DataResult
readData
(
InputStream
is
,
NetcdfFile
ncfile
,
String
location
)
throws
IOException
{
byte
[
]
b
=
new
byte
[
4
]
;
int
bytesRead
=
NcStream
.
readFully
(
is
,
b
)
;
if
(
bytesRead
<
b
.
length
)
throw
new
EOFException
(
location
)
;
if
(
NcStream
.
test
(
b
,
NcStream
.
MAGIC_DATA
)
)
return
readData1
(
is
,
ncfile
)
;
if
(
NcStream
.
test
(
b
,
NcStream
.
MAGIC_DATA2
)
)
return
readData2
(
is
)
;
throw
new
IOException
(
"Data transfer corrupted on "
+
location
)
;
}

Read the result of a data request. Only one variable at a time.

@param is     read from input stream
@param ncfile need the metadata from here to interpret structure data
@return DataResult
@throws IOException on read error

Read the result of a data request . Only one variable at a time .


public void setStationInfo(String stnIdVName, String stnDescVName, String stnIndexVName, StationHelper stationHelper) {
    this.stnIdVName = stnIdVName;
    this.stnDescVName = stnDescVName;
    this.stnIndexVName = stnIndexVName;
    this.stationHelper = stationHelper;

    if (stnIdVName != null) {
      Variable stationVar = ncfile.findVariable(stnIdVName);
      stationIdType = stationVar.getDataType();
    }
  }

public void setStationInfo ( String stnIdVName , String stnDescVName , String stnIndexVName , StationHelper stationHelper ) { this . stnIdVName = stnIdVName ; this . stnDescVName = stnDescVName ; this . stnIndexVName = stnIndexVName ; this . stationHelper = stationHelper ; if ( stnIdVName != null ) { Variable stationVar = ncfile . findVariable ( stnIdVName ) ; stationIdType = stationVar . getDataType ( ) ; } }

Set extra information used by station obs datasets.
Use stnIdVName or stnIndexVName.

@param stnIdVName   the obs variable that is used to find the station in the stnHash; may be type  int or a String (char).
@param stnDescVName optional station var containing station description

Set extra information used by station obs datasets . Use stnIdVName or stnIndexVName .


public void setShortNames(String latVName, String lonVName, String altVName, String obsTimeVName, String nomTimeVName) {
    this.latVName = latVName;
    this.lonVName = lonVName;
    this.zcoordVName = altVName;
    this.obsTimeVName = obsTimeVName;
    this.nomTimeVName = nomTimeVName;
  }

public void setShortNames ( String latVName , String lonVName , String altVName , String obsTimeVName , String nomTimeVName ) { this . latVName = latVName ; this . lonVName = lonVName ; this . zcoordVName = altVName ; this . obsTimeVName = obsTimeVName ; this . nomTimeVName = nomTimeVName ; }


public FeatureCollectionConfig readConfigFromCatalog(String catalogAndPath) {
    String catFilename;
    String fcName = null;

    int pos = catalogAndPath.indexOf("#");
    if (pos > 0) {
      catFilename = catalogAndPath.substring(0, pos);
      fcName = catalogAndPath.substring(pos + 1);
    } else {
      catFilename = catalogAndPath;
    }

    File cat = new File(catFilename);
    org.jdom2.Document doc;
    try {
      SAXBuilder builder = new SAXBuilder();
      doc = builder.build(cat);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }

    try {
      List<Element> fcElems = new ArrayList<>();
      findFeatureCollection(doc.getRootElement(), fcName, fcElems);
      if (fcElems.size() > 0)
        return readConfig(fcElems.get(0));

    } catch (IllegalStateException e) {
      e.printStackTrace();
    }

    return null;
  }

public FeatureCollectionConfig readConfigFromCatalog ( String catalogAndPath ) { String catFilename ; String fcName = null ; int pos = catalogAndPath . indexOf ( "#" ) ; if ( pos > 0 ) { catFilename = catalogAndPath . substring ( 0 , pos ) ; fcName = catalogAndPath . substring ( pos + 1 ) ; } else { catFilename = catalogAndPath ; } File cat = new File ( catFilename ) ; org . jdom2 . Document doc ; try { SAXBuilder builder = new SAXBuilder ( ) ; doc = builder . build ( cat ) ; } catch ( Exception e ) { e . printStackTrace ( ) ; return null ; } try { List < Element > fcElems = new ArrayList <> ( ) ; findFeatureCollection ( doc . getRootElement ( ) , fcName , fcElems ) ; if ( fcElems . size ( ) > 0 ) return readConfig ( fcElems . get ( 0 ) ) ; } catch ( IllegalStateException e ) { e . printStackTrace ( ) ; } return null ; }

Read a catalog and extract a FeatureCollectionConfig from it

@param catalogAndPath catalog filename, or catalog#featureName
@return FeatureCollectionConfig or null


public void
    addDecl(DapNode newdecl)
            throws DapException
    {
        DapSort newsort = newdecl.getSort();
        String newname = newdecl.getShortName();
        boolean suppress = false;
        // Look for name conflicts (ignore anonymous dimensions)
        if(newsort != DapSort.DIMENSION || newname != null) {
            for(DapNode decl : decls) {
                if(newsort == decl.getSort()
                        && newname.equals(decl.getShortName()))
                    throw new DapException("DapGroup: attempt to add duplicate decl: " + newname);
            }
        } else { // Anonymous
            DapDimension anon = (DapDimension) newdecl;
            assert (newsort == DapSort.DIMENSION && newname == null);
            // Search for matching anonymous dimension
            boolean found = false;
            for(DapDimension dim : dimensions) {
                if(!dim.isShared() && dim.getSize() == anon.getSize()) {
                    found = true;
                    break;
                }
            }
            // Define the anondecl in root group
            if(!found && !isTopLevel()) getDataset().addDecl(anon);
            suppress = found || !isTopLevel();
        }
        if(!suppress) {
            decls.add(newdecl);
            newdecl.setParent(this); // Cross link
        }
        switch (newdecl.getSort()) {
        case ATTRIBUTE:
        case ATTRIBUTESET:
        case OTHERXML:
            super.addAttribute((DapAttribute) newdecl);
            break;
        case DIMENSION:
            if(!suppress)
                dimensions.add((DapDimension) newdecl);
            break;
        case ENUMERATION:
            enums.add((DapEnumeration) newdecl);
            break;
        case ATOMICTYPE:
            break; // do nothing
        case STRUCTURE:
        case SEQUENCE:
            compounds.add((DapStructure)newdecl);
            break;
        case VARIABLE:
            variables.add((DapVariable) newdecl);
            break;
        case GROUP:
        case DATASET:
            if(this != (DapGroup) newdecl)
                groups.add((DapGroup) newdecl);
            break;
        default:
            throw new ClassCastException(newdecl.getShortName());
        }
    }


void
    updateGroups(List<DapGroup> groups)
    {
        // Verify that the incoming groups are all and only in the list of groups.
        assert (groups.size() == this.groups.size()) : "Update groups: not same size";
        for(DapGroup g : groups) {
            if(!this.groups.contains(g))
                assert (false) : "Update groups: attempt to add new group";
        }
    }


public DapVariable
    findVariable(String name)
    {
        DapNode var = findInGroup(name, DapSort.VARIABLE);
        return (DapVariable) var;
    }

public DapVariable findVariable ( String name ) { DapNode var = findInGroup ( name , DapSort . VARIABLE ) ; return ( DapVariable ) var ; }

Locate a variable in this group

@param name the variable's name
@return the matching Dap Node or null if not found


protected AxisType getAxisType( NetcdfDataset ncDataset, VariableEnhanced v) {

    String unit = v.getUnitsString();
    if (unit == null)
      return null;
    unit = unit.trim();

    if( unit.equalsIgnoreCase("degrees_east") ||
            unit.equalsIgnoreCase("degrees_E") ||
            unit.equalsIgnoreCase("degreesE") ||
            unit.equalsIgnoreCase("degree_east") ||
            unit.equalsIgnoreCase("degree_E") ||
            unit.equalsIgnoreCase("degreeE"))
      return AxisType.Lon;

    if ( unit.equalsIgnoreCase("degrees_north") ||
            unit.equalsIgnoreCase("degrees_N") ||
            unit.equalsIgnoreCase("degreesN") ||
            unit.equalsIgnoreCase("degree_north") ||
            unit.equalsIgnoreCase("degree_N") ||
            unit.equalsIgnoreCase("degreeN"))
      return AxisType.Lat;

    if (SimpleUnit.isDateUnit(unit)) {
      return AxisType.Time;
    }
    // look for other z coordinate
    if (SimpleUnit.isCompatible("mbar", unit))
      return AxisType.Pressure;
    if (unit.equalsIgnoreCase("level") || unit.equalsIgnoreCase("layer") || unit.equalsIgnoreCase("sigma_level"))
      return AxisType.GeoZ;

    String positive = ncDataset.findAttValueIgnoreCase((Variable) v, CF.POSITIVE, null);
    if (positive != null) {
      if (SimpleUnit.isCompatible("m", unit))
        return AxisType.Height;
      else
        return AxisType.GeoZ;
    }

    // a bad idea, but CDC SST relies on it :
    // :Source = "NOAA/National Climatic Data Center";
   // :Contact = "Dick Reynolds, email: Richard.W.Reynolds@noaa.gov & Chunying Liu, email: Chunying.liu@noaa.gov";
   //:netcdf_Convention = "COARDS";
   // if (checkForMeter && SimpleUnit.isCompatible("m", unit))
   //   return AxisType.Height;

    return null;
  }

we assume that coordinate axes get identified by being coordinate variables


@Nullable
  public static GribStatType getStatType(int timeRangeIndicator) {
    switch (timeRangeIndicator) {
      case 3:
      case 6:
      case 7:
      case 51:
      case 113:
      case 115:
      case 117:
      case 120:
      case 123:
        return GribStatType.Average;
      case 4:
      case 114:
      case 116:
      case 124:
        return GribStatType.Accumulation;
      case 5:
        return GribStatType.DifferenceFromEnd;
      case 118:
        return GribStatType.Covariance;
      case 119:
      case 125:
        return GribStatType.StandardDeviation;
      default:
        return null;
    }
  }

@ Nullable public static GribStatType getStatType ( int timeRangeIndicator ) { switch ( timeRangeIndicator ) { case 3 : case 6 : case 7 : case 51 : case 113 : case 115 : case 117 : case 120 : case 123 : return GribStatType . Average ; case 4 : case 114 : case 116 : case 124 : return GribStatType . Accumulation ; case 5 : return GribStatType . DifferenceFromEnd ; case 118 : return GribStatType . Covariance ; case 119 : case 125 : return GribStatType . StandardDeviation ; default : return null ; } }

The time unit statistical type, derived from code table 5)

@return time unit statistical type, or null if unknown.

The time unit statistical type derived from code table 5 )


private Optional<CoverageCoordAxis> subsetLon(LatLonRect llbb, int stride) throws InvalidRangeException {
    double wantMin = LatLonPointImpl.lonNormalFrom(llbb.getLonMin(), lonAxis.getStartValue());
    double wantMax = LatLonPointImpl.lonNormalFrom(llbb.getLonMax(), lonAxis.getStartValue());
    double start = lonAxis.getStartValue();
    double end  = lonAxis.getEndValue();

    // use MAMath.MinMax as a container for two values, min and max
    List<MAMath.MinMax> lonIntvs = subsetLonIntervals(wantMin, wantMax, start, end);

    if (lonIntvs.size() == 0)
      return Optional.empty(String.format(
              "longitude want [%f,%f] does not intersect lon axis [%f,%f]", wantMin, wantMax, start, end));

    if (lonIntvs.size() == 1) {
      MAMath.MinMax lonIntv = lonIntvs.get(0);
      return lonAxis.subset(lonIntv.min, lonIntv.max, stride);
    }

    // this is the seam crossing case
    return lonAxis.subsetByIntervals(lonIntvs, stride);
 }


public List<RangeIterator> getRanges() {
    List<RangeIterator> result = new ArrayList<>();
    result.add(getYAxis().getRange());
    RangeIterator lonRange = getXAxis().getRangeIterator();
    if (lonRange == null) lonRange = getXAxis().getRange(); // clumsy
    result.add(lonRange);

    return result;
  }

public
List
<
RangeIterator
>
getRanges
(
)
{
List
<
RangeIterator
>
result
=
new
ArrayList
<>
(
)
;
result
.
add
(
getYAxis
(
)
.
getRange
(
)
)
;
RangeIterator
lonRange
=
getXAxis
(
)
.
getRangeIterator
(
)
;
if
(
lonRange
==
)
lonRange
=
getXAxis
(
)
.
getRange
(
)
;
// clumsy
result
.
add
(
lonRange
)
;
return
result
;
}


static synchronized protected void setDefaults(Map<Prop, Object> props)
    {
        if(false) {// turn off for now
            props.put(Prop.HANDLE_AUTHENTICATION, Boolean.TRUE);
        }
        props.put(Prop.HANDLE_REDIRECTS, Boolean.TRUE);
        props.put(Prop.ALLOW_CIRCULAR_REDIRECTS, Boolean.TRUE);
        props.put(Prop.MAX_REDIRECTS, (Integer) DFALTREDIRECTS);
        props.put(Prop.SO_TIMEOUT, (Integer) DFALTSOTIMEOUT);
        props.put(Prop.CONN_TIMEOUT, (Integer) DFALTCONNTIMEOUT);
        props.put(Prop.CONN_REQ_TIMEOUT, (Integer) DFALTCONNREQTIMEOUT);
        props.put(Prop.USER_AGENT, DFALTUSERAGENT);
    }

static
synchronized
protected
void
setDefaults
(
Map
<
Prop
,
Object
>
props
)
{
if
(
false
)
{
// turn off for now
props
.
put
(
Prop
.
HANDLE_AUTHENTICATION
,
Boolean
.
TRUE
)
;
}
props
.
put
(
Prop
.
HANDLE_REDIRECTS
,
Boolean
.
TRUE
)
;
props
.
put
(
Prop
.
ALLOW_CIRCULAR_REDIRECTS
,
Boolean
.
TRUE
)
;
props
.
put
(
Prop
.
MAX_REDIRECTS
,
(
Integer
)
DFALTREDIRECTS
)
;
props
.
put
(
Prop
.
SO_TIMEOUT
,
(
Integer
)
DFALTSOTIMEOUT
)
;
props
.
put
(
Prop
.
CONN_TIMEOUT
,
(
Integer
)
DFALTCONNTIMEOUT
)
;
props
.
put
(
Prop
.
CONN_REQ_TIMEOUT
,
(
Integer
)
DFALTCONNREQTIMEOUT
)
;
props
.
put
(
Prop
.
USER_AGENT
,
DFALTUSERAGENT
)
;
}


public String getSessionID()
    {
        String sid = null;
        String jsid = null;
        List<Cookie> cookies = this.sessioncontext.getCookieStore().getCookies();
        for(Cookie cookie : cookies) {
            if(cookie.getName().equalsIgnoreCase("sessionid"))
                sid = cookie.getValue();
            if(cookie.getName().equalsIgnoreCase("jsessionid"))
                jsid = cookie.getValue();
        }
        return (sid == null ? jsid : sid);
    }

public String getSessionID ( ) { String sid = null ; String jsid = null ; List < Cookie > cookies = this . sessioncontext . getCookieStore ( ) . getCookies ( ) ; for ( Cookie cookie : cookies ) { if ( cookie . getName ( ) . equalsIgnoreCase ( "sessionid" ) ) sid = cookie . getValue ( ) ; if ( cookie . getName ( ) . equalsIgnoreCase ( "jsessionid" ) ) jsid = cookie . getValue ( ) ; } return ( sid == null ? jsid : sid ) ; }

Extract the sessionid cookie value

@return sessionid string


public HTTPSession setMaxRedirects(int n)
    {
        if(n < 0) //validate
            throw new IllegalArgumentException("setMaxRedirects");
        localsettings.put(Prop.MAX_REDIRECTS, n);
        this.cachevalid = false;
        return this;
    }

public HTTPSession setMaxRedirects ( int n ) { if ( n < 0 ) //validate throw new IllegalArgumentException ( "setMaxRedirects" ) ; localsettings . put ( Prop . MAX_REDIRECTS , n ) ; this . cachevalid = false ; return this ; }

Set the max number of redirects to follow

@param n


public HTTPSession setUseSessions(boolean tf)
    {
        localsettings.put(Prop.USESESSIONS, (Boolean) tf);
        this.cachevalid = false;
        return this;
    }

public HTTPSession setUseSessions ( boolean tf ) { localsettings . put ( Prop . USESESSIONS , ( Boolean ) tf ) ; this . cachevalid = false ; return this ; }


synchronized public void close()
    {
        if(this.closed)
            return; // multiple calls ok
        closed = true;
        for(HTTPMethod m : this.methods) {
            m.close(); // forcibly close; will invoke removemethod().
        }
        methods.clear();
    }

Close the session. This implies closing
any open methods.

Close the session . This implies closing any open methods .


synchronized
    protected void
    setAuthenticationAndProxy(HttpClientBuilder cb)
            throws HTTPException
    {
        // First, setup the ssl factory
        cb.setSSLSocketFactory((SSLConnectionSocketFactory) authcontrols.get(AuthProp.SSLFACTORY));

        // Second, Construct a CredentialsProvider that is
        // the union of the Proxy credentials plus
        // either the global or local credentials; local overrides global
        // Unfortunately, we cannot either clone or extract the contents
        // of the client supplied provider, so we are forced (for now)
        // to modify the client supplied provider.

        // Look in the local credentials first for for best scope match
        AuthScope bestMatch = HTTPAuthUtil.bestmatch(scope, localcreds.keySet());
        CredentialsProvider cp = null;
        if(bestMatch != null) {
            cp = localcreds.get(bestMatch);
        } else {
            bestMatch = HTTPAuthUtil.bestmatch(scope, globalcredfactories.keySet());
            if(bestMatch != null) {
                HTTPProviderFactory factory = globalcredfactories.get(bestMatch);
                cp = factory.getProvider(bestMatch);
            }
        }
        // Build the proxy credentials and AuthScope
        Credentials proxycreds = null;
        AuthScope proxyscope = null;
        String user = (String) authcontrols.get(AuthProp.PROXYUSER);
        String pwd = (String) authcontrols.get(AuthProp.PROXYPWD);
        HttpHost httpproxy = (HttpHost) authcontrols.get(AuthProp.HTTPPROXY);
        HttpHost httpsproxy = (HttpHost) authcontrols.get(AuthProp.HTTPSPROXY);
        if(user != null && (httpproxy != null || httpsproxy != null)) {
            if(httpproxy != null)
                proxyscope = HTTPAuthUtil.hostToAuthScope(httpproxy);
            else //httpsproxy != null
                proxyscope = HTTPAuthUtil.hostToAuthScope(httpsproxy);
            proxycreds = new UsernamePasswordCredentials(user, pwd);
        }
        if(cp == null && proxycreds != null && proxyscope != null) {
            // If client provider is null and proxycreds are not,
            // then use proxycreds alone
            cp = new BasicCredentialsProvider();
            cp.setCredentials(proxyscope, proxycreds);
        } else if(cp != null && proxycreds != null && proxyscope != null) {
            // If client provider is not null and proxycreds are not,
            // then add proxycreds to the client provider
            cp.setCredentials(proxyscope, proxycreds);
        }
        if(cp != null)
            this.sessioncontext.setCredentialsProvider(cp);
    }

Handle authentication and Proxy'ing

@param cb
@throws HTTPException


static protected synchronized void track(HTTPSession session)
    {
        if(!TESTING) throw new UnsupportedOperationException();
        if(sessionList == null)
            sessionList = new ConcurrentSkipListSet<HTTPSession>();
        sessionList.add(session);
    }

static protected synchronized void track ( HTTPSession session ) { if ( ! TESTING ) throw new UnsupportedOperationException ( ) ; if ( sessionList == null ) sessionList = new ConcurrentSkipListSet < HTTPSession > ( ) ; sessionList . add ( session ) ; }

If we are testing, then track the sessions for kill

If we are testing then track the sessions for kill


@Deprecated
    static public void
    setGlobalCredentialsProvider(AuthScope scope, CredentialsProvider provider)
            throws HTTPException
    {
        setGlobalCredentialsProvider(provider, scope);
    }

@ Deprecated static public void setGlobalCredentialsProvider ( AuthScope scope , CredentialsProvider provider ) throws HTTPException { setGlobalCredentialsProvider ( provider , scope ) ; }

Deprecated, but here for back compatibility

Deprecated but here for back compatibility


void validate(String urlString) {
      if (urlString == null) return;
      URI uri;
      try {
        uri = new URI(urlString);
      }
      catch (URISyntaxException e) {
        javax.swing.JOptionPane.showMessageDialog(null, "URISyntaxException on URL (" +
            urlString + ") " + e.getMessage() + "\n");
        return;
      }
      String contents = getText();
      //boolean isCatalog = contents.indexOf("queryCapability") < 0;

      ByteArrayInputStream is = new ByteArrayInputStream(contents.getBytes(CDM.utf8Charset));

      try {
        CatalogBuilder catFactory = new CatalogBuilder();
        Catalog cat = catFactory.buildFromLocation(urlString, null);
        boolean isValid = !catFactory.hasFatalError();

       javax.swing.JOptionPane.showMessageDialog(this,
          "Catalog Validation = " + isValid + "\n" +  catFactory.getErrorMessage());

      } catch (IOException e) {
        e.printStackTrace();
      }

    }