/**
* Copyright (c) 2002-2013 "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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.cypherdsl;
import static java.util.Arrays.asList;
import static org.neo4j.cypherdsl.CypherQuery.identifier;
import static org.neo4j.cypherdsl.CypherQuery.identifiers;
import static org.neo4j.cypherdsl.query.Direction.BOTH;
import static org.neo4j.cypherdsl.query.Direction.IN;
import static org.neo4j.cypherdsl.query.Direction.OUT;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.neo4j.cypherdsl.expression.Expression;
import org.neo4j.cypherdsl.expression.PathExpression;
import org.neo4j.cypherdsl.query.AbstractExpression;
import org.neo4j.cypherdsl.query.LabelValue;
import org.neo4j.cypherdsl.query.LabelValues;
import org.neo4j.cypherdsl.query.PropertyValue;
import org.neo4j.cypherdsl.query.PropertyValues;
/**
* Represents either a single node or a path from one node to another.
*/
public class Path
extends AbstractExpression
implements PathExpression
{
private final Expression node;
private final Expression nodePropertyValues;
private final Expression nodeLabels;
private final PathRelationship relationship;
Path( Expression node, PathRelationship relationship, Expression nodePropertyValues, Expression labels )
{
this.node = node;
this.relationship = relationship;
this.nodePropertyValues = nodePropertyValues;
this.nodeLabels = labels;
}
public Path labels( LabelValue... labels )
{
return new Path( node, relationship, nodePropertyValues, new LabelValues( asList( labels ) ) );
}
public Path labels( Iterable<LabelValue> labels )
{
return new Path( node, relationship, nodePropertyValues, new LabelValues( labels ) );
}
public Path label( String label )
{
return new Path( node, relationship, nodePropertyValues, new LabelValue( identifier(label) ) );
}
public Path label( Identifier label )
{
return new Path( node, relationship, nodePropertyValues, new LabelValue( label ) );
}
/**
* If this node is used in a CREATE or CREATE UNIQUE clause,
* then you can use this method to specify property values.
* Use e.g. {@link CypherQuery.value( String,Object )} to create
* the individual values to be passed in here.
* <p/>
* Corresponds to:
* <pre>
* (n {prop1:value1,prop2:value2})
* </pre>
*
* @param propertyValues
* @return
*/
public Path values( PropertyValue... propertyValues )
{
return new Path( node, relationship, new PropertyValues( asList( propertyValues ) ), nodeLabels );
}
/**
* If this node is used in a CREATE or CREATE UNIQUE clause,
* then you can use this method to specify property values.
* Use e.g. {@link CypherQuery.value( String,Object )} to create
* the individual values to be passed in here.
* <p/>
* Corresponds to:
* <pre>
* (n {prop1:value1,prop2:value2})
* </pre>
*
* @param propertyValues
* @return
*/
public Path values( Iterable<PropertyValue> propertyValues )
{
return new Path( node, relationship, new PropertyValues( propertyValues ), nodeLabels );
}
/**
* If this node is used in a CREATE or CREATE UNIQUE clause,
* then you can use this method to specify property values which
* should be taken from a map parameter.
* <p/>
* Corresponds to:
* <pre>
* (n {propertyValues})
* </pre>
*
* @param propertyValues
* @return
*/
public Path values( Parameter propertyValues )
{
return new Path( node, relationship, propertyValues, nodeLabels );
}
/**
* Declare a new outgoing relationship from this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-->(m)
* </pre>
*
* @return
*/
public PathRelationship out()
{
return new PathRelationship( this, OUT, null, Collections.<Identifier>emptyList(), null, null, null );
}
/**
* Declare a new outgoing relationship from this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-[:relationship1|relationship2]->(m)
* </pre>
*
* @return
*/
public PathRelationship out( String... relationships )
{
return new PathRelationship( this, OUT, null, asList( identifiers( relationships ) ), null, null, null );
}
/**
* Declare a new outgoing relationship from this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-[:relationship1|relationship2]->(m)
* </pre>
*
* @return
*/
public PathRelationship out( Identifier... relationships )
{
return new PathRelationship( this, OUT, null, asList( relationships ), null, null, null );
}
/**
* Declare a new outgoing relationship from this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-[:relationship1|relationship2]->(m)
* </pre>
*
* @return
*/
public PathRelationship out( Enum<?>... relationships )
{
List<Identifier> relationshipNames = new ArrayList<Identifier>();
for ( Enum<?> relationship : relationships )
{
relationshipNames.add( identifier( relationship.name() ) );
}
return new PathRelationship( this, OUT, null, relationshipNames, null, null, null );
}
/**
* Declare a new outgoing relationship from this node.
* <p/>
* Corresponds to:
* <pre>
* (n)<--(m)
* </pre>
*
* @return
*/
public PathRelationship in()
{
return new PathRelationship( this, IN, null, Collections.<Identifier>emptyList(), null, null, null );
}
/**
* Declare a new incoming relationship to this node.
* <p/>
* Corresponds to:
* <pre>
* (n)<-[:relationship1|relationship2]-(m)
* </pre>
*
* @return
*/
public PathRelationship in( String... relationships )
{
return new PathRelationship( this, IN, null, asList( identifiers( relationships ) ), null, null, null );
}
/**
* Declare a new incoming relationship to this node.
* <p/>
* Corresponds to:
* <pre>
* (n)<-[:relationship1|relationship2]-(m)
* </pre>
*
* @return
*/
public PathRelationship in( Identifier... relationships )
{
return new PathRelationship( this, IN, null, asList( relationships ), null, null, null );
}
/**
* Declare a new incoming relationship to this node.
* <p/>
* Corresponds to:
* <pre>
* (n)<-[:relationship1|relationship2]-(m)
* </pre>
*
* @return
*/
public PathRelationship in( Enum<?>... relationships )
{
List<Identifier> relationshipNames = new ArrayList<Identifier>();
for ( Enum<?> relationship : relationships )
{
relationshipNames.add( identifier( relationship.name() ) );
}
return new PathRelationship( this, IN, null, relationshipNames, null, null, null );
}
/**
* Declare a new relationship on this node.
* <p/>
* Corresponds to:
* <pre>
* (n)--(m)
* </pre>
*
* @return
*/
public PathRelationship both()
{
return new PathRelationship( this, BOTH, null, Collections.<Identifier>emptyList(), null, null, null );
}
/**
* Declare a new relationship on this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-[:relationship1|relationship2]-(m)
* </pre>
*
* @return
*/
public PathRelationship both( String... relationships )
{
return new PathRelationship( this, BOTH, null, asList( identifiers( relationships ) ), null, null,
null );
}
/**
* Declare a new relationship on this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-[:relationship1|relationship2]-(m)
* </pre>
*
* @return
*/
public PathRelationship both( Identifier... relationships )
{
return new PathRelationship( this, BOTH, null, asList( relationships ), null, null, null );
}
/**
* Declare a new relationship on this node.
* <p/>
* Corresponds to:
* <pre>
* (n)-[:relationship1|relationship2]-(m)
* </pre>
*
* @return
*/
public PathRelationship both( Enum<?>... relationships )
{
List<Identifier> relationshipNames = new ArrayList<Identifier>();
for ( Enum<?> relationship : relationships )
{
relationshipNames.add( identifier( relationship.name() ) );
}
return new PathRelationship( this, BOTH, null, relationshipNames, null, null, null );
}
@Override
public void asString( StringBuilder builder )
{
if ( relationship != null )
{
relationship.asString( builder );
}
builder.append( '(' );
if ( node != null )
{
node.asString( builder );
if ( nodeLabels != null )
{
nodeLabels.asString( builder );
}
if ( nodePropertyValues != null )
{
builder.append( ' ' );
nodePropertyValues.asString( builder );
}
}
else
{
if ( nodeLabels != null )
{
nodeLabels.asString( builder );
}
if ( nodePropertyValues != null )
{
nodePropertyValues.asString( builder );
}
}
builder.append( ')' );
}
}