ucar.nc2.ft.point.standard.PointConfigXML 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.ft.point.standard;
import org.jdom2.output.XMLOutputter;
import org.jdom2.output.Format;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.util.List;
import java.util.ArrayList;
import java.util.Formatter;
import ucar.nc2.ft.FeatureDatasetPoint;
import ucar.nc2.dataset.NetcdfDataset;
import ucar.nc2.dataset.VariableDS;
import ucar.nc2.util.IO;
import ucar.nc2.constants.FeatureType;
import ucar.nc2.Dimension;
import ucar.nc2.Variable;
import ucar.nc2.Structure;
import ucar.ma2.DataType;
/**
* Helper class to convert a TableConfig to and from XML
*
* @author caron
* @since Aug 18, 2009
*/
public class PointConfigXML {
public static void writeConfigXML(FeatureDatasetPoint pfd, java.util.Formatter f) {
if (!(pfd instanceof PointDatasetStandardFactory.PointDatasetStandard)) {
f.format("%s not instance of PointDatasetStandard%n", pfd.getLocation());
return;
}
PointDatasetStandardFactory.PointDatasetStandard spfd = (PointDatasetStandardFactory.PointDatasetStandard) pfd;
TableAnalyzer analyser = spfd.getTableAnalyzer();
TableConfig config = analyser.getTableConfig();
TableConfigurer tc = analyser.getTableConfigurer();
if (tc == null) {
f.format("%s has no TableConfig%n", pfd.getLocation());
return;
}
PointConfigXML writer = new PointConfigXML();
try {
writer.writeConfigXML(config, tc.getClass().getName(), f);
} catch (IOException e) {
f.format("%s error writing=%s%n", pfd.getLocation(), e.getMessage());
}
}
////////////////////////////////////////////////////////////////////
private TableConfig tc;
private String tableConfigurerClass;
public void writeConfigXML(TableConfig tc, String tableConfigurerClass, java.util.Formatter sf) throws IOException {
this.tc = tc;
this.tableConfigurerClass = tableConfigurerClass;
XMLOutputter fmt = new XMLOutputter(Format.getPrettyFormat());
sf.format("%s", fmt.outputString(makeDocument()));
}
/**
* Create an XML document from this info
*
* @return netcdfDatasetInfo XML document
*/
public Document makeDocument() {
Element rootElem = new Element("pointConfig");
Document doc = new Document(rootElem);
if (tableConfigurerClass != null)
rootElem.addContent( new Element("tableConfigurer").setAttribute("class", tableConfigurerClass));
if (tc.featureType != null)
rootElem.setAttribute("featureType", tc.featureType.toString());
rootElem.addContent(writeTable(tc));
return doc;
}
private Element writeTable(TableConfig config) {
Element tableElem = new Element("table");
//if (config.name != null)
// tableElem.setAttribute("name", config.name);
if (config.type != null) {
tableElem.setAttribute("type", config.type.toString());
switch (config.type) {
case ArrayStructure:
tableElem.setAttribute("dimension", config.dimName);
break;
case Construct:
break;
case Contiguous:
if (config.start != null)
tableElem.setAttribute("start", config.start);
if (config.numRecords != null)
tableElem.setAttribute("numRecords", config.numRecords);
break;
case LinkedList:
tableElem.setAttribute("start", config.start);
tableElem.setAttribute("next", config.next);
break;
case MultidimInner:
tableElem.setAttribute("structName", config.structName);
//coverity[missing_break]
case MultidimInnerPsuedo:
tableElem.setAttribute("dim0", config.outerName);
tableElem.setAttribute("dim1", config.innerName);
tableElem.setAttribute("subtype", config.structureType.toString());
break;
case MultidimInner3D:
break;
case MultidimInnerPsuedo3D:
break;
case MultidimStructure:
tableElem.setAttribute("structName", config.structName);
break;
case NestedStructure:
tableElem.setAttribute("structName", config.structName);
break;
case ParentId:
case ParentIndex:
tableElem.setAttribute("parentIndex", config.parentIndex);
break;
case Singleton:
break;
case Structure:
tableElem.setAttribute("subtype", config.structureType.toString());
switch (config.structureType) {
case Structure:
tableElem.setAttribute("structName", config.structName);
break;
case PsuedoStructure:
tableElem.setAttribute("dim", config.dimName);
break;
case PsuedoStructure2D:
tableElem.setAttribute("dim0", config.dimName);
tableElem.setAttribute("dim1", config.outerName);
break;
}
break;
case Top:
tableElem.setAttribute("structName", config.structName);
break;
}
}
List varNames = (config.vars == null) ? new ArrayList() : new ArrayList<>(config.vars);
// add coordinates
for (Table.CoordName coord : Table.CoordName.values()) {
addCoord(tableElem, config, coord, varNames);
}
// add variables
if (config.vars != null) {
for (String col : varNames)
tableElem.addContent(new Element("variable").addContent(col));
}
// add joins
if (config.extraJoin != null) {
for (Join j : config.extraJoin) {
if (j instanceof JoinArray)
tableElem.addContent(writeJoinArray((JoinArray) j));
else if (j instanceof JoinMuiltdimStructure)
tableElem.addContent(writeJoinMuiltdimStructure((JoinMuiltdimStructure) j));
else if (j instanceof JoinParentIndex)
tableElem.addContent(writeJoinParentIndex((JoinParentIndex) j));
}
}
if (config.children != null) {
for (TableConfig child : config.children)
tableElem.addContent(writeTable(child));
}
return tableElem;
}
private void addCoord(Element tableElem, TableConfig table, Table.CoordName type, List varNames) {
String name = table.findCoordinateVariableName(type);
if (name != null) {
Element elem = new Element("coordinate").setAttribute("type", type.name());
elem.addContent(name);
tableElem.addContent(elem);
varNames.remove(name);
}
}
private Element writeJoinArray(JoinArray join) {
Element joinElem = new Element("join");
joinElem.setAttribute("class", join.getClass().toString());
if (join.type != null)
joinElem.setAttribute("type", join.type.toString());
if (join.v != null)
joinElem.addContent(new Element("variable").addContent(join.v.getFullName()));
joinElem.addContent(new Element("param").addContent(Integer.toString(join.param)));
return joinElem;
}
private JoinArray readJoinArray(NetcdfDataset ds, Element joinElement) {
JoinArray.Type type = JoinArray.Type.valueOf(joinElement.getAttributeValue("type"));
Element paramElem = joinElement.getChild("param");
String paramS = paramElem.getText();
Integer param = Integer.parseInt(paramS);
Element varElem = joinElement.getChild("variable");
String varName = varElem.getText();
VariableDS v = (VariableDS) ds.findVariable(varName);
return new JoinArray(v, type, param);
}
private Element writeJoinMuiltdimStructure(JoinMuiltdimStructure join) {
Element joinElem = new Element("join");
joinElem.setAttribute("class", join.getClass().toString());
if (join.parentStructure != null)
joinElem.addContent(new Element("parentStructure").addContent(join.parentStructure.getFullName()));
joinElem.addContent(new Element("dimLength").setAttribute("value", Integer.toString(join.dimLength)));
return joinElem;
}
private Element writeJoinParentIndex(JoinParentIndex join) {
Element joinElem = new Element("join");
joinElem.setAttribute("class", join.getClass().toString());
if (join.parentStructure != null)
joinElem.addContent(new Element("parentStructure").addContent(join.parentStructure.getFullName()));
if (join.parentIndex != null)
joinElem.addContent(new Element("parentIndex").addContent(join.parentIndex));
return joinElem;
}
///////////////////////////////////////////////////////////////////////////
private static boolean debugXML = false;
private static boolean debugURL = false;
private static boolean showParsedXML = false;
public TableConfig readConfigXMLfromResource(String resourceLocation, FeatureType wantFeatureType, NetcdfDataset ds, Formatter errlog) throws IOException {
ClassLoader cl = this.getClass().getClassLoader();
try (InputStream is = cl.getResourceAsStream(resourceLocation)) {
if (is == null)
throw new FileNotFoundException(resourceLocation);
if (debugXML) {
System.out.println(" PointConfig URL = <" + resourceLocation + ">");
try (InputStream is2 = cl.getResourceAsStream(resourceLocation)) {
System.out.println(" contents=\n" + IO.readContents(is2));
}
}
org.jdom2.Document doc;
try {
SAXBuilder builder = new SAXBuilder();
if (debugURL) System.out.println(" PointConfig URL = <" + resourceLocation + ">");
doc = builder.build(is);
} catch (JDOMException e) {
throw new IOException(e.getMessage());
}
if (debugXML) System.out.println(" SAXBuilder done");
if (showParsedXML) {
XMLOutputter xmlOut = new XMLOutputter();
System.out.println("*** PointConfig/showParsedXML = \n" + xmlOut.outputString(doc) + "\n*******");
}
Element configElem = doc.getRootElement();
String featureType = configElem.getAttributeValue("featureType");
Element tableElem = configElem.getChild("table");
assert tableElem != null;
TableConfig tc = parseTableConfig(ds, tableElem, null);
tc.featureType = FeatureType.valueOf(featureType);
return tc;
}
}
public TableConfig readConfigXML(String fileLocation, FeatureType wantFeatureType, NetcdfDataset ds, Formatter errlog) throws IOException {
org.jdom2.Document doc;
try {
SAXBuilder builder = new SAXBuilder();
if (debugURL) System.out.println(" PointConfig URL = <" + fileLocation + ">");
doc = builder.build(fileLocation);
} catch (JDOMException e) {
throw new IOException(e.getMessage());
}
if (debugXML) System.out.println(" SAXBuilder done");
if (showParsedXML) {
XMLOutputter xmlOut = new XMLOutputter();
System.out.println("*** PointConfig/showParsedXML = \n" + xmlOut.outputString(doc) + "\n*******");
}
Element configElem = doc.getRootElement();
String featureType = configElem.getAttributeValue("featureType");
Element tableElem = configElem.getChild("table");
TableConfig tc = parseTableConfig(ds, tableElem, null);
tc.featureType = FeatureType.valueOf(featureType);
return tc;
}
private TableConfig parseTableConfig(NetcdfDataset ds, Element tableElem, TableConfig parent) {
String typeS = tableElem.getAttributeValue("type");
Table.Type ttype = Table.Type.valueOf(typeS);
String name = tableElem.getAttributeValue("name");
TableConfig tc = new TableConfig(ttype, name);
switch (ttype) {
case ArrayStructure:
tc.dimName = tableElem.getAttributeValue("dimension");
break;
case Construct:
break;
case Contiguous:
tc.numRecords = tableElem.getAttributeValue("numRecords");
tc.start = tableElem.getAttributeValue("start");
break;
case LinkedList:
tc.start = tableElem.getAttributeValue("start");
tc.next = tableElem.getAttributeValue("next");
break;
case MultidimInner:
tc.structName = tableElem.getAttributeValue("structName");
//coverity[missing_break]
case MultidimInnerPsuedo:
tc.outerName = tableElem.getAttributeValue("dim0");
tc.dimName = tc.outerName;
tc.innerName = tableElem.getAttributeValue("dim1");
tc.structureType = TableConfig.StructureType.valueOf(tableElem.getAttributeValue("subtype"));
assert parent != null;
makeMultidimInner(ds, parent, tc);
break;
case MultidimInner3D:
break;
case MultidimInnerPsuedo3D:
break;
case MultidimStructure:
tc.structName = tableElem.getAttributeValue("structName");
break;
case NestedStructure:
tc.structName = tableElem.getAttributeValue("structName");
break;
case ParentId:
case ParentIndex:
tc.parentIndex = tableElem.getAttributeValue("parentIndex");
break;
case Singleton:
break;
case Structure:
tc.structureType = TableConfig.StructureType.valueOf(tableElem.getAttributeValue("subtype"));
switch (tc.structureType) {
case Structure:
tc.structName = tableElem.getAttributeValue("structName");
break;
case PsuedoStructure:
tc.dimName = tableElem.getAttributeValue("dim");
break;
case PsuedoStructure2D:
tc.dimName = tableElem.getAttributeValue("dim0");
tc.outerName = tableElem.getAttributeValue("dim1");
break;
}
break;
case Top:
tc.structName = tableElem.getAttributeValue("structName");
break;
}
List coordList = tableElem.getChildren("coordinate");
for (Element coordElem : coordList) {
String coordNameType = coordElem.getAttributeValue("type");
Table.CoordName coordName = Table.CoordName.valueOf(coordNameType);
tc.setCoordinateVariableName(coordName, coordElem.getText());
}
List joinList = tableElem.getChildren("join");
for (Element joinElem : joinList) {
tc.addJoin( readJoinArray(ds, joinElem));
}
List nestedTableList = tableElem.getChildren("table");
for (Element nestedTable : nestedTableList)
tc.addChild( parseTableConfig(ds, nestedTable, tc));
return tc;
}
private void makeMultidimInner(NetcdfDataset ds, TableConfig parentTable, TableConfig childTable) {
Dimension parentDim = ds.findDimension(parentTable.dimName);
Dimension childDim = ds.findDimension(childTable.innerName);
// divide up the variables between the parent and the child
List obsVars;
List vars = ds.getVariables();
List parentVars = new ArrayList<>(vars.size());
obsVars = new ArrayList<>(vars.size());
for (Variable orgV : vars) {
if (orgV instanceof Structure) continue;
Dimension dim0 = orgV.getDimension(0);
if ((dim0 != null) && dim0.equals(parentDim)) {
if ((orgV.getRank() == 1) || ((orgV.getRank() == 2) && orgV.getDataType() == DataType.CHAR)) {
parentVars.add(orgV.getShortName());
} else {
Dimension dim1 = orgV.getDimension(1);
if ((dim1 != null) && dim1.equals(childDim))
obsVars.add(orgV.getShortName());
}
}
}
parentTable.vars = parentVars;
childTable.vars = obsVars;
}
/* the inner table of Structure(outer, middle, inner)
private TableConfig makeMultidimInner3D(NetcdfDataset ds, TableConfig outerTable, TableConfig middleTable, Dimension innerDim, Formatter errlog) throws IOException {
Dimension outerDim = ds.findDimension(outerTable.dimName);
Dimension middleDim = ds.findDimension(middleTable.innerName);
Table.Type obsTableType = (outerTable.structureType == TableConfig.StructureType.PsuedoStructure) ? Table.Type.MultidimInnerPsuedo3D : Table.Type.MultidimInner3D;
TableConfig obsTable = new TableConfig(obsTableType, innerDim.getName());
obsTable.structureType = TableConfig.StructureType.PsuedoStructure2D;
obsTable.dimName = outerTable.dimName;
obsTable.outerName = middleTable.innerName;
obsTable.innerName = innerDim.getName();
obsTable.structName = innerDim.getName();
obsTable.lat = matchAxisTypeAndDimension(ds, AxisType.Lat, outerDim, middleDim, innerDim);
obsTable.lon = matchAxisTypeAndDimension(ds, AxisType.Lon, outerDim, middleDim, innerDim);
obsTable.elev = matchAxisTypeAndDimension(ds, AxisType.Height, outerDim, middleDim, innerDim);
obsTable.time = matchAxisTypeAndDimension(ds, AxisType.Time, outerDim, middleDim, innerDim);
// divide up the variables between the 3 tables
List vars = ds.getVariables();
List outerVars = new ArrayList(vars.size());
List middleVars = new ArrayList(vars.size());
List innerVars = new ArrayList(vars.size());
for (Variable orgV : vars) {
if (orgV instanceof Structure) continue;
if ((orgV.getRank() == 1) || ((orgV.getRank() == 2) && orgV.getDataType() == DataType.CHAR)) {
if (outerDim.equals(orgV.getDimension(0)))
outerVars.add(orgV.getShortName());
} else if (orgV.getRank() == 2) {
if (outerDim.equals(orgV.getDimension(0)) && middleDim.equals(orgV.getDimension(1)))
middleVars.add(orgV.getShortName());
} else if (orgV.getRank() == 3) {
if (outerDim.equals(orgV.getDimension(0)) && middleDim.equals(orgV.getDimension(1)) && innerDim.equals(orgV.getDimension(2)))
innerVars.add(orgV.getShortName());
}
}
outerTable.vars = outerVars;
middleTable.vars = middleVars;
obsTable.vars = innerVars;
return obsTable;
} */
}