summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-05-10 11:02:07 +0200
committerPeter Wu <peter@lekensteyn.nl>2014-05-10 11:02:07 +0200
commit670fc2a89d65d9855d50a62f87c1cc061b280215 (patch)
treea543eba5dc663f6e580c4eeafabff5a9ee7c2ae3
parent651e477d0da9f74f3e2193de6827c9ff9d098564 (diff)
downloadDatafiller-670fc2a89d65d9855d50a62f87c1cc061b280215.tar.gz
Coordinates is an object with an array
Ensure that the array is of a fixed length, add tests to check for that.
-rw-r--r--src/data/Tweet.java10
-rw-r--r--src/data/ValidatingJsonDeserializer.java48
-rw-r--r--src/database/QueryUtils.java8
-rw-r--r--test/data/ValidatingJsonDeserializerTest.java28
4 files changed, 86 insertions, 8 deletions
diff --git a/src/data/Tweet.java b/src/data/Tweet.java
index 384a9e1..3caae6a 100644
--- a/src/data/Tweet.java
+++ b/src/data/Tweet.java
@@ -18,7 +18,8 @@ public class Tweet {
@ValidatingJsonDeserializer.Validator
public Place place;
@ValidatingJsonDeserializer.Nullable
- public String coordinates;
+ @ValidatingJsonDeserializer.Validator
+ public Coordinates coordinates;
public String text;
@ValidatingJsonDeserializer.Nullable
@ValidatingJsonDeserializer.Validator
@@ -45,6 +46,13 @@ public class Tweet {
public String full_name; // "Danbury, CT"
}
+ public static class Coordinates {
+
+ //public String type; // always "Point"?
+ @ValidatingJsonDeserializer.ArrayValidator(minLen = 2, maxLen = 2)
+ public float[] coordinates; // e.g. [-73.49513755, 41.43286284]
+ }
+
public static class Entities {
@ValidatingJsonDeserializer.Validator
diff --git a/src/data/ValidatingJsonDeserializer.java b/src/data/ValidatingJsonDeserializer.java
index 5dca3bd..431622b 100644
--- a/src/data/ValidatingJsonDeserializer.java
+++ b/src/data/ValidatingJsonDeserializer.java
@@ -31,7 +31,8 @@ public class ValidatingJsonDeserializer<T> implements JsonDeserializer<T> {
return obj;
}
- void checkObject(String path, JsonElement je, Class type) {
+ void checkObject(String path, JsonElement je, Class type)
+ throws JsonParseException {
JsonObject jsonObj = je.getAsJsonObject();
for (Field f : type.getDeclaredFields()) {
JsonElement val = jsonObj.get(f.getName());
@@ -52,12 +53,33 @@ public class ValidatingJsonDeserializer<T> implements JsonDeserializer<T> {
}
}
- private void tryValidateProperty(String path, JsonElement je, Field f) {
+ private void tryValidateProperty(String path, JsonElement je, Field f)
+ throws JsonParseException {
+ Class<?> type = f.getType();
// assume that this annotation is only applied to objects
Validator v = f.getAnnotation(Validator.class);
+ ArrayValidator av = f.getAnnotation(ArrayValidator.class);
path += f.getName();
+ if (av != null) {
+ if (!type.isArray()) {
+ throw new RuntimeException("Invalid " + av.getClass().getName()
+ + " + annotation for " + path);
+ }
+ if (!je.isJsonArray()) {
+ throw new JsonParseException("Expected array: " + path);
+ }
+ JsonArray ja = je.getAsJsonArray();
+ int minLen = av.minLen(), maxLen = av.maxLen();
+ if (minLen >= 0 && ja.size() < minLen) {
+ throw new JsonParseException("Array smaller than "
+ + minLen + ": " + path);
+ }
+ if (maxLen >= 0 && ja.size() > maxLen) {
+ throw new JsonParseException("Array larger than "
+ + maxLen + ": " + path);
+ }
+ }
if (v != null) {
- Class<?> type = f.getType();
if (type.isArray()) {
// the class expects an array, so the value must have one too.
if (!je.isJsonArray()) {
@@ -84,9 +106,25 @@ public class ValidatingJsonDeserializer<T> implements JsonDeserializer<T> {
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
- public @interface Validator {
+ public @interface ArrayValidator {
- Class deserializer() default ValidatingJsonDeserializer.class;
+ /**
+ * @return Minimal length for array types (-1 if not checked).
+ */
+ int minLen() default -1;
+
+ /**
+ * @return Maximum length for array types (-1 if not checked).
+ */
+ int maxLen() default -1;
+ }
+
+ /**
+ * Marks a member as object that should be validated too.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ public @interface Validator {
}
/**
diff --git a/src/database/QueryUtils.java b/src/database/QueryUtils.java
index 228ccc8..66edd1c 100644
--- a/src/database/QueryUtils.java
+++ b/src/database/QueryUtils.java
@@ -94,7 +94,13 @@ public class QueryUtils {
tweetStatement.setLong("favoritecount", tweet.favorite_count);
tweetStatement.setLong("retweetcount", tweet.retweet_count);
tweetStatement.setString("text", tweet.text);
- tweetStatement.setString("coordinates", tweet.coordinates);
+ if (tweet.coordinates != null) {
+ float[] coords = tweet.coordinates.coordinates;
+ String coords_str = String.format("%f,%f", coords[0], coords[1]);
+ tweetStatement.setString("coordinates", coords_str);
+ } else {
+ tweetStatement.setString("coordinates", null);
+ }
tweetStatement.setString("language", tweet.lang);
if (tweet.retweeted_status != null) {
tweetStatement.setLong("retweetid", tweet.retweeted_status.id);
diff --git a/test/data/ValidatingJsonDeserializerTest.java b/test/data/ValidatingJsonDeserializerTest.java
index 85f1661..b51631a 100644
--- a/test/data/ValidatingJsonDeserializerTest.java
+++ b/test/data/ValidatingJsonDeserializerTest.java
@@ -362,7 +362,7 @@ public class ValidatingJsonDeserializerTest {
tweet.addProperty("created_at", "X");
tweet.addProperty("favorite_count", 4);
tweet.add("place", JsonNull.INSTANCE);
- tweet.addProperty("coordinates", "X");
+ tweet.add("coordinates", JsonNull.INSTANCE);
tweet.addProperty("text", "X");
tweet.add("retweeted_status", JsonNull.INSTANCE); // Tweet object
JsonObject entities = new JsonObject();
@@ -469,6 +469,32 @@ public class ValidatingJsonDeserializerTest {
}
@Test
+ public void testTweetCoordinates() {
+ JsonObject tweet = buildMinimalTweet(buildMinimalUser());
+ addProperty(tweet, new JsonPrimitive("X"), "coordinates");
+ checkTweetFail(tweet, "Expected object: coordinates");
+
+ JsonObject coords = new JsonObject();
+ // overwrite coordinates with object
+ addProperty(tweet, coords, "coordinates");
+ checkTweetFail(tweet, "Missing field: coordinates.coordinates");
+
+ // set coordinates.coordinates
+ JsonArray coordsFloat = new JsonArray();
+ coords.add("coordinates", coordsFloat);
+ checkTweetFail(tweet, "Array smaller than 2: coordinates.coordinates");
+
+ coordsFloat.add(new JsonPrimitive(1.0f));
+ checkTweetFail(tweet, "Array smaller than 2: coordinates.coordinates");
+
+ coordsFloat.add(new JsonPrimitive(1.0f));
+ checkTweetPass(tweet);
+
+ coordsFloat.add(new JsonPrimitive(1.0f));
+ checkTweetFail(tweet, "Array larger than 2: coordinates.coordinates");
+ }
+
+ @Test
public void testTweetEntities() {
checkImpairedTweet("entities");
checkImpairedTweet("entities", "hashtags");