public void read(AbstractCityObject cityObject, long cityObjectId, HashSet<Long> generalizesToSet) throws SQLException { for (Long generalizationId : generalizesToSet) { ResultSet rs = null; try { psGeneralization.setLong(1, generalizationId); rs = psGeneralization.executeQuery(); if (rs.next()) { String gmlId = rs.getString("GMLID"); if (rs.wasNull() || gmlId == null) continue; int classId = rs.getInt("CLASS_ID"); CityGMLClass type = Util.classId2cityObject(classId); PGgeometry pgGeom = (PGgeometry) rs.getObject("ENVELOPE"); if (!rs.wasNull() && pgGeom != null && boundingBoxFilter.isActive()) { Geometry geom = pgGeom.getGeometry(); Envelope env = new EnvelopeImpl(); Point lower = new Point(geom.getFirstPoint().x, geom.getFirstPoint().y, geom.getFirstPoint().z); Point upper = new Point(geom.getPoint(2).x, geom.getPoint(2).y, geom.getPoint(2).z); env.setLowerCorner(lower); env.setUpperCorner(upper); if (boundingBoxFilter.filter(env)) continue; } if (featureGmlIdFilter.isActive() && featureGmlIdFilter.filter(gmlId)) continue; if (featureClassFilter.isActive() && featureClassFilter.filter(type)) continue; if (featureGmlNameFilter.isActive()) { // we need to get the gml:name of the feature // we only check top-level features TableEnum table = null; switch (type) { case BUILDING: table = TableEnum.BUILDING; break; case CITY_FURNITURE: table = TableEnum.CITY_FURNITURE; break; case LAND_USE: table = TableEnum.LAND_USE; break; case WATER_BODY: table = TableEnum.WATERBODY; break; case PLANT_COVER: table = TableEnum.SOLITARY_VEGETAT_OBJECT; break; case SOLITARY_VEGETATION_OBJECT: table = TableEnum.PLANT_COVER; break; case TRANSPORTATION_COMPLEX: case ROAD: case RAILWAY: case TRACK: case SQUARE: table = TableEnum.TRANSPORTATION_COMPLEX; break; case RELIEF_FEATURE: table = TableEnum.RELIEF_FEATURE; break; case GENERIC_CITY_OBJECT: table = TableEnum.GENERIC_CITYOBJECT; break; case CITY_OBJECT_GROUP: table = TableEnum.CITYOBJECTGROUP; break; } if (table != null) { Statement stmt = null; ResultSet nameRs = null; try { String query = "select NAME from " + table.toString() + " where ID=" + generalizationId; stmt = connection.createStatement(); nameRs = stmt.executeQuery(query); if (nameRs.next()) { String gmlName = nameRs.getString("NAME"); if (gmlName != null && featureGmlNameFilter.filter(gmlName)) continue; } } catch (SQLException sqlEx) { continue; } finally { if (nameRs != null) { try { nameRs.close(); } catch (SQLException sqlEx) { // } nameRs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { // } stmt = null; } } } } GeneralizationRelation generalizesTo = new GeneralizationRelationImpl(); generalizesTo.setHref("#" + gmlId); cityObject.addGeneralizesTo(generalizesTo); } } finally { if (rs != null) rs.close(); } } }
/** * This retrieves the data and the public metadata for a single attribute column. * * @param columnId Either an entity ID (int) or a Map specifying public metadata values that * uniquely identify a column. * @param minParam Used for filtering numeric data * @param maxParam Used for filtering numeric data * @param sqlParams Specifies parameters to be used in place of '?' placeholders that appear in * the SQL query for the column. * @return The column data. * @throws RemoteException */ @SuppressWarnings("unchecked") public AttributeColumnData getColumn( Object columnId, double minParam, double maxParam, Object[] sqlParams) throws RemoteException { DataEntity entity = null; if (columnId instanceof Map) { @SuppressWarnings({"rawtypes"}) Map metadata = (Map) columnId; metadata.put(PublicMetadata.ENTITYTYPE, EntityType.COLUMN); int[] ids = findEntityIds(metadata, null); if (ids.length == 0) throw new RemoteException("No column with id " + columnId); if (ids.length > 1) throw new RemoteException( String.format( "The specified metadata does not uniquely identify a column (%s matching columns found): %s", ids.length, columnId)); entity = getColumnEntity(ids[0]); } else { columnId = cast(columnId, Integer.class); entity = getColumnEntity((Integer) columnId); } // if it's a geometry column, just return the metadata if (assertStreamingGeometryColumn(entity, false)) { GeometryStreamMetadata gsm = (GeometryStreamMetadata) getGeometryData(entity, GeomStreamComponent.TILE_DESCRIPTORS, null); AttributeColumnData result = new AttributeColumnData(); result.id = entity.id; result.metadata = entity.publicMetadata; result.metadataTileDescriptors = gsm.metadataTileDescriptors; result.geometryTileDescriptors = gsm.geometryTileDescriptors; return result; } // TODO - check if entity is a table String query = entity.privateMetadata.get(PrivateMetadata.SQLQUERY); int tableId = DataConfig.NULL; String tableField = null; if (Strings.isEmpty(query)) { String entityType = entity.publicMetadata.get(PublicMetadata.ENTITYTYPE); tableField = entity.privateMetadata.get(PrivateMetadata.SQLCOLUMN); if (!Strings.equal(entityType, EntityType.COLUMN)) throw new RemoteException( String.format( "Entity %s has no sqlQuery and is not a column (entityType=%s)", entity.id, entityType)); if (Strings.isEmpty(tableField)) throw new RemoteException( String.format( "Entity %s has no sqlQuery and no sqlColumn private metadata", entity.id)); // if there's no query, the query lives in the table entity instead of the column entity DataConfig config = getDataConfig(); List<Integer> parentIds = config.getParentIds(entity.id); Map<Integer, String> idToType = config.getEntityTypes(parentIds); for (int id : parentIds) { if (Strings.equal(idToType.get(id), EntityType.TABLE)) { tableId = id; break; } } } String dataType = entity.publicMetadata.get(PublicMetadata.DATATYPE); ConnectionInfo connInfo = getColumnConnectionInfo(entity); List<String> keys = null; List<Double> numericData = null; List<String> stringData = null; List<Object> thirdColumn = null; // hack for dimension slider format List<PGGeom> geometricData = null; if (!Strings.isEmpty(query)) { keys = new ArrayList<String>(); ////// begin MIN/MAX code // use config min,max or param min,max to filter the data double minValue = Double.NaN; double maxValue = Double.NaN; // server min,max values take priority over user-specified params if (entity.publicMetadata.containsKey(PublicMetadata.MIN)) { try { minValue = Double.parseDouble(entity.publicMetadata.get(PublicMetadata.MIN)); } catch (Exception e) { } } else { minValue = minParam; } if (entity.publicMetadata.containsKey(PublicMetadata.MAX)) { try { maxValue = Double.parseDouble(entity.publicMetadata.get(PublicMetadata.MAX)); } catch (Exception e) { } } else { maxValue = maxParam; } if (Double.isNaN(minValue)) minValue = Double.NEGATIVE_INFINITY; if (Double.isNaN(maxValue)) maxValue = Double.POSITIVE_INFINITY; ////// end MIN/MAX code try { Connection conn = getStaticReadOnlyConnection(connInfo); // use default sqlParams if not specified by query params if (sqlParams == null || sqlParams.length == 0) { String sqlParamsString = entity.privateMetadata.get(PrivateMetadata.SQLPARAMS); sqlParams = CSVParser.defaultParser.parseCSVRow(sqlParamsString, true); } SQLResult result = SQLUtils.getResultFromQuery(conn, query, sqlParams, false); // if dataType is defined in the config file, use that value. // otherwise, derive it from the sql result. if (Strings.isEmpty(dataType)) { dataType = DataType.fromSQLType(result.columnTypes[1]); entity.publicMetadata.put( PublicMetadata.DATATYPE, dataType); // fill in missing metadata for the client } if (dataType.equalsIgnoreCase(DataType.NUMBER)) // special case: "number" => Double { numericData = new LinkedList<Double>(); } else if (dataType.equalsIgnoreCase(DataType.GEOMETRY)) { geometricData = new LinkedList<PGGeom>(); } else { stringData = new LinkedList<String>(); } // hack for dimension slider format if (result.columnTypes.length == 3) thirdColumn = new LinkedList<Object>(); Object keyObj, dataObj; double value; for (int i = 0; i < result.rows.length; i++) { keyObj = result.rows[i][0]; if (keyObj == null) continue; dataObj = result.rows[i][1]; if (dataObj == null) continue; if (numericData != null) { try { if (dataObj instanceof String) dataObj = Double.parseDouble((String) dataObj); value = ((Number) dataObj).doubleValue(); } catch (Exception e) { continue; } // filter the data based on the min,max values if (minValue <= value && value <= maxValue) numericData.add(value); else continue; } else if (geometricData != null) { // The dataObj must be cast to PGgeometry before an individual Geometry can be // extracted. if (!(dataObj instanceof PGgeometry)) continue; Geometry geom = ((PGgeometry) dataObj).getGeometry(); int numPoints = geom.numPoints(); // Create PGGeom Bean here and fill it up! PGGeom bean = new PGGeom(); bean.type = geom.getType(); bean.xyCoords = new double[numPoints * 2]; for (int j = 0; j < numPoints; j++) { Point pt = geom.getPoint(j); bean.xyCoords[j * 2] = pt.x; bean.xyCoords[j * 2 + 1] = pt.y; } geometricData.add(bean); } else { stringData.add(dataObj.toString()); } // if we got here, it means a data value was added, so add the corresponding key keys.add(keyObj.toString()); // hack for dimension slider format if (thirdColumn != null) thirdColumn.add(result.rows[i][2]); } } catch (SQLException e) { System.err.println(query); e.printStackTrace(); throw new RemoteException(String.format("Unable to retrieve data for column %s", columnId)); } catch (NullPointerException e) { e.printStackTrace(); throw new RemoteException("Unexpected error", e); } } AttributeColumnData result = new AttributeColumnData(); result.id = entity.id; result.tableId = tableId; result.tableField = tableField; result.metadata = entity.publicMetadata; if (keys != null) result.keys = keys.toArray(new String[keys.size()]); if (numericData != null) result.data = numericData.toArray(); else if (geometricData != null) result.data = geometricData.toArray(); else if (stringData != null) result.data = stringData.toArray(); // hack for dimension slider if (thirdColumn != null) result.thirdColumn = thirdColumn.toArray(); return result; }