thredds.client.catalog.tools.CatalogXmlWriter Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package thredds.client.catalog.tools;
import java.nio.charset.StandardCharsets;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.output.XMLOutputter;
import thredds.client.catalog.*;
import ucar.nc2.units.DateRange;
import ucar.nc2.units.DateType;
import ucar.nc2.units.TimeDuration;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import ucar.unidata.util.Format;
/**
* Write client side catalogs out as XML.
* Used for server catalogs too.
* Note there is no reference to the catalog's baseURI.
*
* @author caron
* @since 1/11/2015
*/
public class CatalogXmlWriter {
private static boolean useBytesForDataSize;
public static void useBytesForDataSize(boolean b) {
useBytesForDataSize = b;
}
private static final String version = "1.2";
////////////////////////////////////////////////////////////////////////
private boolean raw;
/**
* Write the catalog as an XML document to the specified stream.
*
* @param catalog write this catalog
* @param os write to this OutputStream
* @param raw write raw file if true (for server configuration)
*/
public void writeXML(Catalog catalog, OutputStream os, boolean raw) throws IOException {
this.raw = raw;
writeXML(catalog, os);
this.raw = false;
}
public String writeXML(Catalog catalog) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(100 * 1000);
writeXML(catalog, bos);
this.raw = false;
return new String(bos.toByteArray(), StandardCharsets.UTF_8);
}
/**
* Write the catalog as an XML document to the specified stream.
*
* @param catalog write this catalog
* @param os write to this OutputStream
*/
public void writeXML(Catalog catalog, OutputStream os) throws IOException {
// Output the document, use standard formatter
// XMLOutputter fmt = new XMLOutputter();
// fmt.setNewlines(true);
// fmt.setIndent(" ");
// fmt.setTrimAllWhite( true);
XMLOutputter fmt = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat()); // LOOK maybe compact ??
fmt.output(writeCatalog(catalog), os);
}
public Document writeCatalog(Catalog cat) {
Element rootElem = new Element("catalog", Catalog.defNS);
Document doc = new Document(rootElem);
// attributes
if (cat.getName() != null)
rootElem.setAttribute("name", cat.getName());
rootElem.setAttribute("version", version);
rootElem.addNamespaceDeclaration(Catalog.xlinkNS);
if (cat.getExpires() != null)
rootElem.setAttribute("expires", cat.getExpires().toString());
// services
Iterator iter = cat.getServices().iterator();
while (iter.hasNext()) {
Service service = (Service) iter.next();
rootElem.addContent(writeService(service));
}
/*
* dataset roots
* if (raw) {
* iter = cat.getDatasetRoots().iterator();
* while (iter.hasNext()) {
* Property p = (Property) iter.next();
* rootElem.addContent(writeDatasetRoot(p));
* }
* }
*/
// properties
iter = cat.getProperties().iterator();
while (iter.hasNext()) {
Property p = (Property) iter.next();
rootElem.addContent(writeProperty(p));
}
// datasets
iter = cat.getDatasetsLocal().iterator();
while (iter.hasNext()) {
Dataset ds = (Dataset) iter.next();
if (ds instanceof CatalogRef)
rootElem.addContent(writeCatalogRef((CatalogRef) ds));
else
rootElem.addContent(writeDataset(ds));
}
return doc;
}
private Element writeAccess(Access access) {
Element accessElem = new Element("access", Catalog.defNS);
accessElem.setAttribute("urlPath", access.getUrlPath());
if (access.getService() != null)
accessElem.setAttribute("serviceName", access.getService().getName());
if (access.getDataFormatName() != null)
accessElem.setAttribute("dataFormat", access.getDataFormatName());
if (access.getDataSize() > 0)
accessElem.addContent(writeDataSize(access.getDataSize()));
return accessElem;
}
private Element writeCatalogRef(CatalogRef catRef) {
Element catrefElem = new Element("catalogRef", Catalog.defNS);
catrefElem.setAttribute("href", catRef.getXlinkHref(), Catalog.xlinkNS);
String name = catRef.getName() == null ? "" : catRef.getName();
catrefElem.setAttribute("title", name, Catalog.xlinkNS);
if (catRef.getId() != null)
catrefElem.setAttribute("ID", catRef.getId());
if (catRef.getRestrictAccess() != null)
catrefElem.setAttribute("restrictAccess", catRef.getRestrictAccess());
catrefElem.setAttribute("name", "");
writeDatasetInfo(catRef, catrefElem, false, raw);
return catrefElem;
}
protected Element writeContributor(ThreddsMetadata.Contributor c) {
Element elem = new Element("contributor", Catalog.defNS);
if (c.getRole() != null)
elem.setAttribute("role", c.getRole());
elem.setText(c.getName());
return elem;
}
private Element writeControlledVocabulary(ThreddsMetadata.Vocab v, String name) {
Element elem = new Element(name, Catalog.defNS);
if (v.getVocabulary() != null)
elem.setAttribute("vocabulary", v.getVocabulary());
elem.addContent(v.getText());
return elem;
}
private Element writeDataset(Dataset ds) {
Element dsElem = new Element("dataset", Catalog.defNS);
/*
* if (ds instanceof DatasetProxy) {
* dsElem.setAttribute("name", ((DatasetProxy) ds).getAliasName());
* dsElem.setAttribute("alias", ds.getID());
* return dsElem;
* }
*/
writeDatasetInfo(ds, dsElem, true, raw);
return dsElem;
}
private void writeDatasetInfo(Dataset ds, Element dsElem, boolean doNestedDatasets, boolean showNcml) {
String name = ds.getName();
if (name == null)
name = ""; // eg catrefs
dsElem.setAttribute("name", name);
// other attributes, note the others get made into an element
if (ds.getCollectionType() != null)
dsElem.setAttribute("collectionType", ds.getCollectionType());
if (ds.isHarvest())
dsElem.setAttribute("harvest", "true");
if (ds.getID() != null)
dsElem.setAttribute("ID", ds.getID());
if (ds.getUrlPath() != null)
dsElem.setAttribute("urlPath", ds.getUrlPath());
if (ds.getRestrictAccess() != null)
dsElem.setAttribute("restrictAccess", ds.getRestrictAccess());
/*
* services (local only)
* for (Service service : ds.getServices()) {
* dsElem.addContent(writeService(service));
* }
*/
// thredds metadata
writeThreddsMetadata(dsElem, ds);
writeInheritedMetadata(dsElem, ds);
// access (local only)
List access = (List) ds.getLocalFieldAsList(Dataset.Access);
for (Access a : access) {
dsElem.addContent(writeAccess(a));
}
/*
* if (showNcML && ds.getNcmlElement() != null) {
* org.jdom2.Element ncml = ds.getNcmlElement().clone();
* ncml.detach();
* dsElem.addContent(ncml);
* }
*/
if (!doNestedDatasets)
return;
// nested datasets
for (Dataset nested : ds.getDatasetsLocal()) {
// if (nested instanceof DatasetScan)
// dsElem.addContent(writeDatasetScan((DatasetScan) nested));
if (nested instanceof CatalogRef)
dsElem.addContent(writeCatalogRef((CatalogRef) nested));
else
dsElem.addContent(writeDataset(nested));
}
}
protected Element writeDate(String name, DateType date) {
Element dateElem = new Element(name, Catalog.defNS);
dateElem.addContent(date.getText());
if (date.getType() != null)
dateElem.setAttribute("type", date.getType());
if (date.getFormat() != null)
dateElem.setAttribute("format", date.getFormat());
return dateElem;
}
private Element writeDocumentation(Documentation doc, String name) {
Element docElem = new Element(name, Catalog.defNS);
if (doc.getType() != null)
docElem.setAttribute("type", doc.getType());
if (doc.hasXlink()) {
docElem.setAttribute("href", doc.getXlinkHref(), Catalog.xlinkNS);
if (!doc.getXlinkTitle().equals(doc.getURI().toString()))
docElem.setAttribute("title", doc.getXlinkTitle(), Catalog.xlinkNS);
}
String inline = doc.getInlineContent();
if (inline != null)
docElem.addContent(inline);
return docElem;
}
public Element writeGeospatialCoverage(ThreddsMetadata.GeospatialCoverage gc) {
Element elem = new Element("geospatialCoverage", Catalog.defNS);
if (gc.getZPositive() != null)
elem.setAttribute("zpositive", gc.getZPositive());
if (gc.getNorthSouthRange() != null)
writeGeospatialRange(elem, new Element("northsouth", Catalog.defNS), gc.getNorthSouthRange());
if (gc.getEastWestRange() != null)
writeGeospatialRange(elem, new Element("eastwest", Catalog.defNS), gc.getEastWestRange());
if (gc.getUpDownRange() != null)
writeGeospatialRange(elem, new Element("updown", Catalog.defNS), gc.getUpDownRange());
/*
* serialize isGlobal
* java.util.List names = gc.getNames();
* ThreddsMetadata.Vocab global = new ThreddsMetadata.Vocab("global", null);
* if (gc.isGlobal() && !names.contains(global)) {
* names.add(global);
* } else if (!gc.isGlobal() && names.contains(global)) {
* names.remove(global);
* }
*/
for (ThreddsMetadata.Vocab name : gc.getNames()) {
elem.addContent(writeControlledVocabulary(name, "name"));
}
return elem;
}
private void writeGeospatialRange(Element parent, Element elem, ThreddsMetadata.GeospatialRange r) {
if (r == null)
return;
elem.addContent(new Element("start", Catalog.defNS).setText(Double.toString(r.getStart())));
elem.addContent(new Element("size", Catalog.defNS).setText(Double.toString(r.getSize())));
if (r.hasResolution())
elem.addContent(new Element("resolution", Catalog.defNS).setText(Double.toString(r.getResolution())));
if (r.getUnits() != null)
elem.addContent(new Element("units", Catalog.defNS).setText(r.getUnits()));
parent.addContent(elem);
}
private Element writeMetadata(ThreddsMetadata.MetadataOther mdata) {
Element mdataElem = new Element("metadata", Catalog.defNS);
if (mdata.getType() != null)
mdataElem.setAttribute("metadataType", mdata.getType());
if (mdata.isInherited())
mdataElem.setAttribute("inherited", "true");
String ns = mdata.getNamespaceURI();
if ((ns != null) && !ns.equals(Catalog.CATALOG_NAMESPACE_10)) {
Namespace mdataNS = Namespace.getNamespace(mdata.getPrefix(), ns);
mdataElem.addNamespaceDeclaration(mdataNS);
}
if (mdata.getXlinkHref() != null) {
mdataElem.setAttribute("href", mdata.getXlinkHref(), Catalog.xlinkNS);
if (mdata.getTitle() != null)
mdataElem.setAttribute("title", mdata.getTitle(), Catalog.xlinkNS);
} else if (mdata.getContentObject() != null && mdata.getContentObject() instanceof Element) {
Element content = (Element) mdata.getContentObject();
mdataElem.setContent(content);
}
return mdataElem;
}
private Element writeProperty(Property prop) {
Element propElem = new Element("property", Catalog.defNS);
propElem.setAttribute("name", prop.getName());
propElem.setAttribute("value", prop.getValue());
return propElem;
}
protected Element writeSource(String elementName, ThreddsMetadata.Source p) {
Element elem = new Element(elementName, Catalog.defNS);
elem.addContent(writeControlledVocabulary(p.getNameVocab(), "name"));
Element contact = new Element("contact", Catalog.defNS);
if (p.getUrl() != null)
contact.setAttribute("url", p.getUrl());
if (p.getEmail() != null)
contact.setAttribute("email", p.getEmail());
elem.addContent(contact);
return elem;
}
private Element writeService(Service service) {
Element serviceElem = new Element("service", Catalog.defNS);
serviceElem.setAttribute("name", service.getName());
String svctype = service.getServiceTypeName();
serviceElem.setAttribute("serviceType", svctype);
String base = service.getBase();
if ("compound".equalsIgnoreCase(svctype) && base == null)
base = ""; // Add some error tolerance
serviceElem.setAttribute("base", base);
if ((service.getSuffix() != null) && (!service.getSuffix().isEmpty()))
serviceElem.setAttribute("suffix", service.getSuffix());
// properties
for (Property p : service.getProperties()) {
serviceElem.addContent(writeProperty(p));
}
// services
for (Service nested : service.getNestedServices()) {
serviceElem.addContent(writeService(nested));
}
/*
* dataset roots
* if (raw) {
* for (Property p : service.getDatasetRoots()) {
* serviceElem.addContent(writeDatasetRoot(p));
* }
* }
*/
return serviceElem;
}
private Element writeDataSize(double size) {
Element sizeElem = new Element("dataSize", Catalog.defNS);
// want exactly the number of bytes
if (useBytesForDataSize) {
sizeElem.setAttribute("units", "bytes");
long bytes = (long) size;
sizeElem.setText(Long.toString(bytes));
return sizeElem;
}
// otherwise choose appropriate unit
String unit;
if (size > 1.0e15) {
unit = "Pbytes";
size *= 1.0e-15;
} else if (size > 1.0e12) {
unit = "Tbytes";
size *= 1.0e-12;
} else if (size > 1.0e9) {
unit = "Gbytes";
size *= 1.0e-9;
} else if (size > 1.0e6) {
unit = "Mbytes";
size *= 1.0e-6;
} else if (size > 1.0e3) {
unit = "Kbytes";
size *= 1.0e-3;
} else {
unit = "bytes";
}
sizeElem.setAttribute("units", unit);
sizeElem.setText(Format.d(size, 4));
return sizeElem;
}
/*
* protected void writeCat6InheritedMetadata( Element elem, ThreddsMetadata tmi) {
* if ((tmi.getDataType() == null) && (tmi.getServiceName() == null) &&
* (tmi.getAuthority() == null) && ( tmi.getProperties().size() == 0))
* return;
*
* Element mdataElem = new Element("metadata", Catalog.defNS);
* mdataElem.setAttribute("inherited", "true");
* writeThreddsMetadata( mdataElem, tmi);
* elem.addContent( mdataElem);
* }
*/
protected void writeInheritedMetadata(Element elem, Dataset ds) {
Element mdataElem = new Element("metadata", Catalog.defNS);
mdataElem.setAttribute("inherited", "true");
ThreddsMetadata tmi = (ThreddsMetadata) ds.getLocalField(Dataset.ThreddsMetadataInheritable);
if (tmi == null)
return;
writeThreddsMetadata(mdataElem, tmi);
if (!mdataElem.getChildren().isEmpty())
elem.addContent(mdataElem);
}
protected void writeThreddsMetadata(Element elem, ThreddsMetadataContainer ds) {
String serviceName = (String) ds.getLocalField(Dataset.ServiceName);
if (serviceName != null) {
Element serviceNameElem = new Element("serviceName", Catalog.defNS);
serviceNameElem.setText(serviceName);
elem.addContent(serviceNameElem);
}
String authority = (String) ds.getLocalField(Dataset.Authority);
if (authority != null) {
Element authElem = new Element("authority", Catalog.defNS);
authElem.setText(authority);
elem.addContent(authElem);
}
String featureTypeName = (String) ds.getLocalField(Dataset.FeatureType);
if (featureTypeName != null) {
Element dataTypeElem = new Element("dataType", Catalog.defNS);
dataTypeElem.setText(featureTypeName);
elem.addContent(dataTypeElem);
}
String dataFormatName = (String) ds.getLocalField(Dataset.DataFormatType);
if (dataFormatName != null) {
Element dataFormatElem = new Element("dataFormat", Catalog.defNS);
dataFormatElem.setText(dataFormatName);
elem.addContent(dataFormatElem);
}
Long dataSize = (Long) ds.getLocalField(Dataset.DataSize);
if (dataSize != null && dataSize > 0)
elem.addContent(writeDataSize(dataSize));
List docList = (List) ds.getLocalFieldAsList(Dataset.Documentation);
for (Documentation doc : docList) {
elem.addContent(writeDocumentation(doc, "documentation"));
}
List contribList =
(List) ds.getLocalFieldAsList(Dataset.Contributors);
for (ThreddsMetadata.Contributor c : contribList) {
elem.addContent(writeContributor(c));
}
List creatorList = (List) ds.getLocalFieldAsList(Dataset.Creators);
for (ThreddsMetadata.Source p : creatorList) {
elem.addContent(writeSource("creator", p));
}
List kewordList = (List) ds.getLocalFieldAsList(Dataset.Keywords);
for (ThreddsMetadata.Vocab v : kewordList) {
elem.addContent(writeControlledVocabulary(v, "keyword"));
}
List mdList =
(List) ds.getLocalFieldAsList(Dataset.MetadataOther);
for (ThreddsMetadata.MetadataOther m : mdList) {
elem.addContent(writeMetadata(m));
}
List projList = (List) ds.getLocalFieldAsList(Dataset.Projects);
for (ThreddsMetadata.Vocab v : projList) {
elem.addContent(writeControlledVocabulary(v, "project"));
}
List propertyList = (List) ds.getLocalFieldAsList(Dataset.Properties);
for (Property p : propertyList) {
elem.addContent(writeProperty(p));
}
List pubList = (List) ds.getLocalFieldAsList(Dataset.Publishers);
for (ThreddsMetadata.Source p : pubList) {
elem.addContent(writeSource("publisher", p));
}
List dateList = (List) ds.getLocalFieldAsList(Dataset.Dates);
for (DateType d : dateList) {
elem.addContent(writeDate("date", d));
}
ThreddsMetadata.GeospatialCoverage gc =
(ThreddsMetadata.GeospatialCoverage) ds.getLocalField(Dataset.GeospatialCoverage);
if (gc != null)
elem.addContent(writeGeospatialCoverage(gc));
DateRange tc = (DateRange) ds.getLocalField(Dataset.TimeCoverage);
if (tc != null)
elem.addContent(writeTimeCoverage(tc));
List varList =
(List) ds.getLocalFieldAsList(Dataset.VariableGroups);
for (ThreddsMetadata.VariableGroup v : varList) {
elem.addContent(writeVariables(v));
}
// LOOK what about VariableMapLink ??
ThreddsMetadata.UriResolved varMapLink = (ThreddsMetadata.UriResolved) ds.getLocalField(Dataset.VariableMapLinkURI);
if (varMapLink != null) {
Element velem = new Element("variableMap", Catalog.defNS);
velem.setAttribute("title", "variables", Catalog.xlinkNS);
velem.setAttribute("href", varMapLink.href, Catalog.xlinkNS);
elem.addContent(velem);
}
}
protected Element writeTimeCoverage(DateRange t) {
Element elem = new Element("timeCoverage", Catalog.defNS);
DateType start = t.getStart();
DateType end = t.getEnd();
TimeDuration duration = t.getDuration();
TimeDuration resolution = t.getResolution();
if (t.useStart() && (start != null) && !start.isBlank()) {
Element startElem = new Element("start", Catalog.defNS);
startElem.setText(start.toString());
elem.addContent(startElem);
}
if (t.useEnd() && (end != null) && !end.isBlank()) {
Element telem = new Element("end", Catalog.defNS);
telem.setText(end.toString());
elem.addContent(telem);
}
if (t.useDuration() && (duration != null) && !duration.isBlank()) {
Element telem = new Element("duration", Catalog.defNS);
telem.setText(duration.toString());
elem.addContent(telem);
}
if (t.useResolution() && (resolution != null) && !resolution.isBlank()) {
Element telem = new Element("resolution", Catalog.defNS);
telem.setText(t.getResolution().toString());
elem.addContent(telem);
}
return elem;
}
protected Element writeVariable(ThreddsMetadata.Variable v) {
Element elem = new Element("variable", Catalog.defNS);
if (v.getName() != null)
elem.setAttribute("name", v.getName());
if (v.getDescription() != null) {
String desc = v.getDescription().trim();
if (!desc.isEmpty())
elem.setText(v.getDescription());
}
if (v.getVocabularyName() != null)
elem.setAttribute("vocabulary_name", v.getVocabularyName());
if (v.getUnits() != null)
elem.setAttribute("units", v.getUnits());
String id = v.getVocabularyId();
if (id != null)
elem.setAttribute("vocabulary_id", id);
return elem;
}
protected Element writeVariables(ThreddsMetadata.VariableGroup vs) {
Element elem = new Element("variables", Catalog.defNS);
if (vs.getVocabulary() != null)
elem.setAttribute("vocabulary", vs.getVocabulary());
if (vs.getVocabUri() != null)
elem.setAttribute("href", vs.getVocabUri().resolved.toString(), Catalog.xlinkNS);
if (vs.getVariableMap() != null) { // variable map
Element mapElem = new Element("variableMap", Catalog.defNS);
mapElem.setAttribute("href", vs.getVariableMap().resolved.toString(), Catalog.xlinkNS);
elem.addContent(mapElem);
} else { // inline variables
List varList = vs.getVariableList();
for (ThreddsMetadata.Variable v : varList) {
elem.addContent(writeVariable(v));
}
}
return elem;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy