@Override public void postCreateFeatureType( SimpleFeatureType featureType, DatabaseMetaData metadata, String schemaName, Connection cx) throws SQLException { // figure out if the table has a spatial index and mark the feature type as so for (AttributeDescriptor ad : featureType.getAttributeDescriptors()) { if (!(ad instanceof GeometryDescriptor)) { continue; } GeometryDescriptor gd = (GeometryDescriptor) ad; String idxTableName = "idx_" + featureType.getTypeName() + "_" + gd.getLocalName(); ResultSet rs = metadata.getTables( null, dataStore.escapeNamePattern(metadata, schemaName), dataStore.escapeNamePattern(metadata, idxTableName), new String[] {"TABLE"}); try { if (rs.next()) { gd.getUserData().put(SPATIALITE_SPATIAL_INDEX, idxTableName); } } finally { dataStore.closeSafe(rs); } } }
@Override public FeatureIterator getSortedFeatures( GeometryDescriptor geom, ReferencedEnvelope latLongEnv, ReferencedEnvelope nativeEnv, Connection cacheConn) throws Exception { FeatureSource fs = featureType.getFeatureSource(null, null); // build the bbox filter FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); BBOX filter = ff.bbox( geom.getLocalName(), nativeEnv.getMinX(), nativeEnv.getMinY(), nativeEnv.getMaxX(), nativeEnv.getMaxY(), null); // build an optimized query (only the necessary attributes Query q = new Query(); q.setFilter(filter); // TODO: enable this when JTS learns how to compute centroids // without triggering the // generation of Coordinate[] out of the sequences... // q.setHints(new Hints(Hints.JTS_COORDINATE_SEQUENCE_FACTORY, // PackedCoordinateSequenceFactory.class)); q.setPropertyNames(new String[] {geom.getLocalName()}); // return the reader return fs.getFeatures(q).features(); }
@Override public void encodeGeometryColumn( GeometryDescriptor gatt, String prefix, int srid, Hints hints, StringBuffer sql) { boolean geography = "geography".equals(gatt.getUserData().get(JDBCDataStore.JDBC_NATIVE_TYPENAME)); if (geography) { sql.append("encode(ST_AsBinary("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append("),'base64')"); } else { boolean force2D = hints != null && hints.containsKey(Hints.FEATURE_2D) && Boolean.TRUE.equals(hints.get(Hints.FEATURE_2D)); if (force2D) { sql.append("encode(ST_AsBinary(ST_Force_2D("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append(")),'base64')"); } else { sql.append("encode(ST_AsEWKB("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append("),'base64')"); } } }
/* * Adds a feature layer to the geopackage. */ void addFeatureLayer( GeoPackage geopkg, FeatureLayer layer, MapLayerInfo mapLayer, WMSMapContent map) throws IOException { FeatureEntry e = new FeatureEntry(); initEntry(e, layer, mapLayer, map); Filter filter = layer.getQuery().getFilter(); GeometryDescriptor gd = mapLayer.getFeature().getFeatureType().getGeometryDescriptor(); if (gd != null) { Envelope bnds = bounds(map); BBOX bboxFilter = filterFactory.bbox( gd.getLocalName(), bnds.getMinX(), bnds.getMinY(), bnds.getMaxX(), bnds.getMaxY(), map.getRequest().getSRS()); filter = filterFactory.and(filter, bboxFilter); } LOGGER.fine("Creating feature entry" + e.getTableName()); geopkg.add(e, layer.getSimpleFeatureSource(), filter); }
/** * Forces the specified CRS on geometry attributes (all or some, depends on the parameters). * * @param schema the original schema * @param crs the forced crs * @param forceOnlyMissing if true, will force the specified crs only on the attributes that do * miss one * @return * @throws SchemaException */ public static SimpleFeatureType transform( SimpleFeatureType schema, CoordinateReferenceSystem crs, boolean forceOnlyMissing) throws SchemaException { SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); tb.setName(schema.getTypeName()); tb.setNamespaceURI(schema.getName().getNamespaceURI()); tb.setAbstract(schema.isAbstract()); GeometryDescriptor defaultGeometryType = null; for (int i = 0; i < schema.getAttributeCount(); i++) { AttributeDescriptor attributeType = schema.getDescriptor(i); if (attributeType instanceof GeometryDescriptor) { GeometryDescriptor geometryType = (GeometryDescriptor) attributeType; AttributeDescriptor forced; tb.descriptor(geometryType); if (!forceOnlyMissing || geometryType.getCoordinateReferenceSystem() == null) { tb.crs(crs); } tb.add(geometryType.getLocalName(), geometryType.getType().getBinding()); } else { tb.add(attributeType); } } if (schema.getGeometryDescriptor() != null) { tb.setDefaultGeometry(schema.getGeometryDescriptor().getLocalName()); } tb.setSuperType((SimpleFeatureType) schema.getSuper()); return tb.buildFeatureType(); }
@Override public SimpleFeature decode(String recordId, String[] csvRecord) { SimpleFeatureType featureType = getFeatureType(); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(featureType); GeometryDescriptor geometryDescriptor = featureType.getGeometryDescriptor(); GeometryFactory geometryFactory = new GeometryFactory(); Double lat = null, lng = null; String[] headers = csvFileState.getCSVHeaders(); for (int i = 0; i < headers.length; i++) { String header = headers[i]; if (i < csvRecord.length) { String value = csvRecord[i].trim(); if (geometryDescriptor != null && header.equals(latField)) { lat = Double.valueOf(value); } else if (geometryDescriptor != null && header.equals(lngField)) { lng = Double.valueOf(value); } else { builder.set(header, value); } } else { builder.set(header, null); } } if (geometryDescriptor != null && lat != null && lng != null) { Coordinate coordinate = new Coordinate(lng, lat); Point point = geometryFactory.createPoint(coordinate); builder.set(geometryDescriptor.getLocalName(), point); } return builder.buildFeature(csvFileState.getTypeName() + "-" + recordId); }
/** * Creates a new SimpleFeature for <code>targetType</code> that holds the common attributes from * <code>sourceFeature</code> and the buffered geometry. * * @param sourceFeature the original SimpleFeature from which to extract matching attributes for * the new SimpleFeature, or <code>null</code> if the new SimpleFeature has to have empty * attributes other than the default geometry. * @param targetType * @param bufferedGeometry the product geometry of running {@link BufferOp} over the default * geometry of <code>sourceFeature</code> with the parameters provided to this operation. * @return a new SimpleFeature of type <code>targetType</code> holding the common attributes with * <code>sourceFeature</code> and <code>bufferedGeometry</code> as the feature's default * geometry * @throws SOProcessException */ @SuppressWarnings("unchecked") private SimpleFeature createBufferedFeature( SimpleFeature sourceFeature, SimpleFeatureType targetType, Geometry bufferedGeometry) throws SOProcessException { SimpleFeature newFeature; try { newFeature = DataUtilities.template(targetType); final GeometryDescriptor targetGeometryType = targetType.getDefaultGeometry(); if (sourceFeature != null) { GeoToolsUtils.match(sourceFeature, newFeature); } final String attName = targetGeometryType.getLocalName(); final Class geomClass = targetGeometryType.getType().getBinding(); bufferedGeometry = GeometryUtil.adapt(bufferedGeometry, geomClass); newFeature.setAttribute(attName, bufferedGeometry); } catch (IllegalAttributeException e) { throw new SOProcessException(e.getMessage(), e); } return newFeature; }
@Override public void createSchema(SimpleFeatureType featureType) throws IOException { List<String> header = new ArrayList<String>(); GeometryDescriptor geometryDescrptor = featureType.getGeometryDescriptor(); if (geometryDescrptor != null && CRS.equalsIgnoreMetadata( DefaultGeographicCRS.WGS84, geometryDescrptor.getCoordinateReferenceSystem()) && geometryDescrptor.getType().getBinding().isAssignableFrom(Point.class)) { header.add(this.latField); header.add(this.lngField); } else { throw new IOException( "Unable use '" + this.latField + "' / '" + this.lngField + "' to represent " + geometryDescrptor); } for (AttributeDescriptor descriptor : featureType.getAttributeDescriptors()) { if (descriptor instanceof GeometryDescriptor) continue; header.add(descriptor.getLocalName()); } // Write out header, producing an empty file of the correct type CsvWriter writer = new CsvWriter(new FileWriter(this.csvFileState.getFile()), ','); try { writer.writeRecord(header.toArray(new String[header.size()])); } finally { writer.close(); } }
public void testGeometryMetadataTable() throws Exception { testSetup.setupMetadataTable(dataStore); GeometryDescriptor gd = dataStore.getFeatureSource(tname("gtmeta")).getSchema().getGeometryDescriptor(); assertEquals(Point.class, gd.getType().getBinding()); assertEquals(4326, (int) CRS.lookupEpsgCode(gd.getCoordinateReferenceSystem(), false)); }
public static <T extends FeatureType, F extends org.opengis.feature.Feature> void featuresToJson( FeatureCollection<T, F> collection, JSONBuilder json, boolean returnGeometry) throws IOException { FeatureIterator<F> iterator = collection.features(); T schema = collection.getSchema(); json.object().key("objectIdFieldName").value("objectid").key("globalIdFieldName").value(""); if (returnGeometry) { GeometryDescriptor geometryDescriptor = schema.getGeometryDescriptor(); if (geometryDescriptor == null) throw new RuntimeException( "No geometry descriptor for type " + schema + "; " + schema.getDescriptors()); GeometryType geometryType = geometryDescriptor.getType(); if (geometryType == null) throw new RuntimeException("No geometry type for type " + schema); Class<?> binding = geometryType.getBinding(); if (binding == null) throw new RuntimeException("No binding for geometry type " + schema); GeometryTypeEnum geometryTypeEnum = GeometryTypeEnum.forJTSClass(binding); json.key("geometryType").value(geometryTypeEnum.getGeometryType()); } if (schema.getCoordinateReferenceSystem() != null) { try { SpatialReference sr = SpatialReferences.fromCRS(schema.getCoordinateReferenceSystem()); json.key("spatialReference"); SpatialReferenceEncoder.toJson(sr, json); } catch (FactoryException e) { throw new RuntimeException(e); } } json.key("fields").array(); for (PropertyDescriptor desc : schema.getDescriptors()) { if (schema.getGeometryDescriptor() != null && !desc.getName().equals(schema.getGeometryDescriptor().getName())) { descriptorToJson(desc, json); } } json.endArray(); try { json.key("features"); json.array(); while (iterator.hasNext()) { F feature = iterator.next(); featureToJson(feature, json, returnGeometry); } json.endArray(); } finally { iterator.close(); } json.endObject(); }
public void testImportCSVIndirect() throws Exception { File dir = unpack("csv/locations.zip"); String wsName = getCatalog().getDefaultWorkspace().getName(); DataStoreInfo h2DataStore = createH2DataStore(wsName, "csvindirecttest"); SpatialFile importData = new SpatialFile(new File(dir, "locations.csv")); ImportContext context = importer.createContext(importData, h2DataStore); assertEquals(1, context.getTasks().size()); ImportTask task = context.getTasks().get(0); TransformChain transformChain = task.getTransform(); transformChain.add(new AttributesToPointGeometryTransform("LAT", "LON")); assertEquals(ImportTask.State.NO_CRS, task.getState()); LayerInfo layer = task.getLayer(); ResourceInfo resource = layer.getResource(); resource.setSRS("EPSG:4326"); assertTrue("Item not ready", importer.prep(task)); assertEquals(ImportTask.State.READY, task.getState()); context.updated(); assertEquals(ImportContext.State.PENDING, context.getState()); importer.run(context); assertEquals(ImportContext.State.COMPLETE, context.getState()); FeatureTypeInfo fti = (FeatureTypeInfo) resource; SimpleFeatureType featureType = (SimpleFeatureType) fti.getFeatureType(); GeometryDescriptor geometryDescriptor = featureType.getGeometryDescriptor(); assertNotNull("Expecting geometry", geometryDescriptor); assertEquals("Invalid geometry name", "location", geometryDescriptor.getLocalName()); assertEquals(3, featureType.getAttributeCount()); FeatureSource<? extends FeatureType, ? extends Feature> featureSource = fti.getFeatureSource(null, null); FeatureCollection<? extends FeatureType, ? extends Feature> features = featureSource.getFeatures(); assertEquals(9, features.size()); FeatureIterator<? extends Feature> featureIterator = features.features(); assertTrue("Expected features", featureIterator.hasNext()); SimpleFeature feature = (SimpleFeature) featureIterator.next(); assertNotNull(feature); assertEquals("Invalid city attribute", "Trento", feature.getAttribute("CITY")); assertEquals("Invalid number attribute", 140, feature.getAttribute("NUMBER")); Object geomAttribute = feature.getAttribute("location"); assertNotNull("Expected geometry", geomAttribute); Point point = (Point) geomAttribute; Coordinate coordinate = point.getCoordinate(); assertEquals("Invalid x coordinate", 11.12, coordinate.x, 0.1); assertEquals("Invalid y coordinate", 46.07, coordinate.y, 0.1); featureIterator.close(); }
/** * Applies transform to all geometry attribute. * * @param feature Feature to be transformed * @param schema Schema for target transformation - transform( schema, crs ) * @param transform MathTransform used to transform coordinates - reproject( crs, crs ) * @return transformed Feature of type schema * @throws TransformException * @throws MismatchedDimensionException * @throws IllegalAttributeException */ public static SimpleFeature transform( SimpleFeature feature, SimpleFeatureType schema, MathTransform transform) throws MismatchedDimensionException, TransformException, IllegalAttributeException { feature = SimpleFeatureBuilder.copy(feature); GeometryDescriptor geomType = schema.getGeometryDescriptor(); Geometry geom = (Geometry) feature.getAttribute(geomType.getLocalName()); geom = JTS.transform(geom, transform); feature.setAttribute(geomType.getLocalName(), geom); return feature; }
/** * Create a new helper to work with a {@code MapLayer} that has vector feature data. * * @param layer the map layer * @param geomAttributeName the name of the geometry attribute for {@code Features} * @param geomClass the geometry class */ public VectorLayerHelper(MapContext context, MapLayer layer) { super(context, layer.getFeatureSource().getSchema().getCoordinateReferenceSystem()); this.layerRef = new WeakReference<MapLayer>(layer); final GeometryDescriptor geomDesc = layer.getFeatureSource().getSchema().getGeometryDescriptor(); this.attrName = geomDesc.getLocalName(); final Class<? extends Geometry> geomClass = (Class<? extends Geometry>) geomDesc.getType().getBinding(); final Geometries type = Geometries.getForBinding(geomClass); this.isPolygonGeometry = (type == Geometries.POLYGON || type == Geometries.MULTIPOLYGON); }
// todo - add API doc describing what the method does (nf,ts - 2012-04-23) @Override public void setUserDataOf(SimpleFeatureType compatibleFeatureType) { compatibleFeatureType .getUserData() .put(PROPERTY_NAME_PLACEMARK_DESCRIPTOR, getClass().getName()); final org.opengis.feature.type.GeometryDescriptor geometryDescriptor = compatibleFeatureType.getGeometryDescriptor(); if (geometryDescriptor != null) { compatibleFeatureType .getUserData() .put(PROPERTY_NAME_DEFAULT_GEOMETRY, geometryDescriptor.getLocalName()); } }
private Integer getSRID(GeometryDescriptor gDescr) { Integer result = null; if (gDescr != null) result = (Integer) gDescr.getUserData().get(JDBCDataStore.JDBC_NATIVE_SRID); if (result == null) result = currentSRID; return result; }
@Override public void encodeGeometryColumn( GeometryDescriptor gatt, String prefix, int srid, Hints hints, StringBuffer sql) { sql.append("AsBinary("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append(")"); }
private boolean intersects(SimpleFeature feature) { GeometryDescriptor geomDescriptor = getGeometryAttDescriptor(feature.getFeatureType()); Geometry bboxGeom = new GeometryFactory().toGeometry(bbox); Geometry geom = (Geometry) feature.getAttribute(geomDescriptor.getName()); try { return geom.intersects(bboxGeom); } catch (Exception e) { // ok so exception happened during intersection. This usually means geometry is a little // crazy // what to do?... EditPlugin.log("Can't do intersection so I'm assuming they intersect", e); // $NON-NLS-1$ return false; } }
/** * Returns the vector icon associated to the specified geometry descriptor * * @param gd */ public ResourceReference getVectoryIcon(GeometryDescriptor gd) { if (gd == null) { return GEOMETRY_ICON; } Class geom = gd.getType().getBinding(); return getVectorIcon(geom); }
/** * if the query has been parsed as just a where clause filter, or has no filter at all, the result * count calculation is optimized by selecting a <code>count()</code> single row. If the filter * involves any kind of spatial filter, such as BBOX, the calculation can't be optimized by this * way, because the ArcSDE Java API throws a <code>"DATABASE LEVEL * ERROR OCURRED"</code> exception. So, in this case, a query over the shape field is made and the * result is traversed counting the number of rows inside a while loop */ public int calculateResultCount() throws IOException { final SimpleFeatureType schema = this.schema; final GeometryDescriptor geometryDescriptor = schema.getGeometryDescriptor(); final String colName; if (geometryDescriptor == null) { // gemetryless type, use any other column for the query colName = schema.getDescriptor(0).getLocalName(); } else { colName = geometryDescriptor.getLocalName(); } final SeQueryInfo qInfo = filters.getQueryInfo(new String[] {colName}); final SeFilter[] spatialFilters = filters.getSpatialFilters(); final Command<Integer> countCmd = new Command<Integer>() { @Override public Integer execute(ISession session, SeConnection connection) throws SeException, IOException { SeQuery query = new SeQuery(connection); try { versioningHandler.setUpStream(session, query); if (spatialFilters != null && spatialFilters.length > 0) { query.setSpatialConstraints(SeQuery.SE_OPTIMIZE, true, spatialFilters); } SeTable.SeTableStats tableStats = query.calculateTableStatistics( "*", SeTable.SeTableStats.SE_COUNT_STATS, qInfo, 0); int actualCount = tableStats.getCount(); return new Integer(actualCount); } finally { query.close(); } } }; final Integer count = session.issue(countCmd); return count.intValue(); }
/** Convenient method to just calculate the resulting bound box of a given query. */ public static Envelope calculateQueryExtent( final ISession session, final FeatureTypeInfo typeInfo, final Query query, final ArcSdeVersionHandler versioningHandler) throws IOException { final SimpleFeatureType fullSchema = typeInfo.getFeatureType(); final GeometryDescriptor geometryDescriptor = fullSchema.getGeometryDescriptor(); if (geometryDescriptor == null) { return null; } final String defaultGeomAttName = geometryDescriptor.getLocalName(); // we're calculating the bounds, so we'd better be sure and add the // spatial column to the query's propertynames final Query realQuery = new Query(query); realQuery.setPropertyNames(new String[] {defaultGeomAttName}); final ArcSDEQuery boundsQuery; if (typeInfo.isInProcessView()) { final SeQueryInfo definitionQuery = typeInfo.getSdeDefinitionQuery(); final PlainSelect viewSelectStatement = typeInfo.getDefinitionQuery(); boundsQuery = createInprocessViewQuery( session, fullSchema, realQuery, definitionQuery, viewSelectStatement); } else { final FIDReader fidStrategy = typeInfo.getFidStrategy(); boundsQuery = createQuery(session, fullSchema, realQuery, fidStrategy, versioningHandler); } Envelope queryExtent = null; try { Filter unsupportedFilter = boundsQuery.getFilters().getUnsupportedFilter(); if (unsupportedFilter == Filter.INCLUDE) { // we can only use an optimized bounds calculation if the // query is fully supported by sde queryExtent = boundsQuery.calculateQueryExtent(); } } finally { boundsQuery.close(); } return queryExtent; }
/** Retrieve information about the feature geometry */ private void setGeometry() { GeometryDescriptor geomDesc = featureSource.getSchema().getGeometryDescriptor(); geometryAttributeName = geomDesc.getLocalName(); Class<?> clazz = geomDesc.getType().getBinding(); if (Polygon.class.isAssignableFrom(clazz) || MultiPolygon.class.isAssignableFrom(clazz)) { geometryType = GeomType.POLYGON; } else if (LineString.class.isAssignableFrom(clazz) || MultiLineString.class.isAssignableFrom(clazz)) { geometryType = GeomType.LINE; } else { geometryType = GeomType.POINT; } }
/** * Connect to the original FeatureConnection * * @param originalFC FeatureCollection * @param intersList FeatureCollection */ public UnionFeatureCollection( final FeatureCollection<Feature> inputFC, final FeatureCollection<Feature> unionFC, final String inputGeomName, final String unionGeomName) { super(inputFC); this.unionFC = unionFC; /* * We ensure that inputGeomName and unionGeomName are not null and we get the CRS of * these geometry. This in order to genereate the new FeatureType based on two FeatureType * and with only one geometry (in this case inputGeomName) * If inputGeomName or unionGeomName is null, we use default geometry name and CRS. */ CoordinateReferenceSystem geometryCRS; if (inputGeomName == null) { this.inputGeomName = inputFC.getFeatureType().getGeometryDescriptor().getName().getLocalPart(); geometryCRS = inputFC.getFeatureType().getGeometryDescriptor().getCoordinateReferenceSystem(); } else { this.inputGeomName = inputGeomName; final GeometryDescriptor buffDesc = (GeometryDescriptor) inputFC.getFeatureType().getDescriptor(inputGeomName); geometryCRS = buffDesc.getCoordinateReferenceSystem(); } if (unionGeomName == null) { this.unionGeomName = unionFC.getFeatureType().getGeometryDescriptor().getName().getLocalPart(); } else { this.unionGeomName = unionGeomName; } // Create the new FeatureType which concatenate two FeatureCollection FeatureType but with only // one geometry // (inputGeomName) this.newFeatureType = Union.mergeType( inputFC.getFeatureType(), unionFC.getFeatureType(), this.inputGeomName, geometryCRS); }
public static SimpleFeatureType retype(SimpleFeatureType original, List<String> types) { SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); // initialize the builder b.init(original); // clear the attributes b.attributes().clear(); // add attributes in order for (int i = 0; i < types.size(); i++) { b.add(original.getDescriptor(types.get(i))); } // handle default geometry GeometryDescriptor defaultGeometry = original.getGeometryDescriptor(); if (defaultGeometry != null && types.contains(defaultGeometry.getLocalName())) { b.setDefaultGeometry(defaultGeometry.getLocalName()); } return b.buildFeatureType(); }
private Query reprojectFilter(Query query) throws IOException { final Filter originalFilter = query.getFilter() != null ? query.getFilter() : Filter.INCLUDE; if (Filter.INCLUDE.equals(originalFilter)) { return query; } final SimpleFeatureType nativeFeatureType = getSchema(); final GeometryDescriptor geom = nativeFeatureType.getGeometryDescriptor(); // if no geometry involved, no reprojection needed if (geom == null) { return query; } final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); try { CoordinateReferenceSystem nativeCRS = geom.getCoordinateReferenceSystem(); // now we apply a default to all geometries and bbox in the filter DefaultCRSFilterVisitor defaultCRSVisitor = new DefaultCRSFilterVisitor(ff, nativeCRS); final Filter defaultedFilter = (Filter) originalFilter.accept(defaultCRSVisitor, null); // and then we reproject all geometries so that the datastore // receives // them in the native projection system (or the forced one, in case // of force) ReprojectingFilterVisitor reprojectingVisitor = new ReprojectingFilterVisitor(ff, nativeFeatureType); final Filter reprojectedFilter = (Filter) defaultedFilter.accept(reprojectingVisitor, null); Query reprojectedQuery = new Query(query); reprojectedQuery.setFilter(reprojectedFilter); return reprojectedQuery; } catch (Exception e) { throw new DataSourceException("Had troubles handling filter reprojection...", e); } }
/** * Create a SimpleFeatureType with the same content; just updating the geometry attribute to match * the provided coordinate reference system. * * @param original SimpleFeatureType * @param crs CoordinateReferenceSystem of result * @return SimpleFeatureType updated with the provided CoordinateReferenceSystem */ public static SimpleFeatureType retype( SimpleFeatureType original, CoordinateReferenceSystem crs) { SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); // initialize the builder b.init(original); // clear the attributes b.attributes().clear(); // add attributes in order for (AttributeDescriptor descriptor : original.getAttributeDescriptors()) { if (descriptor instanceof GeometryDescriptor) { GeometryDescriptor geometryDescriptor = (GeometryDescriptor) descriptor; AttributeTypeBuilder adjust = new AttributeTypeBuilder(b.factory); adjust.init(geometryDescriptor); adjust.setCRS(crs); b.add(adjust.buildDescriptor(geometryDescriptor.getLocalName())); continue; } b.add(descriptor); } return b.buildFeatureType(); }
@Override public void postCreateTable(String schemaName, SimpleFeatureType featureType, Connection cx) throws SQLException, IOException { // create any geometry columns entries after the fact for (AttributeDescriptor ad : featureType.getAttributeDescriptors()) { if (ad instanceof GeometryDescriptor) { GeometryDescriptor gd = (GeometryDescriptor) ad; StringBuffer sql = new StringBuffer("INSERT INTO geometry_columns VALUES ("); // table name sql.append("'").append(featureType.getTypeName()).append("',"); // geometry name sql.append("'").append(gd.getLocalName()).append("',"); // type String gType = Geometries.getForBinding((Class<? extends Geometry>) gd.getType().getBinding()) .getName(); if (gType == null) { throw new IOException("Unknown geometry type: " + gd.getType().getBinding()); } sql.append("'").append(gType).append("',"); // coord dimension sql.append(2).append(","); // srid Integer epsgCode = null; if (gd.getCoordinateReferenceSystem() != null) { CoordinateReferenceSystem crs = gd.getCoordinateReferenceSystem(); try { epsgCode = CRS.lookupEpsgCode(crs, true); } catch (Exception e) { } } if (epsgCode == null) { throw new IOException("Unable to find epsg code code."); } sql.append(epsgCode).append(","); // spatial index enabled sql.append(0).append(")"); LOGGER.fine(sql.toString()); Statement st = cx.createStatement(); try { st.executeUpdate(sql.toString()); } finally { dataStore.closeSafe(st); } } } }
/** Maps the default geometry attribute regardless of whether they are the same type. */ @SuppressWarnings("unchecked") private static void mapGeometryAttributes( SimpleFeatureType sourceSchema, SimpleFeatureType targetSchema, Map<String, String> queryAttributes) { // Now we'll match the geometry on type only. I don't care if it has the same type name. GeometryDescriptor defaultGeometry = targetSchema.getGeometryDescriptor(); if (defaultGeometry == null) { return; } else if (!queryAttributes.containsKey(defaultGeometry.getName())) { // first check source's default geom and see if it matches Class<?> binding = sourceSchema.getGeometryDescriptor().getType().getBinding(); if (defaultGeometry.getType().getBinding().isAssignableFrom(binding)) { queryAttributes.put( defaultGeometry.getName().getLocalPart(), sourceSchema.getGeometryDescriptor().getName().getLocalPart()); } else { // we have to look through all the source attributes looking for a geometry that // matches. boolean found = false; for (int i = 0; i < sourceSchema.getAttributeCount(); i++) { AttributeDescriptor source = sourceSchema.getDescriptor(i); if (defaultGeometry .getType() .getBinding() .isAssignableFrom(source.getType().getBinding())) { queryAttributes.put( defaultGeometry.getName().getLocalPart(), source.getName().getLocalPart()); found = true; break; } } // ok so we're going to have to do some transformations. Match default geometries // then. if (!found) { queryAttributes.put( defaultGeometry.getName().getLocalPart(), sourceSchema.getGeometryDescriptor().getName().getLocalPart()); } } } }
/** * Clones the given schema, changing the geometry attribute to match the given dimensionality. * * @param schema schema to clone * @param dimensionality dimensionality for the geometry 1= points, 2= lines, 3= polygons */ private FeatureType cloneWithDimensionality(FeatureType schema, int dimensionality) { SimpleFeatureType simpleFt = (SimpleFeatureType) schema; SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName(schema.getName()); builder.setCRS(schema.getCoordinateReferenceSystem()); for (AttributeDescriptor desc : simpleFt.getAttributeDescriptors()) { if (isMixedGeometry(desc)) { GeometryDescriptor geomDescriptor = (GeometryDescriptor) desc; GeometryType geomType = geomDescriptor.getType(); Class<?> geometryClass = getGeometryForDimensionality(dimensionality); GeometryType gt = new GeometryTypeImpl( geomType.getName(), geometryClass, geomType.getCoordinateReferenceSystem(), geomType.isIdentified(), geomType.isAbstract(), geomType.getRestrictions(), geomType.getSuper(), geomType.getDescription()); builder.add( new GeometryDescriptorImpl( gt, geomDescriptor.getName(), geomDescriptor.getMinOccurs(), geomDescriptor.getMaxOccurs(), geomDescriptor.isNillable(), geomDescriptor.getDefaultValue())); } else { builder.add(desc); } } schema = builder.buildFeatureType(); return schema; }
@Override public void postCreateTable(String schemaName, SimpleFeatureType featureType, Connection cx) throws SQLException { Statement st = cx.createStatement(); String tableName = featureType.getTypeName(); try { // post process the feature type and set up constraints based on geometry type for (PropertyDescriptor ad : featureType.getDescriptors()) { if (ad instanceof GeometryDescriptor) { GeometryDescriptor gd = (GeometryDescriptor) ad; Class binding = ad.getType().getBinding(); String propertyName = ad.getName().getLocalPart(); // create a spatial index int epsg = -1; try { CoordinateReferenceSystem crs = gd.getCoordinateReferenceSystem(); if (crs == null) { continue; } epsg = CRS.lookupEpsgCode(crs, true); } catch (FactoryException e) { LOGGER.log(Level.FINER, "Unable to look epsg code", e); } StringBuffer sql = new StringBuffer(); sql.append("CALL AddGeometryColumn("); if (schemaName != null) { sql.append("'").append(schemaName).append("'"); } else { sql.append("NULL"); } sql.append(", '").append(tableName).append("'"); sql.append(", '").append(gd.getLocalName()).append("'"); sql.append(", ").append(epsg); sql.append(", '").append(Geometries.getForBinding(binding).getName()).append("'"); sql.append(", ").append(2); // TODO: dimension sql.append(")"); LOGGER.fine(sql.toString()); st.execute(sql.toString()); if (epsg != -1) { sql = new StringBuffer(); sql.append("CALL CreateSpatialIndex("); if (schemaName == null) { sql.append("NULL"); } else { sql.append("'").append(schemaName).append("'"); } sql.append(",'").append(tableName).append("'"); sql.append(",'").append(propertyName).append("'"); sql.append(",'").append(epsg).append("')"); LOGGER.fine(sql.toString()); st.execute(sql.toString()); } } } } finally { dataStore.closeSafe(st); } }
/** Creates GEOMETRY_COLUMN registrations and spatial indexes for all geometry columns */ @Override public void postCreateTable(String schemaName, SimpleFeatureType featureType, Connection cx) throws SQLException { schemaName = schemaName != null ? schemaName : "public"; String tableName = featureType.getName().getLocalPart(); Statement st = null; try { st = cx.createStatement(); // register all geometry columns in the database for (AttributeDescriptor att : featureType.getAttributeDescriptors()) { if (att instanceof GeometryDescriptor) { GeometryDescriptor gd = (GeometryDescriptor) att; // lookup or reverse engineer the srid int srid = -1; if (gd.getUserData().get(JDBCDataStore.JDBC_NATIVE_SRID) != null) { srid = (Integer) gd.getUserData().get(JDBCDataStore.JDBC_NATIVE_SRID); } else if (gd.getCoordinateReferenceSystem() != null) { try { Integer result = CRS.lookupEpsgCode(gd.getCoordinateReferenceSystem(), true); if (result != null) srid = result; } catch (Exception e) { LOGGER.log( Level.FINE, "Error looking up the " + "epsg code for metadata " + "insertion, assuming -1", e); } } // assume 2 dimensions, but ease future customisation int dimensions = 2; // grab the geometry type String geomType = CLASS_TO_TYPE_MAP.get(gd.getType().getBinding()); if (geomType == null) geomType = "GEOMETRY"; String sql = null; if (getVersion(cx).compareTo(V_2_0_0) >= 0) { // postgis 2 and up we don't muck with geometry_columns, we just alter the // type directly to set the geometry type and srid // setup the geometry type sql = "ALTER TABLE \"" + schemaName + "\".\"" + tableName + "\" " + "ALTER COLUMN \"" + gd.getLocalName() + "\" " + "TYPE geometry (" + geomType + ", " + srid + ");"; LOGGER.fine(sql); st.execute(sql); } else { // register the geometry type, first remove and eventual // leftover, then write out the real one sql = "DELETE FROM GEOMETRY_COLUMNS" + " WHERE f_table_catalog=''" // + " AND f_table_schema = '" + schemaName + "'" // + " AND f_table_name = '" + tableName + "'" // + " AND f_geometry_column = '" + gd.getLocalName() + "'"; LOGGER.fine(sql); st.execute(sql); sql = "INSERT INTO GEOMETRY_COLUMNS VALUES (''," // + "'" + schemaName + "'," // + "'" + tableName + "'," // + "'" + gd.getLocalName() + "'," // + dimensions + "," // + srid + "," // + "'" + geomType + "')"; LOGGER.fine(sql); st.execute(sql); } // add srid checks if (srid > -1) { sql = "ALTER TABLE " // + "\"" + schemaName + "\"" // + "." // + "\"" + tableName + "\"" // + " ADD CONSTRAINT \"enforce_srid_" // + gd.getLocalName() + "\"" // + " CHECK (ST_SRID(" // + "\"" + gd.getLocalName() + "\"" // + ") = " + srid + ")"; LOGGER.fine(sql); st.execute(sql); } // add dimension checks sql = "ALTER TABLE " // + "\"" + schemaName + "\"" // + "." // + "\"" + tableName + "\"" // + " ADD CONSTRAINT \"enforce_dims_" // + gd.getLocalName() + "\"" // + " CHECK (st_ndims(\"" + gd.getLocalName() + "\")" // + " = 2)"; LOGGER.fine(sql); st.execute(sql); // add geometry type checks if (!geomType.equals("GEOMETRY")) { sql = "ALTER TABLE " // + "\"" + schemaName + "\"" // + "." // + "\"" + tableName + "\"" // + " ADD CONSTRAINT \"enforce_geotype_" // + gd.getLocalName() + "\"" // + " CHECK (geometrytype(" // + "\"" + gd.getLocalName() + "\"" // + ") = '" + geomType + "'::text " + "OR \"" + gd.getLocalName() + "\"" // + " IS NULL)"; LOGGER.fine(sql); st.execute(sql); } // add the spatial index sql = "CREATE INDEX \"spatial_" + tableName // + "_" + gd.getLocalName().toLowerCase() + "\"" // + " ON " // + "\"" + schemaName + "\"" // + "." // + "\"" + tableName + "\"" // + " USING GIST (" // + "\"" + gd.getLocalName() + "\"" // + ")"; LOGGER.fine(sql); st.execute(sql); } } if (!cx.getAutoCommit()) { cx.commit(); } } finally { dataStore.closeSafe(st); } }