7

I am attempting to build a simple java program that loads shapefiles into a Postgis 2.0 database. Everything is working out great except that I would like to be able to modify the FeatureType in the following ways:

1) change the geometry column name from "the_geom" to "geom" 2) set all columns to be lower case. 3) change the primary key from serial to bigserial.

The following is my current code which basically is just transferring the shpSchema to the pgSchema. I am fairly certain that what I am trying to do is fairly simple and common, but I can find no obvious way to do it or any documentation --or even any examples of someone trying to do this.

    Map shpConnectParams = new HashMap();
    shpConnectParams.put("url", shapefile.toURI().toURL());

    DataStore shpStore = DataStoreFinder.getDataStore(shpConnectParams);

    String shpTypeName = shpStore.getTypeNames()[0];
    FeatureSource shpFS = shpStore.getFeatureSource(shpTypeName);

    SimpleFeatureType shpSchema = (SimpleFeatureType) shpFS.getSchema();
    CoordinateReferenceSystem crs = shpSchema.getCoordinateReferenceSystem();
    Map pgParams = new HashMap();
    out.println(shpSchema.getGeometryDescriptor().getType());
    for (AttributeDescriptor attrDesc : shpSchema.getAttributeDescriptors()) {

        out.println(attrDesc.getName());
    }

    pgParams.put("dbtype", "postgis");                   //must be postgis
    pgParams.put("host", "localhost");      //the name or ip address of the machine running PostGIS
    pgParams.put("port", new Integer(5432));             //the port that PostGIS is running on (generally 5432)
    pgParams.put("database", "test");              //the name of the database to connect to.
    pgParams.put("user", "postgres");                    //the user to connect with
    pgParams.put("passwd", "test!");                 //the password of the user.
    pgParams.put("schema", "scratch");   //the schema of the database
    pgParams.put("create spatial index", Boolean.TRUE);



    SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();

    builder.addAll(shpSchema.getAttributeDescriptors());
    builder.setCRS(crs);
    builder.setName(shpTypeName);

    DataStore pgDatastore = DataStoreFinder.getDataStore(pgParams);
    pgDatastore.createSchema(builder.buildFeatureType());

    SimpleFeatureSource pgFS = pgDatastore.getFeatureSource(shpTypeName);

    SimpleFeatureType pgSchema = pgFS.getSchema();


    Transaction transaction = new DefaultTransaction("create");


    if (pgFS instanceof SimpleFeatureStore) {
        SimpleFeatureStore pgFeatureStore = (SimpleFeatureStore) pgFS;





        SimpleFeatureCollection features = (SimpleFeatureCollection) shpFS.getFeatures();
        pgFeatureStore.setTransaction(transaction);
        try {
            pgFeatureStore.addFeatures(features);
            transaction.commit();

        } catch (Exception problem) {
            problem.printStackTrace();
            transaction.rollback();

        } finally {
            transaction.close();
        }
        System.exit(0); // success!
    } else {
        System.out.println(shpTypeName + " does not support read/write access");
        System.exit(1);
    }

    pgDatastore.dispose();

1 Answer 1

1

Schemas are immutable in GeoTools so you need to create a new one that has different names in it and then copy the features over to the new schema.

Here are two methods, one to change everything to lower case and one to change just the Geometry column name. You can combine the two if you want but I wanted to show how you need to handle the Geometry Column specially even if you are doing nothing special to it.

  /**
   * Convert all the attribute names to be lowercase.
   * 
   * @param schema
   * @return
   */
  private SimpleFeatureType lowerCase(SimpleFeatureType schema) {
    SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
    builder.setName(schema.getName());
    builder.setSuperType((SimpleFeatureType) schema.getSuper());
    for (AttributeDescriptor att : schema.getAttributeDescriptors()) {
      String name = att.getLocalName().toLowerCase();
      changed.put(name, att.getLocalName());
      NameImpl name2 = new NameImpl(att.getName().getNamespaceURI(), name);
      AttributeType type = att.getType();
      AttributeDescriptor descriptor;
      if (type instanceof GeometryType) {
        GeometryType geomType = (GeometryType) type;
        GeometryDescriptor geom = (GeometryDescriptor) att;
        descriptor = new GeometryDescriptorImpl(geomType, new NameImpl(name), geom.getMinOccurs(),
            geom.getMaxOccurs(), geom.isNillable(), geom.getDefaultValue());
        builder.setDefaultGeometry(name);
      } else {
         descriptor = new AttributeDescriptorImpl(
            new AttributeTypeImpl(name2, type.getBinding(), type.isIdentified(), type.isAbstract(),
                type.getRestrictions(), type.getSuper(), type.getDescription()),
            name2, att.getMinOccurs(), att.getMaxOccurs(), att.isNillable(), att.getDefaultValue());
      }
      builder.add(descriptor);
    }
    return builder.buildFeatureType();
  }

  /**
   * Convert all the attribute names to be lowercase.
   * 
   * @param schema
   * @return
   */
  private SimpleFeatureType changeDeafultGeomName(SimpleFeatureType schema, String name) {
    SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
    builder.setName(schema.getName());
    builder.setName(schema.getName());
    builder.setSuperType((SimpleFeatureType) schema.getSuper());
    for (AttributeDescriptor att : schema.getAttributeDescriptors()) {
      AttributeType type = att.getType();
      if (type instanceof GeometryType) {
        GeometryType geomType = (GeometryType) type;
        GeometryDescriptor geom = (GeometryDescriptor) att;
        GeometryDescriptor geomDesc = new GeometryDescriptorImpl(geomType, new NameImpl(name), geom.getMinOccurs(),
            geom.getMaxOccurs(), geom.isNillable(), geom.getDefaultValue());
        changed.put(name, att.getLocalName());
        builder.add(geomDesc);
        builder.setDefaultGeometry(name);
      } else {
        builder.add(att);
      }
    }
    return builder.buildFeatureType();

  }

You can retype your features using something like:

SimpleFeature retype(SimpleFeature source, SimpleFeatureType schema, Map<String,String> changes) throws IllegalAttributeException {
    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema);
    for (int i = 0; i < schema.getAttributeCount(); i++) {
      AttributeDescriptor attributeType = schema.getDescriptor(i);
      Object value = null;
      String name = changes.get(attributeType.getLocalName());
      if (source.getFeatureType().getDescriptor(name) != null) {
        value = source.getAttribute(name);
      }

      builder.set(attributeType.getLocalName(), value);
    }

    FeatureId id = source.getIdentifier();
    SimpleFeature retyped = builder.buildFeature(id.getID());
    retyped.getUserData().putAll(source.getUserData());
    return retyped;
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.