Skip to content

Commit

Permalink
Support returning arrays of geometrical and temporal types in server.
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed Oct 12, 2018
1 parent 6ee1cdb commit 29f2a4c
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.codehaus.jackson.map.SerializationConfig;

import java.io.IOException;
import java.lang.reflect.Array;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand Down Expand Up @@ -138,12 +139,39 @@ else if ( value instanceof Temporal || value instanceof TemporalAmount )
{
super.writeValue( out, value.toString() );
}
else if ( value.getClass().isArray() && supportedArrayType( value.getClass().getComponentType() ) )
{
writeReflectiveArray( out, value );
}
else
{
super.writeValue( out, value );
}
}

private boolean supportedArrayType( Class<?> valueClass )
{
return Geometry.class.isAssignableFrom( valueClass ) || CRS.class.isAssignableFrom( valueClass ) ||
Temporal.class.isAssignableFrom( valueClass ) || TemporalAmount.class.isAssignableFrom( valueClass );
}

private void writeReflectiveArray( JsonGenerator out, Object array ) throws IOException
{
out.writeStartArray();
try
{
int length = Array.getLength( array );
for ( int i = 0; i < length; i++ )
{
writeValue( out, Array.get( array, i ) );
}
}
finally
{
out.writeEndArray();
}
}

private void writeMap( JsonGenerator out, Map value ) throws IOException
{
out.writeStartObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import static org.neo4j.graphdb.Label.label;
import static org.neo4j.values.storable.CoordinateReferenceSystem.Cartesian;
import static org.neo4j.values.storable.CoordinateReferenceSystem.WGS84;
import static org.neo4j.values.storable.Values.pointValue;

public class PointTypeIT extends AbstractRestFunctionalTestBase
{
Expand Down Expand Up @@ -81,6 +82,34 @@ public void shouldReturnPoint2DWithLatitudeAndLongitude() throws Exception
testPoint( "RETURN point({longitude: 56.7, latitude: 12.78})", new double[]{56.7, 12.78}, WGS84, "point" );
}

@Test
public void shouldHandlePointArrays() throws Exception
{
//Given
GraphDatabaseFacade db = server().getDatabase().getGraph();
try ( Transaction tx = db.beginTx() )
{
Node node = db.createNode( label( "N" ) );
//node.setProperty( "coordinates", new double[]{30.655691, 104.081602} );
node.setProperty( "coordinates", new Point[]{pointValue( WGS84, 30.655691, 104.081602 )} );
node.setProperty( "location", "Shanghai" );
node.setProperty( "type", "gps" );
tx.success();
}

// When
HTTP.Response response = runQuery( "MATCH (n:N) RETURN n" );

assertEquals( 200, response.status() );
assertNoErrors( response );

JsonNode data = response.get( "results" ).get( 0 ).get( "data" ).get(0);
JsonNode row = data.get( "row" ).get(0).get( "coordinates" ).get(0);
assertGeometryTypeEqual( GeometryType.GEOMETRY_POINT, row );
assertCoordinatesEqual( new double[]{30.655691, 104.081602}, row );
assertCrsEqual( WGS84, row );
}

private static void testPoint( String query, double[] expectedCoordinate, CoordinateReferenceSystem expectedCrs, String expectedType ) throws Exception
{
HTTP.Response response = runQuery( query );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,27 @@
import org.junit.Before;
import org.junit.Test;

import java.time.Duration;
import java.time.ZoneId;
import java.time.ZonedDateTime;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.spatial.Point;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacade;
import org.neo4j.kernel.impl.store.GeometryType;
import org.neo4j.server.rest.AbstractRestFunctionalTestBase;
import org.neo4j.server.rest.domain.JsonParseException;
import org.neo4j.test.server.HTTP;
import org.neo4j.test.server.HTTP.Response;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.neo4j.graphdb.Label.label;
import static org.neo4j.server.rest.transactional.integration.TransactionMatchers.containsNoErrors;
import static org.neo4j.server.rest.transactional.integration.TransactionMatchers.graphContainsDeletedNodes;
import static org.neo4j.server.rest.transactional.integration.TransactionMatchers.graphContainsDeletedRelationships;
Expand All @@ -49,6 +60,8 @@
import static org.neo4j.server.rest.transactional.integration.TransactionMatchers.rowContainsDeletedEntitiesInPath;
import static org.neo4j.server.rest.transactional.integration.TransactionMatchers.rowContainsNoDeletedEntities;
import static org.neo4j.test.server.HTTP.RawPayload.quotedJson;
import static org.neo4j.values.storable.CoordinateReferenceSystem.WGS84;
import static org.neo4j.values.storable.Values.pointValue;

public class QueryResultsSerializationTest extends AbstractRestFunctionalTestBase
{
Expand Down Expand Up @@ -552,6 +565,59 @@ public void nestedShouldWorkRow()
assertThat( nodesInDatabase(), equalTo( 0L ) );
}

@Test
public void shouldHandleTemporalArrays() throws Exception
{
//Given
GraphDatabaseFacade db = server().getDatabase().getGraph();
ZonedDateTime now = ZonedDateTime.of( 1980, 3, 11, 0, 0,
0, 0, ZoneId.of( "Europe/Stockholm" ) );
try ( Transaction tx = db.beginTx() )
{
Node node = db.createNode( label( "N" ) );
node.setProperty( "now", new ZonedDateTime[]{now} );
tx.success();
}

// When
HTTP.Response response = runQuery( "MATCH (n:N) RETURN n" );

// Then
assertEquals( 200, response.status() );
assertNoErrors( response );

JsonNode row = response.get( "results" ).get( 0 ).get( "data" ).get(0).get( "row" ).get(0)
.get( "now" ).get(0);

assertEquals( "\"1980-03-11T00:00+01:00[Europe/Stockholm]\"", row.toString() );
}

@Test
public void shouldHandleDurationArrays() throws Exception
{
//Given
GraphDatabaseFacade db = server().getDatabase().getGraph();
Duration duration = Duration.ofSeconds( 73 );
try ( Transaction tx = db.beginTx() )
{
Node node = db.createNode( label( "N" ) );
node.setProperty( "duration", new Duration[]{duration} );
tx.success();
}

// When
HTTP.Response response = runQuery( "MATCH (n:N) RETURN n" );

// Then
assertEquals( 200, response.status() );
assertNoErrors( response );

JsonNode row = response.get( "results" ).get( 0 ).get( "data" ).get(0).get( "row" ).get(0)
.get( "duration" ).get(0);

assertEquals( "\"PT1M13S\"", row.toString() );
}

private HTTP.RawPayload queryAsJsonGraph( String query )
{
return quotedJson( "{ 'statements': [ { 'statement': '" + query + "', 'resultDataContents': [ 'graph' ] } ] }" );
Expand Down

0 comments on commit 29f2a4c

Please sign in to comment.