use of org.opengis.feature.FeatureAssociationRole in project geotoolkit by Geomatys.
the class JAXPStreamFeatureReader method readFeature.
private Feature readFeature(final FeatureType featureType, final GenericName tagName) throws XMLStreamException {
final Feature feature = featureType.newInstance();
/*
* We create a map and a collection because we can encounter two cases :
* - The case featureType defines a property with max occur > 1.
* - The case featureType defines a property with max occur = 1, and its
* value instance of collection or map.
* We store all encountered name with its linked property in the map, so
* at each value parsed, we can add it in the existing property if its
* value is a list or map. The collection is the final property store,
* we add the all the created properties in it (so we can put multiple
* properties with the same name).
*/
final List<Entry<Operation, Object>> ops = new ArrayList<>();
// read attributes
final int nbAtts = reader.getAttributeCount();
for (int i = 0; i < nbAtts; i++) {
final QName attName = reader.getAttributeName(i);
if ("href".equals(attName.getLocalPart())) {
// or if can't be resolved we will still have the id
try {
final String attVal = reader.getAttributeValue(i);
feature.setPropertyValue(AttributeConvention.IDENTIFIER, attVal);
} catch (IllegalArgumentException ex) {
// do nothing
}
} else {
try {
final AttributeType pd = (AttributeType) featureType.getProperty("@" + attName.getLocalPart());
final String attVal = reader.getAttributeValue(i);
final Object val = ObjectConverters.convert(attVal, pd.getValueClass());
feature.setPropertyValue(pd.getName().toString(), val);
} catch (PropertyNotFoundException ex) {
// do nothing
}
}
}
boolean doNext = true;
// read a real complex type
while (!doNext || reader.hasNext()) {
if (doNext) {
reader.next();
}
doNext = true;
int event = reader.getEventType();
if (event == START_ELEMENT) {
GenericName propName = nameCache.get(reader.getName());
// we skip the boundedby attribute if it's present
if ("boundedBy".equals(propName.tip().toString())) {
toTagEnd("boundedBy");
continue;
}
final String nameAttribute = reader.getAttributeValue(null, "name");
// search property
PropertyType propertyType = null;
FeatureType associationSubType = null;
// search direct name
try {
propertyType = featureType.getProperty(propName.toString());
} catch (PropertyNotFoundException e) {
/*can happen*/
}
// search using only local part
if (propertyType == null) {
try {
propertyType = featureType.getProperty(propName.tip().toString());
} catch (PropertyNotFoundException e) {
/*can happen*/
}
}
// search if we are dealing with a subtype of a feature association role value type
if (propertyType == null) {
try {
final FeatureType candidate = featureTypes.get(propName.toString());
if (candidate != null) {
// search for a FeatureAssociationRole
for (PropertyType pt : featureType.getProperties(true)) {
if (pt instanceof FeatureAssociationRole) {
final FeatureAssociationRole far = (FeatureAssociationRole) pt;
final FeatureType vt = far.getValueType();
if (vt.isAssignableFrom(candidate)) {
propertyType = far;
associationSubType = candidate;
// change property name where data will be stored
propName = far.getName();
break;
}
}
}
}
} catch (IllegalNameException ex) {
Logger.getLogger(JAXPStreamFeatureReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
// skip property if we couldn't find it and user requested it
if (propertyType == null && Boolean.TRUE.equals(this.properties.get(SKIP_UNEXPECTED_PROPERTY_TAGS))) {
toTagEnd(propName.tip().toString());
continue;
}
// search if we have an _any attribute available
if (propertyType == null) {
try {
final AttributeType pd = (AttributeType) featureType.getProperty("_any");
// convert the content as a dom node
final Document doc = readAsDom(propName.tip().toString());
feature.setPropertyValue(pd.getName().toString(), doc);
doNext = false;
continue;
} catch (PropertyNotFoundException e) {
throw new XMLStreamException("Could not find any property fitting named tag " + propName);
}
}
if (propertyType instanceof Operation) {
final Operation opType = (Operation) propertyType;
final PropertyType resultType = (PropertyType) opType.getResult();
final Object value = readPropertyValue(resultType, null, null);
ops.add(new AbstractMap.SimpleImmutableEntry<>((Operation) propertyType, value));
if (resultType.getName().equals(propertyType.getName())) {
// we are already on the next element here, jaxb ate one
doNext = false;
}
continue;
}
// read attributes
if (propertyType instanceof AttributeType) {
final AttributeType<?> attType = (AttributeType) propertyType;
final int nbPropAtts = reader.getAttributeCount();
if (nbPropAtts > 0) {
final Attribute att = (Attribute) feature.getProperty(propName.toString());
for (int i = 0; i < nbPropAtts; i++) {
final QName qname = reader.getAttributeName(i);
final GenericName attName = nameCache.get(new QName(qname.getNamespaceURI(), "@" + qname.getLocalPart()));
final AttributeType<?> charType = attType.characteristics().get(attName.toString());
if (charType != null) {
final String attVal = reader.getAttributeValue(i);
final Object val = ObjectConverters.convert(attVal, charType.getValueClass());
final Attribute chara = charType.newInstance();
chara.setValue(val);
att.characteristics().put(attName.toString(), chara);
}
}
}
}
// check if attribute has it's own mapping
final XSDMapping mapping = GMLConvention.getMapping(propertyType);
if (mapping != null) {
mapping.readValue(reader, propName, feature);
} else {
// parse the value
final Object value = readPropertyValue(propertyType, associationSubType, feature);
setValue(feature, propertyType, propName, nameAttribute, value);
}
} else if (event == END_ELEMENT) {
final QName q = reader.getName();
if (q.getLocalPart().equals("featureMember") || nameCache.get(q).equals(tagName)) {
break;
}
}
}
return feature;
}
use of org.opengis.feature.FeatureAssociationRole in project geotoolkit by Geomatys.
the class JAXPStreamFeatureReader method readPropertyValue.
private Object readPropertyValue(PropertyType propertyType, FeatureType associationSubType, Feature feature) throws XMLStreamException {
boolean skipCurrent = GMLConvention.isDecoratedProperty(propertyType);
final GenericName propName = nameCache.get(reader.getName());
Object value = null;
if (AttributeConvention.isGeometryAttribute(propertyType)) {
final boolean longitudeFirst;
if (getProperty(LONGITUDE_FIRST) != null) {
longitudeFirst = (boolean) getProperty(LONGITUDE_FIRST);
} else {
longitudeFirst = true;
}
GeometryMapping mapping = new GeometryMapping(null, propertyType, getPool(), longitudeFirst, skipCurrent);
mapping.readValue(reader, propName, feature);
} else if (propertyType instanceof FeatureAssociationRole) {
final FeatureAssociationRole far = (FeatureAssociationRole) propertyType;
final FeatureType valueType = (associationSubType == null) ? far.getValueType() : associationSubType;
// GML properties have one level of encapsulation (in properties which follow the ogc convention)
final QName currentName = reader.getName();
if (!skipCurrent) {
// no encapsulation
value = readFeature(valueType, nameCache.get(currentName));
} else {
boolean doNext = true;
while (!doNext || reader.hasNext()) {
if (doNext) {
reader.next();
}
doNext = true;
int event = reader.getEventType();
if (event == START_ELEMENT) {
final GenericName subName = nameCache.get(reader.getName());
value = readFeature(((FeatureAssociationRole) propertyType).getValueType(), subName);
} else if (event == END_ELEMENT) {
final QName q = reader.getName();
if (nameCache.get(q).equals(propName)) {
break;
}
}
}
}
} else if (propertyType instanceof AttributeType) {
final String content = reader.getElementText();
final Class typeBinding = ((AttributeType) propertyType).getValueClass();
if (List.class.equals(typeBinding) || Map.class.equals(typeBinding)) {
value = content;
} else {
value = readValue(content, (AttributeType) propertyType);
}
}
return value;
}
use of org.opengis.feature.FeatureAssociationRole in project geotoolkit by Geomatys.
the class JAXPStreamFeatureReader method resolveReferences.
/**
* Replace each feature xlink href characteristic by it's real value if it exist.
*
* @param obj
* @throws DataStoreException
*/
private void resolveReferences(Object obj) throws DataStoreException {
if (obj instanceof Feature) {
final Feature feature = (Feature) obj;
final FeatureType type = feature.getType();
for (PropertyType pt : type.getProperties(true)) {
if (pt instanceof AttributeType) {
AttributeType attType = (AttributeType) pt;
if (attType.getMaximumOccurs() == 1) {
Attribute att = (Attribute) feature.getProperty(pt.getName().toString());
Object value = att.getValue();
if (value == null) {
Attribute charatt = (Attribute) att.characteristics().get(GMLConvention.XLINK_HREF.tip().toString());
if (charatt != null) {
String refGmlId = (String) charatt.getValue();
Object target = index.get(refGmlId);
if (target == null && refGmlId.startsWith("#")) {
// local references start with a #
target = index.get(refGmlId.substring(1));
}
if (target != null)
att.setValue(target);
}
}
}
} else if (pt instanceof FeatureAssociationRole) {
final Object value = feature.getPropertyValue(pt.getName().toString());
// if association is a gml:referenceType try to resolve the real feature
FeatureType valueType = ((FeatureAssociationRole) pt).getValueType();
if ("AbstractGMLType".equals(valueType.getName().tip().toString())) {
if (value instanceof Feature) {
Feature f = (Feature) value;
try {
Object fid = f.getPropertyValue(AttributeConvention.IDENTIFIER);
if (String.valueOf(fid).startsWith("#")) {
// local references start with a #
Feature target = (Feature) index.get(fid.toString().substring(1));
if (target != null) {
feature.setPropertyValue(pt.getName().toString(), target);
}
}
} catch (IllegalArgumentException ex) {
// do nothing
}
} else if (value instanceof Collection) {
final List<Feature> newFeatures = new ArrayList<>();
final Collection col = (Collection) value;
Iterator<Feature> iterator = col.iterator();
while (iterator.hasNext()) {
Feature f = (Feature) iterator.next();
try {
Object fid = f.getPropertyValue(AttributeConvention.IDENTIFIER);
if (String.valueOf(fid).startsWith("#")) {
// local references start with a #
Feature target = (Feature) index.get(fid.toString().substring(1));
if (target != null) {
f = target;
}
}
} catch (IllegalArgumentException ex) {
// do nothing
}
newFeatures.add(f);
}
feature.setPropertyValue(pt.getName().toString(), newFeatures);
}
} else {
// resolve sub children references
resolveReferences(value);
}
}
}
} else if (obj instanceof WritableFeatureSet) {
final WritableFeatureSet fs = (WritableFeatureSet) obj;
final List<Feature> newFeatures = new ArrayList<>();
try (Stream<Feature> stream = fs.features(false)) {
Iterator<Feature> iterator = stream.iterator();
while (iterator.hasNext()) {
Feature f = iterator.next();
resolveReferences(f);
newFeatures.add(f);
}
}
fs.removeIf((Feature t) -> true);
fs.add(newFeatures.iterator());
} else if (obj instanceof FeatureSet) {
// can not update features, not writable
} else if (obj instanceof Collection) {
final Collection col = (Collection) obj;
Iterator<Feature> iterator = col.iterator();
while (iterator.hasNext()) {
resolveReferences(iterator.next());
}
}
}
use of org.opengis.feature.FeatureAssociationRole in project geotoolkit by Geomatys.
the class JAXPStreamFeatureWriter method writeProperty.
private void writeProperty(Feature parent, PropertyType typeA, Object valueA, String id) throws XMLStreamException {
final GenericName nameA = typeA.getName();
if (AttributeConvention.contains(nameA) || isAttributeProperty(nameA))
return;
final String nameProperty = nameA.tip().toString();
String namespaceProperty = getNamespace(nameA);
final boolean hasChars = typeA instanceof AttributeType && !((AttributeType) typeA).characteristics().isEmpty();
if (typeA instanceof FeatureAssociationRole && valueA instanceof Feature) {
final FeatureAssociationRole far = (FeatureAssociationRole) typeA;
final Feature ca = (Feature) valueA;
final FeatureType valueType = far.getValueType();
// write feature
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
// nill case
final Object isNil = Utils.isNill(ca);
if (isNil != null) {
writeAttributeProperties(ca);
writer.writeEndElement();
return;
}
// check if we are working on a gml:ReferenceType
if ("AbstractGMLType".equals(valueType.getName().tip().toString())) {
// write and xlink href in local file
Object valueId = ca.getPropertyValue(AttributeConvention.IDENTIFIER);
writer.writeAttribute(GMLConvention.XLINK_NAMESPACE, "href", "#" + valueId);
writer.writeEndElement();
return;
}
final String gmlid = getId(ca, null);
/*
Note : the GML 3.2 identifier element is this only one which does not
follow the OGC 'PropertyType' pattern and is not encapsulated.
Note : if more cases are found, a more generic approach should be used.
*/
boolean encapsulate = GMLConvention.isDecoratedProperty(far);
if (encapsulate) {
// we need to encapsulate type
final String encapName = Utils.getNameWithoutTypeSuffix(valueType.getName().tip().toString());
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, encapName);
} else {
writer.writeStartElement(encapName);
}
if (gmlid != null) {
writer.writeAttribute("gml", gmlNamespace, "id", gmlid);
}
writeAttributeProperties(ca);
writeComplexProperties(ca, getId(ca, id));
// close encapsulation
writer.writeEndElement();
} else {
if (gmlid != null) {
writer.writeAttribute("gml", gmlNamespace, "id", gmlid);
}
writeAttributeProperties(ca);
writeComplexProperties(ca, getId(ca, id));
}
writer.writeEndElement();
} else if (valueA instanceof Collection && !(AttributeConvention.isGeometryAttribute(typeA))) {
for (Object value : (Collection) valueA) {
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
if (hasChars)
writeCharacteristics((Attribute) parent.getProperty(nameA.toString()));
writer.writeCharacters(Utils.getStringValue(value));
writer.writeEndElement();
}
} else if (valueA != null && valueA.getClass().isArray() && !(AttributeConvention.isGeometryAttribute(typeA))) {
final int length = Array.getLength(valueA);
for (int i = 0; i < length; i++) {
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
if (hasChars)
writeCharacteristics((Attribute) parent.getProperty(nameA.toString()));
final Object value = Array.get(valueA, i);
final String textValue;
if (value != null && value.getClass().isArray()) {
// matrix
final StringBuilder sb = new StringBuilder();
final int length2 = Array.getLength(value);
for (int j = 0; j < length2; j++) {
final Object subValue = Array.get(value, j);
sb.append(Utils.getStringValue(subValue)).append(" ");
}
textValue = sb.toString();
} else {
textValue = Utils.getStringValue(value);
}
writer.writeCharacters(textValue);
writer.writeEndElement();
}
} else if (valueA instanceof Map && !(AttributeConvention.isGeometryAttribute(typeA))) {
final Map<?, ?> map = (Map) valueA;
for (Entry<?, ?> entry : map.entrySet()) {
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
if (hasChars)
writeCharacteristics((Attribute) parent.getProperty(nameA.toString()));
final Object key = entry.getKey();
if (key != null) {
writer.writeAttribute("name", (String) key);
}
writer.writeCharacters(Utils.getStringValue(entry.getValue()));
writer.writeEndElement();
}
} else if (!(AttributeConvention.isGeometryAttribute(typeA))) {
if (valueA instanceof Document) {
// special case for xml documents
final Document doc = (Document) valueA;
StaxUtils.writeElement(doc.getDocumentElement(), writer, false);
} else {
// simple type
String value = (valueA instanceof Property) ? null : Utils.getStringValue(valueA);
if ((nameProperty.equals("name") || nameProperty.equals("description")) && !gmlNamespace.equals(namespaceProperty)) {
namespaceProperty = gmlNamespace;
LOGGER.finer("the property name and description of a feature must have the GML namespace");
}
if (valueA instanceof Feature || value != null) {
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
if (hasChars)
writeCharacteristics((Attribute) parent.getProperty(nameA.toString()));
if (valueA instanceof Feature) {
// some types, like Observation & Measurement have Object types which can be
// properties again, we ensure to write then as proper xml tags
final Feature prop = (Feature) valueA;
final GenericName propName = prop.getType().getName();
final String namespaceURI = getNamespace(propName);
final String localPart = Utils.getNameWithoutTypeSuffix(propName.tip().toString());
if (namespaceURI != null && !namespaceURI.isEmpty()) {
writer.writeStartElement(namespaceURI, localPart);
} else {
writer.writeStartElement(localPart);
}
writeComplexProperties(prop, getId(prop, id));
writer.writeEndElement();
} else if (value != null) {
writer.writeCharacters(value);
}
writer.writeEndElement();
} else if (value == null && Utils.isNillable(typeA)) {
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
writer.writeAttribute("http://www.w3.org/2001/XMLSchema-instance", "nil", "1");
writer.writeEndElement();
}
}
// we add the geometry
} else {
if (valueA != null) {
final boolean descIsType = Utils.isGeometricType(typeA.getName()) && Utils.isGeometricType(nameA);
if (!descIsType) {
if (namespaceProperty != null && !namespaceProperty.isEmpty()) {
writer.writeStartElement(namespaceProperty, nameProperty);
} else {
writer.writeStartElement(nameProperty);
}
}
final CoordinateReferenceSystem crs = FeatureExt.getCRS(typeA);
final JAXBElement element;
final MarshallerPool POOL;
if ("3.1.1".equals(gmlVersion)) {
final Geometry isoGeometry = JTSUtils.toISO((org.locationtech.jts.geom.Geometry) valueA, crs);
element = OBJECT_FACTORY.buildAnyGeometry(isoGeometry);
POOL = GML_31_POOL;
} else if ("3.2.1".equals(gmlVersion)) {
AbstractGeometry gmlGeometry = null;
try {
gmlGeometry = JTStoGeometry.toGML(gmlVersion, (org.locationtech.jts.geom.Geometry) valueA, crs);
} catch (FactoryException ex) {
LOGGER.log(Level.WARNING, "Factory exception when transforming JTS geometry to GML binding", ex);
}
if (gmlGeometry != null) {
// id is requiered in version 3.2.1
// NOTE we often see gml where the geometry id is the same as the feature
// we use the last parent with an id, seems acceptable.
final String gid = (id + "_g").replace(':', '_');
setId(gmlGeometry, gid);
}
element = GML32_FACTORY.buildAnyGeometry(gmlGeometry);
POOL = GML_32_POOL;
} else {
throw new IllegalArgumentException("Unexpected GML version:" + gmlVersion);
}
try {
final Marshaller marshaller;
marshaller = POOL.acquireMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
marshal(marshaller, element);
POOL.recycle(marshaller);
} catch (JAXBException ex) {
LOGGER.log(Level.WARNING, "JAXB Exception while marshalling the iso geometry: " + ex.getMessage(), ex);
}
if (!descIsType)
writer.writeEndElement();
}
}
}
use of org.opengis.feature.FeatureAssociationRole in project geotoolkit by Geomatys.
the class Utils method propertyValueAsList.
public static Collection<?> propertyValueAsList(Feature feature, String propertyName) {
final Object val = feature.getPropertyValue(propertyName);
final PropertyType type = feature.getType().getProperty(propertyName);
if (type instanceof AttributeType) {
if (((AttributeType) type).getMinimumOccurs() > 1) {
return (Collection<?>) val;
} else {
return Collections.singleton(val);
}
} else if (type instanceof FeatureAssociationRole) {
if (((FeatureAssociationRole) type).getMinimumOccurs() > 1) {
return (Collection<?>) val;
} else {
return Collections.singleton(val);
}
} else if (type instanceof Operation) {
return Collections.singleton(val);
} else {
throw new IllegalArgumentException("Unknown propert type : " + type);
}
}
Aggregations