use of eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty in project hale by halestudio.
the class JDBCInstanceWriter method setStatementParameter.
/**
* Set a prepared statement parameter value.
*
* @param statement the prepared statement
* @param index the parameter index
* @param value the value, not <code>null</code>
* @param propertyDef the associated property definition
* @param sqlType the SQL type
* @param reporter the reporter
* @param conn Connection (currently used for geometry conversion for oracle
* database
* @throws SQLException if setting the parameter fails
*/
@SuppressWarnings("unchecked")
private void setStatementParameter(PreparedStatement statement, int index, Object value, PropertyDefinition propertyDef, int sqlType, IOReporter reporter, Connection conn) throws SQLException {
if (propertyDef.getPropertyType().getConstraint(GeometryType.class).isGeometry()) {
// is a geometry column
// get the geometry advisor
@SuppressWarnings("rawtypes") GeometryAdvisor advisor = propertyDef.getPropertyType().getConstraint(GeometryAdvisorConstraint.class).getAdvisor();
if (advisor != null) {
// use the advisor to convert the geometry
if (value instanceof GeometryProperty<?>) {
// XXX JTS geometry conversion needed beforehand?
try {
value = advisor.convertGeometry((GeometryProperty<?>) value, propertyDef.getPropertyType(), conn);
} catch (Exception e) {
reporter.error(new IOMessageImpl("Something went wrong during conversion", e));
}
} else {
reporter.error(new IOMessageImpl("Geometry value is not of type GeometryProperty and could thus not be converted for the database", null));
}
}
}
SQLArray arrayInfo = propertyDef.getPropertyType().getConstraint(SQLArray.class);
if (arrayInfo.isArray()) {
// is an array column
Object[] values;
if (value.getClass().isArray()) {
values = (Object[]) value;
} else {
values = new Object[] { value };
}
// FIXME for multi-dimensional arrays, make sure internal structures
// are arrays?
// use SQL array as value
Array array = conn.createArrayOf(arrayInfo.getElementTypeName(), values);
value = array;
// FIXME collect arrays to allow them to be freed after the
// statement is executed?
}
// TODO handling of other types?
// set the value
statement.setObject(index, value, sqlType);
}
use of eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty in project hale by halestudio.
the class JacksonMapper method streamWriteGeoJSONInstance.
/**
* Writes a single instance as GeoJSON.
*
* @param instance the instance to write
* @param config the default geometry config
* @param reporter the reporter
* @throws IOException if writing the instance fails
*/
private void streamWriteGeoJSONInstance(Instance instance, GeoJSONConfig config, IOReporter reporter) throws IOException {
jsonGen.writeStartObject();
jsonGen.writeStringField("type", "Feature");
PropertyEntityDefinition geomProperty = config.getDefaultGeometry(instance.getDefinition());
GeometryFinder geomFinder = new GeometryFinder(null);
// check whether a geometry property is set
if (geomProperty != null) {
// find all occurrences of the property
Collection<Object> values = AlignmentUtil.getValues(instance, geomProperty, false);
// find all geometries below any value (the values themselves might
// be geometries)
InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
for (Object value : values) traverser.traverse(value, geomFinder);
}
Collection<GeometryProperty<?>> geometries = geomFinder.getGeometries();
if (!geometries.isEmpty()) {
// XXX It would be better to put CRS to each geometry.
// This is currently not possible because geotools doesn't support
// this.
GeometryProperty<?> geomProp = geometries.iterator().next();
if (geomProp.getCRSDefinition() != null) {
jsonGen.writeFieldName("crs");
jsonGen.writeRawValue(new FeatureJSON().toString(geomProp.getCRSDefinition().getCRS()));
}
}
jsonGen.writeFieldName("geometry");
if (geometries.isEmpty())
jsonGen.writeNull();
else if (geometries.size() == 1)
streamWriteGeometryValue(geometries.iterator().next().getGeometry());
else {
jsonGen.writeStartObject();
jsonGen.writeStringField("type", "GeometryCollection");
jsonGen.writeArrayFieldStart("geometries");
for (GeometryProperty<?> geom : geometries) streamWriteGeometryValue(geom.getGeometry());
jsonGen.writeEndArray();
jsonGen.writeEndObject();
}
jsonGen.writeFieldName("properties");
jsonGen.writeStartObject();
jsonGen.writeStringField("_type", instance.getDefinition().getName().getLocalPart());
streamWriteProperties(instance, reporter);
jsonGen.writeEndObject();
jsonGen.writeEndObject();
}
use of eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty in project hale by halestudio.
the class StreamGmlWriterTest method fillFeatureTest.
/**
* Create a feature, fill it with values, write it as GML, validate the GML
* and load the GML file again to compare the loaded values with the ones
* that were written
*
* @param elementName the element name of the feature type to use, if
* <code>null</code> a random element will be used
* @param targetSchema the schema to use, the first element will be used for
* the type of the feature
* @param values the values to set on the feature
* @param testName the name of the test
* @param srsName the SRS name
* @param skipValueTest if the check for equality shall be skipped
* @param expectWriteFail if the GML writing is expected to fail
* @param windingOrderParam winding order parameter or <code>null</code>
* @return the validation report or the GML writing report if writing
* expected to fail
* @throws Exception if any error occurs
*/
private IOReport fillFeatureTest(String elementName, URI targetSchema, Map<List<QName>, Object> values, String testName, String srsName, boolean skipValueTest, boolean expectWriteFail, EnumWindingOrderTypes windingOrderParam) throws Exception {
// load the sample schema
XmlSchemaReader reader = new XmlSchemaReader();
reader.setSharedTypes(null);
reader.setSource(new DefaultInputSupplier(targetSchema));
IOReport schemaReport = reader.execute(null);
assertTrue(schemaReport.isSuccess());
XmlIndex schema = reader.getSchema();
XmlElement element = null;
if (elementName == null) {
element = schema.getElements().values().iterator().next();
if (element == null) {
// $NON-NLS-1$
fail("No element found in the schema");
}
} else {
for (XmlElement candidate : schema.getElements().values()) {
if (candidate.getName().getLocalPart().equals(elementName)) {
element = candidate;
break;
}
}
if (element == null) {
// $NON-NLS-1$ //$NON-NLS-2$
fail("Element " + elementName + " not found in the schema");
}
}
if (element == null) {
throw new IllegalStateException();
}
// create feature
MutableInstance feature = new DefaultInstance(element.getType(), null);
// set some values
for (Entry<List<QName>, Object> entry : values.entrySet()) {
MutableGroup parent = feature;
List<QName> properties = entry.getKey();
for (int i = 0; i < properties.size() - 1; i++) {
QName propertyName = properties.get(i);
DefinitionGroup def = parent.getDefinition();
Object[] vals = parent.getProperty(propertyName);
if (vals != null && vals.length > 0) {
Object value = vals[0];
if (value instanceof MutableGroup) {
parent = (MutableGroup) value;
} else {
MutableGroup child;
ChildDefinition<?> childDef = def.getChild(propertyName);
if (childDef.asProperty() != null || value != null) {
// create instance
child = new DefaultInstance(childDef.asProperty().getPropertyType(), null);
} else {
// create group
child = new DefaultGroup(childDef.asGroup());
}
if (value != null) {
// wrap value
((MutableInstance) child).setValue(value);
}
parent = child;
}
}
}
parent.addProperty(properties.get(properties.size() - 1), entry.getValue());
}
InstanceCollection instances = new DefaultInstanceCollection(Collections.singleton(feature));
// write to file
InstanceWriter writer = new GmlInstanceWriter();
if (windingOrderParam != null) {
writer.setParameter(GeoInstanceWriter.PARAM_UNIFY_WINDING_ORDER, Value.of(windingOrderParam));
}
writer.setInstances(instances);
DefaultSchemaSpace schemaSpace = new DefaultSchemaSpace();
schemaSpace.addSchema(schema);
writer.setTargetSchema(schemaSpace);
// $NON-NLS-1$
File outFile = File.createTempFile(testName, ".gml");
writer.setTarget(new FileIOSupplier(outFile));
if (windingOrderParam != null && windingOrderParam == EnumWindingOrderTypes.counterClockwise) {
assertTrue(writer.getParameter(GeoInstanceWriter.PARAM_UNIFY_WINDING_ORDER).as(EnumWindingOrderTypes.class) == EnumWindingOrderTypes.counterClockwise);
}
// new LogProgressIndicator());
IOReport report = writer.execute(null);
if (expectWriteFail) {
assertFalse("Writing the GML output should not be successful", report.isSuccess());
return report;
} else {
assertTrue("Writing the GML output not successful", report.isSuccess());
}
List<? extends Locatable> validationSchemas = writer.getValidationSchemas();
System.out.println(outFile.getAbsolutePath());
System.out.println(targetSchema.toString());
// if (!DEL_TEMP_FILES && Desktop.isDesktopSupported()) {
// Desktop.getDesktop().open(outFile);
// }
IOReport valReport = validate(outFile.toURI(), validationSchemas);
// load file
InstanceCollection loaded = loadGML(outFile.toURI(), schema);
ResourceIterator<Instance> it = loaded.iterator();
try {
assertTrue(it.hasNext());
if (!skipValueTest) {
Instance l = it.next();
// test values
for (Entry<List<QName>, Object> entry : values.entrySet()) {
// XXX conversion?
Object expected = entry.getValue();
// String propertyPath = Joiner.on('.').join(Collections2.transform(entry.getKey(), new Function<QName, String>() {
//
// @Override
// public String apply(QName input) {
// return input.toString();
// }
// }));
// Collection<Object> propValues = PropertyResolver.getValues(
// l, propertyPath, true);
// assertEquals(1, propValues.size());
// Object value = propValues.iterator().next();
Collection<GeometryProperty<?>> geoms = GeometryUtil.getAllGeometries(l);
assertEquals(1, geoms.size());
Object value = geoms.iterator().next().getGeometry();
if (expected instanceof Geometry && value instanceof Geometry) {
if (windingOrderParam == null || windingOrderParam == EnumWindingOrderTypes.noChanges) {
matchGeometries((Geometry) expected, (Geometry) value);
}
// Winding Order Test.
if (windingOrderParam != null) {
if (windingOrderParam == EnumWindingOrderTypes.counterClockwise) {
assertTrue(((Geometry) expected).getNumGeometries() == ((Geometry) value).getNumGeometries());
assertTrue(WindingOrder.isCounterClockwise((Geometry) value));
} else if (windingOrderParam == EnumWindingOrderTypes.clockwise) {
assertFalse(WindingOrder.isCounterClockwise((Geometry) value));
} else {
assertTrue(WindingOrder.isCounterClockwise((Geometry) value) == WindingOrder.isCounterClockwise((Geometry) expected));
}
} else {
// TODO check winding order is CCW
if (value instanceof Polygon || value instanceof MultiPolygon)
assertTrue(WindingOrder.isCounterClockwise((Geometry) value));
}
} else {
assertEquals(expected.toString(), value.toString());
}
}
assertFalse(it.hasNext());
}
} finally {
it.close();
}
if (DEL_TEMP_FILES) {
outFile.deleteOnExit();
}
return valReport;
}
use of eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty in project hale by halestudio.
the class StreamGmlHelper method parseInstance.
/**
* Parses an instance with the given type from the given XML stream reader.
*
* @param reader the XML stream reader, the current event must be the start
* element of the instance
* @param type the definition of the instance type
* @param indexInStream the index of the instance in the stream or
* <code>null</code>
* @param strict if associating elements with properties should be done
* strictly according to the schema, otherwise a fall-back is
* used trying to populate values also on invalid property paths
* @param srsDimension the dimension of the instance or <code>null</code>
* @param crsProvider CRS provider in case no CRS is specified, may be
* <code>null</code>
* @param parentType the type of the topmost instance
* @param propertyPath the property path down from the topmost instance, may
* be <code>null</code>
* @param allowNull if a <code>null</code> result is allowed
* @param ignoreNamespaces if parsing of the XML instances should allow
* types and properties with namespaces that differ from those
* defined in the schema
* @param ioProvider the I/O Provider to get value
* @param crs The <code>CRSDefinition</code> to use for geometries
* @return the parsed instance, may be <code>null</code> if allowNull is
* <code>true</code>
* @throws XMLStreamException if parsing the instance failed
*/
public static Instance parseInstance(XMLStreamReader reader, TypeDefinition type, Integer indexInStream, boolean strict, Integer srsDimension, CRSProvider crsProvider, TypeDefinition parentType, List<QName> propertyPath, boolean allowNull, boolean ignoreNamespaces, IOProvider ioProvider, CRSDefinition crs) throws XMLStreamException {
checkState(reader.getEventType() == XMLStreamConstants.START_ELEMENT);
if (propertyPath == null) {
propertyPath = Collections.emptyList();
}
if (srsDimension == null) {
String dim = reader.getAttributeValue(null, "srsDimension");
if (dim != null)
srsDimension = Integer.parseInt(dim);
}
// extract additional settings from I/O provider
boolean suppressParsingGeometry = ioProvider.getParameter(StreamGmlReader.PARAM_SUPPRESS_PARSE_GEOMETRY).as(Boolean.class, false);
MutableInstance instance;
if (indexInStream == null) {
// not necessary to associate data set
instance = new DefaultInstance(type, null);
} else {
instance = new StreamGmlInstance(type, indexInStream);
}
// If the current instance has an srsName attribute, try to resolve the
// corresponding CRS and pass it down the hierarchy and use it for
// nested geometries that don't have their own srsName.
CRSDefinition lastCrs = crs;
String srsName = reader.getAttributeValue(null, "srsName");
if (srsName != null) {
lastCrs = CodeDefinition.tryResolve(srsName);
if (lastCrs == null && crsProvider != null) {
// In case the srsName value could not be resolved to a CRS, try
// to resolve the CRS via the crsProvider.
CRSDefinition unresolvedCrs = new CodeDefinition(srsName);
CRSDefinition resolvedCrs = crsProvider.getCRS(parentType, propertyPath, unresolvedCrs);
// unresolvedCrs unchanged
if (resolvedCrs != null && !resolvedCrs.equals(unresolvedCrs)) {
lastCrs = resolvedCrs;
}
}
// If the provided CRS could not be resolved, it will be ignored
// here silently, so that use cases that don't need the CRS will not
// fail.
}
boolean mixed = type.getConstraint(XmlMixedFlag.class).isEnabled();
if (!mixed) {
// mixed types are treated special (see else)
// check if xsi:nil attribute is there and set to true
String nilString = reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
boolean isNil = nilString != null && "true".equalsIgnoreCase(nilString);
// instance properties
parseProperties(reader, instance, strict, srsDimension, crsProvider, lastCrs, parentType, propertyPath, false, ignoreNamespaces, ioProvider);
// nil instance w/o properties
if (allowNull && isNil && Iterables.isEmpty(instance.getPropertyNames())) {
// no value should be created
/*
* XXX returning null here then results in problems during
* adding other properties to the parent group, as mandatory
* elements are expected to appear, and it will warn about
* possible invalid data loaded
*/
// return null;
}
// instance value
if (!hasElements(type)) {
/*
* Value can only be determined if there are no documents,
* because otherwise elements have already been processed in
* parseProperties and we are already past END_ELEMENT.
*/
if (type.getConstraint(HasValueFlag.class).isEnabled()) {
// try to get text value
String value = reader.getElementText();
if (!isNil && value != null) {
instance.setValue(convertSimple(type, value));
}
}
}
} else {
/*
* XXX For a mixed type currently ignore elements and parse only
* attributes and text.
*/
// instance properties (attributes only)
parseProperties(reader, instance, strict, srsDimension, crsProvider, lastCrs, parentType, propertyPath, true, ignoreNamespaces, ioProvider);
// combined text
String value = readText(reader);
if (value != null) {
instance.setValue(convertSimple(type, value));
}
}
// augmented value XXX should this be an else if?
if (!suppressParsingGeometry && type.getConstraint(AugmentedValueFlag.class).isEnabled()) {
// add geometry as a GeometryProperty value where applicable
GeometryFactory geomFactory = type.getConstraint(GeometryFactory.class);
Object geomValue = null;
// the default value for the srsDimension
int defaultValue = 2;
try {
if (srsDimension != null) {
geomValue = geomFactory.createGeometry(instance, srsDimension, ioProvider);
} else {
// srsDimension is not set
geomValue = geomFactory.createGeometry(instance, defaultValue, ioProvider);
}
} catch (Exception e) {
/*
* Catch IllegalArgumentException that e.g. occurs if a linear
* ring has to few points. NullPointerExceptions may occur
* because an internal geometry could not be created.
*
* XXX a problem is that these messages will not appear in the
* report
*/
log.error("Error creating geometry", e);
}
if (geomValue != null && crsProvider != null && propertyPath != null) {
// check if CRS are set, and if not, try determining them using
// the CRS provider
Collection<?> values;
if (geomValue instanceof Collection) {
values = (Collection<?>) geomValue;
} else {
values = Collections.singleton(geomValue);
}
List<Object> resultVals = new ArrayList<Object>();
for (Object value : values) {
if (value instanceof Geometry || (value instanceof GeometryProperty<?> && ((GeometryProperty<?>) value).getCRSDefinition() == null)) {
// try to resolve value of srsName attribute
CRSDefinition geometryCrs = crsProvider.getCRS(parentType, propertyPath, lastCrs);
if (geometryCrs != null) {
Geometry geom = (value instanceof Geometry) ? ((Geometry) value) : (((GeometryProperty<?>) value).getGeometry());
resultVals.add(new DefaultGeometryProperty<Geometry>(geometryCrs, geom));
continue;
}
}
resultVals.add(value);
}
if (resultVals.size() == 1) {
geomValue = resultVals.get(0);
} else {
geomValue = resultVals;
}
}
if (geomValue != null) {
instance.setValue(geomValue);
}
}
return instance;
}
use of eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty in project hale by halestudio.
the class AbstractInstancePainter method createWaypoint.
/**
* Create a way-point for an instance
*
* @param instance the instance
* @param instanceService the instance service
* @return the created way-point or <code>null</code> if
*/
protected InstanceWaypoint createWaypoint(Instance instance, InstanceService instanceService) {
// retrieve instance reference
// ,
InstanceReference ref = instanceService.getReference(instance);
// getDataSet());
BoundingBox bb = null;
List<GeometryProperty<?>> geometries = new ArrayList<GeometryProperty<?>>(DefaultGeometryUtil.getDefaultGeometries(instance));
ListIterator<GeometryProperty<?>> it = geometries.listIterator();
while (it.hasNext()) {
GeometryProperty<?> prop = it.next();
// check if geometry is valid for display in map
CoordinateReferenceSystem crs = (prop.getCRSDefinition() == null) ? (null) : (prop.getCRSDefinition().getCRS());
if (crs == null) {
// no CRS, can't display in map
// remove from list
it.remove();
} else {
Geometry geometry = prop.getGeometry();
// determine geometry bounding box
BoundingBox geometryBB = BoundingBox.compute(geometry);
if (geometryBB == null) {
// no valid bounding box for geometry
it.remove();
} else {
try {
// get converter to way-point CRS
CRSConverter conv = CRSConverter.getConverter(crs, getWaypointCRS());
// convert BB to way-point SRS
geometryBB = conv.convert(geometryBB);
// add to instance bounding box
if (bb == null) {
bb = new BoundingBox(geometryBB);
} else {
bb.add(geometryBB);
}
} catch (Exception e) {
log.error("Error converting instance bounding box to waypoint bounding box", e);
// ignore geometry
it.remove();
}
}
}
}
if (bb == null || geometries.isEmpty()) {
// don't create way-point w/o geometries
return null;
}
// use bounding box center as GEO position
Point3D center = bb.getCenter();
GeoPosition pos = new GeoPosition(center.getX(), center.getY(), GenericWaypoint.COMMON_EPSG);
// buffer bounding box if x or y dimension empty
if (bb.getMinX() == bb.getMaxX()) {
bb.setMinX(bb.getMinX() - BUFFER_VALUE);
bb.setMaxX(bb.getMaxX() + BUFFER_VALUE);
}
if (bb.getMinY() == bb.getMaxY()) {
bb.setMinY(bb.getMinY() - BUFFER_VALUE);
bb.setMaxY(bb.getMaxY() + BUFFER_VALUE);
}
// set dummy z range (otherwise the RTree can't deal correctly with it)
bb.setMinZ(-BUFFER_VALUE);
bb.setMaxZ(BUFFER_VALUE);
String name = findInstanceName(instance);
// create the way-point
// XXX in abstract method?
InstanceWaypoint wp = new InstanceWaypoint(pos, bb, ref, geometries, instance.getDefinition(), name);
// each way-point must have its own marker, as the marker stores the
// marker areas
wp.setMarker(createMarker(wp));
return wp;
}
Aggregations