
org.neo4j.server.rest.web.RestfulGraphDatabase Maven / Gradle / Ivy
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.server.rest.web;
import org.apache.commons.configuration.Configuration;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.neo4j.graphdb.ConstraintViolationException;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.helpers.collection.Iterables;
import org.neo4j.helpers.collection.Pair;
import org.neo4j.server.configuration.ServerSettings;
import org.neo4j.server.rest.domain.EndNodeNotFoundException;
import org.neo4j.server.rest.domain.EvaluationException;
import org.neo4j.server.rest.domain.PropertySettingStrategy;
import org.neo4j.server.rest.domain.StartNodeNotFoundException;
import org.neo4j.server.rest.domain.TraverserReturnType;
import org.neo4j.server.rest.repr.BadInputException;
import org.neo4j.server.rest.repr.IndexedEntityRepresentation;
import org.neo4j.server.rest.repr.InputFormat;
import org.neo4j.server.rest.repr.InvalidArgumentsException;
import org.neo4j.server.rest.repr.ListEntityRepresentation;
import org.neo4j.server.rest.repr.ListRepresentation;
import org.neo4j.server.rest.repr.OutputFormat;
import org.neo4j.server.rest.repr.Representation;
import org.neo4j.server.rest.web.DatabaseActions.RelationshipDirection;
import static java.lang.String.format;
import static org.neo4j.helpers.collection.Iterables.map;
import static org.neo4j.helpers.collection.MapUtil.toMap;
import static org.neo4j.server.rest.web.Surface.PATH_LABELS;
import static org.neo4j.server.rest.web.Surface.PATH_NODES;
import static org.neo4j.server.rest.web.Surface.PATH_NODE_INDEX;
import static org.neo4j.server.rest.web.Surface.PATH_RELATIONSHIPS;
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.server.rest.web.Surface.PATH_SCHEMA_RELATIONSHIP_CONSTRAINT;
@Path( "/" )
public class RestfulGraphDatabase
{
@SuppressWarnings("serial")
public static class AmpersandSeparatedCollection extends LinkedHashSet
{
public AmpersandSeparatedCollection( String path )
{
for ( String e : path.split( "&" ) )
{
if ( e.trim()
.length() > 0 )
{
add( e );
}
}
}
}
private static final String PATH_NODE = PATH_NODES + "/{nodeId}";
private static final String PATH_NODE_PROPERTIES = PATH_NODE + "/properties";
private static final String PATH_NODE_PROPERTY = PATH_NODE_PROPERTIES + "/{key}";
private static final String PATH_NODE_RELATIONSHIPS = PATH_NODE + "/relationships";
private static final String PATH_RELATIONSHIP = PATH_RELATIONSHIPS + "/{relationshipId}";
private static final String PATH_NODE_RELATIONSHIPS_W_DIR = PATH_NODE_RELATIONSHIPS + "/{direction}";
private static final String PATH_NODE_RELATIONSHIPS_W_DIR_N_TYPES = PATH_NODE_RELATIONSHIPS_W_DIR + "/{types}";
private static final String PATH_RELATIONSHIP_PROPERTIES = PATH_RELATIONSHIP + "/properties";
private static final String PATH_RELATIONSHIP_PROPERTY = PATH_RELATIONSHIP_PROPERTIES + "/{key}";
private static final String PATH_NODE_TRAVERSE = PATH_NODE + "/traverse/{returnType}";
private static final String PATH_NODE_PATH = PATH_NODE + "/path";
private static final String PATH_NODE_PATHS = PATH_NODE + "/paths";
private static final String PATH_NODE_LABELS = PATH_NODE + "/labels";
private static final String PATH_NODE_LABEL = PATH_NODE + "/labels/{label}";
private static final String PATH_NODE_DEGREE = PATH_NODE + "/degree";
private static final String PATH_NODE_DEGREE_W_DIR = PATH_NODE_DEGREE + "/{direction}";
private static final String PATH_NODE_DEGREE_W_DIR_N_TYPES = PATH_NODE_DEGREE_W_DIR + "/{types}";
private static final String PATH_PROPERTY_KEYS = "propertykeys";
protected static final String PATH_NAMED_NODE_INDEX = PATH_NODE_INDEX + "/{indexName}";
protected static final String PATH_NODE_INDEX_GET = PATH_NAMED_NODE_INDEX + "/{key}/{value}";
protected static final String PATH_NODE_INDEX_QUERY_WITH_KEY = PATH_NAMED_NODE_INDEX + "/{key}"; //
// http://localhost/db/data/index/node/foo?query=somelucenestuff
protected static final String PATH_NODE_INDEX_ID = PATH_NODE_INDEX_GET + "/{id}";
protected static final String PATH_NODE_INDEX_REMOVE_KEY = PATH_NAMED_NODE_INDEX + "/{key}/{id}";
protected static final String PATH_NODE_INDEX_REMOVE = PATH_NAMED_NODE_INDEX + "/{id}";
protected static final String PATH_NAMED_RELATIONSHIP_INDEX = PATH_RELATIONSHIP_INDEX + "/{indexName}";
protected static final String PATH_RELATIONSHIP_INDEX_GET = PATH_NAMED_RELATIONSHIP_INDEX + "/{key}/{value}";
protected static final String PATH_RELATIONSHIP_INDEX_QUERY_WITH_KEY = PATH_NAMED_RELATIONSHIP_INDEX + "/{key}";
protected static final String PATH_RELATIONSHIP_INDEX_ID = PATH_RELATIONSHIP_INDEX_GET + "/{id}";
protected static final String PATH_RELATIONSHIP_INDEX_REMOVE_KEY = PATH_NAMED_RELATIONSHIP_INDEX + "/{key}/{id}";
protected static final String PATH_RELATIONSHIP_INDEX_REMOVE = PATH_NAMED_RELATIONSHIP_INDEX + "/{id}";
public static final String PATH_AUTO_INDEX = "index/auto/{type}";
protected static final String PATH_AUTO_INDEX_STATUS = PATH_AUTO_INDEX + "/status";
protected static final String PATH_AUTO_INDEXED_PROPERTIES = PATH_AUTO_INDEX + "/properties";
protected static final String PATH_AUTO_INDEX_PROPERTY_DELETE = PATH_AUTO_INDEXED_PROPERTIES + "/{property}";
protected static final String PATH_AUTO_INDEX_GET = PATH_AUTO_INDEX + "/{key}/{value}";
public static final String PATH_ALL_NODES_LABELED = "label/{label}/nodes";
public static final String PATH_SCHEMA_INDEX_LABEL = PATH_SCHEMA_INDEX + "/{label}";
public static final String PATH_SCHEMA_INDEX_LABEL_PROPERTY = PATH_SCHEMA_INDEX_LABEL + "/{property}";
public static final String PATH_SCHEMA_CONSTRAINT_LABEL = PATH_SCHEMA_CONSTRAINT + "/{label}";
public static final String PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS = PATH_SCHEMA_CONSTRAINT_LABEL + "/uniqueness";
public static final String PATH_SCHEMA_CONSTRAINT_LABEL_EXISTENCE = PATH_SCHEMA_CONSTRAINT_LABEL + "/existence";
public static final String PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS_PROPERTY = PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS + "/{property}";
public static final String PATH_SCHEMA_CONSTRAINT_LABEL_EXISTENCE_PROPERTY = PATH_SCHEMA_CONSTRAINT_LABEL_EXISTENCE + "/{property}";
public static final String PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_TYPE = PATH_SCHEMA_RELATIONSHIP_CONSTRAINT + "/{type}";
public static final String PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_TYPE_EXISTENCE = PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_TYPE + "/existence";
public static final String PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_EXISTENCE_PROPERTY = PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_TYPE_EXISTENCE + "/{property}";
public static final String NODE_AUTO_INDEX_TYPE = "node";
public static final String RELATIONSHIP_AUTO_INDEX_TYPE = "relationship";
private static final String SIXTY_SECONDS = "60";
private static final String FIFTY_ENTRIES = "50";
private static final String UNIQUENESS_MODE_GET_OR_CREATE = "get_or_create";
private static final String UNIQUENESS_MODE_CREATE_OR_FAIL = "create_or_fail";
// TODO Obviously change name/content on this
private static final String HEADER_TRANSACTION = "Transaction";
private final DatabaseActions actions;
private Configuration config;
private final OutputFormat output;
private final InputFormat input;
public static final String PATH_TO_CREATE_PAGED_TRAVERSERS = PATH_NODE + "/paged/traverse/{returnType}";
public static final String PATH_TO_PAGED_TRAVERSERS = PATH_NODE + "/paged/traverse/{returnType}/{traverserId}";
private enum UniqueIndexType
{
None,
GetOrCreate,
CreateOrFail
}
public RestfulGraphDatabase( @Context InputFormat input,
@Context OutputFormat output,
@Context DatabaseActions actions,
@Context Configuration config )
{
this.input = input;
this.output = output;
this.actions = actions;
this.config = config;
}
public OutputFormat getOutputFormat()
{
return output;
}
private Response nothing()
{
return output.noContent();
}
private Long extractNodeIdOrNull( String uri ) throws BadInputException
{
if ( uri == null )
{
return null;
}
return extractNodeId( uri );
}
private long extractNodeId( String uri ) throws BadInputException
{
try
{
return Long.parseLong( uri.substring( uri.lastIndexOf( "/" ) + 1 ) );
}
catch ( NumberFormatException | NullPointerException ex )
{
throw new BadInputException( ex );
}
}
private Long extractRelationshipIdOrNull( String uri ) throws BadInputException
{
if ( uri == null )
{
return null;
}
return extractRelationshipId( uri );
}
private long extractRelationshipId( String uri ) throws BadInputException
{
return extractNodeId( uri );
}
@GET
public Response getRoot()
{
return output.ok( actions.root() );
}
// Nodes
@POST
@Path(PATH_NODES)
public Response createNode( String body )
{
try
{
return output.created( actions.createNode( input.readMap( body ) ) );
}
catch ( ArrayStoreException ase )
{
return generateBadRequestDueToMangledJsonResponse( body );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ClassCastException e )
{
return output.badRequest( e );
}
}
private Response generateBadRequestDueToMangledJsonResponse( String body )
{
return output.badRequest( MediaType.TEXT_PLAIN_TYPE, "Invalid JSON array in POST body: " + body );
}
@GET
@Path(PATH_NODE)
public Response getNode( @PathParam("nodeId") long nodeId )
{
try
{
return output.ok( actions.getNode( nodeId ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
@DELETE
@Path(PATH_NODE)
public Response deleteNode( @PathParam("nodeId") long nodeId )
{
try
{
actions.deleteNode( nodeId );
return nothing();
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
catch ( ConstraintViolationException e )
{
return output.conflict( e );
}
}
// Node properties
@PUT
@Path(PATH_NODE_PROPERTIES)
public Response setAllNodeProperties( @PathParam("nodeId") long nodeId, String body )
{
try
{
actions.setAllNodeProperties( nodeId, input.readMap( body ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ArrayStoreException ase )
{
return generateBadRequestDueToMangledJsonResponse( body );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
return nothing();
}
@GET
@Path(PATH_NODE_PROPERTIES)
public Response getAllNodeProperties( @PathParam("nodeId") long nodeId )
{
try
{
return output.response( Response.Status.OK, actions.getAllNodeProperties( nodeId ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
@PUT
@Path(PATH_NODE_PROPERTY)
public Response setNodeProperty( @PathParam("nodeId") long nodeId,
@PathParam("key") String key, String body )
{
try
{
actions.setNodeProperty( nodeId, key, input.readValue( body ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ArrayStoreException ase )
{
return generateBadRequestDueToMangledJsonResponse( body );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
catch ( org.neo4j.graphdb.ConstraintViolationException e)
{
return output.conflict( e );
}
return nothing();
}
@GET
@Path(PATH_NODE_PROPERTY)
public Response getNodeProperty( @PathParam("nodeId") long nodeId, @PathParam("key") String key )
{
try
{
return output.ok( actions.getNodeProperty( nodeId, key ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
catch ( NoSuchPropertyException e )
{
return output.notFound( e );
}
}
@DELETE
@Path(PATH_NODE_PROPERTY)
public Response deleteNodeProperty( @PathParam("nodeId") long nodeId, @PathParam("key") String key )
{
try
{
actions.removeNodeProperty( nodeId, key );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
catch ( NoSuchPropertyException e )
{
return output.notFound( e );
}
return nothing();
}
@DELETE
@Path(PATH_NODE_PROPERTIES)
public Response deleteAllNodeProperties( @PathParam("nodeId") long nodeId )
{
try
{
actions.removeAllNodeProperties( nodeId );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
catch ( PropertyValueException e )
{
return output.badRequest( e );
}
return nothing();
}
// Node Labels
@POST
@Path( PATH_NODE_LABELS )
public Response addNodeLabel( @PathParam( "nodeId" ) long nodeId, String body )
{
try
{
Object rawInput = input.readValue( body );
if ( rawInput instanceof String )
{
ArrayList s = new ArrayList<>();
s.add((String) rawInput);
actions.addLabelToNode( nodeId, s );
}
else if(rawInput instanceof Collection)
{
actions.addLabelToNode( nodeId, (Collection) rawInput );
}
else
{
throw new InvalidArgumentsException( format( "Label name must be a string. Got: '%s'", rawInput ) );
}
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ArrayStoreException ase )
{
return generateBadRequestDueToMangledJsonResponse( body );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
return nothing();
}
@PUT
@Path( PATH_NODE_LABELS )
public Response setNodeLabels( @PathParam( "nodeId" ) long nodeId, String body )
{
try
{
Object rawInput = input.readValue( body );
if ( !(rawInput instanceof Collection) )
{
throw new InvalidArgumentsException( format( "Input must be an array of Strings. Got: '%s'", rawInput ) );
}
else
{
actions.setLabelsOnNode( nodeId, (Collection) rawInput );
}
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ArrayStoreException ase )
{
return generateBadRequestDueToMangledJsonResponse( body );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
return nothing();
}
@DELETE
@Path( PATH_NODE_LABEL )
public Response removeNodeLabel( @PathParam( "nodeId" ) long nodeId, @PathParam( "label" ) String labelName )
{
try
{
actions.removeLabelFromNode( nodeId, labelName );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
return nothing();
}
@GET
@Path( PATH_NODE_LABELS )
public Response getNodeLabels( @PathParam( "nodeId" ) long nodeId )
{
try
{
return output.ok( actions.getNodeLabels( nodeId ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
@GET
@Path( PATH_ALL_NODES_LABELED )
public Response getNodesWithLabelAndProperty( @PathParam("label") String labelName, @Context UriInfo uriInfo )
{
try
{
if ( labelName.isEmpty() )
{
throw new InvalidArgumentsException( "Empty label name" );
}
Map properties = toMap( map( queryParamsToProperties, uriInfo.getQueryParameters().entrySet()));
return output.ok( actions.getNodesWithLabel( labelName, properties ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
}
@GET
@Path( PATH_LABELS )
public Response getAllLabels( @QueryParam( "in_use" ) @DefaultValue( "true" ) boolean inUse )
{
return output.ok( actions.getAllLabels( inUse ) );
}
// Property keys
@GET
@Path( PATH_PROPERTY_KEYS )
public Response getAllPropertyKeys( )
{
return output.ok( actions.getAllPropertyKeys() );
}
// Relationships
@SuppressWarnings("unchecked")
@POST
@Path(PATH_NODE_RELATIONSHIPS)
public Response createRelationship( @PathParam("nodeId") long startNodeId, String body )
{
final Map data;
final long endNodeId;
final String type;
final Map properties;
try
{
data = input.readMap( body );
endNodeId = extractNodeId( (String) data.get( "to" ) );
type = (String) data.get( "type" );
properties = (Map) data.get( "data" );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ClassCastException e )
{
return output.badRequest( e );
}
try
{
return output.created( actions.createRelationship( startNodeId, endNodeId, type, properties ) );
}
catch ( StartNodeNotFoundException e )
{
return output.notFound( e );
}
catch ( EndNodeNotFoundException e )
{
return output.badRequest( e );
}
catch ( PropertyValueException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
}
@GET
@Path(PATH_RELATIONSHIP)
public Response getRelationship( @PathParam("relationshipId") long relationshipId )
{
try
{
return output.ok( actions.getRelationship( relationshipId ) );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
}
@DELETE
@Path(PATH_RELATIONSHIP)
public Response deleteRelationship( @PathParam("relationshipId") long relationshipId )
{
try
{
actions.deleteRelationship( relationshipId );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
return nothing();
}
@GET
@Path(PATH_NODE_RELATIONSHIPS_W_DIR)
public Response getNodeRelationships( @PathParam("nodeId") long nodeId,
@PathParam("direction") RelationshipDirection direction )
{
try
{
return output.ok( actions.getNodeRelationships( nodeId, direction, Collections.emptyList() ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
@GET
@Path(PATH_NODE_RELATIONSHIPS_W_DIR_N_TYPES)
public Response getNodeRelationships( @PathParam("nodeId") long nodeId,
@PathParam("direction") RelationshipDirection direction,
@PathParam("types") AmpersandSeparatedCollection types )
{
try
{
return output.ok( actions.getNodeRelationships( nodeId, direction, types ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
// Degrees
@GET
@Path(PATH_NODE_DEGREE_W_DIR)
public Response getNodeDegree( @PathParam("nodeId") long nodeId,
@PathParam("direction") RelationshipDirection direction )
{
try
{
return output.ok( actions.getNodeDegree( nodeId, direction, Collections.emptyList() ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
@GET
@Path(PATH_NODE_DEGREE_W_DIR_N_TYPES)
public Response getNodeDegree(@PathParam("nodeId") long nodeId,
@PathParam("direction") RelationshipDirection direction,
@PathParam("types") AmpersandSeparatedCollection types )
{
try
{
return output.ok( actions.getNodeDegree( nodeId, direction, types ) );
}
catch ( NodeNotFoundException e )
{
return output.notFound( e );
}
}
// Relationship properties
@GET
@Path(PATH_RELATIONSHIP_PROPERTIES)
public Response getAllRelationshipProperties( @PathParam("relationshipId") long relationshipId )
{
try
{
return output.response( Response.Status.OK, actions.getAllRelationshipProperties( relationshipId ) );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
}
@GET
@Path(PATH_RELATIONSHIP_PROPERTY)
public Response getRelationshipProperty( @PathParam("relationshipId") long relationshipId,
@PathParam("key") String key )
{
try
{
return output.ok( actions.getRelationshipProperty( relationshipId, key ) );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
catch ( NoSuchPropertyException e )
{
return output.notFound( e );
}
}
@PUT
@Path(PATH_RELATIONSHIP_PROPERTIES)
@Consumes(MediaType.APPLICATION_JSON)
public Response setAllRelationshipProperties( @PathParam("relationshipId") long relationshipId, String body )
{
try
{
actions.setAllRelationshipProperties( relationshipId, input.readMap( body ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
return nothing();
}
@PUT
@Path(PATH_RELATIONSHIP_PROPERTY)
@Consumes(MediaType.APPLICATION_JSON)
public Response setRelationshipProperty( @PathParam("relationshipId") long relationshipId,
@PathParam("key") String key, String body )
{
try
{
actions.setRelationshipProperty( relationshipId, key, input.readValue( body ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
return nothing();
}
@DELETE
@Path(PATH_RELATIONSHIP_PROPERTIES)
public Response deleteAllRelationshipProperties( @PathParam("relationshipId") long relationshipId )
{
try
{
actions.removeAllRelationshipProperties( relationshipId );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
catch ( PropertyValueException e )
{
return output.badRequest( e );
}
return nothing();
}
@DELETE
@Path(PATH_RELATIONSHIP_PROPERTY)
public Response deleteRelationshipProperty( @PathParam("relationshipId") long relationshipId,
@PathParam("key") String key )
{
try
{
actions.removeRelationshipProperty( relationshipId, key );
}
catch ( RelationshipNotFoundException e )
{
return output.notFound( e );
}
catch ( NoSuchPropertyException e )
{
return output.notFound( e );
}
return nothing();
}
// Index
@GET
@Path(PATH_NODE_INDEX)
public Response getNodeIndexRoot()
{
if ( actions.getNodeIndexNames().length == 0 )
{
return output.noContent();
}
return output.ok( actions.nodeIndexRoot() );
}
@POST
@Path(PATH_NODE_INDEX)
@Consumes(MediaType.APPLICATION_JSON)
public Response jsonCreateNodeIndex( String json )
{
try
{
return output.created( actions.createNodeIndex( input.readMap( json ) ) );
}
catch ( IllegalArgumentException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
}
@GET
@Path(PATH_RELATIONSHIP_INDEX)
public Response getRelationshipIndexRoot()
{
if ( actions.getRelationshipIndexNames().length == 0 )
{
return output.noContent();
}
return output.ok( actions.relationshipIndexRoot() );
}
@POST
@Path(PATH_RELATIONSHIP_INDEX)
@Consumes(MediaType.APPLICATION_JSON)
public Response jsonCreateRelationshipIndex( String json )
{
try
{
return output.created( actions.createRelationshipIndex( input.readMap( json ) ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( IllegalArgumentException e )
{
return output.badRequest( e );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_NAMED_NODE_INDEX)
public Response getIndexedNodesByQuery( @PathParam("indexName") String indexName,
@QueryParam("query") String query,
@QueryParam("order") String order )
{
try
{
return output.ok( actions.getIndexedNodesByQuery( indexName, query,
order ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_AUTO_INDEX)
public Response getAutoIndexedNodesByQuery( @PathParam("type") String type, @QueryParam("query") String query )
{
try
{
if ( type.equals( NODE_AUTO_INDEX_TYPE ) )
{
return output.ok( actions.getAutoIndexedNodesByQuery( query ) );
}
else if ( type.equals( RELATIONSHIP_AUTO_INDEX_TYPE ) )
{
return output.ok( actions.getAutoIndexedRelationshipsByQuery( query ) );
}
else
{
return output.badRequest( new RuntimeException( "Unrecognized auto-index type, " +
"expected '" + NODE_AUTO_INDEX_TYPE + "' or '" + RELATIONSHIP_AUTO_INDEX_TYPE + "'" ) );
}
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_NAMED_NODE_INDEX)
@Consumes(MediaType.APPLICATION_JSON)
public Response deleteNodeIndex(
@PathParam("indexName") String indexName )
{
try
{
actions.removeNodeIndex( indexName );
return output.noContent();
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
}
@DELETE
@Path(PATH_NAMED_RELATIONSHIP_INDEX)
@Consumes(MediaType.APPLICATION_JSON)
public Response deleteRelationshipIndex( @PathParam("indexName") String indexName )
{
try
{
actions.removeRelationshipIndex( indexName );
return output.noContent();
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
}
@POST
@Path(PATH_NAMED_NODE_INDEX)
@Consumes(MediaType.APPLICATION_JSON)
public Response addToNodeIndex( @PathParam("indexName") String indexName, @QueryParam("unique") String unique,
@QueryParam("uniqueness") String uniqueness, String postBody )
{
int otherHeaders = 512;
int maximumSizeInBytes = config.getInt( ServerSettings.maximum_response_header_size.name() ) - otherHeaders;
try
{
Map entityBody;
Pair result;
switch ( unique( unique, uniqueness ) )
{
case GetOrCreate:
entityBody = input.readMap( postBody, "key", "value" );
String getOrCreateValue = String.valueOf( entityBody.get( "value" ) );
if ( getOrCreateValue.length() > maximumSizeInBytes )
{
return valueTooBig();
}
result = actions.getOrCreateIndexedNode( indexName,
String.valueOf( entityBody.get( "key" ) ),
getOrCreateValue, extractNodeIdOrNull( getStringOrNull(
entityBody, "uri" ) ), getMapOrNull( entityBody, "properties" ) );
return result.other() ? output.created( result.first() ) : output.okIncludeLocation( result.first
() );
case CreateOrFail:
entityBody = input.readMap( postBody, "key", "value" );
String createOrFailValue = String.valueOf( entityBody.get( "value" ) );
if ( createOrFailValue.length() > maximumSizeInBytes )
{
return valueTooBig();
}
result = actions.getOrCreateIndexedNode( indexName,
String.valueOf( entityBody.get( "key" ) ),
createOrFailValue, extractNodeIdOrNull( getStringOrNull(
entityBody, "uri" ) ), getMapOrNull( entityBody, "properties" ) );
if ( result.other() )
{
return output.created( result.first() );
}
String uri = getStringOrNull( entityBody, "uri" );
if ( uri == null )
{
return output.conflict( result.first() );
}
long idOfNodeToBeIndexed = extractNodeId( uri );
long idOfNodeAlreadyInIndex = extractNodeId( result.first().getIdentity() );
if ( idOfNodeToBeIndexed == idOfNodeAlreadyInIndex )
{
return output.created( result.first() );
}
return output.conflict( result.first() );
default:
entityBody = input.readMap( postBody, "key", "value", "uri" );
String value = String.valueOf( entityBody.get( "value" ) );
if ( value.length() > maximumSizeInBytes )
{
return valueTooBig();
}
return output.created( actions.addToNodeIndex( indexName,
String.valueOf( entityBody.get( "key" ) ),
value, extractNodeId( entityBody.get( "uri" )
.toString() ) ) );
}
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( IllegalArgumentException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
private Response valueTooBig()
{
return Response.status( 413 ).entity( String.format(
"The property value provided was too large. The maximum size is currently set to %d bytes. " +
"You can configure this by setting the '%s' property.",
config.getInt(ServerSettings.maximum_response_header_size.name()),
ServerSettings.maximum_response_header_size.name() ) ).build();
}
@POST
@Path(PATH_NAMED_RELATIONSHIP_INDEX)
public Response addToRelationshipIndex( @PathParam("indexName") String indexName,
@QueryParam("unique") String unique, @QueryParam("uniqueness") String
uniqueness, String postBody )
{
try
{
Map entityBody;
Pair result;
switch ( unique( unique, uniqueness ) )
{
case GetOrCreate:
entityBody = input.readMap( postBody, "key", "value" );
result = actions.getOrCreateIndexedRelationship( indexName,
String.valueOf( entityBody.get( "key" ) ),
String.valueOf( entityBody.get( "value" ) ), extractRelationshipIdOrNull( getStringOrNull
( entityBody, "uri" ) ),
extractNodeIdOrNull( getStringOrNull( entityBody, "start" ) ),
getStringOrNull( entityBody, "type" ), extractNodeIdOrNull( getStringOrNull( entityBody,
"end" ) ),
getMapOrNull( entityBody, "properties" ) );
return result.other() ? output.created( result.first() ) : output.ok( result.first() );
case CreateOrFail:
entityBody = input.readMap( postBody, "key", "value" );
result = actions.getOrCreateIndexedRelationship( indexName,
String.valueOf( entityBody.get( "key" ) ),
String.valueOf( entityBody.get( "value" ) ), extractRelationshipIdOrNull( getStringOrNull
( entityBody, "uri" ) ),
extractNodeIdOrNull( getStringOrNull( entityBody, "start" ) ),
getStringOrNull( entityBody, "type" ), extractNodeIdOrNull( getStringOrNull( entityBody,
"end" ) ),
getMapOrNull( entityBody, "properties" ) );
if ( result.other() )
{
return output.created( result.first() );
}
String uri = getStringOrNull( entityBody, "uri" );
if ( uri == null )
{
return output.conflict( result.first() );
}
long idOfRelationshipToBeIndexed = extractRelationshipId( uri );
long idOfRelationshipAlreadyInIndex = extractRelationshipId( result.first().getIdentity() );
if ( idOfRelationshipToBeIndexed == idOfRelationshipAlreadyInIndex )
{
return output.created( result.first() );
}
return output.conflict( result.first() );
default:
entityBody = input.readMap( postBody, "key", "value", "uri" );
return output.created( actions.addToRelationshipIndex( indexName,
String.valueOf( entityBody.get( "key" ) ),
String.valueOf( entityBody.get( "value" ) ), extractRelationshipId( entityBody.get( "uri"
).toString() ) ) );
}
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( IllegalArgumentException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
private UniqueIndexType unique( String uniqueParam, String uniquenessParam )
{
UniqueIndexType unique = UniqueIndexType.None;
if ( uniquenessParam == null || uniquenessParam.equals( "" ) )
{
// Backward compatibility check
if ( "".equals( uniqueParam ) || Boolean.parseBoolean( uniqueParam ) )
{
unique = UniqueIndexType.GetOrCreate;
}
}
else if ( UNIQUENESS_MODE_GET_OR_CREATE.equalsIgnoreCase( uniquenessParam ) )
{
unique = UniqueIndexType.GetOrCreate;
}
else if ( UNIQUENESS_MODE_CREATE_OR_FAIL.equalsIgnoreCase( uniquenessParam ) )
{
unique = UniqueIndexType.CreateOrFail;
}
return unique;
}
private String getStringOrNull( Map map, String key ) throws BadInputException
{
Object object = map.get( key );
if ( object instanceof String )
{
return (String) object;
}
if ( object == null )
{
return null;
}
throw new InvalidArgumentsException( "\"" + key + "\" should be a string" );
}
@SuppressWarnings("unchecked")
private static Map getMapOrNull( Map data, String key ) throws BadInputException
{
Object object = data.get( key );
if ( object instanceof Map, ?> )
{
return (Map) object;
}
if ( object == null )
{
return null;
}
throw new InvalidArgumentsException( "\"" + key + "\" should be a map" );
}
@GET
@Path(PATH_NODE_INDEX_ID)
public Response getNodeFromIndexUri( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("value") String value,
@PathParam("id") long id )
{
try
{
return output.ok( actions.getIndexedNode( indexName, key, value, id ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_RELATIONSHIP_INDEX_ID)
public Response getRelationshipFromIndexUri( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("value") String value,
@PathParam("id") long id )
{
return output.ok( actions.getIndexedRelationship( indexName, key, value, id ) );
}
@GET
@Path(PATH_NODE_INDEX_GET)
public Response getIndexedNodes( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("value") String value )
{
try
{
return output.ok( actions.getIndexedNodes( indexName, key, value ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_AUTO_INDEX_GET)
public Response getAutoIndexedNodes( @PathParam("type") String type, @PathParam("key") String key,
@PathParam("value") String value )
{
try
{
if ( type.equals( NODE_AUTO_INDEX_TYPE ) )
{
return output.ok( actions.getAutoIndexedNodes( key, value ) );
}
else if ( type.equals( RELATIONSHIP_AUTO_INDEX_TYPE ) )
{
return output.ok( actions.getAutoIndexedRelationships( key, value ) );
}
else
{
return output.badRequest( new RuntimeException( "Unrecognized auto-index type, " +
"expected '" + NODE_AUTO_INDEX_TYPE + "' or '" + RELATIONSHIP_AUTO_INDEX_TYPE + "'" ) );
}
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_NODE_INDEX_QUERY_WITH_KEY)
public Response getIndexedNodesByQuery(
@PathParam("indexName") String indexName,
@PathParam("key") String key,
@QueryParam("query") String query,
@PathParam("order") String order )
{
try
{
return output.ok( actions.getIndexedNodesByQuery( indexName, key,
query, order ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_RELATIONSHIP_INDEX_GET)
public Response getIndexedRelationships( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("value") String value )
{
try
{
return output.ok( actions.getIndexedRelationships( indexName, key, value ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_AUTO_INDEX_STATUS)
public Response isAutoIndexerEnabled( @PathParam("type") String type )
{
return output.ok( actions.isAutoIndexerEnabled( type ) );
}
@PUT
@Path(PATH_AUTO_INDEX_STATUS)
public Response setAutoIndexerEnabled( @PathParam("type") String type, String enable )
{
actions.setAutoIndexerEnabled( type, Boolean.parseBoolean( enable ) );
return output.ok( Representation.emptyRepresentation() );
}
@GET
@Path(PATH_AUTO_INDEXED_PROPERTIES)
public Response getAutoIndexedProperties( @PathParam("type") String type )
{
return output.ok( actions.getAutoIndexedProperties( type ) );
}
@POST
@Path(PATH_AUTO_INDEXED_PROPERTIES)
public Response startAutoIndexingProperty( @PathParam("type") String type, String property )
{
actions.startAutoIndexingProperty( type, property );
return output.ok( Representation.emptyRepresentation() );
}
@DELETE
@Path(PATH_AUTO_INDEX_PROPERTY_DELETE)
public Response stopAutoIndexingProperty( @PathParam("type") String type, @PathParam("property") String property )
{
actions.stopAutoIndexingProperty( type, property );
return output.ok( Representation.emptyRepresentation() );
}
@GET
@Path(PATH_NAMED_RELATIONSHIP_INDEX)
public Response getIndexedRelationshipsByQuery( @PathParam("indexName") String indexName,
@QueryParam("query") String query,
@QueryParam("order") String order )
{
try
{
return output.ok( actions.getIndexedRelationshipsByQuery(
indexName, query, order ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@GET
@Path(PATH_RELATIONSHIP_INDEX_QUERY_WITH_KEY)
public Response getIndexedRelationshipsByQuery( @PathParam("indexName") String indexName,
@PathParam("key") String key,
@QueryParam("query") String query,
@QueryParam("order") String order )
{
try
{
return output.ok( actions.getIndexedRelationshipsByQuery(
indexName, key, query, order ) );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_NODE_INDEX_ID)
public Response deleteFromNodeIndex( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("value") String value,
@PathParam("id") long id )
{
try
{
actions.removeFromNodeIndex( indexName, key, value, id );
return nothing();
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_NODE_INDEX_REMOVE_KEY)
public Response deleteFromNodeIndexNoValue( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("id") long id )
{
try
{
actions.removeFromNodeIndexNoValue( indexName, key, id );
return nothing();
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_NODE_INDEX_REMOVE)
public Response deleteFromNodeIndexNoKeyValue( @PathParam("indexName") String indexName, @PathParam("id") long id )
{
try
{
actions.removeFromNodeIndexNoKeyValue( indexName, id );
return nothing();
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_RELATIONSHIP_INDEX_ID)
public Response deleteFromRelationshipIndex( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("value") String value,
@PathParam("id") long id )
{
try
{
actions.removeFromRelationshipIndex( indexName, key, value, id );
return nothing();
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_RELATIONSHIP_INDEX_REMOVE_KEY)
public Response deleteFromRelationshipIndexNoValue( @PathParam("indexName") String indexName,
@PathParam("key") String key, @PathParam("id") long id )
{
try
{
actions.removeFromRelationshipIndexNoValue( indexName, key, id );
return nothing();
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
@DELETE
@Path(PATH_RELATIONSHIP_INDEX_REMOVE)
public Response deleteFromRelationshipIndex( @PathParam("indexName") String indexName,
@PathParam("id") long id )
{
try
{
actions.removeFromRelationshipIndexNoKeyValue( indexName, id );
return nothing();
}
catch ( UnsupportedOperationException e )
{
return output.methodNotAllowed( e );
}
catch ( NotFoundException nfe )
{
return output.notFound( nfe );
}
catch ( Exception e )
{
return output.serverError( e );
}
}
// Traversal
@POST
@Path(PATH_NODE_TRAVERSE)
public Response traverse( @PathParam("nodeId") long startNode,
@PathParam("returnType") TraverserReturnType returnType, String body )
{
try
{
return output.ok( actions.traverse( startNode, input.readMap( body ), returnType ) );
}
catch ( EvaluationException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( NotFoundException e )
{
return output.notFound( e );
}
}
// Paged traversal
@DELETE
@Path(PATH_TO_PAGED_TRAVERSERS)
public Response removePagedTraverser( @PathParam("traverserId") String traverserId )
{
if ( actions.removePagedTraverse( traverserId ) )
{
return output.ok();
}
else
{
return output.notFound();
}
}
@GET
@Path(PATH_TO_PAGED_TRAVERSERS)
public Response pagedTraverse( @PathParam("traverserId") String traverserId,
@PathParam("returnType") TraverserReturnType returnType )
{
try
{
return output.ok( actions.pagedTraverse( traverserId, returnType ) );
}
catch ( EvaluationException e )
{
return output.badRequest( e );
}
catch ( NotFoundException e )
{
return output.notFound( e );
}
}
@POST
@Path(PATH_TO_CREATE_PAGED_TRAVERSERS)
public Response createPagedTraverser( @PathParam("nodeId") long startNode,
@PathParam("returnType") TraverserReturnType returnType,
@QueryParam("pageSize") @DefaultValue(FIFTY_ENTRIES) int pageSize,
@QueryParam("leaseTime") @DefaultValue(SIXTY_SECONDS) int
leaseTimeInSeconds, String body )
{
try
{
validatePageSize( pageSize );
validateLeaseTime( leaseTimeInSeconds );
String traverserId = actions.createPagedTraverser( startNode, input.readMap( body ), pageSize,
leaseTimeInSeconds );
URI uri = new URI( "node/" + startNode + "/paged/traverse/" + returnType + "/" + traverserId );
return output.created( new ListEntityRepresentation( actions.pagedTraverse( traverserId, returnType ),
uri.normalize() ) );
}
catch ( EvaluationException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( NotFoundException e )
{
return output.notFound( e );
}
catch ( URISyntaxException e )
{
return output.serverError( e );
}
}
private void validateLeaseTime( int leaseTimeInSeconds ) throws BadInputException
{
if ( leaseTimeInSeconds < 1 )
{
throw new InvalidArgumentsException( "Lease time less than 1 second is not supported" );
}
}
private void validatePageSize( int pageSize ) throws BadInputException
{
if ( pageSize < 1 )
{
throw new InvalidArgumentsException( "Page size less than 1 is not permitted" );
}
}
@POST
@Path(PATH_NODE_PATH)
public Response singlePath( @PathParam("nodeId") long startNode, String body )
{
final Map description;
final long endNode;
try
{
description = input.readMap( body );
endNode = extractNodeId( (String) description.get( "to" ) );
return output.ok( actions.findSinglePath( startNode, endNode, description ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ClassCastException e )
{
return output.badRequest( e );
}
catch ( NotFoundException e )
{
return output.notFound( e );
}
}
@POST
@Path(PATH_NODE_PATHS)
public Response allPaths( @PathParam("nodeId") long startNode, String body )
{
final Map description;
final long endNode;
try
{
description = input.readMap( body );
endNode = extractNodeId( (String) description.get( "to" ) );
return output.ok( actions.findPaths( startNode, endNode, description ) );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( ClassCastException e )
{
return output.badRequest( e );
}
}
@POST
@Path( PATH_SCHEMA_INDEX_LABEL )
public Response createSchemaIndex( @PathParam( "label" ) String labelName, String body )
{
try
{
Map data = input.readMap( body, "property_keys" );
Iterable singlePropertyKey = singleOrList( data, "property_keys" );
if ( singlePropertyKey == null )
{
return output.badRequest( new IllegalArgumentException(
"Supply single property key or list of property keys" ) );
}
return output.ok( actions.createSchemaIndex( labelName, singlePropertyKey ) );
}
catch( UnsupportedOperationException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
}
private Iterable singleOrList( Map data, String key )
{
Object propertyKeys = data.get( key );
Iterable singlePropertyKey = null;
if ( propertyKeys instanceof List )
{
singlePropertyKey = (List) propertyKeys;
}
else if ( propertyKeys instanceof String )
{
singlePropertyKey = Arrays.asList((String)propertyKeys);
}
return singlePropertyKey;
}
@DELETE
@Path( PATH_SCHEMA_INDEX_LABEL_PROPERTY )
public Response dropSchemaIndex( @PathParam( "label" ) String labelName,
@PathParam( "property" ) AmpersandSeparatedCollection properties )
{
// TODO assumption, only a single property key
if ( properties.size() != 1 )
{
return output.badRequest( new IllegalArgumentException( "Single property key assumed" ) );
}
String property = Iterables.single( properties );
try
{
if ( actions.dropSchemaIndex( labelName, property ) )
{
return nothing();
}
else
{
return output.notFound();
}
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
}
@GET
@Path( PATH_SCHEMA_INDEX )
public Response getSchemaIndexes()
{
return output.ok( actions.getSchemaIndexes() );
}
@GET
@Path( PATH_SCHEMA_INDEX_LABEL )
public Response getSchemaIndexesForLabel( @PathParam("label") String labelName )
{
return output.ok( actions.getSchemaIndexes( labelName ) );
}
@POST
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS )
public Response createPropertyUniquenessConstraint( @PathParam( "label" ) String labelName, String body )
{
try
{
Map data = input.readMap( body, "property_keys" );
Iterable singlePropertyKey = singleOrList( data, "property_keys" );
if ( singlePropertyKey == null )
{
return output.badRequest( new IllegalArgumentException(
"Supply single property key or list of property keys" ) );
}
return output.ok( actions.createPropertyUniquenessConstraint( labelName, singlePropertyKey ) );
}
catch( UnsupportedOperationException e )
{
return output.badRequest( e );
}
catch ( BadInputException e )
{
return output.badRequest( e );
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
}
@DELETE
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS_PROPERTY )
public Response dropPropertyUniquenessConstraint( @PathParam( "label" ) String labelName,
@PathParam( "property" ) AmpersandSeparatedCollection properties )
{
try
{
if ( actions.dropPropertyUniquenessConstraint( labelName, properties ) )
{
return nothing();
}
else
{
return output.notFound();
}
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
}
@DELETE
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_EXISTENCE_PROPERTY )
public Response dropNodePropertyExistenceConstraint( @PathParam( "label" ) String labelName,
@PathParam( "property" ) AmpersandSeparatedCollection properties )
{
try
{
if ( actions.dropNodePropertyExistenceConstraint( labelName, properties ) )
{
return nothing();
}
else
{
return output.notFound();
}
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
}
@DELETE
@Path( PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_EXISTENCE_PROPERTY )
public Response dropRelationshipPropertyExistenceConstraint( @PathParam( "type" ) String typeName,
@PathParam( "property" ) AmpersandSeparatedCollection properties )
{
try
{
if ( actions.dropRelationshipPropertyExistenceConstraint( typeName, properties ) )
{
return nothing();
}
else
{
return output.notFound();
}
}
catch ( org.neo4j.graphdb.ConstraintViolationException e )
{
return output.conflict( e );
}
}
@GET
@Path(PATH_SCHEMA_CONSTRAINT)
public Response getSchemaConstraints()
{
return output.ok( actions.getConstraints() );
}
@GET
@Path( PATH_SCHEMA_CONSTRAINT_LABEL )
public Response getSchemaConstraintsForLabel( @PathParam( "label" ) String labelName )
{
return output.ok( actions.getLabelConstraints( labelName ) );
}
@GET
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS )
public Response getSchemaConstraintsForLabelAndUniqueness( @PathParam( "label" ) String labelName )
{
return output.ok( actions.getLabelUniquenessConstraints( labelName ) );
}
@GET
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_EXISTENCE )
public Response getSchemaConstraintsForLabelAndExistence( @PathParam( "label" ) String labelName )
{
return output.ok( actions.getLabelExistenceConstraints( labelName ) );
}
@GET
@Path( PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_TYPE_EXISTENCE )
public Response getSchemaConstraintsForRelationshipTypeAndExistence( @PathParam( "type" ) String typeName )
{
return output.ok( actions.getRelationshipTypeExistenceConstraints( typeName ) );
}
@GET
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_UNIQUENESS_PROPERTY )
public Response getSchemaConstraintsForLabelAndPropertyUniqueness( @PathParam( "label" ) String labelName,
@PathParam( "property" ) AmpersandSeparatedCollection propertyKeys )
{
try
{
ListRepresentation constraints = actions.getPropertyUniquenessConstraint( labelName, propertyKeys );
return output.ok( constraints );
}
catch ( IllegalArgumentException e )
{
return output.notFound( e );
}
}
@GET
@Path( PATH_SCHEMA_CONSTRAINT_LABEL_EXISTENCE_PROPERTY )
public Response getSchemaConstraintsForLabelAndPropertyExistence( @PathParam( "label" ) String labelName,
@PathParam( "property" ) AmpersandSeparatedCollection propertyKeys )
{
try
{
ListRepresentation constraints = actions.getNodePropertyExistenceConstraint( labelName, propertyKeys );
return output.ok( constraints );
}
catch ( IllegalArgumentException e )
{
return output.notFound( e );
}
}
@GET
@Path( PATH_SCHEMA_RELATIONSHIP_CONSTRAINT_EXISTENCE_PROPERTY )
public Response getSchemaConstraintsForRelationshipTypeAndPropertyExistence( @PathParam( "type" ) String typeName,
@PathParam( "property" ) AmpersandSeparatedCollection propertyKeys )
{
try
{
ListRepresentation constraints = actions.getRelationshipPropertyExistenceConstraint( typeName, propertyKeys );
return output.ok( constraints );
}
catch ( IllegalArgumentException e )
{
return output.notFound( e );
}
}
private final Function>,Pair> queryParamsToProperties =
new Function>, Pair>()
{
@Override
public Pair apply( Map.Entry> queryEntry )
{
try
{
Object propertyValue = input.readValue( queryEntry.getValue().get( 0 ) );
if ( propertyValue instanceof Collection> )
{
propertyValue = PropertySettingStrategy.convertToNativeArray( (Collection>) propertyValue );
}
return Pair.of( queryEntry.getKey(), propertyValue );
}
catch ( BadInputException e )
{
throw new IllegalArgumentException(
String.format( "Unable to deserialize property value for %s.", queryEntry.getKey() ),
e );
}
}
};
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy