/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.ogm.datastore.neo4j.query.parsing.cypherdsl.impl;
import java.util.List;
import java.util.regex.Pattern;
import org.hibernate.ogm.util.impl.Contracts;
/**
* Contains a set of function that can be used to create a cypher query.
*
* @author Davide D'Alto
*/
public class CypherDSL {
/*
* From Neo4j manual v2.1.2:
*
* Identifier names are case sensitive, and can contain underscores and alphanumeric
* characters (a-z, 0-9), but must always start with a letter. If other characters are needed, you can quote the
* identifier using backquote (`) signs. The same rules apply to property names.
*/
private static final Pattern SIMPLE_NAME = Pattern.compile( "\\p{Alpha}[\\p{Alpha}\\d]*" );
public static void identifier(StringBuilder builder, String identifier) {
escapeIdentifier( builder, identifier );
}
public static String identifier(String identifier, String propertyName) {
StringBuilder builder = new StringBuilder();
identifier( builder, identifier, propertyName );
return builder.toString();
}
public static StringBuilder identifier(StringBuilder builder, String identifier, String propertyName) {
identifier( builder, identifier );
if ( propertyName != null ) {
builder.append( "." );
escapeIdentifier( builder, propertyName );
}
return builder;
}
public static void as(StringBuilder builder, String alias) {
if ( alias != null ) {
builder.append( " as " );
escapeIdentifier( builder, alias );
}
}
public static StringBuilder compare(StringBuilder builder, String operator, Object value) {
Contracts.assertNotNull( value, "Value" );
builder.append( operator );
literal( builder, value );
return builder;
}
public static StringBuilder node(StringBuilder builder, String alias, String... labels) {
builder.append( "(" );
escapeIdentifier( builder, alias );
if ( labels != null ) {
for ( String label : labels ) {
builder.append( ":" );
escapeIdentifier( builder, label );
}
}
builder.append( ")" );
return builder;
}
public static StringBuilder relationship(StringBuilder builder, String relationshipType) {
builder.append( " -[:" );
escapeIdentifier( builder, relationshipType );
builder.append( "]-> " );
return builder;
}
public static void collection(StringBuilder builder, List<Object> values) {
builder.append( "[" );
int counter = 1;
for ( Object value : values ) {
literal( builder, value );
if ( counter++ < values.size() ) {
builder.append( ", " );
}
}
builder.append( "]" );
}
public static void limit(StringBuilder builder, Integer maxRows) {
builder.append( " LIMIT " ).append( maxRows );
}
public static void skip(StringBuilder builder, Integer firstRow) {
builder.append( " SKIP " ).append( firstRow );
}
public static void literal(StringBuilder builder, Object value) {
if ( value instanceof String ) {
builder.append( '"' );
escapeLiteral( builder, value );
builder.append( '"' );
}
else {
builder.append( value );
}
}
public static void escapeIdentifier(StringBuilder builder, String name) {
if ( SIMPLE_NAME.matcher( name ).matches() ) {
builder.append( name );
}
else {
builder.append( '`' ).append( name ).append( '`' );
}
}
private static void escapeLiteral(StringBuilder builder, Object value) {
builder.append( value.toString().replace( "\\", "\\\\" ).replace( "\"", "\\\"" ) );
}
}