@Test public void testParsingCite110SF1() throws ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException { String schemaURL = this.getClass().getResource("../testdata/schema/cite/cite-gmlsf1.xsd").toString(); ApplicationSchemaXSDDecoder adapter = new ApplicationSchemaXSDDecoder(GMLVersion.GML_31, null, schemaURL); FeatureType[] fts = adapter.extractFeatureTypeSchema().getFeatureTypes(); Assert.assertEquals(4, fts.length); for (FeatureType ft : fts) { System.out.println("\nFt: " + ft.getName()); for (PropertyType pt : ft.getPropertyDeclarations()) { System.out.println(pt); } } }
static OperatorFilter buildFilter( Operator operator, FeatureType ft, Envelope clickBox, ValueReference geomProp) { if (ft == null) { if (operator == null) { return null; } return new OperatorFilter(operator); } LinkedList<Operator> list = new LinkedList<Operator>(); if (geomProp != null) { list.add(new And(new BBOX(geomProp, clickBox), new Intersects(geomProp, clickBox))); } else { for (PropertyType pt : ft.getPropertyDeclarations()) { if (pt instanceof GeometryPropertyType && (((GeometryPropertyType) pt).getCoordinateDimension() == DIM_2 || ((GeometryPropertyType) pt).getCoordinateDimension() == DIM_2_OR_3)) { list.add( new And( new BBOX(new ValueReference(pt.getName()), clickBox), new Intersects(new ValueReference(pt.getName()), clickBox))); } } } if (list.size() > 1) { Or or = new Or(list.toArray(new Operator[list.size()])); if (operator == null) { return new OperatorFilter(or); } return new OperatorFilter(new And(or, operator)); } if (list.isEmpty()) { // obnoxious case where feature has no geometry properties (but features may have extra // geometry props) list.add(new And(new BBOX(null, clickBox), new Intersects(null, clickBox))); } if (operator == null) { return new OperatorFilter(list.get(0)); } return new OperatorFilter(new And(list.get(0), operator)); }
/** * 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; }
private void writeCreateFeatureType(FeatureType ft, PrintWriter writer, String dbSchema) { List<String> additionalCreates = new ArrayList<String>(); List<Pair<String, String>> comments = new ArrayList<Pair<String, String>>(); FeatureTypeMapping ftMapping = getFtMapping(ft.getName()); String tableName = ftMapping.getFeatureTypeHints().getDBTable().toLowerCase(); int i = 1; writer.println("/* --- BEGIN Feature type '" + ft.getName() + "' --- */"); writer.println(); writer.println("CREATE TABLE " + tableName + " ("); writer.print(" id integer PRIMARY KEY REFERENCES GML_OBJECTS"); comments.add(new Pair<String, String>("id", "Internal id")); for (PropertyType<?> pt : ft.getPropertyDeclarations()) { PropertyMappingType propMapping = ftMapping.getPropertyHints(pt.getName()); if (propMapping instanceof SimplePropertyMappingType) { SimplePropertyMappingType simplePropMapping = (SimplePropertyMappingType) propMapping; if (simplePropMapping.getDBColumn() != null) { DBColumn dbColumn = simplePropMapping.getDBColumn(); comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase(), "Property " + pt.getName().getLocalPart() + " (simple)")); writer.print(",\n " + dbColumn.getName().toLowerCase() + " " + dbColumn.getSqlType()); if (pt.getMinOccurs() > 0) { writer.print(" NOT NULL"); } } else { additionalCreates.add( createPropertyTable(tableName, simplePropMapping.getPropertyTable())); String comment = "COMMENT ON TABLE " + simplePropMapping.getPropertyTable().getTable() + " IS '" + ft.getName().getLocalPart() + ", property " + pt.getName().getLocalPart() + " (simple)';\n"; additionalCreates.add(comment); } } else if (propMapping instanceof GeometryPropertyMappingType) { GeometryPropertyMappingType geometryPropMapping = (GeometryPropertyMappingType) propMapping; if (geometryPropMapping.getGeometryDBColumn() != null) { GeometryDBColumn dbColumn = geometryPropMapping.getGeometryDBColumn(); comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase(), "Property " + pt.getName().getLocalPart() + " (geometry)")); comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase() + "_ID", "Property " + pt.getName().getLocalPart() + " (geometry id)")); writer.print(",\n " + dbColumn.getName() + "_ID integer REFERENCES gml_objects"); String create = "SELECT ADDGEOMETRYCOLUMN('" + dbSchema + "','" + tableName + "','" + dbColumn.getName().toLowerCase() + "','" + dbColumn.getSrid() + "','" + dbColumn.getSqlType() + "'," + dbColumn.getDimension() + ");\n"; create += "ALTER TABLE " + tableName + " ADD CONSTRAINT " + tableName + "_geochk" + i + " CHECK (isvalid(" + dbColumn.getName().toLowerCase() + "));\n"; create += "CREATE INDEX " + tableName + "_sidx" + i + " ON " + tableName + " USING GIST ( " + dbColumn.getName().toLowerCase() + " GIST_GEOMETRY_OPS );\n"; additionalCreates.add(create); comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase() + "_xlink", "Property " + pt.getName().getLocalPart() + " (geometry URI)")); writer.print(",\n " + dbColumn.getName().toLowerCase() + "_xlink text"); i++; } else { additionalCreates.add( createPropertyTable( tableName, geometryPropMapping.getGeometryPropertyTable(), dbSchema)); String comment = "COMMENT ON TABLE " + geometryPropMapping.getGeometryPropertyTable().getTable() + " IS '" + ft.getName().getLocalPart() + ", property " + pt.getName().getLocalPart() + " (geometry)';\n"; additionalCreates.add(comment); } } else if (propMapping instanceof FeaturePropertyMappingType) { FeaturePropertyMappingType featurePropMapping = (FeaturePropertyMappingType) propMapping; FeatureType targetFt = ((FeaturePropertyType) pt).getValueFt(); // TODO also non-abstract types may have derived types boolean isTargetTypeUnique = targetFt == null ? false : !targetFt.isAbstract(); if (featurePropMapping.getDBColumn() != null) { DBColumn dbColumn = featurePropMapping.getDBColumn(); String valueFeatureTypeName = targetFt == null ? "Any feature" : targetFt.getName().getLocalPart(); if (!isTargetTypeUnique) { valueFeatureTypeName += " (abstract)"; } comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase(), "Property " + pt.getName().getLocalPart() + " (feature), value feature type: " + valueFeatureTypeName)); writer.print( ",\n " + dbColumn.getName().toLowerCase() + " integer REFERENCES gml_objects"); if (!isTargetTypeUnique) { writer.print( ",\n " + dbColumn.getName().toLowerCase() + "_ft smallint REFERENCES feature_types"); comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase() + "_ft", "Property " + pt.getName().getLocalPart() + " (feature type id)")); } comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase() + "_xlink", "Property " + pt.getName().getLocalPart() + " (feature URI)")); writer.print(",\n " + dbColumn.getName().toLowerCase() + "_xlink text"); } else { additionalCreates.add( createPropertyTable( tableName, featurePropMapping.getFeatureJoinTable(), isTargetTypeUnique)); String comment = "COMMENT ON TABLE " + featurePropMapping.getFeatureJoinTable().getTable() + " IS '" + ft.getName().getLocalPart() + ", property " + pt.getName().getLocalPart() + " (feature)';\n"; additionalCreates.add(comment); } } else if (propMapping instanceof MeasurePropertyMappingType) { MeasurePropertyMappingType measurePropMapping = (MeasurePropertyMappingType) propMapping; if (measurePropMapping.getDBColumn() != null) { DBColumn dbColumn = measurePropMapping.getDBColumn(); comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase(), "Property " + pt.getName().getLocalPart() + "(measure, text)")); writer.print(",\n " + dbColumn.getName().toLowerCase() + " double precision"); if (pt.getMinOccurs() > 0) { writer.print(" NOT NULL"); } comments.add( new Pair<String, String>( dbColumn.getName().toLowerCase(), "Property " + pt.getName().getLocalPart() + "_uom (measure, uom attribute)")); writer.print(",\n " + dbColumn.getName().toLowerCase() + "_uom text"); } else { additionalCreates.add( createMeasurePropertyTable(tableName, measurePropMapping.getPropertyTable())); String comment = "COMMENT ON TABLE " + measurePropMapping.getPropertyTable().getTable() + " IS '" + ft.getName().getLocalPart() + ", property " + pt.getName().getLocalPart() + " (measure)';\n"; additionalCreates.add(comment); } } else { throw new RuntimeException("Unhandled property mapping: " + propMapping.getClass()); } } writer.println("\n);"); writer.println("COMMENT ON TABLE " + tableName + " IS '" + ft.getName().getLocalPart() + "';"); // write collected creates for property and join tables for (String create : additionalCreates) { writer.println(); writer.print(create); } for (Pair<String, String> comment : comments) { writer.println( "COMMENT ON COLUMN " + tableName + "." + comment.first + " IS '" + comment.second + "';"); } writer.println(); writer.println("/* --- END Feature type '" + ft.getName() + "' --- */"); }