Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
thredds.catalog.ThreddsMetadata Maven / Gradle / Ivy
Go to download
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package thredds.catalog;
import thredds.catalog.parser.jdom.InvCatalogFactory10;
import java.util.*;
import java.net.URI;
import java.io.IOException;
import ucar.nc2.constants.CDM;
import ucar.nc2.time.CalendarDateRange;
import ucar.unidata.geoloc.LatLonRect;
import ucar.unidata.geoloc.LatLonPointImpl;
import ucar.nc2.dataset.CoordinateAxis1D;
import ucar.nc2.units.SimpleUnit;
import ucar.nc2.units.DateRange;
import ucar.nc2.units.DateType;
import ucar.nc2.Attribute;
import ucar.nc2.constants.FeatureType;
import org.jdom2.output.XMLOutputter;
import org.jdom2.output.Format;
import org.jdom2.Element;
/**
* Metadata for "enhanced catalogs", type THREDDS.
*
* @author John Caron
*/
public class ThreddsMetadata {
protected boolean inherited;
protected List creators = new ArrayList();
protected List contributors = new ArrayList();
protected List dates = new ArrayList();
protected List docs = new ArrayList();
protected List keywords = new ArrayList(); //
protected List metadata = new ArrayList();
protected List projects = new ArrayList();
protected List properties = new ArrayList(); //
protected List publishers = new ArrayList(); //
protected List variables = new ArrayList(); //
protected String variableMapLink;
// singles
protected GeospatialCoverage gc;
protected DateRange timeCoverage;
//protected CalendarDateRange cdateCoverage;
protected String authorityName, serviceName;
protected FeatureType dataType;
protected DataFormatType dataFormat;
protected double dataSize = 0.0;
public ThreddsMetadata(boolean inherited) {
this.inherited = inherited;
}
/**
* Copy Constructor.
*
* @param from copy from here
*/
public ThreddsMetadata(ThreddsMetadata from) {
this.inherited = from.inherited;
add(from, true);
}
/**
* Add all the content from another ThreddsMetadata
*
* @param tmd get content from here
* @param includeInherited if false, dont add inherited InvMetadata
*/
public void add(ThreddsMetadata tmd, boolean includeInherited) {
creators.addAll(tmd.getCreators());
contributors.addAll(tmd.getContributors());
dates.addAll(tmd.getDates());
docs.addAll(tmd.getDocumentation());
keywords.addAll(tmd.getKeywords());
projects.addAll(tmd.getProjects());
properties.addAll(tmd.getProperties());
publishers.addAll(tmd.getPublishers());
variables.addAll(tmd.getVariables());
if (includeInherited)
metadata.addAll(tmd.getMetadata());
else {
for (InvMetadata mdata : tmd.getMetadata() ) {
if (!mdata.isInherited())
metadata.add(mdata);
}
}
// LOOK! should be copies ??!!
if (gc == null) gc = tmd.getGeospatialCoverage();
if (timeCoverage == null) timeCoverage = tmd.getTimeCoverage();
if (serviceName == null) serviceName = tmd.getServiceName();
if (dataType == null) dataType = tmd.getDataType();
if (dataSize == 0.0) dataSize = tmd.getDataSize();
if (dataFormat == null) dataFormat = tmd.getDataFormatType();
if (authorityName == null) authorityName = tmd.getAuthority();
if (variableMapLink == null) variableMapLink = tmd.getVariableMap();
}
/**
* Add a creator
* @param c add this
*/
public void addCreator(Source c) {
if (c != null) creators.add(c);
}
/**
* @return list of creators (type Source); may be empty, not null.
*/
public List getCreators() {
return creators;
}
/**
* Set list of creators (type Source); may be empty, not null.
* @param creators set creators to this list
*/
public void setCreators(List creators) {
this.creators = creators;
}
/**
* Add a contributor
* @param c add this
*/
public void addContributor(Contributor c) {
if (c != null) contributors.add(c);
}
/**
* @return list of contributors (type Contributor); may be empty, not null.
*/
public List getContributors() {
return contributors;
}
/**
* Set list of contributors (type Contributor); may be empty, not null.
* @param contributors set contributers to this
*/
public void setContributors(List contributors) {
this.contributors = contributors;
}
/**
* Add a date
* @param d add this dateType
*/
public void addDate(DateType d) {
if (d != null) dates.add(d);
}
/**
* @return list of DateType; may be empty, not null.
*/
public List getDates() {
return dates;
}
/**
* Add a documentation
* @param d add this
*/
public void addDocumentation(InvDocumentation d) {
if (d != null) docs.add(d);
}
/**
* @return list of InvDocumentation; may be empty, not null.
*/
public List getDocumentation() {
return docs;
}
/**
* Add a keyword
* @param keyword add this
*/
public void addKeyword(Vocab keyword) {
if (keyword != null) keywords.add(keyword);
}
/**
* @return list of contributors; may be empty, not null.
*/
public List getKeywords() {
return keywords;
}
/**
* Set list of contributors; may be empty, not null.
* @param keywords set list of keywords to this
*/
public void setKeywords(List keywords) {
this.keywords = keywords;
}
/**
* Add InvMetadata
* @param m add this
*/
public void addMetadata(InvMetadata m) {
if (m != null) metadata.add(m);
}
/**
* remove an InvMetadata element from list, using equals() to locate it.
* @param m remove this
*/
public void removeMetadata(InvMetadata m) {
metadata.remove(m);
}
/**
* @return list of InvMetadata; may be empty, not null.
*/
public List getMetadata() {
return metadata;
}
/**
* Add a project
* @param project add this
*/
public void addProject(Vocab project) {
if (project != null) projects.add(project);
}
/**
* @return list of projects (type Vocab); may be empty, not null.
*/
public List getProjects() {
return projects;
}
/**
* Set list of projects (type Vocab); may be empty, not null.
* @param projects set list of projects to this
*/
public void setProjects(List projects) {
this.projects = projects;
}
/**
* Add a property
* @param p add this
*/
public void addProperty(InvProperty p) {
if (p != null) properties.add(p);
}
/**
* @return list of properties; may be empty, not null.
*/
public List getProperties() {
return properties;
}
/**
* Add a publisher
* @param p add this
*/
public void addPublisher(Source p) {
if (p != null) publishers.add(p);
}
/**
* @return list of publishers (type Source); may be empty, not null.
*/
public List getPublishers() {
return publishers;
}
/**
* Set list of publishers (type Source); may be empty, not null.
* @param publishers set list of publishers to this
*/
public void setPublishers(List publishers) {
this.publishers = publishers;
}
/**
* Add variables
* @param vs add this
*/
public void addVariables(Variables vs) {
if (vs != null) variables.add(vs);
}
/**
* @return list of Variables; may be empty, not null.
*/
public List getVariables() {
return variables;
}
/**
* Add a variable Map link
* @param xlinkHref : URI of xlink
* */
public void addVariableMapLink(String xlinkHref) {
variableMapLink = xlinkHref;
}
public String getVariableMap() {
return variableMapLink;
}
/**
* set GeospatialCoverage element
* @param gc set GeospatialCoverage to this
*/
public void setGeospatialCoverage(GeospatialCoverage gc) {
this.gc = gc;
}
/**
* @return GeospatialCoverage element
*/
public GeospatialCoverage getGeospatialCoverage() {
return gc;
}
/**
* set TimeCoverage element
* @param tc set TimeCoverage to this
*/
public void setTimeCoverage(DateRange tc) {
this.timeCoverage = tc;
}
/**
* set TimeCoverage from a CalendarDateRange
* @param cdc set CalendarDateRange to this
*/
public void setTimeCoverage(CalendarDateRange cdc) {
this.timeCoverage = cdc.toDateRange();
}
/**
* @return TimeCoverage element as DateRange
*/
public DateRange getTimeCoverage() {
return timeCoverage;
}
/**
* @return TimeCoverage element as CalendarDateRange
*/
public CalendarDateRange getCalendarDateCoverage() {
return timeCoverage == null ? null : CalendarDateRange.of(timeCoverage);
}
/**
* @return true if this is inherited
*/
public boolean isInherited() {
return inherited;
}
/**
* Set inherited
* @param inherited set true if inherited
*/
public void setInherited(boolean inherited) {
this.inherited = inherited;
}
/**
* @return serviceName
*/
public String getServiceName() {
return serviceName;
}
/**
* Set serviceName
* @param serviceName set service name to this, must be valid service
*/
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
/**
* @return dataType
*/
public FeatureType getDataType() {
return dataType;
}
/**
* Set dataType
* @param dataType set to this dataType
*/
public void setDataType(FeatureType dataType) {
this.dataType = dataType;
}
/**
* @return dataType
*/
public DataFormatType getDataFormatType() {
return dataFormat;
}
/**
* Set dataTypeFormat
* @param dataFormat set to this dataTypeFormat
*/
public void setDataFormatType(DataFormatType dataFormat) {
this.dataFormat = dataFormat;
}
/**
* @return authority
*/
public String getAuthority() {
return authorityName;
}
/**
* Set authority
* @param authorityName set to this
*/
public void setAuthority(String authorityName) {
this.authorityName = authorityName;
}
/**
* @return specific type of documentation
* @param type match on doc.getType()
*/
public String getDocumentation(String type) {
for (InvDocumentation doc : getDocumentation()) {
String dtype = doc.getType();
if ((dtype != null) && dtype.equalsIgnoreCase(type)) return doc.getInlineContent();
}
return null;
}
/* @return Documentation that are xlinks
public List getDocumentationLinks() {
List result = new ArrayList();
for (InvDocumentation doc : getDocumentation()) {
if (doc.hasXlink())
result.add(doc);
}
return result;
}
/* set the list of Documentation that are xlinks
public void setDocumentationLinks(List newdocs) {
ArrayList result = new ArrayList(newdocs);
java.util.List olddocs = getDocumentation();
for (int i=0; i 0)
addDocumentation(new InvDocumentation(null, null, null, type, content));
}
/**
* remove all instances of specified type of documentation
* @param type type of documentation
*/
public void removeDocumentation(String type) {
Iterator iter = docs.iterator();
while (iter.hasNext()) {
InvDocumentation doc = (InvDocumentation) iter.next();
String dtype = doc.getType();
if ((dtype != null) && dtype.equalsIgnoreCase(type))
iter.remove();
}
}
String dump(int n) {
StringBuilder buff = new StringBuilder(100);
if (docs.size() > 0) {
String indent = InvDatasetImpl.indent(n + 2);
buff.append(indent);
buff.append("Docs:\n");
for (InvDocumentation doc : docs) {
buff.append(InvDatasetImpl.indent(n + 4)).append(doc).append("\n");
}
}
if (metadata.size() > 0) {
String indent = InvDatasetImpl.indent(n + 2);
buff.append(indent);
buff.append("Metadata:\n");
for (InvMetadata m : metadata) {
buff.append(InvDatasetImpl.indent(n + 4)).append(m).append("\n");
}
}
if (properties.size() > 0) {
String indent = InvDatasetImpl.indent(n + 2);
buff.append(indent);
buff.append("Properties:\n");
for (InvProperty p : properties) {
buff.append(InvDatasetImpl.indent(n + 4)).append(p).append("\n");
}
}
return buff.toString();
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ThreddsMetadata)) return false;
return o.hashCode() == this.hashCode();
}
// Generated by IntelliJ (with a few minor changes).
public int hashCode() {
if (hashCode == 0) {
int result = 17;
long temp;
result = 37 * result + (inherited ? 1 : 0);
result = 29 * result + (creators != null ? creators.hashCode() : 0);
result = 29 * result + (contributors != null ? contributors.hashCode() : 0);
result = 29 * result + (dates != null ? dates.hashCode() : 0);
result = 29 * result + (docs != null ? docs.hashCode() : 0);
result = 29 * result + (keywords != null ? keywords.hashCode() : 0);
result = 29 * result + (metadata != null ? metadata.hashCode() : 0);
result = 29 * result + (projects != null ? projects.hashCode() : 0);
result = 29 * result + (properties != null ? properties.hashCode() : 0);
result = 29 * result + (publishers != null ? publishers.hashCode() : 0);
result = 29 * result + (variables != null ? variables.hashCode() : 0);
result = 29 * result + (gc != null ? gc.hashCode() : 0);
result = 29 * result + (timeCoverage != null ? timeCoverage.hashCode() : 0);
result = 29 * result + (authorityName != null ? authorityName.hashCode() : 0);
result = 29 * result + (serviceName != null ? serviceName.hashCode() : 0);
result = 29 * result + (dataType != null ? dataType.hashCode() : 0);
result = 29 * result + (dataFormat != null ? dataFormat.hashCode() : 0);
temp = dataSize != +0.0d ? Double.doubleToLongBits(dataSize) : 0l;
result = 29 * result + (int) (temp ^ (temp >>> 32));
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8 - lazily initialize hash value
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Implements Contributor type.
*/
static public class Contributor {
private String name;
private String role;
public Contributor() {
}
public Contributor(String name, String role) {
this.name = name;
this.role = role;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
hashCode = 0;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
hashCode = 0;
}
// for bean editing
static public String editableProperties() {
return "role name";
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Contributor)) return false;
return o.hashCode() == this.hashCode();
}
/**
* Override Object.hashCode() to implement equals.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
// result = 37*result + dataset.getName().hashCode();
result = 37 * result + getName().hashCode();
if (null != getRole())
result = 37 * result + getRole().hashCode();
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
}
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Implements Source type, used by publisher and creator elements.
*/
static public class Source {
private Vocab name, long_name;
private String url, email;
// need no-arg constructor for bean handling
public Source() {
this.name = new Vocab();
this.long_name = new Vocab();
}
public Source(Vocab name, String url, String email) {
this.name = name;
this.url = url;
this.email = email;
}
public Vocab getNameVocab() {
return this.name;
}
/**
* @return name
*/
public String getName() {
return this.name.getText();
}
/**
* Set name
* @param name to set
*/
public void setName(String name) {
this.name.setText(name);
hashCode = 0;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
hashCode = 0;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
hashCode = 0;
}
public String getVocabulary() {
return this.name.getVocabulary();
}
public void setVocabulary(String vocabulary) {
this.name.setVocabulary(vocabulary);
this.long_name.setVocabulary(vocabulary);
hashCode = 0;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Source)) return false;
return o.hashCode() == this.hashCode();
}
/**
* Override Object.hashCode() to implement equals.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
// result = 37*result + dataset.getName().hashCode();
result = 37 * result + getName().hashCode();
if (null != getVocabulary())
result = 37 * result + getVocabulary().hashCode();
if (null != getUrl())
result = 37 * result + getUrl().hashCode();
if (null != getEmail())
result = 37 * result + getEmail().hashCode();
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
// for bean editing
static public String hiddenProperties() {
return "nameVocab";
}
static public String editableProperties() {
return "name email url vocabulary";
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Implements Vocab type, just text with an optional "vocabulary" attribute.
*/
static public class Vocab {
private String text;
private String vocabulary;
// need no-arg constructor for bean handling
public Vocab() {
}
public Vocab(String text, String vocabulary) {
this.text = text;
this.vocabulary = vocabulary;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
hashCode = 0;
}
public String getVocabulary() {
return vocabulary;
}
public void setVocabulary(String vocabulary) {
this.vocabulary = vocabulary;
hashCode = 0;
}
// for bean editing
static public String editableProperties() {
return "text vocabulary";
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Vocab)) return false;
return o.hashCode() == this.hashCode();
}
/**
* Override Object.hashCode() to implement equals.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
// result = 37*result + dataset.getName().hashCode();
if (null != getText())
result = 37 * result + getText().hashCode();
if (null != getVocabulary())
result = 37 * result + getVocabulary().hashCode();
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
}
/* static private java.text.SimpleDateFormat dateFormat;
static {
dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
} */
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Implements GeospatialCoverage type.
*/
static public class GeospatialCoverage {
static private Range defaultEastwest = new Range(0.0, 0.0, Double.NaN, CDM.LON_UNITS);
static private Range defaultNorthsouth = new Range(0.0, 0.0, Double.NaN, CDM.LAT_UNITS);
static private Range defaultUpdown = new Range(0.0, 0.0, Double.NaN, "km");
static private GeospatialCoverage empty = new GeospatialCoverage();
private Range eastwest, northsouth, updown;
private boolean isGlobal = false;
private String zpositive = "up";
private List names = new ArrayList(); // Vocab
// need no-arg constructor for bean handling
public GeospatialCoverage() {
}
public GeospatialCoverage(Range eastwest, Range northsouth, Range updown, List names, String zpositive) {
this.eastwest = eastwest; // : new Range(defaultEastwest);
this.northsouth = northsouth; // : new Range(defaultNorthsouth);
this.updown = updown; // : new Range(defaultUpdown);
if (names != null) this.names = new ArrayList(names);
if (zpositive != null) this.zpositive = zpositive;
if (names != null) {
for (Vocab name : names) {
String elem = name.getText();
if (elem.equalsIgnoreCase("global")) isGlobal = true;
}
}
}
public void extend(GeospatialCoverage gc) {
this.eastwest.extend(gc.getEastWestRange());
this.northsouth.extend(gc.getNorthSouthRange());
}
public boolean isEmpty() {
return this.equals(empty);
}
public Range getEastWestRange() {
return eastwest;
}
public Range getNorthSouthRange() {
return northsouth;
}
public Range getUpDownRange() {
return updown;
}
public List getNames() {
return names;
}
/**
* @return "up" or "down"
*/
public String getZPositive() {
return zpositive;
}
public void setZPositive(String positive) {
this.zpositive = positive;
hashCode = 0;
}
/**
* @return true or false
*/
public boolean getZPositiveUp() {
return zpositive.equalsIgnoreCase("up");
}
public void setZPositiveUp(boolean positive) {
this.zpositive = positive ? "up" : "down";
hashCode = 0;
}
public boolean isValid() {
return isGlobal || ((eastwest != null) && (northsouth != null));
}
/**
* @return true if coverage is Global
*/
public boolean isGlobal() {
return isGlobal;
}
/**
* Set isGlobal
* @param isGlobal true if global coverage
*/
public void setGlobal(boolean isGlobal) {
this.isGlobal = isGlobal;
hashCode = 0;
}
/**
* @return starting latitude, or Double.NaN if not valie
*/
public double getLatStart() {
return (northsouth == null) ? Double.NaN : northsouth.start;
}
/**
* Set starting latitude
* @param start starting latitude, decimal degrees north
*/
public void setLatStart(double start) {
if (northsouth == null)
northsouth = new Range(defaultNorthsouth);
northsouth.start = start;
hashCode = 0;
}
/**
* @return latitude extent - may be positive or negetive
*/
public double getLatExtent() {
return (northsouth == null) ? Double.NaN : northsouth.size;
}
/**
* Set latitude extent
* @param size latitude extent, decimal degrees north
*/
public void setLatExtent(double size) {
if (northsouth == null)
northsouth = new Range(defaultNorthsouth);
northsouth.size = size;
hashCode = 0;
}
/**
* @return latitude resolution: 0.0 or NaN means not set.
*/
public double getLatResolution() {
return (northsouth == null) ? Double.NaN : northsouth.resolution;
}
/**
* Set latitude resolution
* @param resolution latitude resolution, decimal degrees north
*/
public void setLatResolution(double resolution) {
if (northsouth == null)
northsouth = new Range(defaultNorthsouth);
northsouth.resolution = resolution;
hashCode = 0;
}
/**
* @return latitude units
*/
public String getLatUnits() {
return (northsouth == null) ? null : northsouth.units;
}
/**
* Set latitude units
* @param units set units
*/
public void setLatUnits(String units) {
if (northsouth == null)
northsouth = new Range(defaultNorthsouth);
northsouth.units = units;
hashCode = 0;
}
// LOOK not dealing with units degrees_south
public double getLatNorth() {
return Math.max(northsouth.start, northsouth.start + northsouth.size);
}
public double getLatSouth() {
return Math.min(northsouth.start, northsouth.start + northsouth.size);
}
/**
* @return starting longitude
*/
public double getLonStart() {
return (eastwest == null) ? Double.NaN : eastwest.start;
}
/**
* Set starting longitude
* @param start starting longitude
*/
public void setLonStart(double start) {
if (eastwest == null)
eastwest = new Range(defaultEastwest);
eastwest.start = start;
hashCode = 0;
}
/**
* @return longitude extent - may be positive or negetive
*/
public double getLonExtent() {
return (eastwest == null) ? Double.NaN : eastwest.size;
}
/**
* Set longitude extent
* @param size longitude extent
*/
public void setLonExtent(double size) {
if (eastwest == null)
eastwest = new Range(defaultEastwest);
eastwest.size = size;
hashCode = 0;
}
/**
* @return longitude resolution: 0.0 or NaN means not set.
*/
public double getLonResolution() {
return (eastwest == null) ? Double.NaN : eastwest.resolution;
}
/**
* Set longitude resolution
* @param resolution longitude resolution
*/
public void setLonResolution(double resolution) {
if (eastwest == null)
eastwest = new Range(defaultEastwest);
eastwest.resolution = resolution;
hashCode = 0;
}
/**
* @return longitude units
*/
public String getLonUnits() {
return (eastwest == null) ? null : eastwest.units;
}
/**
* Set longitude units
* @param units longitude units
*/
public void setLonUnits(String units) {
if (eastwest == null)
eastwest = new Range(defaultEastwest);
eastwest.units = units;
hashCode = 0;
}
// LOOK not dealing with units degrees_west
public double getLonEast() {
if (eastwest == null) return Double.NaN;
return Math.max(eastwest.start, eastwest.start + eastwest.size);
}
public double getLonWest() {
if (eastwest == null) return Double.NaN;
return Math.min(eastwest.start, eastwest.start + eastwest.size);
}
/**
* @return starting height
*/
public double getHeightStart() {
return updown == null ? 0.0 : updown.start;
}
/**
* Set starting height
* @param start starting height
*/
public void setHeightStart(double start) {
if (updown == null)
updown = new Range(defaultUpdown);
updown.start = start;
hashCode = 0;
}
/**
* @return height extent - may be positive or negetive
*/
public double getHeightExtent() {
return updown == null ? 0.0 : updown.size;
}
/**
* Set height extent
* @param size height extent
*/
public void setHeightExtent(double size) {
if (updown == null)
updown = new Range(defaultUpdown);
updown.size = size;
hashCode = 0;
}
/**
* @return height resolution: 0.0 or NaN means not set.
*/
public double getHeightResolution() {
return updown == null ? 0.0 : updown.resolution;
}
/**
* Set height resolution
* @param resolution height resolution
*/
public void setHeightResolution(double resolution) {
if (updown == null)
updown = new Range(defaultUpdown);
updown.resolution = resolution;
hashCode = 0;
}
/**
* @return height units
*/
public String getHeightUnits() {
return updown == null ? null : updown.units;
}
/**
* Set height units
* @param units height units
*/
public void setHeightUnits(String units) {
if (updown == null)
updown = new Range(defaultUpdown);
updown.units = units;
hashCode = 0;
}
public LatLonRect getBoundingBox() {
return isGlobal ? new LatLonRect() :
new LatLonRect(new LatLonPointImpl(getLatStart(), getLonStart()), getLatExtent(), getLonExtent());
}
public void setBoundingBox(LatLonRect bb) {
LatLonPointImpl llpt = bb.getLowerLeftPoint();
LatLonPointImpl urpt = bb.getUpperRightPoint();
double height = urpt.getLatitude() - llpt.getLatitude();
this.eastwest = new Range(llpt.getLongitude(), bb.getWidth(), 0.0, CDM.LON_UNITS);
this.northsouth = new Range(llpt.getLatitude(), height, 0.0, CDM.LAT_UNITS);
if ((bb.getWidth() > 358) && (height > 178))
setGlobal(true); // LOOK ??
}
public void setVertical(CoordinateAxis1D vaxis) {
int n = (int) vaxis.getSize();
double size = vaxis.getCoordValue(n - 1) - vaxis.getCoordValue(0);
double resolution = vaxis.getIncrement();
String units = vaxis.getUnitsString();
this.updown = new Range(vaxis.getCoordValue(0), size, resolution, units);
if (units != null) {
setZPositiveUp(SimpleUnit.isCompatible("m", units));
}
}
public void setVertical(double start, double end, double resolution, String units, boolean isPositiveUp) {
double size = end - start;
this.updown = new Range(start, size, resolution, units);
setZPositiveUp(isPositiveUp);
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GeospatialCoverage)) return false;
return o.hashCode() == this.hashCode();
}
/**
* Override Object.hashCode() to implement equals.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
if (null != getEastWestRange())
result = 37 * result + getEastWestRange().hashCode();
if (null != getNorthSouthRange())
result = 37 * result + getNorthSouthRange().hashCode();
if (null != getUpDownRange())
result = 37 * result + getUpDownRange().hashCode();
if (null != getNames())
result = 37 * result + getNames().hashCode();
if (null != getZPositive())
result = 2 * result + getZPositive().hashCode();
result = 2 * result + (isGlobal() ? 1 : 0);
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
public void toXML(java.io.OutputStream out) throws IOException {
// hack, hack
InvCatalogFactory10 converter = new InvCatalogFactory10();
Element elem = converter.writeGeospatialCoverage(this);
//XMLOutputter outputter = new XMLOutputter(" ", true);
XMLOutputter fmt = new XMLOutputter(Format.getPrettyFormat());
fmt.output(elem, out);
}
}
/**
* Implements spatialRange type.
*/
static public class Range {
private double start, size, resolution;
private String units;
/**
* Constructor
*
* @param start starting value
* @param size ending = start + size
* @param resolution data resolution, or NaN if unknown
* @param units what units are start, size in?
*/
public Range(double start, double size, double resolution, String units) {
this.start = start;
this.size = size;
this.resolution = resolution;
this.units = units;
}
/**
* Copy constructor
* @param from copy this
*/
public Range(Range from) {
this.start = from.start;
this.size = from.size;
this.resolution = from.resolution;
this.units = from.units;
}
public double getStart() {
return start;
}
public double getSize() {
return size;
}
public double getResolution() {
return resolution;
}
public String getUnits() {
return units;
}
public boolean hasResolution() {
return (resolution != 0.0) && !Double.isNaN(resolution);
}
public void extend(Range r) {
double stop = Math.max(this.start+this.size, r.start+r.size);
this.start = Math.min(this.start, r.start);
this.size = this.start - stop;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Range)) return false;
return o.hashCode() == this.hashCode();
}
/**
* Override Object.hashCode() to implement equals.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
if (null != getUnits())
result = 37 * result + getUnits().hashCode();
result = 37 * result + (int) (getStart() * 1000.0);
result = 37 * result + (int) (getSize() * 1000.0);
if (hasResolution())
result = 37 * result + (int) (getResolution() * 1000.0);
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
}
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Implements TimeCoverage type.
*
static public class TimeCoverage {
static private TimeCoverage empty = new TimeCoverage();
private DateType start, end;
private TimeDuration duration, resolution;
private double durationSecs;
boolean hasStart, hasEnd, hasDuration, invalid;
private DateType _start, _end;
// need no-arg constructor for bean handling
public TimeCoverage() {
}
public TimeCoverage(DateType start, DateType end, TimeDuration duration, TimeDuration resolution) {
this.start = start;
this.end = end;
this.duration = duration;
this.resolution = resolution;
recalc();
}
private void recalc() {
hasStart = (start != null) && !start.isBlank();
hasEnd = (end != null) && !end.isBlank();
hasDuration = (duration != null) && !duration.isBlank();
invalid = true;
if (hasStart && hasEnd) {
invalid = false;
} else if (hasStart && hasDuration) {
invalid = false;
_end = start.add( duration);
} else if (hasEnd && hasDuration) {
invalid = false;
_start = end.subtract( duration);
}
hashCode = 0;
}
public boolean isEmpty() { return this.equals( empty); }
public boolean included( Date d) {
if (invalid) return false;
if (hasStart && hasEnd) {
if (start.after( d)) return false;
if (end.before( d)) return false;
} else if (hasStart && hasDuration) {
if (start.after( d)) return false;
if (_end.before( d)) return false;
} else if (hasEnd && hasDuration) {
if (_start.after( d)) return false;
if (end.before( d)) return false;
}
return true;
}
public DateType getStart() { return start; }
public void setStart(DateType start) {
this.start = start;
recalc();
}
public DateType getEnd() { return end; }
public void setEnd(DateType end) {
this.end = end;
recalc();
}
public TimeDuration getDuration() { return duration; }
public void setDuration(TimeDuration duration) {
this.duration = duration;
recalc();
}
public TimeDuration getResolution() { return resolution; }
public void setResolution(TimeDuration resolution) {
this.resolution = resolution;
recalc();
}
public String toString() { return "start= "+start +" end= "+end+ " duration= "+ duration
+ " resolution= "+ resolution; }
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TimeCoverage)) return false;
return o.hashCode() == this.hashCode();
}
public int hashCode() {
if (hashCode == 0) {
int result = 17;
if (hasStart && !start.isBlank())
result = 37*result + start.hashCode();
if (hasEnd && !end.isBlank())
result = 37*result + end.hashCode();
if (hasDuration && !duration.isBlank())
result = 37*result + duration.hashCode();
if (resolution != null && !resolution.isBlank())
result = 37*result + resolution.hashCode();
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
} */
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Implements Variable type.
*/
static public class Variable implements Comparable {
private String name, desc, vocabulary_name, units, id;
// no-arg constructor for beans
public Variable() {
this.name = "";
this.desc = "";
this.vocabulary_name = "";
this.units = "";
this.id = "";
}
public Variable(String name, String desc, String vocabulary_name, String units, String id) {
this.name = name;
this.desc = desc;
this.vocabulary_name = vocabulary_name;
this.units = units;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return desc;
}
public void setDescription(String desc) {
this.desc = desc;
}
public String getVocabularyName() {
return vocabulary_name;
}
public void setVocabularyName(String vocabulary_name) {
this.vocabulary_name = vocabulary_name;
}
// need unique id, cant count on name, eg because of variant GRIB tables
public String getVocabularyId() {
return id;
}
public void setVocabularyId(String id) {
this.id = id;
}
public void setVocabularyId(Attribute id) {
if (id == null) return;
StringBuilder sbuff = new StringBuilder();
for (int i = 0; i < id.getLength(); i++) {
if (i > 0) sbuff.append(",");
sbuff.append(id.getNumericValue(i));
}
this.id = sbuff.toString();
}
public String getUnits() {
return units;
}
public void setUnits(String units) {
this.units = units;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Variable)) return false;
return o.hashCode() == this.hashCode();
}
public int hashCode() {
if (hashCode == 0) {
int result = 17;
if (null != getName())
result = 37 * result + getName().hashCode();
if (null != getDescription())
result = 37 * result + getDescription().hashCode();
if (null != getVocabularyName())
result = 37 * result + getVocabularyName().hashCode();
if (null != getUnits())
result = 37 * result + getUnits().hashCode();
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
public String toString()
{
return "Variable [" + name + "]";
}
public int compareTo(Object o) {
Variable ov = (Variable) o;
return name.compareTo(ov.name);
}
// for bean editing
static public String hiddenProperties() {
return "nameVocab";
}
static public String editableProperties() {
return "name description units vocabularyName";
}
}
/**
* Implements Variables type.
*/
static public class Variables {
private String vocabulary, vocabHref, mapHref;
private URI vocabUri, mapUri;
private List variables = new ArrayList();
public Variables(String vocab) {
this.vocabulary = vocab;
}
public Variables(String vocab, String vocabHref, URI vocabUri, String mapHref, URI mapUri) {
this.vocabulary = vocab;
this.vocabHref = vocabHref;
this.vocabUri = vocabUri;
this.mapHref = mapHref;
this.mapUri = mapUri;
}
public String getVocabulary() {
return vocabulary;
}
public String getVocabHref() {
return vocabHref;
}
public URI getVocabUri() {
return vocabUri;
}
public URI getMapUri() {
return mapUri;
}
public String getMapHref() {
return mapHref;
}
public void addVariable(Variable v) {
variables.add(v);
}
public List getVariableList() {
init();
return variables;
}
public void sort() {
Collections.sort(variables);
}
private boolean isInit = false;
private void init() {
if (isInit || (mapUri != null)) return;
isInit = true;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Variables)) return false;
return o.hashCode() == this.hashCode();
}
/**
* Override Object.hashCode() to implement equals.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
if (null != getVocabulary())
result = 37 * result + getVocabulary().hashCode();
if (null != getVocabUri())
result = 37 * result + getVocabUri().hashCode();
if (null != getMapUri())
result = 37 * result + getMapUri().hashCode();
if (null != getVariableList())
result = 37 * result + getVariableList().hashCode();
hashCode = result;
}
return hashCode;
}
private volatile int hashCode = 0; // Bloch, item 8
public String toString()
{
StringBuilder sb = new StringBuilder( "Variables" );
sb.append( " [" )
.append( getVocabulary() != null ? getVocabulary() : "" )
.append( "]" );
if ( mapUri != null )
sb.append( "map [").append( mapUri.toString()).append("]");
else
for ( Variable v : variables )
sb.append( " " ).append( v.toString() );
return sb.toString();
}
}
/**
* Factory for metadata of type THREDDS.
*
static public class Parser implements thredds.catalog.MetadataConverterIF {
private DOMBuilder builder = new DOMBuilder();
/**
* Read metadata from an XLink href, and convert to Java object representing
* the metadata.
* @param dataset : InvDataset that this metadata refers to.
* @param urlString : the location of the metadata: this must be an XML document whose
* root Element contains the proper metadata.
* @return ThreddsMetadata object
*
public Object readMetadataContentFromURL(InvDataset dataset, String urlString) throws java.net.MalformedURLException, java.io.IOException {
Document doc;
try {
SAXBuilder builder = new SAXBuilder(true);
doc = builder.build(urlString);
}
catch (JDOMException e) {
System.out.println("ThreddsMetadataFactory parsing error= \n" + e.getMessage());
throw new IOException("ThreddsMetadataFactory parsing error= " + e.getMessage());
}
if (showParsedXML) {
XMLOutputter xmlOut = new XMLOutputter();
System.out.println("*** catalog/showParsedXML = \n" + xmlOut.outputString(doc) + "\n*******");
}
return readMetadataContent(dataset, doc.getRootElement());
}
/**
* Read metadata from a org.w3c.dom.Element, and convert to Java object representing
* the metadata.
* @param dataset : InvDataset that this metadata refers to.
* @param domElement : the DOM Element containing metadata info.
* @return ThreddsMetadata object
*
public Object readMetadataContent(InvDataset dataset, org.w3c.dom.Element domElement) {
// convert to JDOM element
Element mdataElement = builder.build(domElement);
return readMetadataContent(dataset, mdataElement);
}
/**
* Read metadata from a org.w3c.dom.Element, and convert to Java object representing
* the metadata.
* @param dataset : InvDataset that this metadata refers to.
* @param mdataElement : the JDOM Element containing aggregation children.
* @return List of objects of type Aggregation
*
public Object readMetadataContent(InvDataset dataset, Element mdataElement) {
ThreddsMetadata tm = new ThreddsMetadata();
boolean ok = true;
Element spatialElem = mdataElement.getChild("spatialExtent", defNS);
if (null == spatialElem) {
tm.err.append("** Warning: THREDDS Metadata record has no SpatialExtent element\n");
}
else if (null != spatialElem.getAttributeValue("isGlobal"))
tm.isGlobal = true;
else {
String minLat = spatialElem.getChildText("minLat", defNS);
String minLon = spatialElem.getChildText("minLon", defNS);
String maxLat = spatialElem.getChildText("maxLat", defNS);
String maxLon = spatialElem.getChildText("maxLon", defNS);
if (minLat == null) {
tm.err.append("Missing SpatialExtent minLat element\n");
} else {
try { tm.minLat = Double.parseDouble( minLat); }
catch (NumberFormatException e) {
tm.err.append("Bad format for SpatialExtent minLat = "+minLat+"\n");
}
}
if (minLon == null) {
tm.err.append("Missing SpatialExtent minLon element\n");
} else {
try { tm.minLon = Double.parseDouble( minLon); }
catch (NumberFormatException e) {
tm.err.append("Bad format for SpatialExtent minLon = "+minLon+"\n");
}
}
if (maxLat == null) {
tm.err.append("Missing SpatialExtent maxLat element\n");
} else {
try { tm.maxLat = Double.parseDouble( maxLat); }
catch (NumberFormatException e) {
tm.err.append("Bad format for SpatialExtent maxLat = "+maxLat+"\n");
}
}
if (maxLon == null) {
tm.err.append("Missing SpatialExtent maxLon element\n");
} else {
try { tm.maxLon = Double.parseDouble( maxLon); }
catch (NumberFormatException e) {
tm.err.append("Bad format for SpatialExtent maxLon = "+maxLon+"\n");
}
}
}
Element timeElem = mdataElement.getChild("timeExtent", defNS);
if (null == timeElem) {
tm.err.append("** Warning: THREDDS Metadata record has no TimeExtent element\n");
}
else {
String minDate = timeElem.getChildText("minDate", defNS);
String maxDate = timeElem.getChildText("maxDate", defNS);
if (minDate == null) {
tm.err.append("Missing TimeExtent minDate element\n");
} else {
try { tm.minDate = dateFormat.parse( minDate); }
catch (ParseException e) {
tm.err.append("Bad format for TimeExtent minDate = "+minDate+"\n");
}
}
if (maxDate == null) {
tm.err.append("Missing TimeExtent maxDate element\n");
} else {
try { tm.maxDate = dateFormat.parse( maxDate); }
catch (ParseException e) {
tm.err.append("Bad format for TimeExtent maxDate = "+maxDate+"\n");
}
}
}
// get fileAccess elements
java.util.List list = mdataElement.getChildren("param", defNS);
for (int j = 0; j < list.size(); j++) {
Element paramElement = (Element) list.get(j);
String name = paramElement.getText();
tm.params.add(name);
}
if (debug) System.out.println (" ThredddsMetadata added: "+ tm);
return ok ? tm : null;
}
/**
* Create a JDOM element from an InvMetadata content object
*
* @param contentObject : the content object
* @return an object representing the metadata content as a JDOM element
*
public void addMetadataContent(org.w3c.dom.Element dome, Object contentObject) {
Element mdataElem = builder.build(dome);
ThreddsMetadata tm = (ThreddsMetadata) contentObject;
Element spatialElem = new Element("spatialExtent", defNS);
if (tm.isGlobal)
spatialElem.setAttribute("isGlobal", "true");
else {
spatialElem.addContent( new Element("minLat", defNS).setText(Double.toString(tm.minLat)));
spatialElem.addContent( new Element("minLon", defNS).setText(Double.toString(tm.minLon)));
spatialElem.addContent( new Element("maxLat", defNS).setText(Double.toString(tm.maxLat)));
spatialElem.addContent( new Element("maxLon", defNS).setText(Double.toString(tm.maxLon)));
}
mdataElem.addContent(spatialElem);
Element timeElem = new Element("timeExtent", defNS);
timeElem.addContent( new Element("minDate", defNS).setText(dateFormat.format( tm.minDate)));
timeElem.addContent( new Element("maxDate", defNS).setText(dateFormat.format( tm.maxDate)));
mdataElem.addContent(timeElem);
for (int i=0; i 0;
if (hasErr) out.append( tm.err);
return !hasErr;
}
} // Factory */
/**
* ********************************************************************
*/
/* testing
public static void main (String[] args) throws Exception {
InvCatalogFactory catFactory = InvCatalogFactory.getDefaultFactory(false);
catFactory.registerMetadataConverter( MetadataType.THREDDS, new ThreddsMetadata.Parser());
InvCatalogImpl cat = (InvCatalogImpl) catFactory.readXML("file:///C:/dev/thredds/catalog/test/data/enhancedCat.xml");
System.out.println("\nDump=\n" + cat.dump());
StringBuffer buff = new StringBuffer();
boolean isValid = cat.check( buff);
System.out.println("catalog <" + cat.getName()+ "> "+ (isValid ? "is" : "is not") + " valid");
System.out.println(" messages=\n" + buff.toString());
if (isValid) System.out.println("\nBack to XML=\n" + catFactory.writeXML( cat));
} */
static public void main(String[] args) throws IOException {
GeospatialCoverage gc = new GeospatialCoverage();
LatLonRect bb = new LatLonRect();
gc.setBoundingBox(bb);
gc.toXML(System.out);
}
}