use of eu.esdihumboldt.hale.common.instance.model.MutableGroup in project hale by halestudio.
the class GroupPath method isValid.
/**
* Determines if the group path in this configuration is valid in respect to
* the creation of new groups based on the contained definition groups.
*
* @return if the path is valid
*/
public boolean isValid() {
if (children == null || children.isEmpty()) {
// parents is assumed to be valid
return true;
}
MutableGroup parentGroup = parents.get(parents.size() - 1);
DefinitionGroup parentDef = parentGroup.getDefinition();
for (DefinitionGroup child : children) {
if (child instanceof GroupPropertyDefinition) {
if (!GroupUtil.allowAdd(parentGroup, parentDef, ((GroupPropertyDefinition) child).getName())) {
return false;
}
} else {
// XXX TypeDefinitions not supported in path
return false;
}
// prepare next iteration
parentGroup = null;
parentDef = child;
}
return true;
}
use of eu.esdihumboldt.hale.common.instance.model.MutableGroup in project hale by halestudio.
the class GroupPath method createChildGroups.
/**
* Create groups for the children in the path (which are only represented as
* definitions). May only be called if the path is valid. This will also
* update the path to include the groups instead of the definitions.
*
* @return the list of created groups
*
* @see #isValid()
*/
protected List<MutableGroup> createChildGroups() {
MutableGroup parent = parents.get(parents.size() - 1);
final List<MutableGroup> result = new ArrayList<MutableGroup>();
for (DefinitionGroup child : children) {
checkState(child instanceof GroupPropertyDefinition);
// create group
MutableGroup group = new DefaultGroup(child);
// add to parent
QName propertyName = ((GroupPropertyDefinition) child).getName();
parent.addProperty(propertyName, group);
// add to result
result.add(group);
// prepare for next iteration
parent = group;
}
// update children and parents
children.clear();
parents.addAll(result);
return result;
}
use of eu.esdihumboldt.hale.common.instance.model.MutableGroup in project hale by halestudio.
the class GroupUtil method determineProperty.
/**
* Determine the property definition for the given property name.
*
* @param groups the stack of the current group objects. The topmost element
* is the current group object
* @param propertyName the property name
* @param strict states if for assessing possible property definitions
* strict checks regarding the structure are applied
* @param allowFallback states if with strict mode being enabled, falling
* back to non-strict mode is allowed (this will not be
* propagated to subsequent calls)
* @param ignoreNamespaces if a property with a differing namespace may be
* accepted
* @return the group property or <code>null</code> if none is found
*/
private static GroupProperty determineProperty(List<MutableGroup> groups, QName propertyName, boolean strict, boolean allowFallback, boolean ignoreNamespaces) {
if (groups.isEmpty()) {
return null;
}
// the current group
final MutableGroup currentGroup = groups.get(groups.size() - 1);
// the queue to collect the siblings of the current group with
LinkedList<GroupPath> siblings = new LinkedList<GroupPath>();
/*
* Policy: find the property as high in the hierarchy as possible
*
* This might lead to problems with some special schemas, e.g. if a
* group is defined that allows unbounded occurrences of an element X
* and the parent type allows one occurrence there will be trouble if we
* have more than two or three of those elements (depending on group and
* element cardinalities).
*
* If this really poses a problem in the practice we might need
* configuration parameters to use different policies. IMHO (ST) in well
* designed schemas this problem will not occur.
*
* This problem only arises because we read all the data from the stream
* and don't know anything about what comes ahead - another possibility
* could be to change this behavior where needed.
*/
// preferred 1: property of a parent group
List<MutableGroup> keep = new ArrayList<MutableGroup>(groups);
List<MutableGroup> close = new ArrayList<MutableGroup>();
// sort groups in those that must be kept and those that may be closed
for (int i = keep.size() - 1; i >= 0 && allowClose(keep.get(i)); i--) {
close.add(0, keep.get(i));
keep.remove(i);
}
if (!close.isEmpty()) {
// collect parents groups
List<MutableGroup> parents = new ArrayList<MutableGroup>(close);
// remove current group
parents.remove(parents.size() - 1);
if (!keep.isEmpty()) {
// insert top allowed parent first
parents.add(0, keep.get(0));
// in list
}
int maxDescent = close.size() - 1;
// prototype that is copied for each parent
List<MutableGroup> stackPrototype = new ArrayList<MutableGroup>(keep);
LinkedList<GroupPath> level = new LinkedList<GroupPath>();
LinkedList<GroupPath> nextLevel = new LinkedList<GroupPath>();
for (int i = 0; i < parents.size(); i++) {
// add existing parent
GroupPath path = new GroupPath(new ArrayList<MutableGroup>(stackPrototype), null);
level.addFirst(path);
GroupProperty gp = null;
// check for a direct match in the group
PropertyDefinition property = determineDirectProperty(parents.get(i), propertyName, strict, ignoreNamespaces);
if (property != null) {
gp = new GroupProperty(property, path);
}
if (gp == null && maxDescent >= 0) {
// >= 0 because also for
// maxDescent 0 we get
// siblings
// check the sub-properties
gp = determineSubProperty(level, propertyName, nextLevel, 0, strict, ignoreNamespaces);
}
if (gp != null) {
return gp;
}
// prepare stack prototype for next parent
if (i + 1 < parents.size()) {
stackPrototype.add(parents.get(i + 1));
}
// swap lists, clear nextLevel
LinkedList<GroupPath> tmp = level;
level = nextLevel;
nextLevel = tmp;
nextLevel.clear();
}
siblings = level;
}
// preferred 2: property of the current group
PropertyDefinition property = determineDirectProperty(currentGroup, propertyName, strict, ignoreNamespaces);
if (property != null) {
return new GroupProperty(property, new GroupPath(groups, null));
}
// preferred 3: property of a sub-group, sibling group or sibling
// sub-group
// add current group
siblings.addFirst(new GroupPath(groups, null));
// check the sub-properties
GroupProperty gp = determineSubProperty(siblings, propertyName, null, -1, strict, ignoreNamespaces);
if (gp != null) {
return gp;
}
if (strict && allowFallback) {
// fall-back: property in any group without validity checks
// XXX though allowClose will still be strict
log.warn(MessageFormat.format("Could not find valid property path for {0}, source data might be invalid regarding the source schema.", propertyName));
return determineProperty(groups, propertyName, false, false, ignoreNamespaces);
}
return null;
}
use of eu.esdihumboldt.hale.common.instance.model.MutableGroup in project hale by halestudio.
the class Rename method structuralRename.
/**
* Performs a structural rename on the given source object to the given
* target definition.
*
* @param source the source value (or group/instance)
* @param targetDefinition the target definition
* @param allowIgnoreNamespaces if for the structure comparison, namespaces
* may be ignored
* @param instanceFactory the instance factory
* @param copyGeometries specifies if geometry objects should be copied
* @return the transformed value (or group/instance) or NO_MATCH
*/
public static Object structuralRename(Object source, ChildDefinition<?> targetDefinition, boolean allowIgnoreNamespaces, InstanceFactory instanceFactory, boolean copyGeometries) {
if (!(source instanceof Group)) {
// source simple value
if (targetDefinition.asProperty() != null) {
// target can have value
TypeDefinition propertyType = targetDefinition.asProperty().getPropertyType();
if (copyGeometries || !isGeometry(source)) {
if (propertyType.getChildren().isEmpty()) {
// simple value
return convertValue(source, targetDefinition.asProperty().getPropertyType());
} else {
// instance with value
MutableInstance instance = instanceFactory.createInstance(propertyType);
instance.setDataSet(DataSet.TRANSFORMED);
instance.setValue(convertValue(source, propertyType));
return instance;
}
} else {
return Result.NO_MATCH;
}
}
}
// source is group or instance
if (targetDefinition.asProperty() != null) {
// target can have value
TypeDefinition propertyType = targetDefinition.asProperty().getPropertyType();
if (source instanceof Instance) {
// source has value
if (propertyType.getChildren().isEmpty()) {
// simple value
return convertValue(((Instance) source).getValue(), targetDefinition.asProperty().getPropertyType());
} else {
// instance with value
MutableInstance instance = instanceFactory.createInstance(targetDefinition.asProperty().getPropertyType());
instance.setDataSet(DataSet.TRANSFORMED);
if (copyGeometries || !isGeometry(((Instance) source).getValue())) {
instance.setValue(convertValue(((Instance) source).getValue(), targetDefinition.asProperty().getPropertyType()));
}
renameChildren((Group) source, instance, targetDefinition, allowIgnoreNamespaces, instanceFactory, copyGeometries);
return instance;
}
} else {
// source has no value
if (targetDefinition.asProperty().getPropertyType().getChildren().isEmpty())
// no match possible
return Result.NO_MATCH;
else {
// instance with no value set
MutableInstance instance = instanceFactory.createInstance(targetDefinition.asProperty().getPropertyType());
instance.setDataSet(DataSet.TRANSFORMED);
if (renameChildren((Group) source, instance, targetDefinition, allowIgnoreNamespaces, instanceFactory, copyGeometries))
return instance;
else
// no child matched and no value
return Result.NO_MATCH;
}
}
} else if (targetDefinition.asGroup() != null) {
// target can not have a value
if (targetDefinition.asGroup().getDeclaredChildren().isEmpty())
// target neither has a value nor
return Result.NO_MATCH;
else // children?
{
// group
MutableGroup group = new DefaultGroup(targetDefinition.asGroup());
if (renameChildren((Group) source, group, targetDefinition, allowIgnoreNamespaces, instanceFactory, copyGeometries))
return group;
else
// no child matched and no value
return Result.NO_MATCH;
}
} else {
// neither asProperty nor asGroup -> illegal ChildDefinition
throw new IllegalStateException("Illegal child type.");
}
}
use of eu.esdihumboldt.hale.common.instance.model.MutableGroup 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;
}
Aggregations