package com.conveyal.lodes;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.Polygon;
public class LodesProcessor {
Geometry boundary;
Blocks blocks = new Blocks();
Attributes attributes;
public LodesProcessor(File attributeGroupCsv) throws IOException {
attributes = new Attributes(attributeGroupCsv);
}
public void setBoundary(Geometry geom) {
boundary = geom;
}
public void addShapefile(File blockShape) throws IOException, FactoryException {
blocks.load(blockShape, boundary);
}
public void addAddtributes(File csvFile) throws IOException, FactoryException {
attributes.load(csvFile);
}
public void createIndicator(String id, String name, File outputFile) throws JsonGenerationException, JsonMappingException, IOException {
System.out.println("Creating indicator " + name + " (" + id + ") from " + attributes.lodesAttributes.keySet().size() + " attributes in " + attributes.attributeGroups.keySet().size() + " attribute groups.");
Indicator indicator = new Indicator(id, name, blocks, attributes);
GeoJsonModule geojsonModule = new GeoJsonModule();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(geojsonModule);
mapper.writerWithDefaultPrettyPrinter().writeValue(outputFile, indicator);
}
public void buildBlocks(File shapeFile) throws IOException, FactoryException {
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("Block");
builder.setCRS(DefaultGeographicCRS.WGS84);
// add attributes in order
builder.add("Block", Polygon.class);
builder.length(16).add("id", String.class);
for(String attribute : attributes.attributeGroups.keySet()) {
builder.add(attribute, Long.class);
}
Map<String, Serializable> params = new HashMap<String, Serializable>();
params.put("url", shapeFile.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
ShapefileDataStore dataStore = (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
dataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
// build the type
final SimpleFeatureType BLOCKS_TYPE = builder.buildFeatureType();
dataStore.createSchema(BLOCKS_TYPE);
DefaultFeatureCollection featureCollection = new DefaultFeatureCollection();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(BLOCKS_TYPE);
for(String blockId : blocks.lodesBlocks.keySet()) {
if(blocks.lodesBlocks.get(blockId).percentLand < 0.5)
continue;
featureBuilder.add(blocks.lodesBlocks.get(blockId).geom);
featureBuilder.add(blockId);
for(String attributeId : attributes.attributeGroups.keySet()) {
HashMap<String, Long> lodesAttribute = attributes.lodesAttributes.get(blockId);
if(lodesAttribute != null) {
Long attributeValue = lodesAttribute.get(attributeId);
featureBuilder.add(attributeValue);
}
else {
//System.out.println("blockId: " + blockId + " is missing " + attributeId);
}
}
SimpleFeature feature = featureBuilder.buildFeature(null);
featureCollection.add(feature);
}
Transaction transaction = new DefaultTransaction("create");
String typeName = dataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
if (featureSource instanceof SimpleFeatureStore)
{
SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
featureStore.setTransaction(transaction);
featureStore.addFeatures(featureCollection);
transaction.commit();
transaction.close();
}
}
public void buildHaltonPopulation(File shapeFile) throws IOException, FactoryException {
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("Block");
builder.setCRS(DefaultGeographicCRS.WGS84);
// add attributes in order
builder.add("Jobs", MultiPoint.class);
builder.length(16).add("id", String.class);
builder.length(5).add("type", String.class);
Map<String, Serializable> params = new HashMap<String, Serializable>();
params.put("url", shapeFile.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
ShapefileDataStore dataStore = (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
dataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
// build the type
final SimpleFeatureType BLOCKS_TYPE = builder.buildFeatureType();
dataStore.createSchema(BLOCKS_TYPE);
DefaultFeatureCollection featureCollection = new DefaultFeatureCollection();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(BLOCKS_TYPE);
for(String blockId : blocks.lodesBlocks.keySet()) {
IndicatorItem block = blocks.lodesBlocks.get(blockId);
for(String attributeId : attributes.attributeGroups.keySet()) {
HashMap<String, Long> lodesAttribute = attributes.lodesAttributes.get(blockId);
if(lodesAttribute != null) {
long attributeValue = lodesAttribute.get(attributeId);
if (attributeValue < Integer.MIN_VALUE || attributeValue > Integer.MAX_VALUE) {
System.out.println(blockId + " " + attributeId + " exceeds int val max: " + attributeValue);
}
else {
featureBuilder.add(block.haltonPoints((int)attributeValue));
featureBuilder.add(blockId);
featureBuilder.add(attributeId);
SimpleFeature feature = featureBuilder.buildFeature(null);
featureCollection.add(feature);
}
}
else {
//System.out.println("blockId: " + blockId + " is missing " + attributeId);
}
}
}
Transaction transaction = new DefaultTransaction("create");
String typeName = dataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
if (featureSource instanceof SimpleFeatureStore)
{
SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
featureStore.setTransaction(transaction);
featureStore.addFeatures(featureCollection);
transaction.commit();
transaction.close();
}
}
}