use of eu.esdihumboldt.hale.common.instance.model.MutableInstance in project hale by halestudio.
the class PropertyResolverTest method testLoadShiporderWrapped.
/**
* Test with a wrapper instance that has no definition itself.
*
* @throws Exception if an error occurs
*/
@Test
public void testLoadShiporderWrapped() throws Exception {
InstanceCollection instances = loadXMLInstances(getClass().getResource("/data/shiporder/shiporder.xsd").toURI(), getClass().getResource("/data/shiporder/shiporder.xml").toURI());
ResourceIterator<Instance> it = instances.iterator();
try {
assertTrue(it.hasNext());
Instance instance = it.next();
assertNotNull(instance);
// create dummy instance
MutableInstance wrapperInstance = new DefaultInstance(null, null);
wrapperInstance.addProperty(new QName("value"), instance);
assertEquals(PropertyResolver.getValues(wrapperInstance, "value.shipto.city").iterator().next(), "4000 Stavanger");
} finally {
it.close();
}
}
use of eu.esdihumboldt.hale.common.instance.model.MutableInstance in project hale by halestudio.
the class FilterTest method simpleFilterTestCQL.
@Test
public void simpleFilterTestCQL() throws CQLException {
DefaultTypeDefinition stringType = new DefaultTypeDefinition(new QName("StringType"));
stringType.setConstraint(Binding.get(String.class));
DefaultTypeDefinition personDef = new DefaultTypeDefinition(new QName("PersonType"));
personDef.addChild(new DefaultPropertyDefinition(new QName("Name"), personDef, stringType));
DefaultTypeDefinition autoDef = new DefaultTypeDefinition(new QName("AutoType"));
autoDef.addChild(new DefaultPropertyDefinition(new QName("Name"), autoDef, stringType));
autoDef.addChild(new DefaultPropertyDefinition(new QName("Besitzer"), autoDef, personDef));
MutableInstance auto = new DefaultInstance(autoDef, null);
auto.addProperty(new QName("Name"), "Mein Porsche");
MutableInstance ich = new DefaultInstance(personDef, null);
ich.addProperty(new QName("Name"), "Ich");
auto.addProperty(new QName("Besitzer"), ich);
Filter filter;
filter = new FilterGeoCqlImpl("Name = 'Mein Porsche'");
assertTrue(filter.match(auto));
Filter filter1 = new FilterGeoCqlImpl("Name like 'Porsche'");
assertFalse(filter1.match(auto));
Filter filter2 = new FilterGeoCqlImpl("Name like '%Porsche'");
assertTrue(filter2.match(auto));
}
use of eu.esdihumboldt.hale.common.instance.model.MutableInstance 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.instance.model.MutableInstance 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.instance.model.MutableInstance in project hale by halestudio.
the class PropertiesMergeHandler method merge.
@Override
protected Instance merge(InstanceCollection instances, TypeDefinition type, DeepIterableKey mergeKey, PropertiesMergeConfig mergeConfig) {
if (instances.hasSize() && instances.size() == 1) {
// early exit if only one instance to merge
try (ResourceIterator<Instance> it = instances.iterator()) {
return it.next();
}
}
MutableInstance result = getInstanceFactory().createInstance(type);
/*
* FIXME This a first VERY basic implementation, where only the first
* item in each property path is regarded, and that whole tree is added
* only once (from the first instance). XXX This especially will be a
* problem, if a path contains a choice. XXX For more advanced stuff we
* need more advanced test cases.
*/
Set<QName> rootNames = new HashSet<QName>();
Set<QName> nonKeyRootNames = new HashSet<QName>();
// collect path roots
for (List<QName> path : mergeConfig.keyProperties) {
rootNames.add(path.get(0));
}
for (List<QName> path : mergeConfig.additionalProperties) {
nonKeyRootNames.add(path.get(0));
}
// XXX what about metadata?!
// XXX for now only retain IDs
Set<Object> ids = new HashSet<Object>();
try (ResourceIterator<Instance> it = instances.iterator()) {
while (it.hasNext()) {
Instance instance = it.next();
for (QName name : instance.getPropertyNames()) {
if (rootNames.contains(name)) {
/*
* Property is merge key -> only use first occurrence
* (as all entries need to be the same)
*
* TODO adapt if multiple keys are possible per instance
*/
addFirstOccurrence(result, instance, name);
} else if (nonKeyRootNames.contains(name)) {
/*
* Property is additional merge property.
*
* Traditional behavior: Only keep unique values.
*
* XXX should this be configurable?
*/
addUnique(result, instance, name);
} else if (mergeConfig.autoDetect) {
/*
* Auto-detection is enabled.
*
* Only keep unique values.
*
* XXX This differs from the traditional behavior in
* that there only the first value would be used, but
* only if all values were equal. That cannot be easily
* checked in an iterative approach.
*/
addUnique(result, instance, name);
} else {
/*
* Property is not to be merged.
*
* XXX but we could do some kind of aggregation
*
* XXX for now just add all values
*/
addValues(result, instance, name);
}
}
List<Object> instanceIDs = instance.getMetaData(InstanceMetadata.METADATA_ID);
for (Object id : instanceIDs) {
ids.add(id);
}
}
}
// store metadata IDs
result.setMetaData(InstanceMetadata.METADATA_ID, ids.toArray());
return result;
}
Aggregations