/** * Returns the object representation for the given property element. * * @param xmlStream cursor must point at the <code>START_ELEMENT</code> event of the property, * afterwards points at the next event after the <code>END_ELEMENT</code> of the property * @param propDecl property declaration * @param crs default SRS for all a descendant geometry properties * @param occurence * @return object representation for the given property element. * @throws XMLParsingException * @throws XMLStreamException * @throws UnknownCRSException */ public Property<?> parseProperty( XMLStreamReaderWrapper xmlStream, PropertyType propDecl, CRS crs, int occurence) throws XMLParsingException, XMLStreamException, UnknownCRSException { Property<?> property = null; QName propName = xmlStream.getName(); LOG.debug("- parsing property (begin): " + xmlStream.getCurrentEventInfo()); LOG.debug("- property declaration: " + propDecl); CustomPropertyReader<?> parser = ptToParser.get(propDecl); if (parser == null) { if (propDecl instanceof SimplePropertyType) { property = createSimpleProperty( xmlStream, (SimplePropertyType) propDecl, xmlStream.getElementText().trim()); } else if (propDecl instanceof GeometryPropertyType) { String href = xmlStream.getAttributeValue(CommonNamespaces.XLNNS, "href"); if (href != null) { // TODO respect geometry type information (Point, Surface, etc.) GeometryReference<Geometry> refGeometry = null; if (specialResolver != null) { refGeometry = new GeometryReference<Geometry>(specialResolver, href, xmlStream.getSystemId()); } else { refGeometry = new GeometryReference<Geometry>(idContext, href, xmlStream.getSystemId()); } idContext.addReference(refGeometry); property = new GenericProperty<Geometry>(propDecl, propName, refGeometry); xmlStream.nextTag(); } else { xmlStream.nextTag(); Geometry geometry = null; geometry = geomReader.parse(xmlStream, crs); property = new GenericProperty<Geometry>(propDecl, propName, geometry); xmlStream.nextTag(); } } else if (propDecl instanceof FeaturePropertyType) { String uri = xmlStream.getAttributeValue(CommonNamespaces.XLNNS, "href"); if (uri != null) { FeatureReference refFeature = null; if (specialResolver != null) { refFeature = new FeatureReference(specialResolver, uri, xmlStream.getSystemId()); } else { refFeature = new FeatureReference(idContext, uri, xmlStream.getSystemId()); } idContext.addReference(refFeature); property = new GenericProperty<Feature>(propDecl, propName, refFeature); xmlStream.nextTag(); } else { // inline feature if (xmlStream.nextTag() != START_ELEMENT) { String msg = Messages.getMessage("ERROR_INVALID_FEATURE_PROPERTY", propName); throw new XMLParsingException(xmlStream, msg); } // TODO make this check (no constraints on contained feature type) better if (((FeaturePropertyType) propDecl).getFTName() != null) { FeatureType expectedFt = ((FeaturePropertyType) propDecl).getValueFt(); FeatureType presentFt = lookupFeatureType(xmlStream, xmlStream.getName()); if (!schema.isSubType(expectedFt, presentFt)) { String msg = Messages.getMessage( "ERROR_PROPERTY_WRONG_FEATURE_TYPE", expectedFt.getName(), propName, presentFt.getName()); throw new XMLParsingException(xmlStream, msg); } } Feature subFeature = parseFeature(xmlStream, crs); property = new GenericProperty<Feature>(propDecl, propName, subFeature); xmlStream.skipElement(); } } else if (propDecl instanceof CustomPropertyType) { Object value = new GenericCustomPropertyReader().parse(xmlStream); property = new GenericProperty<Object>(propDecl, propName, value); } else if (propDecl instanceof EnvelopePropertyType) { Envelope env = null; xmlStream.nextTag(); if (xmlStream.getName().equals(new QName(gmlNs, "Null"))) { // TODO StAXParsingHelper.skipElement(xmlStream); } else { env = geomReader.parseEnvelope(xmlStream, crs); property = new GenericProperty<Object>(propDecl, propName, env); } xmlStream.nextTag(); } else if (propDecl instanceof CodePropertyType) { String codeSpace = xmlStream.getAttributeValue(null, "codeSpace"); String code = xmlStream.getElementText().trim(); Object value = new CodeType(code, codeSpace); property = new GenericProperty<Object>(propDecl, propName, value); } else if (propDecl instanceof MeasurePropertyType) { String uom = xmlStream.getAttributeValue(null, "uom"); Object value = new Measure(xmlStream.getElementText(), uom); property = new GenericProperty<Object>(propDecl, propName, value); } else if (propDecl instanceof StringOrRefPropertyType) { String ref = xmlStream.getAttributeValue(CommonNamespaces.XLNNS, "href"); String string = xmlStream.getElementText().trim(); property = new GenericProperty<Object>(propDecl, propName, new StringOrRef(string, ref)); } } else { LOG.trace("************ Parsing property using custom parser."); Object value = parser.parse(xmlStream); property = new GenericProperty<Object>(propDecl, propName, value); } LOG.debug(" - parsing property (end): " + xmlStream.getCurrentEventInfo()); return property; }
/** * Returns the object representation for the feature (or feature collection) element event that * the cursor of the given <code>XMLStreamReader</code> points at. * * @param xmlStream cursor must point at the <code>START_ELEMENT</code> event of the feature * element, afterwards points at the next event after the <code>END_ELEMENT</code> event of * the feature element * @param crs default CRS for all descendant geometry properties * @return object representation for the given feature element * @throws XMLStreamException * @throws UnknownCRSException * @throws XMLParsingException */ public Feature parseFeature(XMLStreamReaderWrapper xmlStream, CRS crs) throws XMLStreamException, XMLParsingException, UnknownCRSException { if (schema == null) { schema = buildApplicationSchema(xmlStream); } Feature feature = null; String fid = parseFeatureId(xmlStream); QName featureName = xmlStream.getName(); FeatureType ft = lookupFeatureType(xmlStream, featureName); LOG.debug("- parsing feature, gml:id=" + fid + " (begin): " + xmlStream.getCurrentEventInfo()); // parse properties Iterator<PropertyType<?>> declIter = ft.getPropertyDeclarations(version).iterator(); PropertyType activeDecl = declIter.next(); int propOccurences = 0; CRS activeCRS = crs; List<Property<?>> propertyList = new ArrayList<Property<?>>(); xmlStream.nextTag(); while (xmlStream.getEventType() == START_ELEMENT) { QName propName = xmlStream.getName(); LOG.debug("- property '" + propName + "'"); if (findConcretePropertyType(propName, activeDecl) != null) { // current property element is equal to active declaration if (activeDecl.getMaxOccurs() != -1 && propOccurences > activeDecl.getMaxOccurs()) { String msg = Messages.getMessage( "ERROR_PROPERTY_TOO_MANY_OCCURENCES", propName, activeDecl.getMaxOccurs(), ft.getName()); throw new XMLParsingException(xmlStream, msg); } } else { // current property element is not equal to active declaration while (declIter.hasNext() && findConcretePropertyType(propName, activeDecl) == null) { if (propOccurences < activeDecl.getMinOccurs()) { String msg = null; if (activeDecl.getMinOccurs() == 1) { msg = Messages.getMessage( "ERROR_PROPERTY_MANDATORY", activeDecl.getName(), ft.getName()); } else { msg = Messages.getMessage( "ERROR_PROPERTY_TOO_FEW_OCCURENCES", activeDecl.getName(), activeDecl.getMinOccurs(), ft.getName()); } throw new XMLParsingException(xmlStream, msg); } activeDecl = declIter.next(); propOccurences = 0; } if (findConcretePropertyType(propName, activeDecl) == null) { String msg = Messages.getMessage("ERROR_PROPERTY_UNEXPECTED", propName, ft.getName()); throw new XMLParsingException(xmlStream, msg); } } Property<?> property = parseProperty( xmlStream, findConcretePropertyType(propName, activeDecl), activeCRS, propOccurences); if (property != null) { // if this is the "gml:boundedBy" property, override active CRS (see GML spec. (where???)) if (StandardGMLFeatureProps.PT_BOUNDED_BY_GML31.getName().equals(activeDecl.getName())) { Envelope bbox = (Envelope) property.getValue(); if (bbox.getCoordinateSystem() != null) { activeCRS = bbox.getCoordinateSystem(); LOG.debug("- crs (from boundedBy): '" + activeCRS + "'"); } } propertyList.add(property); } propOccurences++; xmlStream.nextTag(); } LOG.debug(" - parsing feature (end): " + xmlStream.getCurrentEventInfo()); feature = ft.newFeature(fid, propertyList, version); if (fid != null && !"".equals(fid)) { if (idContext.getObject(fid) != null) { String msg = Messages.getMessage("ERROR_FEATURE_ID_NOT_UNIQUE", fid); throw new XMLParsingException(xmlStream, msg); } idContext.addObject(feature); } return feature; }