diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/BaseEntity.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/BaseEntity.java index 97718e708e83..1846c2a0e7ae 100644 --- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/BaseEntity.java +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/BaseEntity.java @@ -21,6 +21,7 @@ import static com.google.gcloud.datastore.DateTimeValue.of; import static com.google.gcloud.datastore.DoubleValue.of; import static com.google.gcloud.datastore.EntityValue.of; +import static com.google.gcloud.datastore.LatLngValue.of; import static com.google.gcloud.datastore.KeyValue.of; import static com.google.gcloud.datastore.ListValue.of; import static com.google.gcloud.datastore.LongValue.of; @@ -159,6 +160,11 @@ public B set(String name, DateTime value) { return self(); } + public B set(String name, LatLng value) { + properties.put(name, of(value)); + return self(); + } + public B set(String name, Key value) { properties.put(name, of(value)); return self(); @@ -320,6 +326,17 @@ public DateTime getDateTime(String name) { return ((Value) getValue(name)).get(); } + /** + * Returns the property value as a LatLng. + * + * @throws DatastoreException if not such property. + * @throws ClassCastException if value is not a LatLng. + */ + @SuppressWarnings("unchecked") + public LatLng getLatLng(String name) { + return ((Value) getValue(name)).get(); + } + /** * Returns the property value as a Key. * diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/LatLng.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/LatLng.java new file mode 100644 index 000000000000..7e2b42fac4d3 --- /dev/null +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/LatLng.java @@ -0,0 +1,90 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud.datastore; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.protobuf.InvalidProtocolBufferException; + +import java.util.Objects; + +/** + * A Google Cloud Datastore LatLng (represented by latitude and longitude in degrees). + * This class is immutable. + * + * @see Google Cloud Datastore + * Entities, Properties, and Keys + */ +public final class LatLng extends Serializable { + + private static final long serialVersionUID = 9077060962655752073L; + + private final transient double latitude; + private final transient double longitude; + + LatLng(double latitude, double longitude) { + checkArgument( + latitude >= -90.0 && latitude <= 90.0, "latitude must be in the range [-90, 90] degrees"); + checkArgument( + longitude >= -180.0 && longitude <= 180.0, + "latitude must be in the range [-180, 180] degrees"); + this.latitude = latitude; + this.longitude = longitude; + } + + public double latitude() { + return latitude; + } + + public double longitude() { + return longitude; + } + + @Override + public String toString() { + return Double.toString(latitude) + ", " + Double.toString(longitude); + } + + @Override + public int hashCode() { + return Objects.hash(latitude, longitude); + } + + @Override + public boolean equals(Object obj) { + return obj == this || (obj instanceof LatLng && this.latitude == ((LatLng) obj).latitude + && this.longitude == ((LatLng) obj).longitude); + } + + public static LatLng of(double latitude, double longitude) { + return new LatLng(latitude, longitude); + } + + @Override + protected com.google.type.LatLng toPb() { + return com.google.type.LatLng.newBuilder() + .setLatitude(latitude) + .setLongitude(longitude) + .build(); + } + + @Override + protected Object fromPb(byte[] bytesPb) throws InvalidProtocolBufferException { + com.google.type.LatLng parsedLatLng = com.google.type.LatLng.parseFrom(bytesPb); + return new LatLng(parsedLatLng.getLatitude(), parsedLatLng.getLongitude()); + } +} diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/LatLngValue.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/LatLngValue.java new file mode 100644 index 000000000000..91723f710816 --- /dev/null +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/LatLngValue.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud.datastore; + +import static com.google.datastore.v1beta3.Value.GEO_POINT_VALUE_FIELD_NUMBER; + +public final class LatLngValue extends Value { + + private static final long serialVersionUID = -5810614280642405898L; + + static final BaseMarshaller MARSHALLER = + new BaseMarshaller() { + + private static final long serialVersionUID = -3550567536035178649L; + + @Override + public int getProtoFieldId() { + return GEO_POINT_VALUE_FIELD_NUMBER; + } + + @Override + public Builder newBuilder(LatLng value) { + return builder(value); + } + + @Override + protected LatLng getValue(com.google.datastore.v1beta3.Value from) { + return new LatLng( + from.getGeoPointValue().getLatitude(), from.getGeoPointValue().getLongitude()); + } + + @Override + protected void setValue(LatLngValue from, com.google.datastore.v1beta3.Value.Builder to) { + to.setGeoPointValue(from.get().toPb()); + } + }; + + public static final class Builder extends Value.BaseBuilder { + + private Builder() { + super(ValueType.LAT_LNG); + } + + @Override + public LatLngValue build() { + return new LatLngValue(this); + } + } + + public LatLngValue(LatLng value) { + this(builder(value)); + } + + private LatLngValue(Builder builder) { + super(builder); + } + + @Override + public Builder toBuilder() { + return new Builder().mergeFrom(this); + } + + public static LatLngValue of(LatLng value) { + return new LatLngValue(value); + } + + public static Builder builder(LatLng value) { + return new Builder().set(value); + } +} diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ValueType.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ValueType.java index 20c89a86e7a0..ab16126336f5 100644 --- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ValueType.java +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ValueType.java @@ -78,12 +78,12 @@ public enum ValueType { /** * Represents a raw/unparsed value. */ - RAW_VALUE(RawValue.MARSHALLER); + RAW_VALUE(RawValue.MARSHALLER), /** - * TODO(ajaykannan): add GEO_POINT_VALUE - * Will represent a geolocation value in latitude/longitude + * Represents a {@link LatLng} value */ + LAT_LNG(LatLngValue.MARSHALLER); private static final ImmutableMap DESCRIPTOR_TO_TYPE_MAP; diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/BaseEntityTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/BaseEntityTest.java index 5ece01508d3a..4be8b6c0d96a 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/BaseEntityTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/BaseEntityTest.java @@ -35,6 +35,7 @@ public class BaseEntityTest { private static final Blob BLOB = Blob.copyFrom(new byte[]{1, 2}); private static final DateTime DATE_TIME = DateTime.now(); + private static final LatLng LAT_LNG = new LatLng(37.422035, -122.084124); private static final Key KEY = Key.builder("ds1", "k1", "n1").build(); private static final Entity ENTITY = Entity.builder(KEY).set("name", "foo").build(); private static final IncompleteKey INCOMPLETE_KEY = IncompleteKey.builder("ds1", "k1").build(); @@ -62,9 +63,9 @@ public void setUp() { builder = new Builder(); builder.set("blob", BLOB).set("boolean", true).set("dateTime", DATE_TIME); builder.set("double", 1.25).set("key", KEY).set("string", "hello world"); - builder.set("long", 125).setNull("null").set("entity", ENTITY); + builder.set("long", 125).setNull("null").set("entity", ENTITY).set("latLng", LAT_LNG); builder.set("partialEntity", PARTIAL_ENTITY).set("stringValue", StringValue.of("bla")); - builder.set("list1", NullValue.of(), StringValue.of("foo")); + builder.set("list1", NullValue.of(), StringValue.of("foo"), LatLngValue.of(LAT_LNG)); builder.set("list2", ImmutableList.of(LongValue.of(10), DoubleValue.of(2))); builder.set("list3", Collections.singletonList(BooleanValue.of(true))); } @@ -149,6 +150,12 @@ public void testGetDateTime() throws Exception { assertEquals(dateTime, entity.getDateTime("dateTime")); } + @Test + public void testGetLatLng() throws Exception { + BaseEntity entity = builder.build(); + assertEquals(LAT_LNG, entity.getLatLng("latLng")); + } + @Test public void testGetKey() throws Exception { BaseEntity entity = builder.build(); @@ -171,9 +178,10 @@ public void testGetEntity() throws Exception { public void testGetList() throws Exception { BaseEntity entity = builder.build(); List> list = entity.getList("list1"); - assertEquals(2, list.size()); + assertEquals(3, list.size()); assertEquals(NullValue.of(), list.get(0)); assertEquals("foo", list.get(1).get()); + assertEquals(LAT_LNG, list.get(2).get()); list = entity.getList("list2"); assertEquals(2, list.size()); assertEquals(Long.valueOf(10), list.get(0).get()); @@ -196,9 +204,10 @@ public void testGetBlob() throws Exception { @Test public void testNames() throws Exception { - Set names = ImmutableSet.builder() - .add("string", "stringValue", "boolean", "double", "long", "list1", "list2", "list3") - .add("entity", "partialEntity", "null", "dateTime", "blob", "key") + Set names = + ImmutableSet.builder() + .add("string", "stringValue", "boolean", "double", "long", "list1", "list2", "list3") + .add("entity", "partialEntity", "null", "dateTime", "latLng", "blob", "key") .build(); BaseEntity entity = builder.build(); assertEquals(names, entity.names()); diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java index f0fbd4ab96c0..152aeea0a75e 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java @@ -74,6 +74,8 @@ public class DatastoreTest { .build(); private static final ListValue LIST_VALUE2 = ListValue.of(Collections.singletonList(KEY_VALUE)); private static final DateTimeValue DATE_TIME_VALUE = new DateTimeValue(DateTime.now()); + private static final LatLngValue LAT_LNG_VALUE = + new LatLngValue(new LatLng(37.422035, -122.084124)); private static final FullEntity PARTIAL_ENTITY1 = FullEntity.builder(INCOMPLETE_KEY2).set("str", STR_VALUE).set("bool", BOOL_VALUE) .set("list", LIST_VALUE1).build(); @@ -83,13 +85,15 @@ public class DatastoreTest { private static final FullEntity PARTIAL_ENTITY3 = FullEntity.builder(PARTIAL_ENTITY1).key(IncompleteKey.builder(PROJECT_ID, KIND3).build()) .build(); - private static final Entity ENTITY1 = Entity.builder(KEY1) - .set("str", STR_VALUE) - .set("date", DATE_TIME_VALUE) - .set("bool", BOOL_VALUE) - .set("partial1", EntityValue.of(PARTIAL_ENTITY1)) - .set("list", LIST_VALUE2) - .build(); + private static final Entity ENTITY1 = + Entity.builder(KEY1) + .set("str", STR_VALUE) + .set("date", DATE_TIME_VALUE) + .set("latLng", LAT_LNG_VALUE) + .set("bool", BOOL_VALUE) + .set("partial1", EntityValue.of(PARTIAL_ENTITY1)) + .set("list", LIST_VALUE2) + .build(); private static final Entity ENTITY2 = Entity.builder(ENTITY1).key(KEY2).remove("str") .set("name", "Dan").setNull("null").set("age", 20).build(); private static final Entity ENTITY3 = Entity.builder(ENTITY1).key(KEY3).remove("str") @@ -504,9 +508,11 @@ public void testGet() { assertEquals(LIST_VALUE2, value3); DateTimeValue value4 = entity.getValue("date"); assertEquals(DATE_TIME_VALUE, value4); - FullEntity value5 = entity.getEntity("partial1"); - assertEquals(PARTIAL_ENTITY1, value5); - assertEquals(5, entity.names().size()); + LatLngValue value5 = entity.getValue("latLng"); + assertEquals(LAT_LNG_VALUE, value5); + FullEntity value6 = entity.getEntity("partial1"); + assertEquals(PARTIAL_ENTITY1, value6); + assertEquals(6, entity.names().size()); assertFalse(entity.contains("bla")); } @@ -528,7 +534,8 @@ public void testGetArray() { assertEquals(PARTIAL_ENTITY2, partial1); assertEquals(ENTITY2, partial2); assertEquals(ValueType.BOOLEAN, entity3.getValue("bool").type()); - assertEquals(6, entity3.names().size()); + assertEquals(LAT_LNG_VALUE, entity3.getValue("latLng")); + assertEquals(7, entity3.names().size()); assertFalse(entity3.contains("bla")); try { entity3.getString("str"); diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LatLngTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LatLngTest.java new file mode 100644 index 000000000000..1955ec236300 --- /dev/null +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LatLngTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud.datastore; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class LatLngTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static LatLng gp1 = new LatLng(37.422035, -122.084124); + private static LatLng gp2 = new LatLng(0.0, 0.0); + + private static final String INVALID_LAT_MESSAGE = + "latitude must be in the range [-90, 90] degrees"; + private static final String INVALID_LNG_MESSAGE = + "latitude must be in the range [-180, 180] degrees"; + + @Test + public void testEquals() { + assertEquals(gp1, gp1); + assertNotEquals(gp1, gp2); + } + + @Test + public void testUpperLatRange() { + new LatLng(90, 0); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(INVALID_LAT_MESSAGE); + new LatLng(91, 0); + } + + @Test + public void testLowerLatRange() { + new LatLng(-90, 0); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(INVALID_LAT_MESSAGE); + new LatLng(-91, 0); + } + + @Test + public void testUpperLngRange() { + new LatLng(0, 180); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(INVALID_LNG_MESSAGE); + new LatLng(0, 181); + } + + @Test + public void testLowerLngRange() { + new LatLng(0, 180); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(INVALID_LNG_MESSAGE); + new LatLng(0, -181); + } +} + diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LatLngValueTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LatLngValueTest.java new file mode 100644 index 000000000000..3a25078237d4 --- /dev/null +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LatLngValueTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud.datastore; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class LatLngValueTest { + +private static final LatLng CONTENT = new LatLng(37.4, -122.1); + + @Test + public void testToBuilder() throws Exception { + LatLngValue value = LatLngValue.of(CONTENT); + assertEquals(value, value.toBuilder().build()); + } + + @SuppressWarnings("deprecation") + @Test + public void testOf() throws Exception { + LatLngValue value = LatLngValue.of(CONTENT); + assertEquals(CONTENT, value.get()); + assertFalse(value.excludeFromIndexes()); + } + + @SuppressWarnings("deprecation") + @Test + public void testBuilder() throws Exception { + LatLngValue.Builder builder = LatLngValue.builder(CONTENT); + LatLngValue value = builder.meaning(1).excludeFromIndexes(true).build(); + assertEquals(CONTENT, value.get()); + assertEquals(1, value.meaning()); + assertTrue(value.excludeFromIndexes()); + } +} diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java index 2e083250f35e..a8cbcb294b39 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java @@ -45,6 +45,7 @@ public class SerializationTest { IncompleteKey.builder(KEY1, "v").ancestors(PathElement.of("p", 1)).build(); private static final Key KEY2 = Key.builder(KEY1, "v", 2).build(); private static final DateTime DATE_TIME1 = DateTime.now(); + private static final LatLng LAT_LNG = new LatLng(37.422035, -122.084124); private static final Blob BLOB1 = Blob.copyFrom(UTF_8.encode("hello world")); private static final Cursor CURSOR1 = Cursor.copyFrom(new byte[] {1,2}); private static final Cursor CURSOR2 = Cursor.copyFrom(new byte[]{10}); @@ -89,10 +90,8 @@ public class SerializationTest { private static final DateTimeValue DATE_AND_TIME_VALUE = DateTimeValue.of(DateTime.now()); private static final BlobValue BLOB_VALUE = BlobValue.of(BLOB1); private static final RawValue RAW_VALUE = - RawValue.of(com.google.datastore.v1beta3.Value.newBuilder() - .setGeoPointValue(com.google.type.LatLng.newBuilder() - .setLatitude(0.0).setLongitude(0.0).build()) - .setMeaning(18).build()); + RawValue.of(com.google.datastore.v1beta3.Value.newBuilder().setMeaning(18).build()); + private static final LatLngValue LAT_LNG_VALUE = LatLngValue.of(LAT_LNG); private static final Entity ENTITY1 = Entity.builder(KEY1).build(); private static final Entity ENTITY2 = Entity.builder(KEY2).set("null", NullValue.of()).build(); @@ -119,19 +118,20 @@ public class SerializationTest { @SuppressWarnings("rawtypes") private static final Multimap TYPE_TO_VALUES = ImmutableMultimap.builder() - .put(ValueType.NULL, NULL_VALUE) - .put(ValueType.KEY, KEY_VALUE) - .put(ValueType.STRING, STRING_VALUE) - .putAll(ValueType.ENTITY, EMBEDDED_ENTITY_VALUE1, EMBEDDED_ENTITY_VALUE2, - EMBEDDED_ENTITY_VALUE3) - .put(ValueType.LIST, LIST_VALUE) - .put(ValueType.LONG, LONG_VALUE) - .put(ValueType.DOUBLE, DOUBLE_VALUE) - .put(ValueType.BOOLEAN, BOOLEAN_VALUE) - .put(ValueType.DATE_TIME, DATE_AND_TIME_VALUE) - .put(ValueType.BLOB, BLOB_VALUE) - .put(ValueType.RAW_VALUE, RAW_VALUE) - .build(); + .put(ValueType.NULL, NULL_VALUE) + .put(ValueType.KEY, KEY_VALUE) + .put(ValueType.STRING, STRING_VALUE) + .putAll(ValueType.ENTITY, EMBEDDED_ENTITY_VALUE1, EMBEDDED_ENTITY_VALUE2, + EMBEDDED_ENTITY_VALUE3) + .put(ValueType.LIST, LIST_VALUE) + .put(ValueType.LONG, LONG_VALUE) + .put(ValueType.DOUBLE, DOUBLE_VALUE) + .put(ValueType.BOOLEAN, BOOLEAN_VALUE) + .put(ValueType.DATE_TIME, DATE_AND_TIME_VALUE) + .put(ValueType.BLOB, BLOB_VALUE) + .put(ValueType.RAW_VALUE, RAW_VALUE) + .put(ValueType.LAT_LNG, LAT_LNG_VALUE) + .build(); @Test public void testServiceOptions() throws Exception { @@ -169,8 +169,8 @@ public void testValues() throws Exception { @Test public void testTypes() throws Exception { Serializable[] types = { KEY1, KEY2, INCOMPLETE_KEY1, INCOMPLETE_KEY2, ENTITY1, ENTITY2, - ENTITY3, EMBEDDED_ENTITY, PROJECTION_ENTITY, DATE_TIME1, BLOB1, CURSOR1, GQL1, GQL2, - QUERY1, QUERY2, QUERY3}; + ENTITY3, EMBEDDED_ENTITY, PROJECTION_ENTITY, DATE_TIME1, BLOB1, LAT_LNG, CURSOR1, GQL1, + GQL2, QUERY1, QUERY2, QUERY3}; for (Serializable obj : types) { Object copy = serializeAndDeserialize(obj); assertEquals(obj, obj); diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/ValueTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/ValueTest.java index 12908add4c8e..e433ca9a0666 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/ValueTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/ValueTest.java @@ -41,20 +41,24 @@ public class ValueTest { private static final NullValue NULL_VALUE = NullValue.of(); private static final StringValue STRING_VALUE = StringValue.of("hello"); private static final RawValue RAW_VALUE = RawValue.of(STRING_VALUE.toPb()); - private static final ImmutableMap TYPES = ImmutableMap.builder() - .put(ValueType.NULL, new Object[] {NullValue.class, NULL_VALUE.get()}) - .put(ValueType.KEY, new Object[] {KeyValue.class, KEY}) - .put(ValueType.BLOB, new Object[] {BlobValue.class, BLOB}) - .put(ValueType.BOOLEAN, new Object[] {BooleanValue.class, Boolean.TRUE}) - .put(ValueType.DATE_TIME, new Object[] {DateTimeValue.class, DATE_TIME}) - .put(ValueType.DOUBLE, new Object[] {DoubleValue.class, 1.25D}) - .put(ValueType.ENTITY, new Object[] {EntityValue.class, ENTITY}) - .put(ValueType.LIST, - new Object[] {ListValue.class, ImmutableList.of(NULL_VALUE, STRING_VALUE, RAW_VALUE)}) - .put(ValueType.LONG, new Object[] {LongValue.class, 123L}) - .put(ValueType.RAW_VALUE, new Object[] {RawValue.class, RAW_VALUE.get()}) - .put(ValueType.STRING, new Object[] {StringValue.class, STRING_VALUE.get()}) - .build(); + private static final LatLngValue LAT_LNG_VALUE = + LatLngValue.of(new LatLng(37.422035, -122.084124)); + private static final ImmutableMap TYPES = + ImmutableMap.builder() + .put(ValueType.NULL, new Object[] {NullValue.class, NULL_VALUE.get()}) + .put(ValueType.KEY, new Object[] {KeyValue.class, KEY}) + .put(ValueType.BLOB, new Object[] {BlobValue.class, BLOB}) + .put(ValueType.BOOLEAN, new Object[] {BooleanValue.class, Boolean.TRUE}) + .put(ValueType.DATE_TIME, new Object[] {DateTimeValue.class, DATE_TIME}) + .put(ValueType.DOUBLE, new Object[] {DoubleValue.class, 1.25D}) + .put(ValueType.ENTITY, new Object[] {EntityValue.class, ENTITY}) + .put(ValueType.LIST, new Object[] { + ListValue.class, ImmutableList.of(NULL_VALUE, STRING_VALUE, RAW_VALUE)}) + .put(ValueType.LONG, new Object[] {LongValue.class, 123L}) + .put(ValueType.RAW_VALUE, new Object[] {RawValue.class, RAW_VALUE.get()}) + .put(ValueType.LAT_LNG, new Object[] {LatLngValue.class, LAT_LNG_VALUE.get()}) + .put(ValueType.STRING, new Object[] {StringValue.class, STRING_VALUE.get()}) + .build(); private ImmutableMap> typeToValue;