private void addRelationallyMappedMultiProperty( ParsedPropertyReplacement replacement, Mapping mapping, FeatureTypeMapping ftMapping, List<ResourceId> list) throws FilterEvaluationException, FeatureStoreException, SQLException { UpdateAction action = replacement.getUpdateAction(); if (action == null) { action = UpdateAction.INSERT_AFTER; } switch (action) { case INSERT_BEFORE: case REMOVE: case REPLACE: LOG.warn( "Updating of multi properties is currently only supported for 'insertAfter' update action. Omitting."); break; case INSERT_AFTER: break; default: break; } InsertRowManager mgr = new InsertRowManager(fs, conn, null); List<Property> props = Collections.singletonList(replacement.getNewValue()); for (ResourceId id : list) { IdAnalysis analysis = schema.analyzeId(id.getRid()); FeatureType featureType = schema.getFeatureType(ftMapping.getFeatureType()); Feature f = featureType.newFeature(id.getRid(), props, null); mgr.updateFeature(f, ftMapping, analysis.getIdKernels(), mapping, replacement); } }
private void appendFtInfo(FeatureType ft, FeatureStore store, StringBuffer sb, String indent) throws IOException { if (ft instanceof FeatureCollectionType) { return; } if (ft.isAbstract()) { sb.append( indent + "- <i>" + ft.getName().getPrefix() + ":" + ft.getName().getLocalPart() + " (abstract)</i><br/>"); } else { if (store.isMapped(ft.getName())) { Query query = new Query(ft.getName(), null, 0, -1, -1); int numInstances = -1; try { numInstances = store.queryHits(query); } catch (Exception e) { e.printStackTrace(); } sb.append( indent + "- " + ft.getName().getPrefix() + ":" + ft.getName().getLocalPart() + " (" + numInstances + " instances)<br/>"); } else { sb.append( indent + "- " + ft.getName().getPrefix() + ":" + ft.getName().getLocalPart() + " (not mapped)<br/>"); } } FeatureType[] fts = ft.getSchema().getDirectSubtypes(ft); Arrays.sort( fts, new Comparator<FeatureType>() { public int compare(FeatureType a, FeatureType b) { int order = a.getName().getNamespaceURI().compareTo(b.getName().getNamespaceURI()); if (order == 0) { order = a.getName().getLocalPart().compareTo(b.getName().getLocalPart()); } return order; } }); for (FeatureType childType : fts) { appendFtInfo(childType, store, sb, indent + " "); } }
public List<NamespaceBinding> getNamespaces() { Set<NamespaceBinding> namespaces = new TreeSet<NamespaceBinding>(); FeatureStore fs = getWorkspace().getResource(FeatureStoreProvider.class, getId()); if (fs == null) { return Collections.emptyList(); } AppSchema schema = fs.getSchema(); for (FeatureType ft : schema.getFeatureTypes()) { String prefix = ft.getName().getPrefix(); String ns = ft.getName().getNamespaceURI(); namespaces.add(new NamespaceBinding(prefix, ns)); } return new ArrayList<NamespaceBinding>(namespaces); }
@Test public void testCollectAndSortFeatureTypesToExport_AllFeatureTypes() { List<FeatureType> featureTypes = featureTypes(); StoredQueryHandler storedQueryHandler = new StoredQueryHandler(mockWFS(featureTypes), new ArrayList<URL>()); List<QName> configuredFeatureTypeNames = Collections.emptyList(); List<QName> featureTypeNamesToExport = storedQueryHandler.collectAndSortFeatureTypesToExport(configuredFeatureTypeNames); assertThat(featureTypeNamesToExport.size(), is(featureTypes.size())); for (FeatureType featureType : featureTypes) { assertThat(featureTypeNamesToExport, hasItems(featureType.getName())); } }
@Override public int performDelete(IdFilter filter, Lock lock) throws FeatureStoreException { int deleted = 0; if (blobMapping != null) { deleted = performDeleteBlob(filter, lock); } else { deleted = performDeleteRelational(filter, lock); } // TODO improve this for (FeatureType ft : schema.getFeatureTypes(null, false, false)) { bboxTracker.delete(ft.getName()); } return deleted; }
@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); } } }
@Override public Envelope getBbox() { if (super.getBbox() != null) { return super.getBbox(); } if (datastore == null || !datastore.isAvailable()) { return null; } // always use up-to-date envelope Envelope bbox = null; AppSchema schema = datastore.getSchema(); List<Style> styles = service.registry.getAll(getName()); List<QName> ftNames = new LinkedList<QName>(); for (Style s : styles) { if (s.getFeatureType() != null) { ftNames.add(s.getFeatureType()); } } if (ftNames.isEmpty()) { for (FeatureType t : schema.getFeatureTypes(null, false, false)) { ftNames.add(t.getName()); } } for (QName t : ftNames) { Envelope thisBox = null; try { thisBox = datastore.getEnvelope(t); } catch (FeatureStoreException e) { LOG.error("Error retrieving envelope from FeatureStore: " + e.getMessage(), e); } if (bbox == null) { bbox = thisBox; } else { if (thisBox != null) { bbox = bbox.merge(thisBox); } } } return bbox; }
@Test public void testParsingCityGML() throws ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException { String schemaURL = "http://schemas.opengis.net/citygml/profiles/base/1.0/CityGML.xsd"; ApplicationSchemaXSDDecoder adapter = new ApplicationSchemaXSDDecoder(GMLVersion.GML_31, null, schemaURL); ApplicationSchema schema = adapter.extractFeatureTypeSchema(); FeatureType[] fts = schema.getFeatureTypes(); Assert.assertEquals(54, fts.length); FeatureType buildingFt = schema.getFeatureType( QName.valueOf("{http://www.opengis.net/citygml/building/1.0}Building")); PropertyType<?> pt = buildingFt.getPropertyDeclaration( QName.valueOf( "{http://www.opengis.net/citygml/1.0}_GenericApplicationPropertyOfCityObject")); Assert.assertEquals(8, pt.getSubstitutions().length); }
private void appendFcInfo(FeatureType ft, StringBuffer sb, String indent) throws IOException { if (ft instanceof FeatureCollectionType) { if (ft.isAbstract()) { sb.append( indent + "- <i>" + ft.getName().getPrefix() + ":" + ft.getName().getLocalPart() + " (abstract)</i><br/>"); } else { sb.append( indent + "- " + ft.getName().getPrefix() + ":" + ft.getName().getLocalPart() + "<br/>"); } } FeatureType[] fts = ft.getSchema().getDirectSubtypes(ft); Arrays.sort( fts, new Comparator<FeatureType>() { public int compare(FeatureType a, FeatureType b) { int order = a.getName().getNamespaceURI().compareTo(b.getName().getNamespaceURI()); if (order == 0) { order = a.getName().getLocalPart().compareTo(b.getName().getLocalPart()); } return order; } }); for (FeatureType childType : fts) { appendFcInfo(childType, sb, indent + " "); } }
/** * Prints out an SQL create script for the relational schema. * * @param dbSchema optional db schema, can be null * @param writer */ public void writeCreateScript(String dbSchema, PrintWriter writer) { if (dbSchema == null) { dbSchema = ""; } if (dbSchema.length() != 0) { writer.println("/* --- BEGIN schema setup --- */"); writer.println(); writer.println("CREATE SCHEMA " + dbSchema + ";"); writer.println("SET search_path TO " + dbSchema + ",public;"); writer.println(); writer.println("/* --- END schema setup --- */"); writer.println(); } FeatureType[] fts = appSchema.getFeatureTypes(); Arrays.sort( fts, new Comparator<FeatureType>() { @Override public int compare(FeatureType o1, FeatureType o2) { return o1.getName().toString().compareTo(o2.getName().toString()); } }); if (getGlobalHints().isUseObjectLookupTable()) { writeCreateGeneral(fts, writer, dbSchema); } for (FeatureType ft : fts) { if (!ft.isAbstract()) { writer.println(); writeCreateFeatureType(ft, writer, dbSchema); } } writer.flush(); }
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 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; }
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() + "' --- */"); }
private void writeCreateGeneral(FeatureType[] fts, PrintWriter writer, String dbSchema) { writer.println("/* --- BEGIN global section --- */"); writer.println(); writer.println("CREATE SEQUENCE internal_id_seq;"); writer.println(); writer.println("CREATE TABLE feature_types ("); writer.println(" id smallint PRIMARY KEY,"); writer.println(" qname text NOT NULL,"); writer.println(" tablename varchar(32) NOT NULL"); writer.println(");"); writer.println( "COMMENT ON TABLE feature_types IS 'All concrete feature types and their tables';"); writer.println(); writer.println( "SELECT ADDGEOMETRYCOLUMN('" + dbSchema + "', 'feature_types','wgs84bbox','4326','GEOMETRY',2);"); writer.println( "ALTER TABLE feature_types ADD CONSTRAINT feature_types_check_bbox CHECK (isvalid(wgs84bbox));"); writer.println( "/* (no spatial index needed, as envelope is only used for keeping track of feature type extents) */"); int typeId = 0; for (FeatureType ft : fts) { if (!ft.isAbstract()) { QName qName = ft.getName(); String tableName = ftNamesToHints.get(qName).getFeatureTypeHints().getDBTable(); writer.println( "INSERT INTO feature_types (id,qname,tablename) VALUES (" + (typeId++) + ",'" + qName + "', '" + tableName + "');"); } } writer.println(); writer.println("CREATE TABLE gml_objects ("); writer.println(" id SERIAL PRIMARY KEY,"); writer.println(" gml_id text UNIQUE NOT NULL,"); writer.println(" gml_description text,"); writer.println(" ft_type smallint REFERENCES feature_types,"); writer.println(" binary_object bytea"); writer.println(");"); writer.println("COMMENT ON TABLE gml_objects IS 'All objects (features and geometries)';"); writer.println( "SELECT ADDGEOMETRYCOLUMN('" + dbSchema + "', 'gml_objects','gml_bounded_by','-1','GEOMETRY',2);"); writer.println( "ALTER TABLE gml_objects ADD CONSTRAINT gml_objects_geochk CHECK (isvalid(gml_bounded_by));"); writer.println( "CREATE INDEX gml_objects_sidx ON gml_objects USING GIST ( gml_bounded_by GIST_GEOMETRY_OPS );"); writer.println(); writer.println("CREATE TABLE gml_names ("); writer.println(" gml_object_id integer REFERENCES GML_OBJECTS,"); writer.println(" name text NOT NULL,"); writer.println(" codespace text,"); writer.println(" prop_idx smallint NOT NULL"); writer.println(");"); writer.println(); writer.println("/* --- END global section --- */"); }
private FeatureType mockFeatureType(String name) { FeatureType mockedFeatureType = mock(FeatureType.class); QName qName = new QName(name); when(mockedFeatureType.getName()).thenReturn(qName); return mockedFeatureType; }