use of eu.esdihumboldt.hale.common.schema.model.PropertyDefinition 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.schema.model.PropertyDefinition in project hale by halestudio.
the class StreamGmlWriter method writeProperties.
/**
* Write attribute or element properties.
*
* @param parent the parent group
* @param children the child definitions
* @param attributes <code>true</code> if attribute properties shall be
* written, <code>false</code> if element properties shall be
* written
* @param parentIsNil if the parent property is nil
* @param report the reporter
* @throws XMLStreamException if writing the attributes/elements fails
*/
private void writeProperties(Group parent, Collection<? extends ChildDefinition<?>> children, boolean attributes, boolean parentIsNil, IOReporter report) throws XMLStreamException {
if (parent == null) {
return;
}
boolean parentIsChoice = parent.getDefinition() instanceof GroupPropertyDefinition && ((GroupPropertyDefinition) parent.getDefinition()).getConstraint(ChoiceFlag.class).isEnabled();
for (ChildDefinition<?> child : children) {
Object[] values = parent.getProperty(child.getName());
if (child.asProperty() != null) {
PropertyDefinition propDef = child.asProperty();
boolean isAttribute = propDef.getConstraint(XmlAttributeFlag.class).isEnabled();
if (attributes && isAttribute) {
if (values != null && values.length > 0) {
boolean allowWrite = true;
// special case handling: omit nilReason
if (getParameter(PARAM_OMIT_NIL_REASON).as(Boolean.class, true)) {
Cardinality propCard = propDef.getConstraint(Cardinality.class);
if ("nilReason".equals(propDef.getName().getLocalPart()) && propCard.getMinOccurs() < 1) {
allowWrite = parentIsNil;
}
}
// write attribute
if (allowWrite) {
// nilReason "unpopulated"
if ("nilReason".equals(propDef.getName().getLocalPart()) && "unpopulated".equals(values[0])) {
// TODO more strict check to ensure that this is
// a GML nilReason? (check property type and
// parent types)
writeAttribute("other:unpopulated", propDef);
} else {
// default
writeAttribute(values[0], propDef);
}
}
if (values.length > 1) {
// TODO warning?!
}
}
} else if (!attributes && !isAttribute) {
int numValues = 0;
if (values != null) {
// write element
for (Object value : values) {
writeElement(value, propDef, report);
}
numValues = values.length;
}
// only if parent is not a choice
if (!parentIsChoice) {
Cardinality cardinality = propDef.getConstraint(Cardinality.class);
if (cardinality.getMinOccurs() > numValues) {
if (propDef.getConstraint(NillableFlag.class).isEnabled()) {
// nillable element
for (int i = numValues; i < cardinality.getMinOccurs(); i++) {
// write nil element
writeElement(null, propDef, report);
}
} else {
for (int i = numValues; i < cardinality.getMinOccurs(); i++) {
// write empty element
GmlWriterUtil.writeEmptyElement(writer, propDef.getName());
}
// TODO add warning to report
}
}
}
}
} else if (child.asGroup() != null) {
// handle to child groups
if (values != null) {
for (Object value : values) {
if (value instanceof Group) {
writeProperties((Group) value, DefinitionUtil.getAllChildren(child.asGroup()), attributes, parentIsNil, report);
} else {
// TODO warning/error?
}
}
}
}
}
}
use of eu.esdihumboldt.hale.common.schema.model.PropertyDefinition in project hale by halestudio.
the class AbstractGeometryWriter method writePos.
/**
* Write coordinates into a pos property
*
* @param writer the XML stream writer
* @param coordinates the coordinates to write
* @param elementType the type of the encompassing element
* @param gmlNs the GML namespace
* @param posName the name of the desired DirectPositionType property, or
* <code>null</code> if any
* @param decimalFormatter a decimal formatter to format geometry
* coordinates or <code>null</code> to use
* <code>Double.toString()</code>
* @return if writing the coordinates was successful
* @throws XMLStreamException if an error occurs writing the coordinates
*/
protected static boolean writePos(XMLStreamWriter writer, Coordinate[] coordinates, TypeDefinition elementType, String gmlNs, String posName, DecimalFormat decimalFormatter) throws XMLStreamException {
PropertyDefinition posAttribute = null;
// XXX is this enough? or must groups be handled?
for (PropertyDefinition att : DefinitionUtil.getAllProperties(elementType)) {
if (att.getPropertyType().getName().equals(new QName(gmlNs, "DirectPositionType"))) {
// found a property with DirectPositionType
if (posName == null || posName.equals(att.getName().getLocalPart())) {
posAttribute = att;
break;
}
}
}
if (posAttribute != null) {
// TODO possibly write repeated positions
writer.writeStartElement(posAttribute.getName().getNamespaceURI(), posAttribute.getName().getLocalPart());
// write coordinates separated by spaces
if (coordinates.length > 0) {
Coordinate coordinate = coordinates[0];
writer.writeCharacters(DecimalFormatUtil.applyFormatter(coordinate.x, decimalFormatter));
// $NON-NLS-1$
writer.writeCharacters(" ");
writer.writeCharacters(DecimalFormatUtil.applyFormatter(coordinate.y, decimalFormatter));
if (!Double.isNaN(coordinate.z)) {
// $NON-NLS-1$
writer.writeCharacters(" ");
writer.writeCharacters(DecimalFormatUtil.applyFormatter(coordinate.z, decimalFormatter));
}
}
writer.writeEndElement();
return true;
} else {
return false;
}
}
use of eu.esdihumboldt.hale.common.schema.model.PropertyDefinition in project hale by halestudio.
the class FunctionExecutor method convert.
/**
* Convert a value according to a target property entity definition.
*
* @param value the value to convert
* @param propertyEntityDefinition the target property entity definition
* @return the converted object
* @throws ConversionException if an error occurs during conversion
*/
private Object convert(Object value, PropertyEntityDefinition propertyEntityDefinition) throws ConversionException {
if (value == null) {
return null;
}
PropertyDefinition def = propertyEntityDefinition.getDefinition();
Binding binding = def.getPropertyType().getConstraint(Binding.class);
Class<?> target = binding.getBinding();
// special handling for Value
if (value instanceof Value) {
// try value's internal conversion
Object result = ((Value) value).as(target);
if (result != null) {
return result;
} else {
// unwrap value
value = ((Value) value).getValue();
if (value == null) {
return null;
}
}
}
if (target.isAssignableFrom(value.getClass())) {
return value;
}
if (Collection.class.isAssignableFrom(target) && target.isAssignableFrom(List.class)) {
// collection / list
ElementType elementType = def.getPropertyType().getConstraint(ElementType.class);
return ConversionUtil.getAsList(value, elementType.getBinding(), true);
}
return ConversionUtil.getAs(value, target);
}
use of eu.esdihumboldt.hale.common.schema.model.PropertyDefinition in project hale by halestudio.
the class GenerateDuplicates method generateMapping.
private void generateMapping() {
System.out.println("Indexing example cells...");
// index all cells based on the target property name
SetMultimap<String, Cell> exampleCells = HashMultimap.create();
for (Cell cell : examples.getCells()) {
if (cell.getTarget().size() == 1) {
// only supports cells with one target
EntityDefinition entityDef = CellUtil.getFirstEntity(cell.getTarget()).getDefinition();
if (entityDef.getDefinition() instanceof PropertyDefinition) {
if (ADE_NS.equals(entityDef.getDefinition().getName().getNamespaceURI())) {
exampleCells.put(entityDef.getDefinition().getName().getLocalPart(), cell);
} else
System.out.println("WARNING: ignoring cell with non-ADE target property");
} else
System.out.println("WARNING: ignoring type cell");
} else
System.out.println("WARNING: ignoring cell with multiple or no targets");
}
// collect all ADE feature types
List<TypeDefinition> featureTypes = BGISAppUtil.getADEFeatureTypes(targetSchema);
// visit ADE properties and create cells
System.out.println("Generating mapping from example cells for");
String cellNote = MessageFormat.format("Generated through duplication of example cells on BGIS ADE feature types.\n" + "{0,date,medium}", new Date());
DuplicateVisitor visitor = new DuplicateVisitor(exampleCells, cellNote);
for (TypeDefinition type : featureTypes) {
System.out.println(type.getDisplayName() + "...");
visitor.accept(new TypeEntityDefinition(type, SchemaSpaceID.TARGET, null));
}
if (visitor.getCells().isEmpty()) {
System.out.println("WARNING: no cells were created");
} else {
System.out.println(visitor.getCells().size() + " cells were created.");
}
// create alignment
MutableAlignment align = new DefaultAlignment();
for (MutableCell cell : visitor.getCells()) {
align.addCell(cell);
}
this.alignment = align;
}
Aggregations