use of eu.esdihumboldt.hale.io.gml.writer.internal.geometry.DefinitionPath in project hale by halestudio.
the class Pattern method match.
/**
* Matches the type against the encoding pattern.
*
* @param type the type definition
* @param path the definition path
* @param gmlNs the GML namespace
* @param checkedTypes the type definitions that have already been checked
* (to prevent cycles)
* @param remainingElements the remaining elements to match
*
* @return the new path if there is a match, <code>null</code> otherwise
*/
private static DefinitionPath match(TypeDefinition type, DefinitionPath path, String gmlNs, HashSet<TypeDefinition> checkedTypes, List<PatternElement> remainingElements) {
if (remainingElements == null || remainingElements.isEmpty()) {
return null;
}
if (checkedTypes.contains(type)) {
return null;
} else {
checkedTypes.add(type);
}
PatternElement first = remainingElements.get(0);
PatternElement checkAgainst;
boolean allowAttributeDescent;
boolean removeFirstForAttributeDescent = false;
boolean allowSubtypeDescent = true;
switch(first.getType()) {
case ONE_ELEMENT:
// only descend
checkAgainst = null;
allowAttributeDescent = true;
// first element may not be
removeFirstForAttributeDescent = true;
// special case: was last element
if (remainingElements.size() == 1) {
return path;
}
break;
case ANY_ELEMENTS:
// check against the next named element
PatternElement named = null;
for (int i = 1; i < remainingElements.size() && named == null; i++) {
PatternElement element = remainingElements.get(i);
if (element.getType().equals(ElementType.NAMED_ELEMENT)) {
named = element;
}
}
if (named == null) {
// no named element
return null;
} else {
checkAgainst = named;
}
allowAttributeDescent = true;
break;
case NAMED_ELEMENT:
// check the current
checkAgainst = first;
// only allow sub-type descent
allowAttributeDescent = false;
break;
default:
// $NON-NLS-1$
throw new IllegalStateException("Unknown pattern element type");
}
if (checkAgainst != null) {
// get the last path element
QName elementName = path.getLastName();
QName name = checkAgainst.getName();
// inject namespace if needed
if (name.getNamespaceURI() == GML_NAMESPACE_PLACEHOLDER) {
name = new QName(gmlNs, name.getLocalPart());
}
// check direct match
if (name.equals(elementName)) {
// match for the element name -> we are on the right track
int index = remainingElements.indexOf(checkAgainst);
if (index == remainingElements.size() - 1) {
// is last - we have a full match
return path;
}
// remove the element (and any leading wildcards) from the queue
remainingElements = remainingElements.subList(index + 1, remainingElements.size());
// for a name match, no sub-type descent is allowed
allowSubtypeDescent = false;
// but an attribute descent is ok
allowAttributeDescent = true;
} else {
// no name match
// sub-type descent is still allowed, don't remove element
}
}
if (allowSubtypeDescent) {
// step down sub-types
// XXX now represented in choices
// XXX sub-type must work through parent choice
// for (SchemaElement element : type.getSubstitutions(path.getLastName())) {
// DefinitionPath candidate = match(
// element.getType(),
// new DefinitionPath(path).addSubstitution(element),
// gmlNs,
// new HashSet<TypeDefinition>(checkedTypes),
// new ArrayList<PatternElement>(remainingElements));
//
// if (candidate != null) {
// return candidate;
// }
// }
}
if (allowAttributeDescent) {
if (removeFirstForAttributeDescent) {
remainingElements.remove(0);
}
// step down properties
@java.lang.SuppressWarnings("unchecked") Iterable<ChildDefinition<?>> children = (Iterable<ChildDefinition<?>>) ((path.isEmpty()) ? (type.getChildren()) : (type.getDeclaredChildren()));
Iterable<DefinitionPath> childPaths = GmlWriterUtil.collectPropertyPaths(children, path, true);
for (DefinitionPath childPath : childPaths) {
DefinitionPath candidate = match(childPath.getLastType(), childPath, gmlNs, new HashSet<TypeDefinition>(checkedTypes), new ArrayList<PatternElement>(remainingElements));
if (candidate != null) {
return candidate;
}
}
}
return null;
}
use of eu.esdihumboldt.hale.io.gml.writer.internal.geometry.DefinitionPath in project hale by halestudio.
the class PatternTest method testDirect.
/**
* Test a direct match
*/
@Ignore
@Test
public void testDirect() {
// $NON-NLS-1$
Pattern pattern = Pattern.parse("Curve");
TypeDefinition start = createCurveType();
DefinitionPath path = pattern.match(start, new DefinitionPath(start, CURVE_ELEMENT, false), GML_NS);
// $NON-NLS-1$
assertNotNull("A match should have been found", path);
// $NON-NLS-1$
assertTrue("Path should be empty", path.isEmpty());
assertEquals(start, path.getLastType());
}
use of eu.esdihumboldt.hale.io.gml.writer.internal.geometry.DefinitionPath in project hale by halestudio.
the class StreamGmlWriter method write.
/**
* Write the given instances to an {@link XMLStreamWriter}.<br>
* <br>
* Use {@link #createWriter(OutputStream, IOReporter)} to create a properly
* configured writer for this method.
*
* @param instances the instance collection
* @param writer the writer to write the instances to
* @param reporter the reporter
* @param progress the progress
* @see #createWriter(OutputStream, IOReporter)
*/
protected void write(InstanceCollection instances, PrefixAwareStreamWriter writer, ProgressIndicator progress, IOReporter reporter) {
this.writer = writer;
try {
final SubtaskProgressIndicator sub = new SubtaskProgressIndicator(progress) {
@Override
protected String getCombinedTaskName(String taskName, String subtaskName) {
return taskName + " (" + subtaskName + ")";
}
};
progress = sub;
progress.begin(getTaskName(), instances.size());
XmlElement container = findDefaultContainter(targetIndex, reporter);
TypeDefinition containerDefinition = (container == null) ? (null) : (container.getType());
QName containerName = (container == null) ? (null) : (container.getName());
if (containerDefinition == null) {
XmlElement containerElement = getConfiguredContainerElement(this, getXMLIndex());
containerDefinition = containerElement.getType();
containerName = containerElement.getName();
}
if (containerDefinition == null || containerName == null) {
throw new IllegalStateException("No root element/container found");
}
/*
* Add schema for container to validation schemas, if the namespace
* differs from the main namespace or additional schemas.
*
* Needed for validation based on schemaLocation attribute.
*/
if (!containerName.getNamespaceURI().equals(targetIndex.getNamespace()) && !additionalSchemas.containsKey(containerName.getNamespaceURI())) {
try {
@SuppressWarnings("null") final URI containerSchemaLoc = stripFragment(container.getLocation());
if (containerSchemaLoc != null) {
addValidationSchema(containerName.getNamespaceURI(), new Locatable() {
@Override
public URI getLocation() {
return containerSchemaLoc;
}
}, null);
}
} catch (Exception e) {
reporter.error(new IOMessageImpl("Could not determine location of container definition", e));
}
}
// additional schema namespace prefixes
for (Entry<String, String> schemaNs : additionalSchemaPrefixes.entrySet()) {
GmlWriterUtil.addNamespace(writer, schemaNs.getKey(), schemaNs.getValue());
}
writer.writeStartDocument();
if (documentWrapper != null) {
documentWrapper.startWrap(writer, reporter);
}
GmlWriterUtil.writeStartElement(writer, containerName);
// generate mandatory id attribute (for feature collection)
String containerId = getParameter(PARAM_CONTAINER_ID).as(String.class);
GmlWriterUtil.writeID(writer, containerDefinition, null, false, containerId);
// write schema locations
StringBuffer locations = new StringBuffer();
String noNamespaceLocation = null;
if (targetIndex.getNamespace() != null && !targetIndex.getNamespace().isEmpty()) {
locations.append(targetIndex.getNamespace());
// $NON-NLS-1$
locations.append(" ");
locations.append(targetIndex.getLocation().toString());
} else {
noNamespaceLocation = targetIndex.getLocation().toString();
}
for (Entry<String, Locatable> schema : additionalSchemas.entrySet()) {
if (schema.getKey() != null && !schema.getKey().isEmpty()) {
if (locations.length() > 0) {
// $NON-NLS-1$
locations.append(" ");
}
locations.append(schema.getKey());
// $NON-NLS-1$
locations.append(" ");
locations.append(schema.getValue().getLocation().toString());
} else {
noNamespaceLocation = schema.getValue().getLocation().toString();
}
}
if (locations.length() > 0) {
// $NON-NLS-1$
writer.writeAttribute(SCHEMA_INSTANCE_NS, "schemaLocation", locations.toString());
}
if (noNamespaceLocation != null) {
// $NON-NLS-1$
writer.writeAttribute(// $NON-NLS-1$
SCHEMA_INSTANCE_NS, // $NON-NLS-1$
"noNamespaceSchemaLocation", noNamespaceLocation);
}
writeAdditionalElements(writer, containerDefinition, reporter);
// write the instances
ResourceIterator<Instance> itInstance = instances.iterator();
try {
Map<TypeDefinition, DefinitionPath> paths = new HashMap<TypeDefinition, DefinitionPath>();
long lastUpdate = 0;
int count = 0;
Descent lastDescent = null;
while (itInstance.hasNext() && !progress.isCanceled()) {
Instance instance = itInstance.next();
TypeDefinition type = instance.getDefinition();
/*
* Skip all objects that are no features when writing to a
* GML feature collection.
*/
boolean skip = useFeatureCollection && !GmlWriterUtil.isFeatureType(type);
if (skip) {
progress.advance(1);
continue;
}
// get stored definition path for the type
DefinitionPath defPath;
if (paths.containsKey(type)) {
// get the stored path, may be null
defPath = paths.get(type);
} else {
// determine a valid definition path in the container
defPath = findMemberAttribute(containerDefinition, containerName, type);
// store path (may be null)
paths.put(type, defPath);
}
if (defPath != null) {
// write the feature
lastDescent = Descent.descend(writer, defPath, lastDescent, false);
writeMember(instance, type, reporter);
} else {
reporter.warn(new IOMessageImpl(MessageFormat.format("No compatible member attribute for type {0} found in root element {1}, one instance was skipped", type.getDisplayName(), containerName.getLocalPart()), null));
}
progress.advance(1);
count++;
long now = System.currentTimeMillis();
// only update every 100 milliseconds
if (now - lastUpdate > 100 || !itInstance.hasNext()) {
lastUpdate = now;
sub.subTask(String.valueOf(count) + " instances");
}
}
if (lastDescent != null) {
lastDescent.close();
}
} finally {
itInstance.close();
}
// FeatureCollection
writer.writeEndElement();
if (documentWrapper != null) {
documentWrapper.endWrap(writer, reporter);
}
writer.writeEndDocument();
writer.close();
reporter.setSuccess(reporter.getErrors().isEmpty());
} catch (Exception e) {
reporter.error(new IOMessageImpl(e.getLocalizedMessage(), e));
reporter.setSuccess(false);
} finally {
progress.end();
}
}
use of eu.esdihumboldt.hale.io.gml.writer.internal.geometry.DefinitionPath in project hale by halestudio.
the class XsltGenerator method writeContainerFragment.
/**
* Write the container fragment.
*
* @param templateFile the file to write to
* @param groupedResults the result variable names grouped by associated
* target type
* @param targetElements an empty map that is populated with variable names
* mapped to target element names
* @throws IOException if an error occurs writing the template
* @throws XMLStreamException if an error occurs writing XML content to the
* template
*/
private void writeContainerFragment(File templateFile, Multimap<TypeDefinition, String> groupedResults, Map<String, QName> targetElements) throws XMLStreamException, IOException {
XMLStreamWriter writer = XslTransformationUtil.setupXMLWriter(new BufferedOutputStream(new FileOutputStream(templateFile)), prefixes);
try {
// write container
GmlWriterUtil.writeStartElement(writer, targetContainer.getName());
// generate an eventual required identifier on the container
GmlWriterUtil.writeRequiredID(writer, targetContainer.getType(), null, false);
writeContainerIntro(writer, context);
// cache definition paths
Map<TypeDefinition, DefinitionPath> paths = new HashMap<TypeDefinition, DefinitionPath>();
Descent lastDescent = null;
for (Entry<TypeDefinition, String> entry : groupedResults.entries()) {
TypeDefinition type = entry.getKey();
// get stored definition path for the type
DefinitionPath defPath;
if (paths.containsKey(type)) {
// get the stored path, may be null
defPath = paths.get(type);
} else {
// determine a valid definition path in the container
defPath = findMemberAttribute(targetContainer, type);
// store path (may be null)
paths.put(type, defPath);
}
if (defPath != null) {
// insert xsl:for-each at the appropriate position in
// the path
defPath = pathInsertForEach(defPath, entry.getValue(), targetElements);
lastDescent = Descent.descend(writer, defPath, lastDescent, false, true);
// write single target instance from variable
GmlWriterUtil.writeEmptyElement(writer, new QName(NS_URI_XSL, "copy-of"));
writer.writeAttribute("select", ".");
} else {
reporter.warn(new IOMessageImpl(MessageFormat.format("No compatible member attribute for type {0} found in root element {1}, one instance was skipped", type.getDisplayName(), targetContainer.getName().getLocalPart()), null));
}
}
if (lastDescent != null) {
lastDescent.close();
}
// end container
writer.writeEndElement();
} finally {
writer.close();
}
}
use of eu.esdihumboldt.hale.io.gml.writer.internal.geometry.DefinitionPath in project hale by halestudio.
the class PatternTest method testDirectFail.
/**
* Test a direct match that should fails
*/
@Test
public void testDirectFail() {
// $NON-NLS-1$
Pattern pattern = Pattern.parse("CurveType");
TypeDefinition start = createCurveType();
DefinitionPath path = pattern.match(start, new DefinitionPath(start, CURVE_ELEMENT, false), GML_NS);
// $NON-NLS-1$
assertNull("A match should not have been found", path);
}
Aggregations