ucar.nc2.ncml.NcmlConstructor Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.nc2.ncml;
import java.nio.charset.StandardCharsets;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;
import thredds.client.catalog.Catalog;
import ucar.ma2.*;
import ucar.nc2.*;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import java.util.StringTokenizer;
/**
* Populate a NetcdfFile directly from NcML, can be used by IOSPs.
* All ncml elements are new, not modified.
*
* @deprecated do not use
*/
@Deprecated
public class NcmlConstructor {
// static private final boolean validate = false;
private static final boolean debugConstruct = false;
private static final boolean showParsedXML = false;
private Formatter errlog = new Formatter();
public Formatter getErrlog() {
return errlog;
}
/**
*
* @param resourceLocation eg "resources/nj22/iosp/ghcnm.ncml"
* @param target populate this file
* @return true if success
* @throws IOException on error
*/
public boolean populateFromResource(String resourceLocation, NetcdfFile target) throws IOException {
ClassLoader cl = this.getClass().getClassLoader();
InputStream is = cl.getResourceAsStream(resourceLocation);
if (is == null)
throw new FileNotFoundException(resourceLocation);
return populate(is, target);
}
public boolean populate(String ncml, NetcdfFile target) throws IOException {
return populate(new ByteArrayInputStream(ncml.getBytes(StandardCharsets.UTF_8)), target);
}
public boolean populate(InputStream ncml, NetcdfFile target) throws IOException {
org.jdom2.Document doc;
try {
SAXBuilder builder = new SAXBuilder();
builder.setExpandEntities(false);
doc = builder.build(ncml);
} catch (JDOMException e) {
throw new IOException(e.getMessage());
}
if (showParsedXML) {
XMLOutputter xmlOut = new XMLOutputter();
System.out.println("*** NetcdfDataset/showParsedXML = \n" + xmlOut.outputString(doc) + "\n*******");
}
Element netcdfElem = doc.getRootElement();
readGroup(target, target.getRootGroup(), netcdfElem);
return errlog.toString().isEmpty();
}
private void readGroup(NetcdfFile ncfile, Group parent, Element groupElem) {
String name = groupElem.getAttributeValue("name");
Group g;
if (parent == ncfile.getRootGroup()) { // special handling
g = parent;
} else {
if (name == null) {
errlog.format("NcML Group name is required (%s)%n", groupElem);
return;
}
g = new Group(ncfile, parent, name);
parent.addGroup(g);
}
// look for attributes
java.util.List attList = groupElem.getChildren("attribute", Catalog.ncmlNS);
for (Element attElem : attList) {
readAtt(g, attElem);
}
// look for dimensions
java.util.List dimList = groupElem.getChildren("dimension", Catalog.ncmlNS);
for (Element dimElem : dimList) {
readDim(g, dimElem);
}
// look for variables
java.util.List varList = groupElem.getChildren("variable", Catalog.ncmlNS);
for (Element varElem : varList) {
readVariable(ncfile, g, null, varElem);
}
// LOOK for typedef enums
// look for nested groups
java.util.List groupList = groupElem.getChildren("group", Catalog.ncmlNS);
for (Element gElem : groupList) {
readGroup(ncfile, g, gElem);
}
}
/**
* Read a NcML variable element, and nested elements, when it creates a new Variable.
*
* @param ncfile target dataset
* @param g parent Group
* @param parentS parent Structure
* @param varElem ncml variable element
* @return return new Variable
*/
private Variable readVariable(NetcdfFile ncfile, Group g, Structure parentS, Element varElem) {
String name = varElem.getAttributeValue("name");
if (name == null) {
errlog.format("NcML Variable name is required (%s)%n", varElem);
return null;
}
String type = varElem.getAttributeValue("type");
if (type == null) {
errlog.format("NcML variable (%s) must have type attribute", name);
return null;
}
DataType dtype = DataType.getType(type);
String shape = varElem.getAttributeValue("shape");
if (shape == null)
shape = ""; // deprecated, prefer explicit ""
Variable v;
if (dtype == DataType.STRUCTURE) {
Structure s = new Structure(ncfile, g, parentS, name);
s.setDimensions(shape);
v = s;
// look for nested variables
java.util.List varList = varElem.getChildren("variable", Catalog.ncmlNS);
for (Element vElem : varList) {
readVariable(ncfile, g, s, vElem);
}
} else if (dtype == DataType.SEQUENCE) {
Sequence s = new Sequence(ncfile, g, parentS, name);
v = s;
// look for nested variables
java.util.List varList = varElem.getChildren("variable", Catalog.ncmlNS);
for (Element vElem : varList) {
readVariable(ncfile, g, s, vElem);
}
} else {
v = new Variable(ncfile, g, parentS, name, dtype, shape);
// deal with values
Element valueElem = varElem.getChild("values", Catalog.ncmlNS);
if (valueElem != null)
readValues(v, varElem, valueElem);
// otherwise has fill values.
}
// look for attributes
java.util.List attList = varElem.getChildren("attribute", Catalog.ncmlNS);
for (Element attElem : attList)
readAtt(v, attElem);
if (parentS != null)
parentS.addMemberVariable(v);
else
g.addVariable(v);
return v;
}
private void readValues(Variable v, Element varElem, Element valuesElem) {
// check if values are specified by start / increment
String startS = valuesElem.getAttributeValue("start");
String incrS = valuesElem.getAttributeValue("increment");
String nptsS = valuesElem.getAttributeValue("npts");
int npts = (nptsS == null) ? (int) v.getSize() : Integer.parseInt(nptsS);
// either start, increment are specified
if ((startS != null) && (incrS != null)) {
double start = Double.parseDouble(startS);
double incr = Double.parseDouble(incrS);
v.setValues(npts, start, incr);
return;
}
// otherwise values are listed in text
String values = varElem.getChildText("values", Catalog.ncmlNS);
String sep = valuesElem.getAttributeValue("separator");
if (sep == null)
sep = " ";
if (v.getDataType() == DataType.CHAR) {
int nhave = values.length();
int nwant = (int) v.getSize();
char[] data = new char[nwant];
int min = Math.min(nhave, nwant);
for (int i = 0; i < min; i++) {
data[i] = values.charAt(i);
}
Array dataArray = Array.factory(DataType.CHAR, v.getShape(), data);
v.setCachedData(dataArray, true);
} else {
// or a list of values
List valList = new ArrayList<>();
StringTokenizer tokn = new StringTokenizer(values, sep);
while (tokn.hasMoreTokens())
valList.add(tokn.nextToken());
v.setValues(valList);
}
}
private void readAtt(Object parent, Element attElem) {
String name = attElem.getAttributeValue("name");
if (name == null) {
errlog.format("NcML Attribute name is required (%s)%n", attElem);
return;
}
try {
ucar.ma2.Array values = NcMLReader.readAttributeValues(attElem);
Attribute att = new ucar.nc2.Attribute(name, values);
if (parent instanceof Group)
((Group) parent).addAttribute(att);
else if (parent instanceof Variable)
((Variable) parent).addAttribute(att);
} catch (RuntimeException e) {
errlog.format("NcML new Attribute Exception: %s att=%s in=%s%n", e.getMessage(), name, parent);
}
}
/**
* Read an NcML dimension element.
*
* @param g put dimension into this group
* @param dimElem ncml dimension element
*/
private void readDim(Group g, Element dimElem) {
String name = dimElem.getAttributeValue("name");
if (name == null) {
errlog.format("NcML Dimension name is required (%s)%n", dimElem);
return;
}
String lengthS = dimElem.getAttributeValue("length");
String isUnlimitedS = dimElem.getAttributeValue("isUnlimited");
String isSharedS = dimElem.getAttributeValue("isShared");
String isUnknownS = dimElem.getAttributeValue("isVariableLength");
boolean isUnlimited = "true".equalsIgnoreCase(isUnlimitedS);
boolean isUnknown = "true".equalsIgnoreCase(isUnknownS);
boolean isShared = true;
if ("false".equalsIgnoreCase(isSharedS))
isShared = false;
int len = Integer.parseInt(lengthS);
if ("false".equalsIgnoreCase(isUnknownS))
len = Dimension.VLEN.getLength();
Dimension dim = new Dimension(name, len, isShared, isUnlimited, isUnknown);
if (debugConstruct)
System.out.println(" add new dim = " + dim);
g.addDimension(dim);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy