Skip to content
This repository has been archived by the owner on Apr 4, 2019. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
kpwebb committed Mar 9, 2015
2 parents b843529 + b1fd445 commit 83e2df5
Show file tree
Hide file tree
Showing 35 changed files with 611 additions and 625 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ s3credentials
*.class
conf/application.conf
/bin
/cache/
*~
2 changes: 2 additions & 0 deletions app/Global.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import java.io.IOException;

import models.Scenario;
import models.Shapefile;
import models.User;
import controllers.Api;
import play.Application;
Expand All @@ -17,6 +18,7 @@ public void onStart(Application app) {

try {
Scenario.buildAll();
Shapefile.writeAllToClusterCache();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Expand Down
27 changes: 13 additions & 14 deletions app/controllers/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,7 @@ public Result apply() throws Throwable {
promise = Promise.promise(
new Function0<TimeSurfaceShort>() {
public TimeSurfaceShort apply() {
LatLon latLon = new LatLon(String.format("%s,%s", lat, lon));

ProfileRequest request = analyst.buildProfileRequest(mode, jodaDate, fromTime, toTime, latLon);;
ProfileRequest request = analyst.buildProfileRequest(mode, jodaDate, fromTime, toTime, lat, lon);

if(request == null)
return null;
Expand Down Expand Up @@ -284,20 +282,20 @@ public static Result isochrone(Integer surfaceId, List<Integer> cutoffs) throws
* @param shapefileId
* @return
*/
public static Result result(Integer surfaceId, String shapefileId, String attributeName) {
public static Result result(Integer surfaceId, String shapefileId) {
final Shapefile shp = Shapefile.getShapefile(shapefileId);
ResultSet result;

// it could be a profile request, or not
// The IDs are unique; they come from inside OTP.
try {
result = AnalystProfileRequest.getResult(surfaceId, shapefileId, attributeName);
result = AnalystProfileRequest.getResult(surfaceId, shapefileId);
} catch (NullPointerException e) {
result = AnalystRequest.getResult(surfaceId, shapefileId, attributeName);
result = AnalystRequest.getResult(surfaceId, shapefileId);
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();
result.writeJson(baos, shp.getPointSet(attributeName));
result.writeJson(baos, shp.getPointSet());
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
response().setContentType("application/json");
return ok(bais);
Expand Down Expand Up @@ -330,7 +328,7 @@ public static List<IsochroneData> getIsochronesAccumulative(TimeSurface surf, Li
}

public static Result queryBins(String queryId, Integer timeLimit, String weightByShapefile, String weightByAttribute, String groupBy,
String which, String compareTo) {
String which, String attributeName, String compareTo) {

response().setHeader(CACHE_CONTROL, "no-cache, no-store, must-revalidate");
response().setHeader(PRAGMA, "no-cache");
Expand Down Expand Up @@ -360,13 +358,13 @@ public static Result queryBins(String queryId, Integer timeLimit, String weightB

try {

String queryKey = queryId + "_" + timeLimit + "_" + which;
String queryKey = queryId + "_" + timeLimit + "_" + which + "_" + attributeName;

QueryResults qr = null;

synchronized(QueryResults.queryResultsCache) {
if(!QueryResults.queryResultsCache.containsKey(queryKey)) {
qr = new QueryResults(query, timeLimit, whichEnum);
qr = new QueryResults(query, timeLimit, whichEnum, attributeName);
QueryResults.queryResultsCache.put(queryKey, qr);
}
else
Expand All @@ -376,9 +374,9 @@ public static Result queryBins(String queryId, Integer timeLimit, String weightB
if (otherQuery != null) {
QueryResults otherQr = null;

queryKey = compareTo + "_" + timeLimit + "_" + which;
queryKey = compareTo + "_" + timeLimit + "_" + which + "_" + attributeName;
if (!QueryResults.queryResultsCache.containsKey(queryKey)) {
otherQr = new QueryResults(otherQuery, timeLimit, whichEnum);
otherQr = new QueryResults(otherQuery, timeLimit, whichEnum, attributeName);
QueryResults.queryResultsCache.put(queryKey, otherQr);
}
else {
Expand Down Expand Up @@ -625,9 +623,10 @@ public static Result createShapefile() throws ZipException, IOException {

if (file != null && file.getFile() != null) {

Shapefile s = Shapefile.create(file.getFile(), body.asFormUrlEncoded().get("projectId")[0]);
String projectId = body.asFormUrlEncoded().get("projectId")[0];
String name = body.asFormUrlEncoded().get("name")[0];
Shapefile s = Shapefile.create(file.getFile(), projectId, name);

s.name = body.asFormUrlEncoded().get("name")[0];
s.description = body.asFormUrlEncoded().get("description")[0];

s.save();
Expand Down
36 changes: 22 additions & 14 deletions app/controllers/Gis.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public class Gis extends Controller {
static File TMP_PATH = new File(Application.tmpPath);

public static Result query(String queryId, Integer timeLimit, String weightByShapefile, String weightByAttribute,
String groupBy, String which, String compareTo) {
String groupBy, String which, String attributeName, String compareTo) {

response().setHeader(CACHE_CONTROL, "no-cache, no-store, must-revalidate");
response().setHeader(PRAGMA, "no-cache");
Expand Down Expand Up @@ -114,7 +114,7 @@ public static Result query(String queryId, Integer timeLimit, String weightBySha

synchronized(QueryResults.queryResultsCache) {
if(!QueryResults.queryResultsCache.containsKey(queryKey)) {
qr = new QueryResults(query, timeLimit, whichEnum);
qr = new QueryResults(query, timeLimit, whichEnum, attributeName);
QueryResults.queryResultsCache.put(queryKey, qr);
}
else
Expand All @@ -124,7 +124,7 @@ public static Result query(String queryId, Integer timeLimit, String weightBySha
String q2key = compareTo + "_" + timeLimit + "_" + which;

if(!QueryResults.queryResultsCache.containsKey(q2key)) {
qr2 = new QueryResults(query2, timeLimit, whichEnum);
qr2 = new QueryResults(query2, timeLimit, whichEnum, attributeName);
QueryResults.queryResultsCache.put(q2key, qr2);
}
else {
Expand Down Expand Up @@ -218,14 +218,14 @@ public static Result query(String queryId, Integer timeLimit, String weightBySha
}


public static Result surface(Integer surfaceId, String shapefileId, String attributeName, Integer timeLimit, String compareTo) {
public static Result surface(Integer surfaceId, String shapefileId, Integer timeLimit, String compareTo) {

response().setHeader(CACHE_CONTROL, "no-cache, no-store, must-revalidate");
response().setHeader(PRAGMA, "no-cache");
response().setHeader(EXPIRES, "0");


String shapeName = (timeLimit / 60) + "_mins_" + shapefileId.toString().toLowerCase() + "_" + surfaceId.toString() + "_" + attributeName;
String shapeName = (timeLimit / 60) + "_mins_" + shapefileId.toString().toLowerCase() + "_" + surfaceId.toString();

try {

Expand All @@ -239,33 +239,41 @@ public static Result surface(Integer surfaceId, String shapefileId, String attri
ResultSetWithTimes result;

try {
result = AnalystProfileRequest.getResultWithTimes(surfaceId, shapefileId, attributeName);
result = AnalystProfileRequest.getResultWithTimes(surfaceId, shapefileId);
}
catch (NullPointerException e) {
// not a profile request
result = AnalystRequest.getResultWithTimes(surfaceId, shapefileId, attributeName);
result = AnalystRequest.getResultWithTimes(surfaceId, shapefileId);
}

Collection<ShapeFeature> features = shp.getShapeFeatureStore().getAll();

ArrayList<String> fields = new ArrayList<String>();

fields.add(shp.name.replaceAll("\\W+", ""));


for (Attribute a : shp.attributes.values()) {
if (a.numeric) {
fields.add(a.name);
}
}

ArrayList<GisShapeFeature> gisFeatures = new ArrayList<GisShapeFeature>();

PointSet ps = Shapefile.getShapefile(shapefileId).getPointSet(attributeName);
PointSet ps = Shapefile.getShapefile(shapefileId).getPointSet();

for (ShapeFeature feature : features) {

Integer sampleTime = result.times[ps.getIndexForFeature(feature.id)];

GisShapeFeature gf = new GisShapeFeature();
gf.geom = feature.geom;
gf.id = feature.id;
gf.time = sampleTime;

gf.fields.add(feature.getAttribute(attributeName));
// TODO: handle non-integer attributes
for (Attribute a : shp.attributes.values()) {
if (a.numeric) {
gf.fields.add(feature.getAttribute(a.name));
}
}

gisFeatures.add(gf);

Expand Down Expand Up @@ -342,7 +350,7 @@ static File generateZippedShapefile(String fileName, ArrayList<String> fieldName
featureDefinition += "String";
if(features.get(0).fields.get(fieldPosition) instanceof Number)
featureDefinition += "Double";
fieldPosition++;
fieldPosition++;
}

SimpleFeatureType featureType = DataUtilities.createType("Analyst", featureDefinition);
Expand Down
15 changes: 8 additions & 7 deletions app/controllers/Tiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,24 @@ public static Promise<Result> shape(String shapefileId, Integer x, Integer y, In
return tileBuilder(tileRequest);
}

public static Promise<Result> surface(Integer surfaceId, String shapefileId, String attributeName, Integer x, Integer y, Integer z,
public static Promise<Result> surface(Integer surfaceId, String shapefileId, Integer x, Integer y, Integer z,
Boolean showIso, Boolean showPoints, Integer timeLimit, Integer minTime) {

AnalystTileRequest tileRequest = new SurfaceTile( surfaceId, shapefileId, attributeName, x, y, z, showIso, showPoints, timeLimit, minTime);
AnalystTileRequest tileRequest = new SurfaceTile( surfaceId, shapefileId, x, y, z, showIso, showPoints, timeLimit, minTime);
return tileBuilder(tileRequest);

}

public static Promise<Result> surfaceComparison(Integer surfaceId1, Integer surfaceId2, String shapefileId, String attributeName,
public static Promise<Result> surfaceComparison(Integer surfaceId1, Integer surfaceId2, String shapefileId,
Integer x, Integer y, Integer z, Boolean showIso, Boolean showPoints, Integer timeLimit, Integer minTime) {

AnalystTileRequest tileRequest = new SurfaceComparisonTile(surfaceId1, surfaceId2, shapefileId, attributeName, x, y, z, showIso, showPoints, timeLimit, minTime);
AnalystTileRequest tileRequest = new SurfaceComparisonTile(surfaceId1, surfaceId2, shapefileId, x, y, z, showIso, showPoints, timeLimit, minTime);
return tileBuilder(tileRequest);
}

public static Promise<Result> query(String queryId, Integer x, Integer y, Integer z,
Integer timeLimit, String weightByShapefile, String weightByAttribute, String groupBy, String which, String compareTo) {
Integer timeLimit, String weightByShapefile, String weightByAttribute, String groupBy,
String which, String attributeName, String compareTo) {

ResultEnvelope.Which whichEnum;
try {
Expand All @@ -142,9 +143,9 @@ public Result apply() throws Throwable {
AnalystTileRequest tileRequest;

if (compareTo == null)
tileRequest = new QueryTile(queryId, x, y, z, timeLimit, weightByShapefile, weightByAttribute, groupBy, whichEnum);
tileRequest = new QueryTile(queryId, x, y, z, timeLimit, weightByShapefile, weightByAttribute, groupBy, whichEnum, attributeName);
else
tileRequest = new QueryComparisonTile(queryId, compareTo, x, y, z, timeLimit, weightByShapefile, weightByAttribute, groupBy, whichEnum);
tileRequest = new QueryComparisonTile(queryId, compareTo, x, y, z, timeLimit, weightByShapefile, weightByAttribute, groupBy, whichEnum, attributeName);

return tileBuilder(tileRequest);
}
Expand Down
95 changes: 95 additions & 0 deletions app/migrations/MoveToJavaSerialization.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package migrations;

import java.io.File;
import java.util.Map.Entry;

import com.google.common.io.Files;

import models.Attribute;
import models.Project;
import models.Shapefile;
import models.User;
import utils.DataStore;

/**
* Move the storage of most of the data to Java Serialization format; see discussion in issue 68.
*
* This is a java main class and runs outside the Play framework; I just run it inside Eclipse.
*
* @author mattwigway
*/
public class MoveToJavaSerialization {
public static void main(String... args) {
File inDir = new File(args[0]);
File outDir = new File(args[1]);

if (args.length != 2 || !inDir.isDirectory() || !outDir.isDirectory() || outDir.list().length != 0) {
System.out.println("usage: ... old_data_directory new_data_directory");
System.out.println("both directories must exist. new directory must be empty.");
return;
}

// we don't want to use the built-in datastores of models, so point them at nowhere
DataStore.dataPath = Files.createTempDir().getAbsolutePath();

// for each of the models, get a datastore, read the data, and then write it out
System.out.println("Processing shapefiles");
int migrated = new Migrator<Shapefile>(inDir, outDir, "shapes").migrate();
System.out.println("Done processing " + migrated + " shapefiles");

System.out.println("Processing users");
migrated = new Migrator<User>(inDir, outDir, "users").migrate();
System.out.println("Done processing " + migrated + " users");

System.out.println("Processing projects");
migrated = new Migrator<Project>(inDir, outDir, "projects").migrate();
System.out.println("Done processing " + migrated + " projects");

System.out.println("Processing scenarios");
migrated = new Migrator<User>(inDir, outDir, "scenario").migrate();
System.out.println("Done processing " + migrated + " scenarios");

System.out.println("Processing queries");
migrated = new Migrator<User>(inDir, outDir, "queries").migrate();
System.out.println("Done processing " + migrated + " queries");
}

/** Migrate a datastore to Java serialization */
private static class Migrator<T> {
private File inDir;
private File outDir;
private String name;

public Migrator(File inDir, File outDir, String name) {
this.inDir = inDir;
this.outDir = outDir;
this.name = name;
}

public int migrate() {
// note: hard wired to transactional and hard-ref default cache. these things are tiny anyhow.
DataStore<T> in = new DataStore<T>(inDir, name, true, false, false);
DataStore<T> out = new DataStore<T>(outDir, name, true, false, true);

int migrated = 0;

for (Entry<String, T> kv : in.getEntries()) {

// set category IDs on old shapefiles while we're at it.
if (kv instanceof Shapefile) {
Shapefile shp = (Shapefile) kv;
if (shp.categoryId == null) {
shp.categoryId = Attribute.convertNameToId(shp.name);
}
}

out.saveWithoutCommit(kv.getKey(), kv.getValue());
migrated++;
}

out.commit();

return migrated;
}
}
}
6 changes: 5 additions & 1 deletion app/models/Attribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ else if(f instanceof Long)
count++;
}

static String convertNameToId(String name) {
/**
* Sanitize a name for use as a category ID. Also implemented in the client:
* A.models.Shapefile.getCategoryName()
*/
public static String convertNameToId(String name) {
return name.toLowerCase().trim().replaceAll(" ", "_").replaceAll("\\W","");
}

Expand Down
2 changes: 1 addition & 1 deletion app/models/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class Project implements Serializable {

private static final long serialVersionUID = 1L;

static private DataStore<Project> projectData = new DataStore<Project>("projects");
static private DataStore<Project> projectData = new DataStore<Project>("projects", true);

public String id;
public String name;
Expand Down
Loading

0 comments on commit 83e2df5

Please sign in to comment.