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

com.revolsys.gis.esri.gdb.xml.EsriGeodatabaseXmlDataObjectWriter Maven / Gradle / Ivy

The newest version!
package com.revolsys.gis.esri.gdb.xml;

import java.io.Writer;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.UUID;

import javax.xml.namespace.QName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.revolsys.gis.cs.BoundingBox;
import com.revolsys.gis.cs.CoordinateSystem;
import com.revolsys.gis.cs.GeometryFactory;
import com.revolsys.gis.cs.ProjectedCoordinateSystem;
import com.revolsys.gis.cs.esri.EsriCoordinateSystems;
import com.revolsys.gis.cs.esri.EsriCsWktWriter;
import com.revolsys.gis.data.model.Attribute;
import com.revolsys.gis.data.model.AttributeProperties;
import com.revolsys.gis.data.model.DataObject;
import com.revolsys.gis.data.model.DataObjectMetaData;
import com.revolsys.gis.data.model.types.DataType;
import com.revolsys.gis.data.model.types.DataTypes;
import com.revolsys.gis.esri.gdb.xml.type.EsriGeodatabaseXmlFieldType;
import com.revolsys.gis.esri.gdb.xml.type.EsriGeodatabaseXmlFieldTypeRegistry;
import com.revolsys.io.AbstractWriter;
import com.revolsys.xml.XmlConstants;
import com.revolsys.xml.XsiConstants;
import com.revolsys.xml.io.XmlWriter;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

public class EsriGeodatabaseXmlDataObjectWriter extends
  AbstractWriter implements EsriGeodatabaseXmlConstants {
  private static final Logger LOG = LoggerFactory.getLogger(EsriGeodatabaseXmlDataObjectWriter.class);

  private int datasetId = 1;

  private int objectId = 1;

  private final XmlWriter out;

  private boolean opened;

  private final DataObjectMetaData metaData;

  private String datasetType;

  private final EsriGeodatabaseXmlFieldTypeRegistry fieldTypes = EsriGeodatabaseXmlFieldTypeRegistry.INSTANCE;

  private String geometryType;

  public EsriGeodatabaseXmlDataObjectWriter(final DataObjectMetaData metaData,
    final Writer out) {
    this.metaData = metaData;
    this.out = new XmlWriter(out);
  }

  @Override
  public void close() {
    if (!opened) {
      writeHeader(null);
    }

    writeFooter();
    out.close();
  }

  @Override
  public void flush() {
    out.flush();
  }

  public void write(final DataObject object) {
    if (!opened) {
      writeHeader(object.getGeometryValue());
      writeWorkspaceDataHeader();
    }
    out.startTag(RECORD);
    out.attribute(XsiConstants.TYPE, RECORD_TYPE);

    out.startTag(VALUES);
    out.attribute(XsiConstants.TYPE, VALUES_TYPE);

    for (final Attribute attribute : metaData.getAttributes()) {
      final String attributeName = attribute.getName();
      final Object value = object.getValue(attributeName);
      final DataType type = attribute.getType();
      final EsriGeodatabaseXmlFieldType fieldType = fieldTypes.getFieldType(type);
      if (fieldType != null) {
        fieldType.writeValue(out, value);
      }
    }
    if (metaData.getAttribute("OBJECTID") == null) {
      final EsriGeodatabaseXmlFieldType fieldType = fieldTypes.getFieldType(DataTypes.INTEGER);
      fieldType.writeValue(out, objectId++);
    }

    out.endTag(VALUES);

    out.endTag(RECORD);
  }

  private void writeDataElement(final DataObjectMetaData metaData,
    final Geometry geometry) {
    final String dataElementType;
    final Attribute geometryAttribute = metaData.getGeometryAttribute();
    boolean hasGeometry = false;
    DataType geometryDataType = null;
    if (geometryAttribute != null) {
      geometryDataType = geometryAttribute.getType();
      if (fieldTypes.getFieldType(geometryDataType) != null) {
        hasGeometry = true;

        if (geometryDataType.equals(DataTypes.POINT)) {
          geometryType = GEOMETRY_TYPE_POINT;
        } else if (geometryDataType.equals(DataTypes.MULTI_POINT)) {
          geometryType = GEOMETRY_TYPE_MULTI_POINT;
        } else if (geometryDataType.equals(DataTypes.LINE_STRING)) {
          geometryType = GEOMETRY_TYPE_POLYLINE;
        } else if (geometryDataType.equals(DataTypes.MULTI_LINE_STRING)) {
          geometryType = GEOMETRY_TYPE_POLYLINE;
        } else if (geometryDataType.equals(DataTypes.POLYGON)) {
          geometryType = GEOMETRY_TYPE_POLYGON;
        } else {
          if (geometry instanceof Point) {
            geometryType = GEOMETRY_TYPE_POINT;
          } else if (geometry instanceof MultiPoint) {
            geometryType = GEOMETRY_TYPE_MULTI_POINT;
          } else if (geometry instanceof LineString) {
            geometryType = GEOMETRY_TYPE_POLYLINE;
          } else if (geometry instanceof MultiLineString) {
            geometryType = GEOMETRY_TYPE_POLYLINE;
          } else if (geometry instanceof Polygon) {
            geometryType = GEOMETRY_TYPE_POLYGON;
          } else {
            hasGeometry = false;
          }
        }
      }
    }

    if (hasGeometry) {
      dataElementType = DATA_ELEMENT_FEATURE_CLASS;
      datasetType = DATASET_TYPE_FEATURE_CLASS;
    } else {
      dataElementType = DATA_ELEMENT_TABLE;
      datasetType = DATASET_TYPE_TABLE;
    }

    out.startTag(DATA_ELEMENT);
    out.attribute(XsiConstants.TYPE, dataElementType);

    final QName typeName = metaData.getName();
    final String localName = typeName.getLocalPart();
    out.element(CATALOG_PATH, "/FC=" + localName);
    out.element(NAME, localName);
    out.element(METADATA_RETRIEVED, true);

    out.startTag(METADATA);
    out.attribute(XsiConstants.TYPE, XML_PROPERTY_SET_TYPE);
    out.startTag(XML_DOC);
    out.text("");
    out.text("");
    out.text("");
    out.text("{");
    out.text(UUID.randomUUID().toString().toUpperCase());
    out.text("}");
    out.text("");
    final Timestamp date = new Timestamp(System.currentTimeMillis());
    out.text(new SimpleDateFormat("yyyyMMdd").format(date));
    out.text("");
    out.text("");
    out.text(new SimpleDateFormat("HHmmssSS").format(date));
    out.text("");
    out.text("TRUE");
    out.text("");
    out.text("");
    out.endTag(XML_DOC);
    out.endTag(METADATA);

    out.element(DATASET_TYPE, datasetType);
    out.element(DSID, datasetId++);
    out.element(VERSIONED, false);
    out.element(CAN_VERSION, false);
    out.element(HAS_OID, true);
    out.element(OBJECT_ID_FIELD_NAME, "OBJECTID");
    writeFields(metaData);

    out.element(CLSID, "{52353152-891A-11D0-BEC6-00805F7C4268}");
    out.emptyTag(EXTCLSID);
    out.startTag(RELATIONSHIP_CLASS_NAMES);
    out.attribute(XsiConstants.TYPE, NAMES_TYPE);
    out.endTag(RELATIONSHIP_CLASS_NAMES);
    out.element(ALIAS_NAME, localName);
    out.emptyTag(MODEL_NAME);
    out.element(HAS_GLOBAL_ID, false);
    out.emptyTag(GLOBAL_ID_FIELD_NAME);
    out.emptyTag(RASTER_FIELD_NAME);
    out.startTag(EXTENSION_PROPERTIES);
    out.attribute(XsiConstants.TYPE, PROPERTY_SET_TYPE);
    out.startTag(PROPERTY_ARRAY);
    out.attribute(XsiConstants.TYPE, PROPERTY_ARRAY_TYPE);
    out.endTag(PROPERTY_ARRAY);
    out.endTag(EXTENSION_PROPERTIES);
    out.startTag(CONTROLLER_MEMBERSHIPS);
    out.attribute(XsiConstants.TYPE, CONTROLLER_MEMBERSHIPS_TYPE);
    out.endTag(CONTROLLER_MEMBERSHIPS);
    if (hasGeometry) {
      out.element(FEATURE_TYPE, FEATURE_TYPE_SIMPLE);
      out.element(SHAPE_TYPE, geometryType);
      out.element(SHAPE_FIELD_NAME, geometryAttribute.getName());
      final GeometryFactory geometryFactory = geometryAttribute.getProperty(AttributeProperties.GEOMETRY_FACTORY);
      out.element(HAS_M, false);
      out.element(HAS_Z, geometryFactory.hasZ());
      out.element(HAS_SPATIAL_INDEX, false);
      out.emptyTag(AREA_FIELD_NAME);
      out.emptyTag(LENGTH_FIELD_NAME);

      writeExtent(geometryFactory);
      writeSpatialReference(geometryFactory);
    }

    out.endTag(DATA_ELEMENT);
  }

  public void writeExtent(final GeometryFactory geometryFactory) {
    if (geometryFactory != null) {
      final CoordinateSystem coordinateSystem = geometryFactory.getCoordinateSystem();
      if (coordinateSystem != null) {
        final BoundingBox boundingBox = coordinateSystem.getAreaBoundingBox();
        out.startTag(EXTENT);
        out.attribute(XsiConstants.TYPE, ENVELOPE_N_TYPE);
        out.element(X_MIN, boundingBox.getMinX());
        out.element(Y_MIN, boundingBox.getMinY());
        out.element(X_MAX, boundingBox.getMaxX());
        out.element(Y_MAX, boundingBox.getMaxY());
        out.element(Z_MIN, boundingBox.getMinZ());
        out.element(Z_MAX, boundingBox.getMaxZ());
        writeSpatialReference(geometryFactory);
        out.endTag(EXTENT);
      }
    }
  }

  private void writeField(final Attribute attribute) {
    final String fieldName = attribute.getName();
    if (fieldName.equals("OBJECTID")) {
      writeOidField();
    } else {
      final DataType dataType = attribute.getType();
      final EsriGeodatabaseXmlFieldType fieldType = fieldTypes.getFieldType(dataType);
      if (fieldType == null) {
        LOG.error("Data type not supported " + dataType);
      } else {
        out.startTag(FIELD);
        out.attribute(XsiConstants.TYPE, FIELD_TYPE);
        out.element(NAME, fieldName);
        out.element(TYPE, fieldType.getEsriFieldType());
        out.element(IS_NULLABLE, !attribute.isRequired());
        int length = fieldType.getFixedLength();
        if (length < 0) {
          length = attribute.getLength();
        }
        out.element(LENGTH, length);
        final int precision;
        if (fieldType.isUsePrecision()) {
          precision = attribute.getLength();
        } else {
          precision = 0;
        }
        out.element(PRECISION, precision);
        out.element(SCALE, attribute.getScale());

        final GeometryFactory geometryFactory = attribute.getProperty(AttributeProperties.GEOMETRY_FACTORY);
        if (geometryFactory != null) {
          out.startTag(GEOMETRY_DEF);
          out.attribute(XsiConstants.TYPE, GEOMETRY_DEF_TYPE);

          out.element(AVG_NUM_POINTS, 0);

          out.element(GEOMETRY_TYPE, geometryType);
          out.element(HAS_M, false);
          out.element(HAS_Z, geometryFactory.hasZ());

          writeSpatialReference(geometryFactory);

          out.endTag();
        }
        out.endTag(FIELD);
      }
    }
  }

  private void writeFields(final DataObjectMetaData metaData) {
    out.startTag(FIELDS);
    out.attribute(XsiConstants.TYPE, FIELDS_TYPE);

    out.startTag(FIELD_ARRAY);
    out.attribute(XsiConstants.TYPE, FIELD_ARRAY_TYPE);

    for (final Attribute attribute : metaData.getAttributes()) {
      writeField(attribute);
    }
    if (metaData.getAttribute("OBJECTID") == null) {
      writeOidField();
    }
    out.endTag(FIELD_ARRAY);

    out.endTag(FIELDS);
  }

  public void writeFooter() {
    out.endDocument();
  }

  private void writeHeader(final Geometry geometry) {
    opened = true;
    out.startDocument();
    out.startTag(WORKSPACE);
    out.setPrefix(XsiConstants.PREFIX, XsiConstants.NAMESPACE_URI);
    out.setPrefix(XmlConstants.XML_SCHEMA_NAMESPACE_PREFIX,
      XmlConstants.XML_SCHEMA_NAMESPACE_URI);

    out.startTag(WORKSPACE_DEFINITION);
    out.attribute(XsiConstants.TYPE, WORKSPACE_DEFINITION_TYPE);

    out.element(WORKSPACE_TYPE, "esriLocalDatabaseWorkspace");
    out.element(VERSION, "");

    out.startTag(DOMAINS);
    out.attribute(XsiConstants.TYPE, DOMAINS_TYPE);
    out.endTag(DOMAINS);

    out.startTag(DATASET_DEFINITIONS);
    out.attribute(XsiConstants.TYPE, DATASET_DEFINITIONS_TYPE);
    writeDataElement(metaData, geometry);
    out.endTag(DATASET_DEFINITIONS);

    out.endTag(WORKSPACE_DEFINITION);
  }

  private void writeOidField() {
    out.startTag(FIELD);
    out.attribute(XsiConstants.TYPE, FIELD_TYPE);
    out.element(NAME, "OBJECTID");
    out.element(TYPE, FIELD_TYPE_OBJECT_ID);
    out.element(IS_NULLABLE, false);
    out.element(LENGTH, 4);
    out.element(PRECISION, 10);
    out.element(SCALE, 0);

    out.element(REQUIRED, true);
    out.element(EDIATBLE, false);
    out.endTag(FIELD);
  }

  public void writeSpatialReference(final GeometryFactory geometryFactory) {
    if (geometryFactory != null) {
      final CoordinateSystem coordinateSystem = geometryFactory.getCoordinateSystem();
      if (coordinateSystem != null) {
        final CoordinateSystem esriCoordinateSystem = EsriCoordinateSystems.getCoordinateSystem(coordinateSystem);
        if (esriCoordinateSystem != null) {
          out.startTag(SPATIAL_REFERENCE);
          if (esriCoordinateSystem instanceof ProjectedCoordinateSystem) {
            out.attribute(XsiConstants.TYPE, PROJECTED_COORDINATE_SYSTEM_TYPE);
          } else {
            out.attribute(XsiConstants.TYPE, GEOGRAPHIC_COORDINATE_SYSTEM_TYPE);
          }
          out.element(WKT, EsriCsWktWriter.toWkt(esriCoordinateSystem));
          out.element(X_ORIGIN, 0);
          out.element(Y_ORIGIN, 0);
          final double scaleXy = geometryFactory.getScaleXY();
          out.element(XY_SCALE, (int)scaleXy);
          out.element(Z_ORIGIN, 0);
          final double scaleZ = geometryFactory.getScaleZ();
          out.element(Z_SCALE, (int)scaleZ);
          out.element(M_ORIGIN, 0);
          out.element(M_SCALE, 1);
          out.element(XY_TOLERANCE, 1.0 / scaleXy * 2.0);
          out.element(Z_TOLERANCE, 1.0 / scaleZ * 2.0);
          out.element(M_TOLERANCE, 1);
          out.element(HIGH_PRECISION, true);
          out.element(WKID, coordinateSystem.getId());
          out.endTag(SPATIAL_REFERENCE);
        }
      }
    }
  }

  public void writeWorkspaceDataHeader() {
    out.startTag(WORKSPACE_DATA);
    out.attribute(XsiConstants.TYPE, WORKSPACE_DATA_TYPE);

    out.startTag(DATASET_DATA);
    out.attribute(XsiConstants.TYPE, DATASET_DATA_TABLE_DATA);

    out.element(DATASET_NAME, metaData.getName().getLocalPart());
    out.element(DATASET_TYPE, datasetType);

    out.startTag(DATA);
    out.attribute(XsiConstants.TYPE, DATA_RECORD_SET);

    writeFields(metaData);

    out.startTag(RECORDS);
    out.attribute(XsiConstants.TYPE, RECORDS_TYPE);

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy