All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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;
  } */

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy