/**
   * Parse a geometry starting at offset.
   *
   * @param data ValueGetter with the data to be parsed
   * @return the parsed geometry
   */
  protected Geometry parseGeometry(ValueGetter data) {
    byte endian = data.getByte(); // skip and test endian flag
    if (endian != data.endian) {
      throw new IllegalArgumentException("Endian inconsistency!");
    }
    int typeword = data.getInt();

    int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits

    boolean haveZ = (typeword & 0x80000000) != 0;
    boolean haveM = (typeword & 0x40000000) != 0;
    boolean haveS = (typeword & 0x20000000) != 0;

    int srid = Geometry.UNKNOWN_SRID;

    if (haveS) {
      srid = Geometry.parseSRID(data.getInt());
    }
    Geometry result1;
    switch (realtype) {
      case Geometry.POINT:
        result1 = parsePoint(data, haveZ, haveM);
        break;
      case Geometry.LINESTRING:
        result1 = parseLineString(data, haveZ, haveM);
        break;
      case Geometry.POLYGON:
        result1 = parsePolygon(data, haveZ, haveM);
        break;
      case Geometry.MULTIPOINT:
        result1 = parseMultiPoint(data);
        break;
      case Geometry.MULTILINESTRING:
        result1 = parseMultiLineString(data);
        break;
      case Geometry.MULTIPOLYGON:
        result1 = parseMultiPolygon(data);
        break;
      case Geometry.GEOMETRYCOLLECTION:
        result1 = parseCollection(data);
        break;
      default:
        throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
    }

    Geometry result = result1;

    if (srid != Geometry.UNKNOWN_SRID) {
      result.setSrid(srid);
    }
    return result;
  }
  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();
      }
    }
  }
Exemplo n.º 3
0
  /**
   * 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;
  }