public static DatasetSourceType getType( String name)
  {
    if ( name == null) return null;
    return ( (DatasetSourceType) hash.get( name));
  }

public static DatasetSourceType getType ( String name ) { if ( name == null ) return null ; return ( ( DatasetSourceType ) hash . get ( name ) ) ; }

Find the DatasetSourceType that matches this name.
@param name
@return DatasetSourceType or null if no match.

Find the DatasetSourceType that matches this name .


public InvDataset expand() throws IOException
  {
    // Get the new catalog being generated and its top-level dataset.
    this.resultingCatalog = this.createSkeletonCatalog( prefixUrlPath );
    this.accessPointDataset = (InvDataset) this.resultingCatalog.getDatasets().get( 0);

    // IOException thrown by createSkeletonCatalog() so this check should not be necessary.
    if ( ! this.isCollection( this.accessPointDataset) )
    {
      String tmpMsg = "The access point dataset <" + this.accessPointDataset.getName() + "> must be a collection dataset.";
      logger.warn( "expand(): {}", tmpMsg);
      throw new IOException( tmpMsg);
    }

    // Recurse into directory structure and expand.
    expandRecursive( this.accessPointDataset);

    // Finish the catalog.
    ((InvCatalogImpl) this.resultingCatalog).finish();

    // Remove empty collection datasets. @todo HACK - should use filters instead.
    this.recursivelyRemoveEmptyCollectionDatasets( this.accessPointDataset);

    // Return the top-level dataset.
    return( this.accessPointDataset);
  }

Crawl this DatasetSource and generate a new InvCatalog, return the
top-level InvDataset.

Each object found on the DatasetSource becomes an InvDataset if it is
accepted by at least one DatasetFilter. The catalog reflects the
heirarchical structure of the DatasetSource. All datasets are named
with the location of the object they represent on the dataset source.

@return the top-level InvDataset in the generated InvCatalog.

@throws IOException if the accessPoint for this DatasetSource is not a container dataset.

Crawl this DatasetSource and generate a new InvCatalog return the top - level InvDataset .


public InvCatalog fullExpand() throws IOException
  {
    logger.debug( "fullExpand(): expanding DatasetSource named \"{}\"", this.getName());

    InvDataset topDs = this.expand();
    InvCatalog generatedCat = topDs.getParentCatalog();

    // Add metadata to all datasets.
    for ( Iterator it = this.getDatasetEnhancerList().iterator(); it.hasNext(); )
    {
      DatasetEnhancer1 dsE = (DatasetEnhancer1) it.next();
      dsE.addMetadata( topDs);
    }

    // Name all datasets.
    logger.debug( "fullExpand(): naming the datasets.");
    this.nameDatasets( (InvDatasetImpl) topDs );

    // Sort all datasets
    logger.debug( "fullExpand(): sorting the datasets.");
    this.sortDatasets( topDs);

    // Return the generated catalog
    ((InvCatalogImpl) generatedCat).finish();
    return( generatedCat);

  }

Crawl this DatasetSource and generate a new InvCatalog with all datasets
named, sorted, and organized as defined by this DatasetSource, return the
newly generated InvCatalog.

@return the generated InvCatalog.

@throws IOException if DatasetSource does not reference a container dataset.

Crawl this DatasetSource and generate a new InvCatalog with all datasets named sorted and organized as defined by this DatasetSource return the newly generated InvCatalog .


private void nameDatasets( InvDatasetImpl datasetContainer)
  {
    if ( this.getDatasetNamerList().isEmpty()) return;
    if ( this.isFlatten())
    {
      logger.debug( "nameDatasets(): structure is FLAT calling nameDatasetList()");
      this.nameDatasetList( datasetContainer);
    }
    else
    {
      logger.debug( "nameDatasets(): structure is DIRECTORY_TREE calling" +
              " nameDatasetTree() on each dataset in dataset container");
      InvDatasetImpl curDs = null;
      for ( int j = 0; j < datasetContainer.getDatasets().size(); j++)
      {
        curDs = (InvDatasetImpl) datasetContainer.getDatasets().get( j);
        this.nameDatasetTree( curDs);
      }
    }
    return;
  }

Use the list of dsNamers to name the given list of datasets.

@param datasetContainer - a InvDatasetImpl that contains one or
more datasets to be named.

Use the list of dsNamers to name the given list of datasets .


private void nameDatasetList( InvDatasetImpl dataset)
  {
    // Create temporary dataset in which to hold named datasets.
    InvDatasetImpl namedDs = new InvDatasetImpl( dataset,
          "nameDatastList() temp dataset", null, null, null);
    // InvDatasetImpl(parentDs, name, dataType, serviceName, urlPath)
    dataset.addDataset( namedDs);

    // Loop through the DatasetNamers
    DatasetNamer curNamer = null;
    for ( int i = 0; i < this.datasetNamerList.size(); i++)
    {
      curNamer = (DatasetNamer) this.datasetNamerList.get( i);
      logger.debug( "nameDatasetList(): trying namer ({})", curNamer.getName());

      // If the current DatasetNamer adds a new level, create a new dataset.
      InvDatasetImpl addLevelDs = null;
      if ( curNamer.getAddLevel())
      {
        addLevelDs = new InvDatasetImpl( null, curNamer.getName(),
                                         null, null, null );
      }

      // Iterate over remaining unnamed datasets.
      InvDatasetImpl curDs = null;
      java.util.Iterator dsIter = dataset.getDatasets().iterator();
      while ( dsIter.hasNext())
      {
        curDs = (InvDatasetImpl) dsIter.next();
        logger.debug( "nameDatasetList(): try namer on this ds ({}-{})", curDs.getName(), curDs.getUrlPath() );

        // Try to name the current dataset.
        if ( curNamer.nameDataset( curDs))
        {
          logger.debug( "nameDatasetList(): ds named ({})", curDs.getName());
          // If adding a level, add named datasets to the added level dataset.
          if ( curNamer.getAddLevel())
          {
            addLevelDs.addDataset( curDs);
          }
          // Otherwise, add the named datasets to namedDs.
          else
          {
            namedDs.addDataset( curDs);
          }

          // Remove the now-named dataset from list of unnamed datasets.
          dsIter.remove();
        }
      } // END - InvDatasetImpl loop

      // If the namer added a level and a dataset was named by this namer, add the
      // new level to the list of named datasets.
      if ( curNamer.getAddLevel())
      {
        if ( addLevelDs.hasNestedDatasets())
        {
          namedDs.addDataset( addLevelDs);
        }
      }

    } // END - DatasetNamer loop
    namedDs.finish();

    // Once all datasets are named (or unnamable with these DatasetNamers),
    // add all the datasets in namedDs back into the given containerDataset.
    if (logger.isDebugEnabled()) {
      logger.debug( "nameDatasetList(): number of unnamed datasets is " + dataset.getDatasets().size() + ".");
      logger.debug( "nameDatasetList(): add named datasets back to container.");
    }
    for ( int i = 0; i < namedDs.getDatasets().size(); i++)
    {
      dataset.addDataset( (InvDatasetImpl) namedDs.getDatasets().get( i));
    }
    dataset.removeDataset( namedDs);

    return;
  }

Name the datasets contained in the given dataset.
The given dataset contains a flat list of datasets.

Name the datasets contained in the given dataset . The given dataset contains a flat list of datasets .


private void nameDatasetTree( InvDatasetImpl dataset)
  {
    // If dataset does not have a name, try naming it with dsNamers.
    // @todo Rethink naming of directories (look at how DatasetFilter deals with collection vs atomic datasets).
    if ( dataset.getName().equals("") || ! dataset.hasAccess())
    {
      logger.debug( "nameDatasetTree(): naming dataset ({})...", dataset.getUrlPath());
      DatasetNamer dsN = null;
      for ( int i = 0; i < this.datasetNamerList.size(); i++)
      {
        dsN = (DatasetNamer) this.datasetNamerList.get( i);
        if ( dsN.nameDataset( dataset))
        {
          logger.debug( "nameDatasetTree(): ... used namer ({})", dsN.getName());
          break;
        }
      }
    }

    // Try to name any child datasets.
    InvDatasetImpl curDs = null;
    for ( int j = 0; j < dataset.getDatasets().size(); j++)
    {
      curDs = (InvDatasetImpl) dataset.getDatasets().get( j);
      logger.debug( "nameDatasetTree(): recurse to name child dataset ({})", curDs.getUrlPath());
      this.nameDatasetTree( curDs);
    }

    return;
  }

Name the datasets in the given dataset hierarchy using this
DatasetSource's list of datasetNamers.

Name the datasets in the given dataset hierarchy using this DatasetSource s list of datasetNamers .


public void loadPictureImd(URL imageUrl, double rotation) {
    Tools.log("loadPictureImd invoked with URL: " + imageUrl.toString());
    if (sourcePicture != null) sourcePicture.removeListener(this);
    sourcePicture = new SourcePicture();
    sourcePicture.addListener(this);
    setStatus(LOADING, "Loading: " + imageUrl.toString());
    scaleAfterLoad = true;
    sourcePicture.loadPicture(imageUrl, rotation);
  }

public
void
loadPictureImd
(
URL
imageUrl
,
double
rotation
)
{
Tools
.
log
(
"loadPictureImd invoked with URL: "
+
imageUrl
.
toString
(
)
)
;
if
(
sourcePicture
!=
)
sourcePicture
.
removeListener
(
this
)
;
sourcePicture
=
new
SourcePicture
(
)
;
sourcePicture
.
addListener
(
this
)
;
setStatus
(
LOADING
,
"Loading: "
+
imageUrl
.
toString
(
)
)
;
scaleAfterLoad
=
true
;
sourcePicture
.
loadPicture
(
imageUrl
,
rotation
)
;
}

Synchroneous method to load the image.
It should only be called by something which is a thread itself such as the HtmlDistillerThread.
Since this intended for large batch operations this bypasses the cache.

@param imageUrl The Url of the image to be loaded
@param rotation The angle by which it is to be roated upon loading.

Synchroneous method to load the image . It should only be called by something which is a thread itself such as the HtmlDistillerThread . Since this intended for large batch operations this bypasses the cache .


public void stopLoadingExcept(URL url) {
    if (sourcePicture != null) {
      boolean isCurrentlyLoading = sourcePicture.stopLoadingExcept(url);
      if (!isCurrentlyLoading) {
        // sourcePicture.removeListener( this );
      }
      PictureCache.stopBackgroundLoadingExcept(url);
    }
  }

stops all picture loading except if the Url we desire is being loaded

@param url The URL of the image which is to be loaded.


public void sourceStatusChange(int statusCode, String statusMessage, SourcePicture sp) {
    //Tools.log("ScalablePicture.sourceStatusChange: status received from SourceImage: " + statusMessage);

    switch (statusCode) {
      case SourcePicture.UNINITIALISED:
        Tools.log("ScalablePicture.sourceStatusChange: pictureStatus was: UNINITIALISED message: " + statusMessage);
        setStatus(UNINITIALISED, statusMessage);
        break;
      case SourcePicture.ERROR:
        Tools.log("ScalablePicture.sourceStatusChange: pictureStatus was: ERROR message: " + statusMessage);
        setStatus(ERROR, statusMessage);
        sourcePicture.removeListener(this);
        break;
      case SourcePicture.LOADING:
        Tools.log("ScalablePicture.sourceStatusChange: pictureStatus was: LOADING message: " + statusMessage);
        setStatus(LOADING, statusMessage);
        break;
      case SourcePicture.ROTATING:
        Tools.log("ScalablePicture.sourceStatusChange: pictureStatus was: ROTATING message: " + statusMessage);
        setStatus(LOADING, statusMessage);
        break;
      case SourcePicture.READY:
        Tools.log("ScalablePicture.sourceStatusChange: pictureStatus was: READY message: " + statusMessage);
        setStatus(LOADED, statusMessage);
        sourcePicture.removeListener(this);
        if (scaleAfterLoad) {
          createScaledPictureInThread(Thread.MAX_PRIORITY);
          scaleAfterLoad = false;
        }
        break;
      default:
        Tools.log("ScalablePicture.sourceStatusChange: Don't recognize this status: " + statusMessage);
        break;

    }
  }

method that is invoked by the SourcePictureListener interface. Usually this
will be called by the SourcePicture telling the ScalablePicture that
it has completed loading. The ScalablePicture should then change it's own
status and tell the ScalableListeners what's up.

method that is invoked by the SourcePictureListener interface . Usually this will be called by the SourcePicture telling the ScalablePicture that it has completed loading . The ScalablePicture should then change it s own status and tell the ScalableListeners what s up .


public void sourceLoadProgressNotification(int statusCode, int percentage) {
    Enumeration e = scalablePictureStatusListeners.elements();
    while (e.hasMoreElements()) {
      ((ScalablePictureListener) e.nextElement())
          .sourceLoadProgressNotification(statusCode, percentage);
    }

  }

public void sourceLoadProgressNotification ( int statusCode , int percentage ) { Enumeration e = scalablePictureStatusListeners . elements ( ) ; while ( e . hasMoreElements ( ) ) { ( ( ScalablePictureListener ) e . nextElement ( ) ) . sourceLoadProgressNotification ( statusCode , percentage ) ; } }

pass on the update on the loading Progress to the listening objects


public void createScaledPictureInThread(int priority) {
    setStatus(SCALING, "Scaling picture.");
    ScaleThread t = new ScaleThread(this);
    t.setPriority(priority);
    t.start();
  }

public
void
createScaledPictureInThread
(
int
priority
)
{
setStatus
(
SCALING
,
"Scaling picture."
)
;
ScaleThread
t
=
new
ScaleThread
(
this
)
;
t
.
setPriority
(
priority
)
;
t
.
start
(
)
;
}

method that creates the scaled image in the background in it's own thread.

@param priority The priority this image takes relative to the others.

method that creates the scaled image in the background in it s own thread .


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

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

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


public String getScaledSizeString() {
    if (scaledPicture != null)
      return Integer.toString(scaledPicture.getWidth())
          + " x "
          + Integer.toString(scaledPicture.getHeight());
    else
      return "0 x 0";
  }

public
String
getScaledSizeString
(
)
{
if
(
scaledPicture
!=
)
return
Integer
.
toString
(
scaledPicture
.
getWidth
(
)
)
+
" x "
+
Integer
.
toString
(
scaledPicture
.
getHeight
(
)
)
;
else
return
"0 x 0"
;
}

return the size of the scaled image as a neatly formatted text or Zero if there is none


public List<String> getMergedParts() {
    List<String> list = new ArrayList<>(1);
    list.add(SNDT);
    return list;
  }

public List < String > getMergedParts ( ) { List < String > list = new ArrayList <> ( 1 ) ; list . add ( SNDT ) ; return list ; }

Get the list of merged parts in this file

@return a list of the unmerged parts (only SNDT)


private String makeHeader(GempakStation stn, String date) {
    StringBuilder builder = new StringBuilder();
    builder.append("STID = ");
    builder.append(StringUtil2.padRight((stn.getSTID().trim()
            + stn.getSTD2().trim()), 8));
    builder.append("\t");
    builder.append("STNM = ");
    builder.append(Format.i(stn.getSTNM(), 6));
    builder.append("\t");
    builder.append("TIME = ");
    builder.append(date);
    builder.append("\n");
    builder.append("SLAT = ");
    builder.append(Format.d(stn.getLatitude(), 5));
    builder.append("\t");
    builder.append("SLON = ");
    builder.append(Format.d(stn.getLongitude(), 5));
    builder.append("\t");
    builder.append("SELV = ");
    builder.append(Format.d(stn.getAltitude(), 5));
    builder.append("\n");
    return builder.toString();
  }

private
String
makeHeader
(
GempakStation
stn
,
String
date
)
{
StringBuilder
builder
=
new
StringBuilder
(
)
;
builder
.
append
(
"STID = "
)
;
builder
.
append
(
StringUtil2
.
padRight
(
(
stn
.
getSTID
(
)
.
trim
(
)
+
stn
.
getSTD2
(
)
.
trim
(
)
)
,
8
)
)
;
builder
.
append
(
"\t"
)
;
builder
.
append
(
"STNM = "
)
;
builder
.
append
(
Format
.
i
(
stn
.
getSTNM
(
)
,
6
)
)
;
builder
.
append
(
"\t"
)
;
builder
.
append
(
"TIME = "
)
;
builder
.
append
(
date
)
;
builder
.
append
(
"\n"
)
;
builder
.
append
(
"SLAT = "
)
;
builder
.
append
(
Format
.
d
(
stn
.
getLatitude
(
)
,
5
)
)
;
builder
.
append
(
"\t"
)
;
builder
.
append
(
"SLON = "
)
;
builder
.
append
(
Format
.
d
(
stn
.
getLongitude
(
)
,
5
)
)
;
builder
.
append
(
"\t"
)
;
builder
.
append
(
"SELV = "
)
;
builder
.
append
(
Format
.
d
(
stn
.
getAltitude
(
)
,
5
)
)
;
builder
.
append
(
"\n"
)
;
return
builder
.
toString
(
)
;
}

Make the header for the text report

@param stn  the station
@param date the date
@return the header


private List<String> SN_CKUA() {
    List<String> types = new ArrayList<>();
    boolean above = false;
    boolean done = false;
    String partToCheck;
    while (!done) {
      // check for mandatory groups
      for (int group = 0; group < belowGroups.length; group++) {
        if (above) {
          partToCheck = aboveGroups[group];
        } else {
          partToCheck = belowGroups[group];
        }
        if (checkForValidGroup(partToCheck, parmLists[group])) {
          types.add(partToCheck);
        }
      }
      if (!above) {
        above = true;
      } else {
        done = true;
      }
    }
    return types;
  }

private
List
<
String
>
SN_CKUA
(
)
{
List
<
String
>
types
=
new
ArrayList
<>
(
)
;
boolean
above
=
false
;
boolean
done
=
false
;
String
partToCheck
;
while
(
!
done
)
{
// check for mandatory groups
for
(
int
group
=
0
;
group
<
belowGroups
.
length
;
group
++
)
{
if
(
above
)
{
partToCheck
=
aboveGroups
[
group
]
;
}
else
{
partToCheck
=
belowGroups
[
group
]
;
}
if
(
checkForValidGroup
(
partToCheck
,
parmLists
[
group
]
)
)
{
types
.
add
(
partToCheck
)
;
}
}
if
(
!
above
)
{
above
=
true
;
}
else
{
done
=
true
;
}
}
return
types
;
}

This subroutine checks the parts in a sounding data set for the
unmerged data types.

@return list of part names

This subroutine checks the parts in a sounding data set for the unmerged data types .


private boolean checkForValidGroup(String partToCheck, String[] params) {
    DMPart part = getPart(partToCheck);
    if (part == null) {
      return false;
    }
    int i = 0;
    for (DMParam parm : part.params) {
      if (!(parm.kprmnm.equals(params[i++]))) {
        return false;
      }
    }
    return true;
  }

private boolean checkForValidGroup ( String partToCheck , String [ ] params ) { DMPart part = getPart ( partToCheck ) ; if ( part == null ) { return false ; } int i = 0 ; for ( DMParam parm : part . params ) { if ( ! ( parm . kprmnm . equals ( params [ i ++ ] ) ) ) { return false ; } } return true ; }

Check for valid groups

@param partToCheck the part name
@param params      the parameters that are supposed to be there
@return true if the part is there and has the right params


static public void setRootDirectory(String cacheDir) {
    if (!cacheDir.endsWith("/"))
      cacheDir = cacheDir + "/";
    root = StringUtil2.replace(cacheDir, '\\', "/"); // no nasty backslash

    makeRootDirectory();
  }

static
public
void
setRootDirectory
(
String
cacheDir
)
{
if
(
!
cacheDir
.
endsWith
(
"/"
)
)
cacheDir
=
cacheDir
+
"/"
;
root
=
StringUtil2
.
replace
(
cacheDir
,
'
'
,
"/"
)
;
// no nasty backslash
makeRootDirectory
(
)
;
}

Set the cache root directory. Create it if it doesnt exist.

@param cacheDir the cache directory

Set the cache root directory . Create it if it doesnt exist .


static public void makeRootDirectory() {
    File dir = new File(root);
    if (!dir.exists())
      if (!dir.mkdirs())
        throw new IllegalStateException("DiskCache.setRootDirectory(): could not create root directory <" + root + ">.");
    checkExist = true;
  }

Make sure that the current root directory exists.

Make sure that the current root directory exists .


static public File getCacheFile(String fileLocation) {
    File f = new File(makeCachePath(fileLocation));
    if (f.exists()) {
      if (!f.setLastModified(System.currentTimeMillis()))
        logger.warn("Failed to setLastModified on " + f.getPath());
    }

    if (!checkExist) {
      File dir = f.getParentFile();
      if (!dir.exists() && !dir.mkdirs())
        logger.warn("Failed to mkdirs on " + dir.getPath());
      checkExist = true;
    }
    return f;
  }

static
public
File
getCacheFile
(
String
fileLocation
)
{
File
f
=
new
File
(
makeCachePath
(
fileLocation
)
)
;
if
(
f
.
exists
(
)
)
{
if
(
!
f
.
setLastModified
(
System
.
currentTimeMillis
(
)
)
)
logger
.
warn
(
"Failed to setLastModified on "
+
f
.
getPath
(
)
)
;
}
if
(
!
checkExist
)
{
File
dir
=
f
.
getParentFile
(
)
;
if
(
!
dir
.
exists
(
)
&&
!
dir
.
mkdirs
(
)
)
logger
.
warn
(
"Failed to mkdirs on "
+
dir
.
getPath
(
)
)
;
checkExist
=
true
;
}
return
f
;
}

Get a file in the cache.
File may or may not exist. We assume its always writeable.
If it does exist, set its LastModifiedDate to current time.

@param fileLocation normal file location
@return equivalent File in the cache.

Get a file in the cache . File may or may not exist . We assume its always writeable . If it does exist set its LastModifiedDate to current time .


static public void cleanCache(Date cutoff, StringBuilder sbuff) {
    if (sbuff != null) sbuff.append("CleanCache files before ").append(cutoff).append("\n");
    File dir = new File(root);
    File[] children = dir.listFiles();
    if (children == null) return;
    for (File file : children) {
      Date lastMod = new Date(file.lastModified());
      if (lastMod.before(cutoff)) {
        boolean ret = file.delete();
        if (sbuff != null) {
          sbuff.append(" delete ").append(file).append(" (").append(lastMod).append(")\n");
          if (!ret) sbuff.append("Error deleting ").append(file).append("\n");
        }
      }
    }
  }

static
public
void
cleanCache
(
Date
cutoff
,
StringBuilder
sbuff
)
{
if
(
sbuff
!=
)
sbuff
.
append
(
"CleanCache files before "
)
.
append
(
cutoff
)
.
append
(
"\n"
)
;
File
dir
=
new
File
(
root
)
;
File
[
]
children
=
dir
.
listFiles
(
)
;
if
(
children
==
)
return
;
for
(
File
file
:
children
)
{
Date
lastMod
=
new
Date
(
file
.
lastModified
(
)
)
;
if
(
lastMod
.
before
(
cutoff
)
)
{
boolean
ret
=
file
.
delete
(
)
;
if
(
sbuff
!=
)
{
sbuff
.
append
(
" delete "
)
.
append
(
file
)
.
append
(
" ("
)
.
append
(
lastMod
)
.
append
(
")\n"
)
;
if
(
!
ret
)
sbuff
.
append
(
"Error deleting "
)
.
append
(
file
)
.
append
(
"\n"
)
;
}
}
}
}

Remove all files with date < cutoff.

@param cutoff earliest date to allow
@param sbuff  write results here, null is ok.


static public void cleanCache(long maxBytes, Comparator<File> fileComparator, StringBuilder sbuff) {
    if (sbuff != null) sbuff.append("DiskCache clean maxBytes= ")
            .append(maxBytes).append("on dir ").append(root).append("\n");

    File dir = new File(root);
    long total = 0, total_delete = 0;

    File[] files = dir.listFiles();
    if (files != null) {
      List<File> fileList = Arrays.asList(files);
      Collections.sort(fileList, fileComparator);

      for (File file : fileList) {
        if (file.length() + total > maxBytes) {
          total_delete += file.length();
          if (sbuff != null)
            sbuff.append(" delete ").append(file).append(" (")
                    .append(file.length()).append(")\n");
          if (!file.delete() && sbuff != null)
            sbuff.append("Error deleting ").append(file).append("\n");
        } else {
          total += file.length();
        }
      }
    }
    if (sbuff != null) {
      sbuff.append("Total bytes deleted= ").append(total_delete).append("\n");
      sbuff.append("Total bytes left in cache= ").append(total).append("\n");
    }
  }

static
public
void
cleanCache
(
long
maxBytes
,
Comparator
<
File
>
fileComparator
,
StringBuilder
sbuff
)
{
if
(
sbuff
!=
)
sbuff
.
append
(
"DiskCache clean maxBytes= "
)
.
append
(
maxBytes
)
.
append
(
"on dir "
)
.
append
(
root
)
.
append
(
"\n"
)
;
File
dir
=
new
File
(
root
)
;
long
total
=
0
,
total_delete
=
0
;
File
[
]
files
=
dir
.
listFiles
(
)
;
if
(
files
!=
)
{
List
<
File
>
fileList
=
Arrays
.
asList
(
files
)
;
Collections
.
sort
(
fileList
,
fileComparator
)
;
for
(
File
file
:
fileList
)
{
if
(
file
.
length
(
)
+
total
>
maxBytes
)
{
total_delete
+=
file
.
length
(
)
;
if
(
sbuff
!=
)
sbuff
.
append
(
" delete "
)
.
append
(
file
)
.
append
(
" ("
)
.
append
(
file
.
length
(
)
)
.
append
(
")\n"
)
;
if
(
!
file
.
delete
(
)
&&
sbuff
!=
)
sbuff
.
append
(
"Error deleting "
)
.
append
(
file
)
.
append
(
"\n"
)
;
}
else
{
total
+=
file
.
length
(
)
;
}
}
}
if
(
sbuff
!=
)
{
sbuff
.
append
(
"Total bytes deleted= "
)
.
append
(
total_delete
)
.
append
(
"\n"
)
;
sbuff
.
append
(
"Total bytes left in cache= "
)
.
append
(
total
)
.
append
(
"\n"
)
;
}
}

Remove files if needed to make cache have less than maxBytes bytes file sizes.
This will remove files in sort order defined by fileComparator.
The first files in the sort order are kept, until the max bytes is exceeded, then they are deleted.

@param maxBytes       max number of bytes in cache.
@param fileComparator sort files first with this
@param sbuff          write results here, null is ok.

Remove files if needed to make cache have less than maxBytes bytes file sizes . This will remove files in sort order defined by fileComparator . The first files in the sort order are kept until the max bytes is exceeded then they are deleted .


static public boolean isBufrTable(short fxy) {
    int f = (fxy & 0xC000) >> 14;
    int x = (fxy & 0x3F00) >> 8;
    int y = (fxy & 0xFF);
    return (f == 0) && (x == 0) && (y < 13);
  }

static public boolean isBufrTable ( short fxy ) { int f = ( fxy & 0xC000 ) >> 14 ; int x = ( fxy & 0x3F00 ) >> 8 ; int y = ( fxy & 0xFF ) ; return ( f == 0 ) && ( x == 0 ) && ( y < 13 ) ; }


static public CoordinateAxis factory(NetcdfDataset ncd, VariableDS vds) {
    if ((vds.getRank() == 0) || (vds.getRank() == 1) || (vds.getRank() == 2 && vds.getDataType() == DataType.CHAR)) {
        return new CoordinateAxis1D(ncd, vds);
    } else if (vds.getRank() == 2)
      return new CoordinateAxis2D(ncd, vds);
    else
      return new CoordinateAxis(ncd, vds);
  }

static public CoordinateAxis factory ( NetcdfDataset ncd , VariableDS vds ) { if ( ( vds . getRank ( ) == 0 ) || ( vds . getRank ( ) == 1 ) || ( vds . getRank ( ) == 2 && vds . getDataType ( ) == DataType . CHAR ) ) { return new CoordinateAxis1D ( ncd , vds ) ; } else if ( vds . getRank ( ) == 2 ) return new CoordinateAxis2D ( ncd , vds ) ; else return new CoordinateAxis ( ncd , vds ) ; }

Create a coordinate axis from an existing Variable.

@param ncd the containing dataset
@param vds an existing Variable in dataset.
@return CoordinateAxis or one of its subclasses (CoordinateAxis1D, CoordinateAxis2D, or CoordinateAxis1DTime).

Create a coordinate axis from an existing Variable .


public CoordinateAxis copyNoCache() {
    CoordinateAxis axis = new CoordinateAxis(ncd, getParentGroup(), getShortName(), getDataType(), getDimensionsString(),
            getUnitsString(), getDescription());

    // other state
    axis.axisType = this.axisType;
    axis.boundaryRef = this.boundaryRef;
    axis.isContiguous = this.isContiguous;
    axis.positive = this.positive;

    axis.cache = new Variable.Cache(); // decouple cache
    return axis;
  }

public
CoordinateAxis
copyNoCache
(
)
{
CoordinateAxis
axis
=
new
CoordinateAxis
(
ncd
,
getParentGroup
(
)
,
getShortName
(
)
,
getDataType
(
)
,
getDimensionsString
(
)
,
getUnitsString
(
)
,
getDescription
(
)
)
;
// other state
axis
.
axisType
=
this
.
axisType
;
axis
.
boundaryRef
=
this
.
boundaryRef
;
axis
.
isContiguous
=
this
.
isContiguous
;
axis
.
positive
=
this
.
positive
;
axis
.
cache
=
new
Variable
.
Cache
(
)
;
// decouple cache
return
axis
;
}

Make a copy, with an independent cache.

@return copy of this CoordinateAxis


public boolean isNumeric() {
    return (getDataType() != DataType.CHAR) &&
            (getDataType() != DataType.STRING) &&
            (getDataType() != DataType.STRUCTURE);
  }

public boolean isNumeric ( ) { return ( getDataType ( ) != DataType . CHAR ) && ( getDataType ( ) != DataType . STRING ) && ( getDataType ( ) != DataType . STRUCTURE ) ; }

Does the axis have numeric values.

@return true if the CoordAxis is numeric, false if its string valued ("nominal").


public void getInfo(Formatter buf) {
    buf.format("%-30s", getNameAndDimensions());
    buf.format("%-20s", getUnitsString());
    if (axisType != null) {
      buf.format("%-10s", axisType.toString());
    }
    buf.format("%s", getDescription());

    /* if (isNumeric) {
     boolean debugCoords = ucar.util.prefs.ui.Debug.isSet("Dataset/showCoordValues");
     int ndigits = debugCoords ? 9 : 4;
     for (int i=0; i< getNumElements(); i++) {
       buf.append(Format.d(getCoordValue(i), ndigits));
       buf.append(" ");
     }
     if (debugCoords) {
       buf.append("\n      ");
       for (int i=0; i<=getNumElements(); i++) {
         buf.append(Format.d(getCoordEdge(i), ndigits));
         buf.append(" ");
       }
     }
   } else {
     for (int i=0; i< getNumElements(); i++) {
       buf.append(getCoordName(i));
       buf.append(" ");
     }
   } */

    //buf.append("\n");
  }

Get a string representation

@param buf place info here


public ucar.nc2.time.Calendar getCalendarFromAttribute() {
    Attribute cal = findAttribute(CF.CALENDAR);
    String s = (cal == null) ? null : cal.getStringValue();
    if (s == null) {     // default for CF and COARDS
      Attribute convention = (ncd == null) ? null : ncd.getRootGroup().findAttribute(CDM.CONVENTIONS);
      if (convention != null) {
        String hasName = convention.getStringValue();
        int version = CF1Convention.getVersion(hasName);
        if (version >= 0) {
          return Calendar.gregorian;
          //if (version < 7 ) return Calendar.gregorian;
          //if (version >= 7 ) return Calendar.proleptic_gregorian; //
        }
        if (COARDSConvention.isMine(hasName)) return Calendar.gregorian;
      }
    }
    return ucar.nc2.time.Calendar.get(s);
  }


public void setList ( ArrayList rowList) {
    this.list = rowList;
    if (list.size() > 0)
      jtable.setRowSelectionInterval(0, 0);
    else
      jtable.clearSelection();

    model.sort();
    jtable.revalidate();
  }

public void setList ( ArrayList rowList ) { this . list = rowList ; if ( list . size ( ) > 0 ) jtable . setRowSelectionInterval ( 0 , 0 ) ; else jtable . clearSelection ( ) ; model . sort ( ) ; jtable . revalidate ( ) ; }

Replace the rowList with this one.
@param rowList list of rows


public TableRow getSelected() {
    if (list.size() == 0)
      return null;
    int sel = jtable.getSelectedRow();
    if (sel >= 0)
      return (TableRow) list.get(sel);
    else
      return null;
  }

public TableRow getSelected ( ) { if ( list . size ( ) == 0 ) return null ; int sel = jtable . getSelectedRow ( ) ; if ( sel >= 0 ) return ( TableRow ) list . get ( sel ) ; else return null ; }

Get the currently selected row.
@return selected TableRow


public void incrSelected(boolean increment) {
    if (list.size() == 0)
      return;
    int curr = jtable.getSelectedRow();
    if (increment && (curr < list.size()-1))
      setSelected(curr+1);
    else if (!increment && (curr > 0))
      setSelected(curr-1);
  }

public void incrSelected ( boolean increment ) { if ( list . size ( ) == 0 ) return ; int curr = jtable . getSelectedRow ( ) ; if ( increment && ( curr < list . size ( ) - 1 ) ) setSelected ( curr + 1 ) ; else if ( ! increment && ( curr > 0 ) ) setSelected ( curr - 1 ) ; }

Increment or decrement the current selection by one row.
@param increment true=increment, false=decrement

Increment or decrement the current selection by one row .


public int[] getModelIndex() {
    int [] modelIndex = new int[colName.length];

    TableColumnModel tcm = jtable.getColumnModel();
    for (int i=0; i<colName.length; i++) {
      TableColumn tc = tcm.getColumn(i);
      modelIndex[i] = tc.getModelIndex();
    }

    return modelIndex;
  }

public int [ ] getModelIndex ( ) { int [ ] modelIndex = new int [ colName . length ] ; TableColumnModel tcm = jtable . getColumnModel ( ) ; for ( int i = 0 ; i < colName . length ; i ++ ) { TableColumn tc = tcm . getColumn ( i ) ; modelIndex [ i ] = tc . getModelIndex ( ) ; } return modelIndex ; }


private void setSelectedIndex( int idx) {
    if (zAxis == null)
      return;
    eventOK = false;
    currentIdx = idx;
    slider.setValue( world2slider(zAxis.getCoordValue(currentIdx)));
    eventOK = true;
  }

private void setSelectedIndex ( int idx ) { if ( zAxis == null ) return ; eventOK = false ; currentIdx = idx ; slider . setValue ( world2slider ( zAxis . getCoordValue ( currentIdx ) ) ) ; eventOK = true ; }


static private void quickSort(String a[], int lo0, int hi0) {
        int lo = lo0;
        int hi = hi0;
        String mid;

        if (hi0 > lo0) {
            // Arbitrarily establishing partition element as the array midpoint */
            //Coverity[FB.IM_AVERAGE_COMPUTATION_COULD_OVERFLOW]
            mid = a[(lo0 + hi0) / 2];

            // loop through the array until indices cross
            while (lo <= hi) {
                // find the first element that is >= the partition element
                // starting from the left index.
                while ((lo < hi0) && (a[lo].compareTo(mid) < 0))
                    ++lo;

                // find an element that is <= the partition element
                // starting from the right index.
                while ((hi > lo0) && (a[hi].compareTo(mid) > 0))
                    --hi;

                // if the indexes have not crossed, swap
                if (lo <= hi) {
                    swap(a, lo, hi);
                    ++lo;
                    --hi;
                }
            }
            // If the right index has not reached the left side of array,
            // sort the left partition.
            if (lo0 < hi)
                quickSort(a, lo0, hi);

            // If the left index has not reached the right side of array,
            // sort the right partition.
            if (lo < hi0)
                quickSort(a, lo, hi0);
        }
    }

Internal recursive method to perform Quick Sort on name array.

@param a   an array of String.
@param lo0 the low index to sort.
@param hi0 the high index to sort.

Internal recursive method to perform Quick Sort on name array .


static private void swap(String a[], int i, int j) {
        String T;
        T = a[i];
        a[i] = a[j];
        a[j] = T;
    }

static private void swap ( String a [ ] , int i , int j ) { String T ; T = a [ i ] ; a [ i ] = a [ j ] ; a [ j ] = T ; }

Private method to swap two elements in the array

@param a an array of String.
@param i the index of the first element.
@param j the index of the second element.


static public MFileOS getExistingFile(String filename) {
    if (filename == null) return null;
    File file = new File(filename);
    if (file.exists()) return new MFileOS(file);
    return null;
  }

static public MFileOS getExistingFile ( String filename ) { if ( filename == null ) return null ; File file = new File ( filename ) ; if ( file . exists ( ) ) return new MFileOS ( file ) ; return null ; }

Make MFileOS if file exists, otherwise return null
@param filename
@return MFileOS or null

Make MFileOS if file exists otherwise return null


private double[] rotate(double[] lonlat, double rot1, double rot2, double s) {

    /* original code
      double e = DEG2RAD * (lonlat[0] - rot1); //east
      double n = DEG2RAD * lonlat[1]; //north
      double cn = Math.cos(n);
      double x = cn * Math.cos(e);
      double y = cn * Math.sin(e);
      double z = Math.sin(n);
      double x2 = cosDlat * x + s * z;
      double z2 = -s * x + cosDlat * z;
      double R = Math.sqrt(x2 * x2 + y * y);
      double e2 = Math.atan2(y, x2);
      double n2 = Math.atan2(z2, R);
      double rlon = RAD2DEG * e2 - rot2;
      double rlat = RAD2DEG * n2;
      return new double[]{rlon, rlat};
     */

    double e = Math.toRadians(lonlat[0] - rot1); //east
    double n = Math.toRadians(lonlat[1]); //north
    double cn = Math.cos(n);
    double x = cn * Math.cos(e);
    double y = cn * Math.sin(e);
    double z = Math.sin(n);
    double x2 = cosDlat * x + s * z;
    double z2 = -s * x + cosDlat * z;
    double R = Math.sqrt(x2 * x2 + y * y);
    double e2 = Math.atan2(y, x2);
    double n2 = Math.atan2(z2, R);
    double rlon = Math.toDegrees(e2) - rot2;
    double rlat =  Math.toDegrees(n2);
    return new double[]{rlon, rlat};

  }

Tor's transform algorithm renamed to rotate for clarity

Tor s transform algorithm renamed to rotate for clarity


static public XMLStore createFromFile(String fileName, XMLStore storedDefaults) throws java.io.IOException {
    File prefsFile = new File(fileName);

    // open file if it exists
    InputStream primIS = null, objIS = null;
    if (prefsFile.exists() && prefsFile.length() > 0) {
      primIS = new BufferedInputStream(new FileInputStream( prefsFile));
      objIS = new BufferedInputStream(new FileInputStream( prefsFile));
    }

    if (debugWhichStore) System.out.println("XMLStore read from file "+fileName);
    XMLStore store = new XMLStore( primIS, objIS, storedDefaults);
    store.prefsFile = prefsFile;
    return store;
  }

static
public
XMLStore
createFromFile
(
String
fileName
,
XMLStore
storedDefaults
)
throws
java
.
io
.
IOException
{
File
prefsFile
=
new
File
(
fileName
)
;
// open file if it exists
InputStream
primIS
=
,
objIS
=
;
if
(
prefsFile
.
exists
(
)
&&
prefsFile
.
length
(
)
>
0
)
{
primIS
=
new
BufferedInputStream
(
new
FileInputStream
(
prefsFile
)
)
;
objIS
=
new
BufferedInputStream
(
new
FileInputStream
(
prefsFile
)
)
;
}
if
(
debugWhichStore
)
System
.
out
.
println
(
"XMLStore read from file "
+
fileName
)
;
XMLStore
store
=
new
XMLStore
(
primIS
,
objIS
,
storedDefaults
)
;
store
.
prefsFile
=
prefsFile
;
return
store
;
}

Create an XMLStore reading from the specified filename.

@param fileName The XMLStore is stored in this files.
@param storedDefaults This contains the "stored defaults", or null if none.
@return new XMLStore object
@throws java.io.IOException on error

Create an XMLStore reading from the specified filename .


static public XMLStore createFromInputStream(InputStream is1, InputStream is2, XMLStore storedDefaults) throws java.io.IOException {
    if (debugWhichStore) System.out.println("XMLStore read from input stream "+is1);
    return new XMLStore( is1, is2, storedDefaults);
  }

static
public
XMLStore
createFromInputStream
(
InputStream
is1
,
InputStream
is2
,
XMLStore
storedDefaults
)
throws
java
.
io
.
IOException
{
if
(
debugWhichStore
)
System
.
out
.
println
(
"XMLStore read from input stream "
+
is1
)
;
return
new
XMLStore
(
is1
,
is2
,
storedDefaults
)
;
}

Create an XMLStore reading from an input stream. Because of some peculiariteis, you must open the
input stream wtice, and pass both in.

@param is1 the first copy of the input stream.
@param is2 the second copy of the input stream.
@param storedDefaults This contains the "stored defaults", or null if none.
@return new XMLStore object
@throws java.io.IOException on error

Create an XMLStore reading from an input stream . Because of some peculiariteis you must open the input stream wtice and pass both in .


static public XMLStore createFromResource(String resourceName, XMLStore storedDefaults)
         throws java.io.IOException {

    // open files if exist
    Class c = XMLStore.class;
    InputStream primIS = c.getResourceAsStream(resourceName);
    InputStream objIS = c.getResourceAsStream(resourceName);

    // debug
//    InputStream debugIS = c.getResourceAsStream(fileName);
  //  System.out.println("Resource stream= "+fileName);
    //thredds.util.IO.copy(debugIS, System.out);

    if (primIS == null) {
      //System.out.println("classLoader="+new XMLStore().getClass().getClassLoader());
      throw new java.io.IOException("XMLStore.createFromResource cant find <"+resourceName+">");
    }

    if (debugWhichStore) System.out.println("XMLStore read from resource "+resourceName);
    return new XMLStore( primIS, objIS, storedDefaults);
  }

Create a read-only XMLStore reading from the specified resource, opened as a Resource stream using the
XMLStore ClassLoader. This allows you to find files that are in jar files on
the application CLASSPATH.

@param resourceName The XMLStore is stored in this resource. By convention it has .xml suffix.
@param storedDefaults This contains the "stored defaults", or null if none.
@throws java.io.IOException if Resource not found or error reading it
@return new XMLStore object

Create a read - only XMLStore reading from the specified resource opened as a Resource stream using the XMLStore ClassLoader . This allows you to find files that are in jar files on the application CLASSPATH .


static public String makeStandardFilename(String appName, String storeName) {
      // the directory
    String userHome = null;
    try {
      userHome = System.getProperty("user.home");
    } catch (Exception e) {
      System.out.println( "XMLStore.makeStandardFilename: error System.getProperty(user.home) "+e);
    }
    if (null == userHome) userHome = ".";

    String dirFilename = userHome+"/"+appName;
    File f = new File(dirFilename);
    if (!f.exists()) {
      boolean ok = f.mkdirs(); // now ready for file creation in writeXML
      if (!ok)
        System.out.println("Error creating directories: " + f.getAbsolutePath());
    }
    return dirFilename +"/"+ storeName;
  }

Convenience routine for creating an XMLStore file in a standard place.

<p> Initialize:
<ol>
<li> $user.home = System.getProperty("user.home"), if not exist, use "."
<li> create directory "$(user_home)/appName/" , if not exist, create it
<li> return  "$(user_home)/appName/storeName" for use in createFromFile()
</ol>
@param appName application name
@param storeName store name
@return  standard file name

Convenience routine for creating an XMLStore file in a standard place .


public void save() throws java.io.IOException {
    if (prefsFile == null)
      throw new UnsupportedOperationException("XMLStore is read-only");

      // get temporary file to write to
    File prefTemp;
    String parentFilename = prefsFile.getParent();
    if (parentFilename == null) {
      prefTemp = File.createTempFile("pref", ".xml");
    } else {
      File parentFile = new File(parentFilename);
      prefTemp = File.createTempFile("pref", ".xml", parentFile);
    }
    prefTemp.deleteOnExit();

    // save to the temp file
    FileOutputStream fos = new FileOutputStream( prefTemp, false);
    save( fos);
    fos.close();

    // success - rename files
    Path xmlBackup = Paths.get(prefsFile.getAbsolutePath() + ".bak");
    Path prefsPath = prefsFile.toPath();
    if (Files.exists(prefsPath))
        Files.move(prefsPath, xmlBackup, StandardCopyOption.REPLACE_EXISTING);
    Files.move(prefTemp.toPath(), prefsFile.toPath(),
            StandardCopyOption.REPLACE_EXISTING);
  }

public
void
save
(
)
throws
java
.
io
.
IOException
{
if
(
prefsFile
==
)
throw
new
UnsupportedOperationException
(
"XMLStore is read-only"
)
;
// get temporary file to write to
File
prefTemp
;
String
parentFilename
=
prefsFile
.
getParent
(
)
;
if
(
parentFilename
==
)
{
prefTemp
=
File
.
createTempFile
(
"pref"
,
".xml"
)
;
}
else
{
File
parentFile
=
new
File
(
parentFilename
)
;
prefTemp
=
File
.
createTempFile
(
"pref"
,
".xml"
,
parentFile
)
;
}
prefTemp
.
deleteOnExit
(
)
;
// save to the temp file
FileOutputStream
fos
=
new
FileOutputStream
(
prefTemp
,
false
)
;
save
(
fos
)
;
fos
.
close
(
)
;
// success - rename files
Path
xmlBackup
=
Paths
.
get
(
prefsFile
.
getAbsolutePath
(
)
+
".bak"
)
;
Path
prefsPath
=
prefsFile
.
toPath
(
)
;
if
(
Files
.
exists
(
prefsPath
)
)
Files
.
move
(
prefsPath
,
xmlBackup
,
StandardCopyOption
.
REPLACE_EXISTING
)
;
Files
.
move
(
prefTemp
.
toPath
(
)
,
prefsFile
.
toPath
(
)
,
StandardCopyOption
.
REPLACE_EXISTING
)
;
}

Save the current state of the Preferences tree to disk, using the
original filename. The XMLStore must have been constructed from a
writeable XML file.
@throws UnsupportedOperationException: if XMLStore was created from createFromResource.
@throws java.io.IOException on read error

Save the current state of the Preferences tree to disk using the original filename . The XMLStore must have been constructed from a writeable XML file .


public void save(OutputStream out) throws java.io.IOException {
    outputExceptionMessage = null;

    // the OutputMunger strips off the XMLEncoder header
    OutputMunger bos = new OutputMunger( out);
    PrintWriter pw = new PrintWriter( new OutputStreamWriter(bos,
            CDM.utf8Charset));

    XMLEncoder beanEncoder = new XMLEncoder( bos);
    beanEncoder.setExceptionListener(new ExceptionListener() {
      public void exceptionThrown(Exception exception) {
        System.out.println("XMLStore.save() got Exception: abort saving the preferences!");
        exception.printStackTrace();
        outputExceptionMessage = exception.getMessage();
      }
    });

    pw.printf("<?xml version='1.0' encoding='UTF-8'?>%n");
    pw.printf("<preferences EXTERNAL_XML_VERSION='1.0'>%n");
    if (!rootPrefs.isUserNode())
      pw.printf("  <root type='system'>%n");
    else
      pw.printf("  <root type='user'>%n");

    Indent indent = new Indent(2);
    indent.incr();
    writeXmlNode(bos, pw, rootPrefs, beanEncoder, indent);
    if (outputExceptionMessage != null)
      throw new IOException(outputExceptionMessage);

    pw.printf("  </root>%n");
    pw.printf("</preferences>%n");
    pw.flush();
  }

Save the current state of the Preferences tree to the given OutputStream.

Save the current state of the Preferences tree to the given OutputStream .


protected void
    writeAtomicVariable(DataCursor data, SerialWriter dst)
            throws IOException
    {
        DapVariable template = (DapVariable) data.getTemplate();
        assert (this.ce.references(template));
        DapType basetype = template.getBaseType();
        // get the slices from constraint
        List<Slice> slices = ce.getConstrainedSlices(template);
        if(slices == null)
            throw new DapException("Unknown variable: " + template.getFQN());
        Object values = data.read(slices);
        dst.writeAtomicArray(basetype, values);
    }

protected
void
writeAtomicVariable
(
DataCursor
data
,
SerialWriter
dst
)
throws
IOException
{
DapVariable
template
=
(
DapVariable
)
data
.
getTemplate
(
)
;
assert
(
this
.
ce
.
references
(
template
)
)
;
DapType
basetype
=
template
.
getBaseType
(
)
;
// get the slices from constraint
List
<
Slice
>
slices
=
ce
.
getConstrainedSlices
(
template
)
;
if
(
slices
==
)
throw
new
DapException
(
"Unknown variable: "
+
template
.
getFQN
(
)
)
;
Object
values
=
data
.
read
(
slices
)
;
dst
.
writeAtomicArray
(
basetype
,
values
)
;
}

Write out an atomic variable.

@param data
@param dst
@throws dap4.core.util.DapException


protected void
    writeStructure(DataCursor data, SerialWriter dst)
            throws IOException
    {
        DapVariable template = (DapVariable) data.getTemplate();
        DapStructure ds = (DapStructure) template.getBaseType();
        assert (this.ce.references(template));
        List<Slice> slices = ce.getConstrainedSlices(template);
        Odometer odom = Odometer.factory(slices);
        while(odom.hasNext()) {
            Index index = odom.next();
            DataCursor[] instance = (DataCursor[]) data.read(index);
            writeStructure1(instance[0], dst);
        }
    }

protected void writeStructure ( DataCursor data , SerialWriter dst ) throws IOException { DapVariable template = ( DapVariable ) data . getTemplate ( ) ; DapStructure ds = ( DapStructure ) template . getBaseType ( ) ; assert ( this . ce . references ( template ) ) ; List < Slice > slices = ce . getConstrainedSlices ( template ) ; Odometer odom = Odometer . factory ( slices ) ; while ( odom . hasNext ( ) ) { Index index = odom . next ( ) ; DataCursor [ ] instance = ( DataCursor [ ] ) data . read ( index ) ; writeStructure1 ( instance [ 0 ] , dst ) ; } }

Write out a scalar or array structure instance

@param data
@param dst  - where to write
@throws dap4.core.util.DapException


protected void
    writeStructure1(DataCursor instance, SerialWriter dst)
            throws IOException
    {
        assert instance.getScheme() == DataCursor.Scheme.STRUCTURE;
        DapVariable template = (DapVariable) instance.getTemplate();
        assert (this.ce.references(template));
        DapStructure ds = (DapStructure) template.getBaseType();

        List<DapVariable> fields = ds.getFields();
        for(int i = 0; i < fields.size(); i++) {
            DapVariable field = fields.get(i);
            if(!this.ce.references(field)) continue; // not in the view
            DataCursor df = (DataCursor) instance.readField(i);
            writeVariable(df, dst);
        }
    }

protected
void
writeStructure1
(
DataCursor
instance
,
SerialWriter
dst
)
throws
IOException
{
assert
instance
.
getScheme
(
)
==
DataCursor
.
Scheme
.
STRUCTURE
;
DapVariable
template
=
(
DapVariable
)
instance
.
getTemplate
(
)
;
assert
(
this
.
ce
.
references
(
template
)
)
;
DapStructure
ds
=
(
DapStructure
)
template
.
getBaseType
(
)
;
List
<
DapVariable
>
fields
=
ds
.
getFields
(
)
;
for
(
int
i
=
0
;
i
<
fields
.
size
(
)
;
i
++
)
{
DapVariable
field
=
fields
.
get
(
i
)
;
if
(
!
this
.
ce
.
references
(
field
)
)
continue
;
// not in the view
DataCursor
df
=
(
DataCursor
)
instance
.
readField
(
i
)
;
writeVariable
(
df
,
dst
)
;
}
}

Write out a single structure instance

@param instance
@param dst      - where to write
@throws dap4.core.util.DapException


protected void
    writeSequence(DataCursor data, SerialWriter dst)
            throws IOException
    {
        DapVariable template = (DapVariable) data.getTemplate();
        DapSequence ds = (DapSequence) template.getBaseType();
        assert (this.ce.references(template));
        List<Slice> slices = ce.getConstrainedSlices(template);
        Odometer odom = Odometer.factory(slices);
        if(false) while(odom.hasNext()) {
            Index index = odom.next();
            DataCursor[] instance = (DataCursor[]) data.read(index);
            writeSequence1(instance[0], dst);
        }
        else {
            DataCursor[] instances = (DataCursor[]) data.read(slices);
            for(int i = 0; i < instances.length; i++) {
                writeSequence1(instances[i], dst);
            }

        }
    }

protected void writeSequence ( DataCursor data , SerialWriter dst ) throws IOException { DapVariable template = ( DapVariable ) data . getTemplate ( ) ; DapSequence ds = ( DapSequence ) template . getBaseType ( ) ; assert ( this . ce . references ( template ) ) ; List < Slice > slices = ce . getConstrainedSlices ( template ) ; Odometer odom = Odometer . factory ( slices ) ; if ( false ) while ( odom . hasNext ( ) ) { Index index = odom . next ( ) ; DataCursor [ ] instance = ( DataCursor [ ] ) data . read ( index ) ; writeSequence1 ( instance [ 0 ] , dst ) ; } else { DataCursor [ ] instances = ( DataCursor [ ] ) data . read ( slices ) ; for ( int i = 0 ; i < instances . length ; i ++ ) { writeSequence1 ( instances [ i ] , dst ) ; } } }

Write out a single or array sequence instance

@param data
@param dst  - where to write
@throws dap4.core.util.DapException


protected void
    writeRecord(DataCursor record, SerialWriter dst)
            throws IOException
    {
        DapVariable template = (DapVariable) record.getTemplate();
        DapSequence seq = (DapSequence) template.getBaseType();
        List<DapVariable> fields = seq.getFields();
        for(int i = 0; i < fields.size(); i++) {
            DapVariable field = fields.get(i);
            if(!this.ce.references(field)) continue; // not in the view
            DataCursor df = (DataCursor) record.readField(i);
            writeVariable(df, dst);
        }
    }

protected
void
writeRecord
(
DataCursor
record
,
SerialWriter
dst
)
throws
IOException
{
DapVariable
template
=
(
DapVariable
)
record
.
getTemplate
(
)
;
DapSequence
seq
=
(
DapSequence
)
template
.
getBaseType
(
)
;
List
<
DapVariable
>
fields
=
seq
.
getFields
(
)
;
for
(
int
i
=
0
;
i
<
fields
.
size
(
)
;
i
++
)
{
DapVariable
field
=
fields
.
get
(
i
)
;
if
(
!
this
.
ce
.
references
(
field
)
)
continue
;
// not in the view
DataCursor
df
=
(
DataCursor
)
record
.
readField
(
i
)
;
writeVariable
(
df
,
dst
)
;
}
}

Write out a single Record instance.

@param record the record data cursor
@param dst    to which to write
@throws dap4.core.util.DapException


static public boolean isValidFile(ucar.unidata.io.RandomAccessFile raf) throws IOException {
    raf.seek(0);
    if (!raf.searchForward(matcher, 40 * 1000)) return false; // must find "BUFR" in first 40k
    raf.skipBytes(4);
    BufrIndicatorSection is = new BufrIndicatorSection(raf);
    if (is.getBufrEdition() > 4) return false;
    // if(is.getBufrLength() > MAX_MESSAGE_SIZE) return false;
    return !(is.getBufrLength() > raf.length());
  }

is this a valid BUFR file.

@param raf check this file
@return true if its a BUFR file
@throws IOException on read error


public String getWmoId() {
    String wmoID = "";
    if (!(stnm == GempakConstants.IMISSD)) {
      wmoID = String.valueOf((int) (stnm / 10));
    }
    return wmoID;
  }

public String getWmoId ( ) { String wmoID = "" ; if ( ! ( stnm == GempakConstants . IMISSD ) ) { wmoID = String . valueOf ( ( int ) ( stnm / 10 ) ) ; } return wmoID ; }

Get the WMO Station ID as a string

@return the WMO id


int readRowN(DataInputStream ds, int n) {
    if (n > nrec) return -1;
    /* the assumption here is that the DataInputStream (ds)
    * is already pointing at the right spot!
    */
    try {
      ds.readFully(field, 0, desc.FieldLength);
    } catch (java.io.IOException e) {
      return -1;
    }
    switch (desc.Type) {
      case 'C':
      case 'D':
        character[n] = new String(field, CDM.utf8Charset);
        break;
      case 'N':
        numeric[n] = Double.valueOf(new String(field, CDM.utf8Charset));
        break;
      case 'F':  /* binary floating point */
        if (desc.FieldLength == 4) {
          numeric[n] = (double) Swap.swapFloat(field, 0);
        } else {
          numeric[n] = Swap.swapDouble(field, 0);
        }
        break;
      case 'L':
        switch (field[0]) {
          case 't':
          case 'T':
          case 'Y':
          case 'y':
            logical[n] = true;
            break;
          default:
            logical[n] = false;
            break;
        }
      default:
        return -1;
    }

    return 0;
  }

Method to read an entry from the data stream.  The stream is assumed to be
in the right spot for reading.  This method should be called from something
controlling the reading of the entire file.

@see DbaseFile

Method to read an entry from the data stream . The stream is assumed to be in the right spot for reading . This method should be called from something controlling the reading of the entire file .


public Object getData(int i) {
    switch (type) {
      case TYPE_CHAR:
        return character[i];
      case TYPE_NUMERIC:
        return numeric[i];
      case TYPE_BOOLEAN:
        return logical[i];
    }
    return null;
  }

public Object getData ( int i ) { switch ( type ) { case TYPE_CHAR : return character [ i ] ; case TYPE_NUMERIC : return numeric [ i ] ; case TYPE_BOOLEAN : return logical [ i ] ; } return null ; }

Method to retrieve data for this field

@param i index of desired String, assumes 0 < i < getNumRec()
@return either a Double, Boolean, or String with the data


private float[] getData0(RandomAccessFile raf, Grib2Drs.Type0 gdrs) throws IOException {
    int nb = gdrs.numberOfBits;
    int D = gdrs.decimalScaleFactor;
    float DD = (float) java.lang.Math.pow((double) 10, (double) D);
    float R = gdrs.referenceValue;
    int E = gdrs.binaryScaleFactor;
    float EE = (float) java.lang.Math.pow(2.0, (double) E);

    // LOOK: can # datapoints differ from bitmap and data ?
    // dataPoints are number of points encoded, it could be less than the
    // totalNPoints in the grid record if bitMap is used, otherwise equal
    float[] data = new float[totalNPoints];

    //  Y * 10**D = R + (X1 + X2) * 2**E
    //   E = binary scale factor
    //   D = decimal scale factor
    //   R = reference value
    //   X1 = 0
    //   X2 = scaled encoded value
    //   data[ i ] = (R + ( X1 + X2) * EE)/DD ;

    BitReader reader = new BitReader(raf, startPos + 5);
    if (bitmap == null) {
      for (int i = 0; i < totalNPoints; i++) {
        //data[ i ] = (R + ( X1 + X2) * EE)/DD ;
        data[i] = (R + reader.bits2UInt(nb) * EE) / DD;
      }
    } else {
      for (int i = 0; i < totalNPoints; i++) {
        if (GribNumbers.testBitIsSet(bitmap[i / 8], i % 8)) {
          data[i] = (R + reader.bits2UInt(nb) * EE) / DD;
        } else {
          data[i] = staticMissingValue;
          //data[i] = R / DD;
        }
      }
    }

    return data;
  }


private float[] getData41(RandomAccessFile raf, Grib2Drs.Type0 gdrs) throws IOException {
    int nb = gdrs.numberOfBits;
    int D = gdrs.decimalScaleFactor;
    float DD = (float) java.lang.Math.pow((double) 10, (double) D);
    float R = gdrs.referenceValue;
    int E = gdrs.binaryScaleFactor;
    float EE = (float) java.lang.Math.pow(2.0, (double) E);

    // LOOK: can # datapoints differ from bitmap and data ?
    // dataPoints are number of points encoded, it could be less than the
    // totalNPoints in the grid record if bitMap is used, otherwise equal
    float[] data = new float[totalNPoints];

    // no data to decode, set to reference value
    if (nb == 0) {
      Arrays.fill(data, R);
      return data;
    }

    //  Y * 10**D = R + (X1 + X2) * 2**E
    //   E = binary scale factor
    //   D = decimal scale factor
    //   R = reference value
    //   X1 = 0
    //   X2 = scaled encoded value
    //   data[ i ] = (R + ( X1 + X2) * EE)/DD ;

    byte[] buf = new byte[dataLength - 5];
    raf.readFully(buf);
    InputStream in = new ByteArrayInputStream(buf);
    BufferedImage image = ImageIO.read(in);

    if (nb != image.getColorModel().getPixelSize()) {
      logger.debug("PNG pixel size disagrees with grib number of bits: ",
          image.getColorModel().getPixelSize(), nb);
    }

    DataBuffer db = image.getRaster().getDataBuffer();
    if (bitmap == null) {
      for (int i = 0; i < dataNPoints; i++) {
        data[i] = (R + db.getElem(i) * EE) / DD;
      }
    } else {
      for (int bitPt = 0, dataPt = 0; bitPt < totalNPoints; bitPt++) {
        if (GribNumbers.testBitIsSet(bitmap[bitPt / 8], bitPt % 8)) {
          data[bitPt] = (R + db.getElem(dataPt++) * EE) / DD;
        } else {
          data[bitPt] = staticMissingValue;
        }
      }
    }

    return data;
  }

Code taken from esupport ticket ZVT-415274

Code taken from esupport ticket ZVT - 415274


@Override
    public Object
    read(List<Slice> slices)
            throws DapException
    {
        switch (this.scheme) {
        case ATOMIC:
            return readAtomic(slices);
        case STRUCTURE:
            if(((DapVariable) this.getTemplate()).getRank() > 0
                    || DapUtil.isScalarSlices(slices))
                throw new DapException("Cannot slice a scalar variable");
            CDMCursor[] instances = new CDMCursor[1];
            instances[0] = this;
            return instances;
        case SEQUENCE:
            if(((DapVariable) this.getTemplate()).getRank() > 0
                    || DapUtil.isScalarSlices(slices))
                throw new DapException("Cannot slice a scalar variable");
            instances = new CDMCursor[1];
            instances[0] = this;
            return instances;
        case STRUCTARRAY:
            Odometer odom = Odometer.factory(slices);
            instances = new CDMCursor[(int) odom.totalSize()];
            for(int i = 0; odom.hasNext(); i++) {
                instances[i] = readStructure(odom.next());
            }
            return instances;
        case SEQARRAY:
            instances = readSequence(slices);
            return instances;
        default:
            throw new DapException("Attempt to slice a scalar object");
        }
    }

@
Override
public
Object
read
(
List
<
Slice
>
slices
)
throws
DapException
{
switch
(
this
.
scheme
)
{
case
ATOMIC
:
return
readAtomic
(
slices
)
;
case
STRUCTURE
:
if
(
(
(
DapVariable
)
this
.
getTemplate
(
)
)
.
getRank
(
)
>
0
||
DapUtil
.
isScalarSlices
(
slices
)
)
throw
new
DapException
(
"Cannot slice a scalar variable"
)
;
CDMCursor
[
]
instances
=
new
CDMCursor
[
1
]
;
instances
[
0
]
=
this
;
return
instances
;
case
SEQUENCE
:
if
(
(
(
DapVariable
)
this
.
getTemplate
(
)
)
.
getRank
(
)
>
0
||
DapUtil
.
isScalarSlices
(
slices
)
)
throw
new
DapException
(
"Cannot slice a scalar variable"
)
;
instances
=
new
CDMCursor
[
1
]
;
instances
[
0
]
=
this
;
return
instances
;
case
STRUCTARRAY
:
Odometer
odom
=
Odometer
.
factory
(
slices
)
;
instances
=
new
CDMCursor
[
(
int
)
odom
.
totalSize
(
)
]
;
for
(
int
i
=
0
;
odom
.
hasNext
(
)
;
i
++
)
{
instances
[
i
]
=
readStructure
(
odom
.
next
(
)
)
;
}
return
instances
;
case
SEQARRAY
:
instances
=
readSequence
(
slices
)
;
return
instances
;
default
:
throw
new
DapException
(
"Attempt to slice a scalar object"
)
;
}
}


static public void makeFile(String location, ucar.nc2.dt.GridDataset gds, List<String> gridList, LatLonRect llbb, CalendarDateRange range)
          throws IOException, InvalidRangeException {
    CFGridWriter writer = new CFGridWriter();
    writer.makeFile(location, gds, gridList, llbb, range, false, 1, 1, 1);
  }

static public void makeFile ( String location , ucar . nc2 . dt . GridDataset gds , List < String > gridList , LatLonRect llbb , CalendarDateRange range ) throws IOException , InvalidRangeException { CFGridWriter writer = new CFGridWriter ( ) ; writer . makeFile ( location , gds , gridList , llbb , range , false , 1 , 1 , 1 ) ; }

Write a netcdf-3 file from a subset of a grid dataset

@param location write new file
@param gds      from this grid dataset
@param gridList just these grids
@param llbb     horiz subset, may be null
@param range    time subset, may be null
@throws IOException
@throws InvalidRangeException

Write a netcdf - 3 file from a subset of a grid dataset


public long makeGridFileSizeEstimate(ucar.nc2.dt.GridDataset gds, List<String> gridList,
                                       LatLonRect llbb, int horizStride,
                                       Range zRange,
                                       CalendarDateRange dateRange, int stride_time,
                                       boolean addLatLon) throws IOException, InvalidRangeException {

    return makeOrTestSize(null, gds, gridList, llbb, horizStride, zRange, dateRange, stride_time, addLatLon, true, NetcdfFileWriter.Version.netcdf3);
  }

public long makeGridFileSizeEstimate ( ucar . nc2 . dt . GridDataset gds , List < String > gridList , LatLonRect llbb , int horizStride , Range zRange , CalendarDateRange dateRange , int stride_time , boolean addLatLon ) throws IOException , InvalidRangeException { return makeOrTestSize ( null , gds , gridList , llbb , horizStride , zRange , dateRange , stride_time , addLatLon , true , NetcdfFileWriter . Version . netcdf3 ) ; }

Write a netcdf-3 file from a subset of a grid dataset, as long as it doesnt exceed a certain file size.

@param gds         from this grid dataset
@param gridList    just these grids
@param llbb        horiz subset, may be null
@param zRange      vertical subset, may be null
@param dateRange   time subset, may be null
@param stride_time time may be strided, -1 if want all
@param addLatLon   optionally add a lat/lon coordinate (if dataset uses projection coords)
@return file size
@throws IOException
@throws InvalidRangeException

Write a netcdf - 3 file from a subset of a grid dataset as long as it doesnt exceed a certain file size .


public void makeFile(String location, ucar.nc2.dt.GridDataset gds, List<String> gridList,
                       LatLonRect llbb, CalendarDateRange range,
                       boolean addLatLon,
                       int horizStride, int stride_z, int stride_time)
          throws IOException, InvalidRangeException {
    makeFile(location, gds, gridList, llbb, horizStride, null, range, stride_time, addLatLon, NetcdfFileWriter.Version.netcdf3);
  }

public void makeFile ( String location , ucar . nc2 . dt . GridDataset gds , List < String > gridList , LatLonRect llbb , CalendarDateRange range , boolean addLatLon , int horizStride , int stride_z , int stride_time ) throws IOException , InvalidRangeException { makeFile ( location , gds , gridList , llbb , horizStride , null , range , stride_time , addLatLon , NetcdfFileWriter . Version . netcdf3 ) ; }

Write a CF compliant Netcdf-3 file from any gridded dataset.

@param location    write to this location on disk
@param gds         A gridded dataset
@param gridList    the list of grid names to be written, must not be empty. Full name (not short).
@param llbb        optional lat/lon bounding box
@param range       optional time range
@param addLatLon   should 2D lat/lon variables be added, if its a projection coordinate system?
@param horizStride x,y stride
@param stride_z    not implemented yet
@param stride_time not implemented yet
@throws IOException           if write or read error
@throws InvalidRangeException if subset is illegal

Write a CF compliant Netcdf - 3 file from any gridded dataset .


public void setStations(java.util.List<ucar.unidata.geoloc.Station> stns) {
    stations = new ArrayList<StationUI>( stns.size());
    stationHash.clear();
    for (int i = 0; i < stns.size(); i++) {
      ucar.unidata.geoloc.Station s = (ucar.unidata.geoloc.Station) stns.get(i);
      StationUI sui = new StationUI( s); // wrap in a StationUI
      stations.add(sui); // wrap in a StationUI
      stationHash.put( s.getName(), sui);
    }
    posWasCalc = false;
    calcWorldPos();
  }

public
void
setStations
(
java
.
util
.
List
<
ucar
.
unidata
.
geoloc
.
Station
>
stns
)
{
stations
=
new
ArrayList
<
StationUI
>
(
stns
.
size
(
)
)
;
stationHash
.
clear
(
)
;
for
(
int
i
=
0
;
i
<
stns
.
size
(
)
;
i
++
)
{
ucar
.
unidata
.
geoloc
.
Station
s
=
(
ucar
.
unidata
.
geoloc
.
Station
)
stns
.
get
(
i
)
;
StationUI
sui
=
new
StationUI
(
s
)
;
// wrap in a StationUI
stations
.
add
(
sui
)
;
// wrap in a StationUI
stationHash
.
put
(
s
.
getName
(
)
,
sui
)
;
}
posWasCalc
=
false
;
calcWorldPos
(
)
;
}

Set the list of stations.
@param stns: list of DDStation objects


public void setSelectedStation( String name) {
    StationUI sui = (StationUI) stationHash.get( name);
    if (sui != null) {
      setSelectedStation( sui);
    }
  }

public void setSelectedStation ( String name ) { StationUI sui = ( StationUI ) stationHash . get ( name ) ; if ( sui != null ) { setSelectedStation ( sui ) ; } }

set selected station based on the sttion id.

set selected station based on the sttion id .


public ucar.unidata.geoloc.Station pick(Point2D pickPt) {
    if (world2Normal == null || pickPt == null || stations.isEmpty()) return null;

    world2Normal.transform(pickPt, ptN); // work in normalized coordinate space
    StationUI closest = (StationUI) stationGrid.findIntersection(ptN);
    setSelectedStation( closest);

    return getSelectedStation();
  }

public
ucar
.
unidata
.
geoloc
.
Station
pick
(
Point2D
pickPt
)
{
if
(
world2Normal
==
||
pickPt
==
||
stations
.
isEmpty
(
)
)
return
;
world2Normal
.
transform
(
pickPt
,
ptN
)
;
// work in normalized coordinate space
StationUI
closest
=
(
StationUI
)
stationGrid
.
findIntersection
(
ptN
)
;
setSelectedStation
(
closest
)
;
return
getSelectedStation
(
)
;
}

Find station that contains this point. If it exists, make it the
"selected" station.
@param pickPt: world coordinates
@return station that contains this point, or null if none.

Find station that contains this point . If it exists make it the selected station .


public ucar.unidata.geoloc.Station pickClosest(Point2D pickPt) {
    if (world2Normal == null || pickPt == null || stations.isEmpty()) return null;

    world2Normal.transform(pickPt, ptN); // work in normalized coordinate space
    StationUI closest = (StationUI) stationGrid.findClosest(ptN);

    if (debug) System.out.println("closest= " +closest);
    setSelectedStation( closest);

    return getSelectedStation();
  }

public
ucar
.
unidata
.
geoloc
.
Station
pickClosest
(
Point2D
pickPt
)
{
if
(
world2Normal
==
||
pickPt
==
||
stations
.
isEmpty
(
)
)
return
;
world2Normal
.
transform
(
pickPt
,
ptN
)
;
// work in normalized coordinate space
StationUI
closest
=
(
StationUI
)
stationGrid
.
findClosest
(
ptN
)
;
if
(
debug
)
System
.
out
.
println
(
"closest= "
+
closest
)
;
setSelectedStation
(
closest
)
;
return
getSelectedStation
(
)
;
}

Find station closest to this point. Make it the "selected" station.
@param pickPt: world coordinates
@return station that contains this point, or null if none.

Find station closest to this point . Make it the selected station .


public ucar.unidata.geoloc.Station getSelectedStation() {
    return (selected != null) ? selected.ddStation : null;
  }

public ucar . unidata . geoloc . Station getSelectedStation ( ) { return ( selected != null ) ? selected . ddStation : null ; }

Get the selected station.
@return the selected station, or null if none selected


public String getProjName(int type) {
    String projName;
    switch (type) {

      case PSEUDO_MERCATOR:
      case PSEUDO_MERCATOR_GENERAL:
        projName = "MERC";
        break;

      case PS_OR_LAMBERT_CONIC:
        projName = (vals[38] == vals[39])
                ? "PS"
                : "CONF";
        break;

      case EQUIDISTANT:
        projName = "EQUI";
        break;

      case LAMBERT_CONFORMAL_TANGENT:
        projName = "CONF";
        break;

      default:
        projName = "NAV" + type;
    }
    return projName;

  }

public String getProjName ( int type ) { String projName ; switch ( type ) { case PSEUDO_MERCATOR : case PSEUDO_MERCATOR_GENERAL : projName = "MERC" ; break ; case PS_OR_LAMBERT_CONIC : projName = ( vals [ 38 ] == vals [ 39 ] ) ? "PS" : "CONF" ; break ; case EQUIDISTANT : projName = "EQUI" ; break ; case LAMBERT_CONFORMAL_TANGENT : projName = "CONF" ; break ; default : projName = "NAV" + type ; } return projName ; }

Get the name for the projection type

@param type the projection type
@return a String name for the type


public List getStations(ucar.unidata.geoloc.LatLonRect boundingBox) throws IOException {
    return typical.getStations(boundingBox);
  }

public List getStations ( ucar . unidata . geoloc . LatLonRect boundingBox ) throws IOException { return typical . getStations ( boundingBox ) ; }

Get all the Stations within a bounding box.

@param boundingBox within this bounding box
@return List of Station
@throws java.io.IOException I/O error

Get all the Stations within a bounding box .


public ucar.unidata.geoloc.Station getStation(String name) {
    return typical.getStation(name);
  }

public ucar . unidata . geoloc . Station getStation ( String name ) { return typical . getStation ( name ) ; }

Find a Station by name

@param name name of the Station
@return Station with that name, or null if not found


public DataIterator getDataIterator(ucar.unidata.geoloc.Station s) throws IOException {
    return new StationDataIterator(s);
  }

public DataIterator getDataIterator ( ucar . unidata . geoloc . Station s ) throws IOException { return new StationDataIterator ( s ) ; }

Get all data for this Station.

@param s Station
@return iterator over type getDataClass()
@throws java.io.IOException I/O error


public DataIterator getDataIterator(ucar.unidata.geoloc.Station s, Date start, Date end) throws IOException {
    return new StationDateDataIterator(s, start, end);
  }

public DataIterator getDataIterator ( ucar . unidata . geoloc . Station s , Date start , Date end ) throws IOException { return new StationDateDataIterator ( s , start , end ) ; }

Get data for this Station within the specified date range.

@param s     Station
@param start starting Date
@param end   ending Date
@return Iterator over type getDataClass()
@throws java.io.IOException I/O error

Get data for this Station within the specified date range .


public void readData(RandomAccessFile raf, String abbrev, Range gateRange, IndexIterator ii) throws IOException {
    long offset = rayOffset;
    offset += (getDataOffset(abbrev) * 2 - 2);
    raf.seek(offset);
    byte[] b2 = new byte[2];
    int dataCount = getGateCount(abbrev);
    byte[] data = new byte[dataCount * 2];
    raf.readFully(data);

    for (int gateIdx : gateRange) {
      if (gateIdx >= dataCount)
        ii.setShortNext(uf_header2.missing);
      else {
        b2[0] = data[gateIdx * 2];
        b2[1] = data[gateIdx * 2 + 1];
        short value = getShort(b2, 0);

        ii.setShortNext(value);
      }
    }

  }

public void readData ( RandomAccessFile raf , String abbrev , Range gateRange , IndexIterator ii ) throws IOException { long offset = rayOffset ; offset += ( getDataOffset ( abbrev ) * 2 - 2 ) ; raf . seek ( offset ) ; byte [ ] b2 = new byte [ 2 ] ; int dataCount = getGateCount ( abbrev ) ; byte [ ] data = new byte [ dataCount * 2 ] ; raf . readFully ( data ) ; for ( int gateIdx : gateRange ) { if ( gateIdx >= dataCount ) ii . setShortNext ( uf_header2 . missing ) ; else { b2 [ 0 ] = data [ gateIdx * 2 ] ; b2 [ 1 ] = data [ gateIdx * 2 + 1 ] ; short value = getShort ( b2 , 0 ) ; ii . setShortNext ( value ) ; } } }

Read data from this ray.

@param raf       read from this file
@param abbrev    which data type we want
@param gateRange handles the possible subset of data to return
@param ii        put the data here
@throws java.io.IOException


public double dot(MAVector v) {

    if (nelems != v.getNelems())
      throw new IllegalArgumentException("MAVector.dot "+nelems+" != "+ v.getNelems());

    double sum = 0.0;
    for (int k=0; k<nelems; k++)
      sum += getDouble(k) * v.getDouble(k);

    return sum;
  }

public
double
dot
(
MAVector
v
)
{
if
(
nelems
!=
v
.
getNelems
(
)
)
throw
new
IllegalArgumentException
(
"MAVector.dot "
+
nelems
+
" != "
+
v
.
getNelems
(
)
)
;
double
sum
=
0.0
;
for
(
int
k
=
0
;
k
<
nelems
;
k
++
)
sum
+=
getDouble
(
k
)
*
v
.
getDouble
(
k
)
;
return
sum
;
}

Dot product of 2 vectors
@param v dot product with this vector
@return double result: dot product
@exception IllegalArgumentException if nelems != v.getNelems().


public double norm() {

    double sum = 0.0;
    for (int k=0; k<nelems; k++) {
      double val = getDouble(k);
      sum += val * val;
    }

    return Math.sqrt(sum);
  }

public double norm ( ) { double sum = 0.0 ; for ( int k = 0 ; k < nelems ; k ++ ) { double val = getDouble ( k ) ; sum += val * val ; } return Math . sqrt ( sum ) ; }

Get the L2 norm of this vector.
@return double norm


public void normalize() {
    double norm = norm();
    if (norm <= 0.0)
      return;

    for (int k=0; k<nelems; k++) {
      double val = getDouble(k);
      setDouble(k, val/norm);
    }
  }

public void normalize ( ) { double norm = norm ( ) ; if ( norm <= 0.0 ) return ; for ( int k = 0 ; k < nelems ; k ++ ) { double val = getDouble ( k ) ; setDouble ( k , val / norm ) ; } }

Normalize this vector, so it has norm = 1.0.

Normalize this vector so it has norm = 1 . 0 .


private void setServices(Iterable<DatasetBuilder> dsIter) {
    for (DatasetBuilder dsb : dsIter) {
      for (Service s : dsb.getServices()) {
        addService(s);
      }
      setServices(dsb.getDatasets()); // recurse
    }
  }

private
void
setServices
(
Iterable
<
DatasetBuilder
>
dsIter
)
{
for
(
DatasetBuilder
dsb
:
dsIter
)
{
for
(
Service
s
:
dsb
.
getServices
(
)
)
{
addService
(
s
)
;
}
setServices
(
dsb
.
getDatasets
(
)
)
;
// recurse
}
}

pull services out of the datasets and into the catalog


public Grib1Parameter getParameter(int id) {
    if (parameters == null) {
      parameters = readParameterTable();
    }

    return parameters.get(id);
  }

public Grib1Parameter getParameter ( int id ) { if ( parameters == null ) { parameters = readParameterTable ( ) ; } return parameters . get ( id ) ; }

Get the parameter with id. If not found, look in default table.

@param id the parameter number
@return the Grib1Parameter, or null if not found

Get the parameter with id . If not found look in default table .


public Grib1Parameter getLocalParameter(int id) {
    if (parameters == null) {
      parameters = readParameterTable();
    }
    return parameters.get(id);
  }

public Grib1Parameter getLocalParameter ( int id ) { if ( parameters == null ) { parameters = readParameterTable ( ) ; } return parameters . get ( id ) ; }

Get the parameter with id, but dont look in default table.

@param id the parameter number
@return the Grib1Parameter, or null if not found

Get the parameter with id but dont look in default table .


public void addName(final String name, final double value)
			throws PrefixExistsException {
		final Prefix prefix = new PrefixName(name, value);
		nameSet.add(prefix);
	}

public void addName ( final String name , final double value ) throws PrefixExistsException { final Prefix prefix = new PrefixName ( name , value ) ; nameSet . add ( prefix ) ; }

Adds a prefix to the database by name.

@param name
The name of the prefix to be added.
@param value
The value of the prefix.
@throws PrefixExistsException
Another prefix with the same name or value already exists in
the database.


public void addSymbol(final String symbol, final double value)
			throws PrefixExistsException {
		final Prefix prefix = new PrefixSymbol(symbol, value);
		symbolSet.add(prefix);
		valueMap.put(new Double(value), prefix);
	}

public void addSymbol ( final String symbol , final double value ) throws PrefixExistsException { final Prefix prefix = new PrefixSymbol ( symbol , value ) ; symbolSet . add ( prefix ) ; valueMap . put ( new Double ( value ) , prefix ) ; }

Adds a prefix symbol to the database.

@param symbol
The symbol of the prefix to be added.
@param value
The value of the prefix.
@throws PrefixExistsException
Another prefix with the same symbol or value already exists
in the database.


private static Prefix getPrefix(final String string, final Set<Prefix> set) {
		for (final Iterator<Prefix> iter = set.iterator(); iter.hasNext();) {
			final Prefix prefix = iter.next();
			final int comp = prefix.compareTo(string);
			if (comp == 0) {
				return prefix;
			}
			if (comp > 0) {
				break;
			}
		}
		return null;
	}

private static Prefix getPrefix ( final String string , final Set < Prefix > set ) { for ( final Iterator < Prefix > iter = set . iterator ( ) ; iter . hasNext ( ) ; ) { final Prefix prefix = iter . next ( ) ; final int comp = prefix . compareTo ( string ) ; if ( comp == 0 ) { return prefix ; } if ( comp > 0 ) { break ; } } return null ; }

Returns the prefix from the given set with the given identifier.

@param string
The prefix identifier.
@param set
The set to search.

Returns the prefix from the given set with the given identifier .


protected boolean emailOK(ThreddsMetadata.Source p) {
    String email = p.getEmail();
    return email.indexOf('@') >= 0; // should really do a regexp
  }

protected
boolean
emailOK
(
ThreddsMetadata
.
Source
p
)
{
String
email
=
p
.
getEmail
(
)
;
return
email
.
indexOf
(
'
'
)
>=
0
;
// should really do a regexp
}


public double getParameter(String name) {
    Double val = (Double) parameters.get(name.toLowerCase());
    if (val == null) {
      throw new IllegalArgumentException("no parameter called " + name);
    }
    return val.doubleValue();
  }

public
double
getParameter
(
String
name
)
{
Double
val
=
(
Double
)
parameters
.
get
(
name
.
toLowerCase
(
)
)
;
if
(
val
==
)
{
throw
new
IllegalArgumentException
(
"no parameter called "
+
name
)
;
}
return
val
.
doubleValue
(
)
;
}

Get the value of the projection parameter. An IllegalArgument exception
is thrown if the parameter is not found.

@param name The name of the parameter. Case is ignored.
@return The value of the parameter, as a double.

Get the value of the projection parameter . An IllegalArgument exception is thrown if the parameter is not found .


public long calcCRC() {
    long crc;
    if (rawData == null)
      crc = predefinedGridDefinitionCenter << 16 + predefinedGridDefinition;
    else {
      CRC32 crc32 = new CRC32();
      crc32.update(rawData);
      crc = crc32.getValue();
    }
    return crc;
  }

public long calcCRC ( ) { long crc ; if ( rawData == null ) crc = predefinedGridDefinitionCenter << 16 + predefinedGridDefinition ; else { CRC32 crc32 = new CRC32 ( ) ; crc32 . update ( rawData ) ; crc = crc32 . getValue ( ) ; } return crc ; }

Calculate the CRC of the entire byte array

@return CRC  of the entire byte array


public final boolean isThin() {
    if (rawData == null) return false;
    int octet5 = getOctet(5);
    int nv = getOctet(4);
    return (octet5 != 255) && (nv == 0 || nv == 255);
  }

public final boolean isThin ( ) { if ( rawData == null ) return false ; int octet5 = getOctet ( 5 ) ; int nv = getOctet ( 4 ) ; return ( octet5 != 255 ) && ( nv == 0 || nv == 255 ) ; }

is a "thin" grid

@return if a thin grid


@Override
    public int fieldIndex(String name)
            throws DapException
    {
        DapStructure ds;
        if(getTemplate().getSort().isCompound())
            ds = (DapStructure) getTemplate();
        else if(getTemplate().getSort().isVar()
                && (((DapVariable) getTemplate()).getBaseType().getSort().isCompound()))
            ds = (DapStructure) ((DapVariable) getTemplate()).getBaseType();
        else
            throw new DapException("Attempt to get field name on non-compound object");
        int i = ds.indexByName(name);
        if(i < 0)
            throw new DapException("Unknown field name: " + name);
        return i;
    }


public static String getTimeTypeName(int timeRangeIndicator) {
    String timeRange;

    switch (timeRangeIndicator) {

      /* Forecast product valid for reference time + P1 (P1 > 0), or
        Uninitialized analysis product for reference time (P1 = 0), or
        Image product for reference time (P1 = 0) */
      case 0:
        timeRange = "Uninitialized analysis / image product / forecast product valid for RT + P1";
        break;

      // Initialized analysis product for reference time (P1 = 0)
      case 1:
        timeRange = "Initialized analysis product for reference time";
        break;

      // Product with a valid time ranging between reference time + P1 and reference time + P2
      case 2:
        timeRange = "product valid, interval = (RT + P1) to (RT + P2)";
        break;

      // Average (reference time + P1 to reference time + P2)
      case 3:
        timeRange = "Average, interval = (RT + P1) to (RT + P2)";
        break;

      /* Accumulation  (reference  time  +  P1  to  reference  time  +  P2)  product  considered  valid  at
        reference time + P2 */
      case 4:
        timeRange = "Accumulation, interval = (RT + P1) to (RT + P2)";
        break;

      /* Difference  (reference  time  +  P2  minus  reference  time  +  P1)  product  considered  valid  at
        reference time + P2 */
      case 5:
        timeRange = "Difference, interval = (RT + P2) - (RT + P1)";
        break;

      // Average (reference time - P1 to reference time - P2)
      case 6:
        timeRange = "Average, interval = (RT - P1) to (RT - P2)";
        break;

      // Average (reference time - P1 to reference time + P2)
      case 7:
        timeRange = "Average, interval = (RT - P1) to (RT + P2)";
        break;

      // P1 occupies octets 19 and 20; product valid at reference time + P1
      case 10:
        timeRange = "product valid at RT + P1";
        break;

      /* Climatological  mean  value:  multiple  year  averages  of  quantities  which  are  themselves
        means over some period of time (P2) less than a year. The reference time (R) indicates the
        date and time of the start of a period of time, given by R to R + P2, over which a mean is
        formed; N indicates the number of such period-means that are averaged together to form
        the  climatological  value,  assuming  that  the  N  period-mean  fields  are  separated  by  one
        year. The reference time indicates the start of the N-year climatology.

        If P1 = 0 then the data averaged in the basic interval P2 are assumed to be continuous, i.e. all available data
        are simply averaged together.

        If P1 = 1 (the unit of time  octet 18, Code table 4  is not
        relevant here) then the data averaged together in the basic interval P2 are valid only at the
        time (hour, minute) given in the reference time, for all the days included in the P2 period.
        The units of P2 are given by the contents of octet 18 and Code table 4 */
      case 51:
        timeRange = "Climatological mean values from RT to (RT + P2)";
        // if (p1 == 0) timeRange += " continuous";
        break;

      /* Average  of  N  forecasts  (or  initialized  analyses);  each  product  has  forecast  period  of  P1
        (P1 = 0 for initialized analyses); products have reference times at intervals of P2, beginning
        at the given reference time */
      case 113:
        timeRange = "Average of N forecasts, intervals = (refTime + i * P2, refTime + i * P2 + P1)";
        break;

      /* Accumulation of N forecasts (or initialized analyses); each product has forecast period of
        P1  (P1  =  0  for  initialized  analyses);  products  have  reference  times  at  intervals  of  P2,
        beginning at the given reference time */
      case 114:
        timeRange = "Accumulation of N forecasts, intervals = (refTime + i * P2, refTime + i * P2 + P1)";
        break;

      /* Average of N forecasts, all with the same reference time; the first has a forecast period of
         P1, the remaining forecasts follow at intervals of P2 */
      case 115:
        timeRange = "Average of N forecasts, intervals = (refTime, refTime + P1 + i * P2)";
        break;

      /* Accumulation  of  N  forecasts,  all  with  the  same  reference  time;  the  first  has  a  forecast
        period of P1, the remaining forecasts follow at intervals of P2 */
      case 116:
        timeRange = "Accumulation of N forecasts, intervals = (refTime, refTime + P1 + i * P2)";
        break;

      /* Average of N forecasts; the first has a forecast period of P1, the subsequent ones have
        forecast periods reduced from the previous one by an interval of P2; the reference time for
        the first is given in octets 13 to 17, the subsequent ones have reference times increased
        from the previous one by an interval of P2. Thus all the forecasts have the same valid time,
        given by the initial reference time + P1 */
      case 117:
        timeRange = "Average of N forecasts, intervals = (refTime + i * P2, refTime + P1)";
        break;

      /* Temporal  variance,  or  covariance,  of  N  initialized  analyses;  each  product  has  forecast
        period of P1 = 0; products have reference times at intervals of P2, beginning at the given
        reference time */
      case 118:
        timeRange = "Temporal variance or covariance of N initialized analyses, timeCoord = (refTime + i * P2)";
        break;

      /* Standard deviation of N forecasts, all with the same reference time with respect to the time
        average of forecasts; the first forecast has a forecast period of P1, the remaining forecasts
        follow at intervals of P2 */
      case 119:
        timeRange = "Standard Deviation of N forecasts, timeCoord = (refTime + P1 + i * P2)";
        break;

      // ECMWF "Average of N Forecast" added 11/21/2014. pretend its WMO standard. maybe should move to ecmwf ??
      // see "http://emoslib.sourcearchive.com/documentation/000370.dfsg.2/grchk1_8F-source.html"
      // C     Add Time range indicator = 120 Average of N Forecast. Each product
      // C             is an accumulation from forecast lenght P1 to forecast
      // C              lenght P2, with reference times at intervals P2-P1
      case 120:
        timeRange = "Average of N Forecasts (ECMWF), accumulation from forecast P1 to P2, with reference times at intervals P2-P1";
        break;

      // Average of N uninitialized analyses, starting at the reference time, at intervals of P2
      case 123:
        timeRange = "Average of N uninitialized analyses, intervals = (refTime, refTime + i * P2)";
        break;

      // Accumulation of N uninitialized analyses, starting at the reference time, at intervals of P2
      case 124:
        timeRange = "Accumulation of N uninitialized analyses, intervals = (refTime, refTime + i * P2)";
        break;

      /* Standard deviation of N forecasts, all with the same reference time with respect to time
        average of the time tendency of forecasts; the first forecast has a forecast period of P1,
        the remaining forecasts follow at intervals of P2 */
      case 125:
        timeRange = "Standard deviation of N forecasts, intervals = (refTime, refTime + P1 + i * P2)";
        break;

      default:
        timeRange = "Unknown Time Range Indicator " + timeRangeIndicator;
    }

    return timeRange;
  }

code table 5 - 2010 edition of WMO manual on codes


public String getTimeCoord() {
    if (isInterval()) {
      int[] intv = getInterval();
      return intv[0] + "-" + intv[1];
    }
    return Integer.toString(getForecastTime());
  }

public String getTimeCoord ( ) { if ( isInterval ( ) ) { int [ ] intv = getInterval ( ) ; return intv [ 0 ] + "-" + intv [ 1 ] ; } return Integer . toString ( getForecastTime ( ) ) ; }

A string representation of the time coordinate, whether its an interval or not.
@return string representation of the time coordinate

A string representation of the time coordinate whether its an interval or not .


public void setNext(Polygon next) {
		if(next instanceof CFPolygon) {
			setNext((CFPolygon) next);
		}

		else this.next = next;
	}

public void setNext ( Polygon next ) { if ( next instanceof CFPolygon ) { setNext ( ( CFPolygon ) next ) ; } else this . next = next ; }

Sets the next polygon which make up the multipolygon which this polygon is a part of.
If next is a CFPolygon, automatically connects the other polygon to this polygon as well.

Sets the next polygon which make up the multipolygon which this polygon is a part of . If next is a CFPolygon automatically connects the other polygon to this polygon as well .


public void setPrev(Polygon prev) {

		if(prev instanceof CFPolygon) {
			setPrev((CFPolygon) prev);
		}

		else this.prev = prev;
	}

public void setPrev ( Polygon prev ) { if ( prev instanceof CFPolygon ) { setPrev ( ( CFPolygon ) prev ) ; } else this . prev = prev ; }

Sets the previous polygon which makes up the multipolygon which this polygon is a part of.
If prev is a CFPolygon, automatically connect the other polygon to this polygon as well.

Sets the previous polygon which makes up the multipolygon which this polygon is a part of . If prev is a CFPolygon automatically connect the other polygon to this polygon as well .


public String findProperty(String name) {
    InvProperty result = null;
    for (InvProperty p : properties) {
      if (p.getName().equals(name))
        result = p;
    }
    return (result == null) ? null : result.getValue();
  }

public String findProperty ( String name ) { InvProperty result = null ; for ( InvProperty p : properties ) { if ( p . getName ( ) . equals ( name ) ) result = p ; } return ( result == null ) ? null : result . getValue ( ) ; }

Get named property.

@param name match this name
@return String value of Property or null if not exist.


public void setCurrentProjection(ProjectionImpl proj) {
    int row;
    if (0 <= (row = model.search(proj))) {
      if (debug) System.out.println(" PTsetCurrentProjection found = "+ row);
      selectedRow = row;
      setRowSelectionInterval(row, row);
    } else {
      if (debug) System.out.println(" PTsetCurrentProjection not found = "+ row);
      selectedRow = -1;
      clearSelection();
    }
  }

public
void
setCurrentProjection
(
ProjectionImpl
proj
)
{
int
row
;
if
(
0
<=
(
row
=
model
.
search
(
proj
)
)
)
{
if
(
debug
)
System
.
out
.
println
(
" PTsetCurrentProjection found = "
+
row
)
;
selectedRow
=
row
;
setRowSelectionInterval
(
row
,
row
)
;
}
else
{
if
(
debug
)
System
.
out
.
println
(
" PTsetCurrentProjection not found = "
+
row
)
;
selectedRow
=
1
;
clearSelection
(
)
;
}
}

set current projection if found, else deselect

set current projection if found else deselect


public Optional<TimeOffsetAxis> subsetFromTime(SubsetParams params, CalendarDate runDate) {
    CoordAxisHelper helper = new CoordAxisHelper(this);
    CoverageCoordAxisBuilder builder = null;
    if (params.isTrue(SubsetParams.timePresent)) {
      double offset = getOffsetInTimeUnits(runDate, CalendarDate.present());
      builder = helper.subsetClosest(offset);
    }

    CalendarDate dateWanted = (CalendarDate) params.get(SubsetParams.time);
    if (dateWanted != null) {                           // convertFrom, convertTo
      double offset = getOffsetInTimeUnits(runDate, dateWanted);
      builder =  helper.subsetClosest(offset);
    }

    Integer stride = (Integer) params.get(SubsetParams.timeStride);
    if (stride == null || stride < 0) stride = 1;

    CalendarDateRange dateRange = (CalendarDateRange) params.get(SubsetParams.timeRange);
    if (dateRange != null) {
      double min = getOffsetInTimeUnits(runDate, dateRange.getStart());
      double max = getOffsetInTimeUnits(runDate, dateRange.getEnd());
      Optional<CoverageCoordAxisBuilder> buildero =  helper.subset(min, max, stride);
      if (buildero.isPresent()) builder = buildero.get();
      else return Optional.empty(buildero.getErrorMessage());
    }

    assert (builder != null);

    // all the offsets are reletive to rundate
    builder.setReferenceDate(runDate);
    return Optional.of(new TimeOffsetAxis(builder));
  }

normal case already handled, this is the case where a time has been specified, and only one runtime

normal case already handled this is the case where a time has been specified and only one runtime


static public void registerIOProvider(String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
    Class ioClass = NetcdfFile.class.getClassLoader().loadClass(className);
    registerIOProvider(ioClass);
  }

static public void registerIOProvider ( String className ) throws IllegalAccessException , InstantiationException , ClassNotFoundException { Class ioClass = NetcdfFile . class . getClassLoader ( ) . loadClass ( className ) ; registerIOProvider ( ioClass ) ; }

Register an IOServiceProvider, using its class string name.

@param className Class that implements IOServiceProvider.
@throws IllegalAccessException if class is not accessible.
@throws InstantiationException if class doesnt have a no-arg constructor.
@throws ClassNotFoundException if class not found.

Register an IOServiceProvider using its class string name .


static public void registerIOProvider(Class iospClass, boolean last)
          throws IllegalAccessException, InstantiationException {
    IOServiceProvider spi;
    spi = (IOServiceProvider) iospClass.newInstance(); // fail fast
    if (userLoads && !last)
      registeredProviders.add(0, spi);  // put user stuff first
    else registeredProviders.add(spi);
  }

static
public
void
registerIOProvider
(
Class
iospClass
,
boolean
last
)
throws
IllegalAccessException
,
InstantiationException
{
IOServiceProvider
spi
;
spi
=
(
IOServiceProvider
)
iospClass
.
newInstance
(
)
;
// fail fast
if
(
userLoads
&&
!
last
)
registeredProviders
.
add
(
0
,
spi
)
;
// put user stuff first
else
registeredProviders
.
add
(
spi
)
;
}

Register an IOServiceProvider. A new instance will be created when one of its files is opened.

@param iospClass Class that implements IOServiceProvider.
@param last      true=>insert at the end of the list; otherwise front
@throws IllegalAccessException if class is not accessible.
@throws InstantiationException if class doesnt have a no-arg constructor.
@throws ClassCastException     if class doesnt implement IOServiceProvider interface.

Register an IOServiceProvider . A new instance will be created when one of its files is opened .


static public void registerIOProviderPreferred(Class iospClass, Class target)
           throws IllegalAccessException, InstantiationException
   {
     iospDeRegister(iospClass); // forcibly de-register
     int pos = -1;
     for(int i = 0; i < registeredProviders.size(); i++) {
       IOServiceProvider candidate = registeredProviders.get(i);
       if(candidate.getClass() == target) {
         if(pos < i)
           pos = i;
         break; // this is where is must be placed
       }
     }
     if(pos < 0) pos = 0;
     IOServiceProvider spi = (IOServiceProvider) iospClass.newInstance(); // fail fast
     registeredProviders.add(pos, spi);  // insert before target
   }

static
public
void
registerIOProviderPreferred
(
Class
iospClass
,
Class
target
)
throws
IllegalAccessException
,
InstantiationException
{
iospDeRegister
(
iospClass
)
;
// forcibly de-register
int
pos
=
1
;
for
(
int
i
=
0
;
i
<
registeredProviders
.
size
(
)
;
i
++
)
{
IOServiceProvider
candidate
=
registeredProviders
.
get
(
i
)
;
if
(
candidate
.
getClass
(
)
==
target
)
{
if
(
pos
<
i
)
pos
=
i
;
break
;
// this is where is must be placed
}
}
if
(
pos
<
0
)
pos
=
0
;
IOServiceProvider
spi
=
(
IOServiceProvider
)
iospClass
.
newInstance
(
)
;
// fail fast
registeredProviders
.
add
(
pos
,
spi
)
;
// insert before target
}

Register an IOServiceProvider. A new instance will be created when one of its files is opened.
This differs from the above in that it specifically locates the target iosp and inserts
the new one in front of it in order to override the target.
If the iospclass is already registered, remove it and reinsert.
If the target class is not present, then insert at front of the registry

@param iospClass Class that implements IOServiceProvider.
@param target Class to override
@throws IllegalAccessException if class is not accessible.
@throws InstantiationException if class doesnt have a no-arg constructor.
@throws ClassCastException     if class doesnt implement IOServiceProvider interface.

Register an IOServiceProvider . A new instance will be created when one of its files is opened . This differs from the above in that it specifically locates the target iosp and inserts the new one in front of it in order to override the target . If the iospclass is already registered remove it and reinsert . If the target class is not present then insert at front of the registry