Skip to content

Commit

Permalink
Return type support of Temporal and Point in Rest endpoint
Browse files Browse the repository at this point in the history
Return `Temporal` and `TemporalAmount` as ISO-8601 standard string.
Return type info in meta data section
  • Loading branch information
Zhen committed Mar 15, 2018
1 parent 2c007ed commit 7a0ac84
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 19 deletions.
Expand Up @@ -24,6 +24,13 @@
import org.codehaus.jackson.map.SerializationConfig;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAmount;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
Expand All @@ -37,11 +44,17 @@
import org.neo4j.graphdb.spatial.Coordinate;
import org.neo4j.graphdb.spatial.Geometry;
import org.neo4j.graphdb.spatial.Point;
import org.neo4j.values.storable.PointValue;

import static org.neo4j.helpers.collection.MapUtil.genericMap;

public class Neo4jJsonCodec extends ObjectMapper
{
private enum Neo4jJsonMetaType
{
node, relationship, datetime, time, localdatetime, date, localtime, duration, point2d, point3d
}

private TransitionalPeriodTransactionMessContainer container;

public Neo4jJsonCodec( TransitionalPeriodTransactionMessContainer container )
Expand Down Expand Up @@ -88,20 +101,22 @@ else if ( value instanceof Geometry )
{
Geometry geom = (Geometry) value;
Object coordinates = (geom instanceof Point) ? ((Point) geom).getCoordinate() : geom.getCoordinates();
writeMap( out,
genericMap( new LinkedHashMap<>(), "type", geom.getGeometryType(),
"coordinates", coordinates, "crs", geom.getCRS() ) );
writeMap( out, genericMap( new LinkedHashMap<>(), "type", geom.getGeometryType(), "coordinates", coordinates, "crs", geom.getCRS() ) );
}
else if ( value instanceof Coordinate )
{
Coordinate coordinate = (Coordinate) value;
writeIterator( out, coordinate.getCoordinate().iterator());
writeIterator( out, coordinate.getCoordinate().iterator() );
}
else if ( value instanceof CRS )
{
CRS crs = (CRS) value;
writeMap( out, genericMap(new LinkedHashMap<>(), "name", crs.getType(), "type", "link", "properties",
genericMap(new LinkedHashMap<>(), "href", crs.getHref() + "ogcwkt/", "type", "ogcwkt" ) ) );
writeMap( out, genericMap( new LinkedHashMap<>(), "name", crs.getType(), "type", "link", "properties",
genericMap( new LinkedHashMap<>(), "href", crs.getHref() + "ogcwkt/", "type", "ogcwkt" ) ) );
}
else if ( value instanceof Temporal || value instanceof TemporalAmount )
{
super.writeValue( out, value.toString() );
}
else
{
Expand Down Expand Up @@ -223,15 +238,15 @@ void writeMeta( JsonGenerator out, Object value ) throws IOException
Node node = (Node) value;
try ( TransactionStateChecker stateChecker = TransactionStateChecker.create( container ) )
{
writeNodeOrRelationshipMeta( out, node.getId(), "node", stateChecker.isNodeDeletedInCurrentTx( node.getId() ) );
writeNodeOrRelationshipMeta( out, node.getId(), Neo4jJsonMetaType.node.name(), stateChecker.isNodeDeletedInCurrentTx( node.getId() ) );
}
}
else if ( value instanceof Relationship )
{
Relationship relationship = (Relationship) value;
try ( TransactionStateChecker transactionStateChecker = TransactionStateChecker.create( container ) )
{
writeNodeOrRelationshipMeta( out, relationship.getId(), "relationship",
writeNodeOrRelationshipMeta( out, relationship.getId(), Neo4jJsonMetaType.relationship.name(),
transactionStateChecker.isRelationshipDeletedInCurrentTx( relationship.getId() ) );
}
}
Expand All @@ -254,12 +269,80 @@ else if ( value instanceof Map )
writeMeta( out, map.get( key ) );
}
}
else if ( value instanceof Geometry )
{
writeGeometryTypeMeta( out, (Geometry) value );
}
else if ( value instanceof Temporal )
{
writeTemporalTypeMeta( out, (Temporal) value );
}
else if ( value instanceof TemporalAmount )
{
writeTypeMeta( out, Neo4jJsonMetaType.duration.name() );
}
else
{
out.writeNull();
}
}

private void writeGeometryTypeMeta( JsonGenerator out, Geometry value ) throws IOException
{
Neo4jJsonMetaType type = null;
if ( value instanceof PointValue )
{
PointValue p = (PointValue) value;
int size = p.coordinate().length;
if ( size == 2 )
{
type = Neo4jJsonMetaType.point2d;
}
else if ( size == 3 )
{
type = Neo4jJsonMetaType.point3d;
}
}
if ( type == null )
{
throw new IllegalArgumentException(
String.format( "Unsupported Geometry type: type=%s, value=%s", value.getClass().getSimpleName(), value.toString() ) );
}
writeTypeMeta( out, type.name() );
}

private void writeTemporalTypeMeta( JsonGenerator out, Temporal value ) throws IOException
{
Neo4jJsonMetaType type = null;
if ( value instanceof ZonedDateTime )
{
type = Neo4jJsonMetaType.datetime;
}
else if ( value instanceof LocalDate )
{
type = Neo4jJsonMetaType.date;
}
else if ( value instanceof OffsetTime )
{
type = Neo4jJsonMetaType.time;
}
else if ( value instanceof LocalDateTime )
{
type = Neo4jJsonMetaType.localdatetime;
}
else if ( value instanceof LocalTime )
{
type = Neo4jJsonMetaType.localtime;
}

if ( type == null )
{
throw new IllegalArgumentException(
String.format( "Unsupported Temporal type: type=%s, value=%s", value.getClass().getSimpleName(), value.toString() ) );
}
writeTypeMeta( out, type.name() );
}

private void writeMetaPath( JsonGenerator out, Path value ) throws IOException
{
out.writeStartArray();
Expand All @@ -276,6 +359,20 @@ private void writeMetaPath( JsonGenerator out, Path value ) throws IOException
}
}

private void writeTypeMeta( JsonGenerator out, String type )
throws IOException
{
out.writeStartObject();
try
{
out.writeStringField( "type", type );
}
finally
{
out.writeEndObject();
}
}

private void writeNodeOrRelationshipMeta( JsonGenerator out, long id, String type, boolean isDeleted )
throws IOException
{
Expand Down
Expand Up @@ -52,6 +52,8 @@
import static org.neo4j.server.rest.web.Surface.PATH_RELATIONSHIP_INDEX;
import static org.neo4j.server.rest.web.Surface.PATH_SCHEMA_CONSTRAINT;
import static org.neo4j.server.rest.web.Surface.PATH_SCHEMA_INDEX;
import static org.neo4j.test.server.HTTP.POST;
import static org.neo4j.test.server.HTTP.RawPayload.quotedJson;

public class AbstractRestFunctionalTestBase extends SharedServerTestBase implements GraphHolder
{
Expand Down Expand Up @@ -284,4 +286,16 @@ public static int getLocalHttpPort()
.resolveDependency( ConnectorPortRegister.class );
return connectorPortRegister.getLocalAddress( "http" ).getPort();
}


public static HTTP.Response runQuery( String query )
{
return POST( txCommitUri(), quotedJson( "{'statements': [{'statement': '" + query + "'}]}" ) );
}

public static void assertNoErrors( HTTP.Response response ) throws JsonParseException
{
assertEquals( "[]", response.get( "errors" ).toString() );
assertEquals( 0, response.get( "errors" ).size() );
}
}
Expand Up @@ -296,4 +296,16 @@ public void testGeometryWriting() throws IOException
//Then
verify( jsonGenerator, times( 3 ) ).writeEndObject();
}

@Test
public void testDateTimeWriting() throws Throwable
{
// Given



// When

// Then
}
}
Expand Up @@ -38,8 +38,6 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.neo4j.graphdb.Label.label;
import static org.neo4j.test.server.HTTP.POST;
import static org.neo4j.test.server.HTTP.RawPayload.quotedJson;
import static org.neo4j.values.storable.CoordinateReferenceSystem.Cartesian;
import static org.neo4j.values.storable.CoordinateReferenceSystem.WGS84;

Expand Down Expand Up @@ -74,16 +72,16 @@ public void shouldWorkWithPoint2DArrays() throws Exception
@Test
public void shouldReturnPoint2DWithXAndY() throws Exception
{
testPoint( "RETURN point({x: 42.05, y: 90.99})", new double[]{42.05, 90.99}, Cartesian );
testPoint( "RETURN point({x: 42.05, y: 90.99})", new double[]{42.05, 90.99}, Cartesian, "point2d" );
}

@Test
public void shouldReturnPoint2DWithLatitudeAndLongitude() throws Exception
{
testPoint( "RETURN point({longitude: 56.7, latitude: 12.78})", new double[]{56.7, 12.78}, WGS84 );
testPoint( "RETURN point({longitude: 56.7, latitude: 12.78})", new double[]{56.7, 12.78}, WGS84, "point2d" );
}

private static void testPoint( String query, double[] expectedCoordinate, CoordinateReferenceSystem expectedCrs ) throws Exception
private static void testPoint( String query, double[] expectedCoordinate, CoordinateReferenceSystem expectedCrs, String expectedType ) throws Exception
{
HTTP.Response response = runQuery( query );

Expand All @@ -94,16 +92,16 @@ private static void testPoint( String query, double[] expectedCoordinate, Coordi
assertGeometryTypeEqual( GeometryType.GEOMETRY_POINT, element );
assertCoordinatesEqual( expectedCoordinate, element );
assertCrsEqual( expectedCrs, element );
}

private static HTTP.Response runQuery( String query )
{
return POST( txCommitUri(), quotedJson( "{'statements': [{'statement': '" + query + "'}]}" ) );
assertTypeEqual( expectedType, response );
}

private static void assertNoErrors( HTTP.Response response ) throws JsonParseException
private static void assertTypeEqual( String expectedType, HTTP.Response response ) throws JsonParseException
{
assertEquals( 0, response.get( "errors" ).size() );
JsonNode data = response.get( "results" ).get( 0 ).get( "data" );
JsonNode meta = data.get( 0 ).get( "meta" );
assertEquals( 1, meta.size() );
assertEquals( expectedType, meta.get( 0 ).get( "type" ).asText() );
}

private static JsonNode extractSingleElement( HTTP.Response response ) throws JsonParseException
Expand Down

0 comments on commit 7a0ac84

Please sign in to comment.