├── .gitignore ├── .gitmodules ├── src └── main │ └── java │ └── com │ └── anqit │ └── spanqit │ ├── rdf │ ├── RdfValue.java │ ├── RdfObject.java │ ├── RdfResource.java │ ├── Iri.java │ ├── RdfPredicate.java │ ├── RdfPredicateObjectList.java │ ├── RdfPredicateObjectListCollection.java │ ├── RdfLiteral.java │ ├── RdfBlankNode.java │ ├── RdfSubject.java │ └── Rdf.java │ ├── constraint │ ├── SparqlOperator.java │ ├── Operand.java │ ├── BinaryOperation.java │ ├── ConnectiveOperation.java │ ├── UnaryOperator.java │ ├── BinaryOperator.java │ ├── ConnectiveOperator.java │ ├── UnaryOperation.java │ ├── SparqlAggregate.java │ ├── Function.java │ ├── Operation.java │ ├── SparqlFunction.java │ ├── Expression.java │ ├── Aggregate.java │ └── Expressions.java │ ├── core │ ├── QueryElement.java │ ├── Projectable.java │ ├── Groupable.java │ ├── query │ │ ├── CopyQuery.java │ │ ├── AddQuery.java │ │ ├── DropQuery.java │ │ ├── MoveQuery.java │ │ ├── ClearQuery.java │ │ ├── GraphManagementQuery.java │ │ ├── CreateQuery.java │ │ ├── UpdateDataQuery.java │ │ ├── ConstructQuery.java │ │ ├── InsertDataQuery.java │ │ ├── DeleteDataQuery.java │ │ ├── LoadQuery.java │ │ ├── TargetedGraphManagementQuery.java │ │ ├── UpdateQuery.java │ │ ├── OuterQuery.java │ │ ├── DestinationSourceManagementQuery.java │ │ ├── SelectQuery.java │ │ ├── ModifyQuery.java │ │ ├── Query.java │ │ └── Queries.java │ ├── Base.java │ ├── PrefixDeclarations.java │ ├── Assignable.java │ ├── Assignment.java │ ├── Orderable.java │ ├── GroupBy.java │ ├── OrderBy.java │ ├── TriplesTemplate.java │ ├── Having.java │ ├── Dataset.java │ ├── From.java │ ├── QueryElementCollection.java │ ├── GraphTemplate.java │ ├── OrderCondition.java │ ├── Variable.java │ ├── QueryPattern.java │ ├── Prefix.java │ ├── StandardQueryElementCollection.java │ ├── SpanqitUtils.java │ ├── Projection.java │ └── Spanqit.java │ └── graphpattern │ ├── MinusGraphPattern.java │ ├── GraphName.java │ ├── GraphPattern.java │ ├── BNodeTriplePattern.java │ ├── FilterExistsGraphPattern.java │ ├── AlternativeGraphPattern.java │ ├── Filter.java │ ├── TriplesSameSubject.java │ ├── TriplePattern.java │ ├── GroupGraphPattern.java │ ├── SubSelect.java │ ├── GraphPatterns.java │ └── GraphPatternNotTriple.java ├── pom.xml ├── README.md └── LICENSE.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | bin/ 3 | 4 | .classpath 5 | .project 6 | .settings/ 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "wiki"] 2 | path = wiki 3 | url = https://github.com/anqit/spanqit.wiki.git 4 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfValue.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import com.anqit.spanqit.constraint.Operand; 4 | 5 | /** 6 | * Denotes an RDF Value. 7 | */ 8 | public interface RdfValue extends RdfObject, Operand { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/SparqlOperator.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | /** 6 | * Interface to denote an Expression operator 7 | */ 8 | interface SparqlOperator extends QueryElement { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/QueryElement.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * Denotes a SPARQL Query Element 5 | */ 6 | public interface QueryElement { 7 | /** 8 | * @return the String representing the SPARQL syntax of this element 9 | */ 10 | public String getQueryString(); 11 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfObject.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | /** 6 | * Denotes an element that can represent an object in a 7 | * {@link com.anqit.spanqit.graphpattern.TriplePattern} 8 | */ 9 | public interface RdfObject extends QueryElement { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/Operand.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | /** 6 | * Denotes an element that can be used as an operand to an 7 | * {@link com.anqit.spanqit.constraint.Expression} 8 | */ 9 | public interface Operand extends QueryElement { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/MinusGraphPattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | class MinusGraphPattern extends GroupGraphPattern { 4 | private static final String MINUS = "MINUS"; 5 | 6 | @Override 7 | public String getQueryString() { 8 | return MINUS + " " + super.getQueryString(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/BinaryOperation.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * Represents a SPARQL operation that takes exactly 2 arguments 5 | * 6 | */ 7 | class BinaryOperation extends Operation { 8 | BinaryOperation(BinaryOperator operator) { 9 | super(operator, 2); 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfResource.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | /** 4 | * Denotes an RDF Resource 5 | * 6 | * @see 8 | * RDF Resources 9 | */ 10 | public interface RdfResource extends RdfValue, RdfSubject { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Projectable.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * Denotes a projectable query element (can be SELECT'ed) 5 | * 6 | * @see 8 | * SPARQL Projections 9 | */ 10 | public interface Projectable extends QueryElement { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/ConnectiveOperation.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * Represents a SPARQL connective operation, which takes an arbitrary number of 5 | * arguments 6 | */ 7 | class ConnectiveOperation extends Operation { 8 | ConnectiveOperation(ConnectiveOperator operator) { 9 | super(operator); 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/Iri.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import com.anqit.spanqit.graphpattern.GraphName; 4 | 5 | /** 6 | * Denotes an RDF IRI 7 | * 8 | * @see 10 | * RDF IRIs 11 | */ 12 | public interface Iri extends RdfResource, RdfPredicate, GraphName { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Groupable.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * Denotes a groupable SPARQL query element (can be used in a 5 | * GROUP BY clause) 6 | * 7 | * @see 9 | * SPARQL Group By Clause 10 | */ 11 | public interface Groupable extends QueryElement { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/GraphName.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | /** 6 | * Denotes a query element that can be used as a Graph Name 7 | * 8 | * @see Specifying Datasets 11 | */ 12 | public interface GraphName extends QueryElement { } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/UnaryOperator.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * The SPARQL unary operators 5 | */ 6 | enum UnaryOperator implements SparqlOperator { 7 | NOT("!"), 8 | UNARY_PLUS("+"), 9 | UNARY_MINUS("-"); 10 | 11 | private String operator; 12 | 13 | private UnaryOperator(String operator) { 14 | this.operator = operator; 15 | } 16 | 17 | @Override 18 | public String getQueryString() { 19 | return operator; 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/CopyQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | /** 4 | * A SPARQL COPY Query 5 | * 6 | * @see 7 | * SPARQL COPY query 8 | */ 9 | public class CopyQuery extends DestinationSourceManagementQuery { 10 | private static String COPY = "COPY"; 11 | 12 | CopyQuery() { } 13 | 14 | protected String getQueryActionString() { 15 | return COPY; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/AddQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | /** 4 | * A SPARQL ADD Query 5 | * 6 | * @see 7 | * SPARQL ADD Query 8 | */ 9 | public class AddQuery extends DestinationSourceManagementQuery { 10 | private static final String ADD = "ADD"; 11 | 12 | AddQuery() { } 13 | 14 | @Override 15 | protected String getQueryActionString() { 16 | return ADD; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/DropQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | /** 4 | * A SPARQL DROP Query 5 | * 6 | * @see 7 | * SPARQL DROP Query 8 | */ 9 | public class DropQuery extends TargetedGraphManagementQuery { 10 | private static final String DROP = "DROP"; 11 | 12 | DropQuery() { } 13 | 14 | @Override 15 | protected String getQueryActionString() { 16 | return DROP; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/MoveQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | /** 4 | * A SPARQL MOVE Query 5 | * 6 | * @see 7 | * SPARQL MOVE Query 8 | */ 9 | public class MoveQuery extends DestinationSourceManagementQuery { 10 | private static final String MOVE = "MOVE"; 11 | 12 | MoveQuery() { } 13 | 14 | @Override 15 | protected String getQueryActionString() { 16 | return MOVE; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/ClearQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | /** 4 | * A SPARQL CLEAR Query 5 | * 6 | * @see 7 | * SPARQL CLEAR Query 8 | * 9 | */ 10 | public class ClearQuery extends TargetedGraphManagementQuery { 11 | private static final String CLEAR = "CLEAR"; 12 | 13 | ClearQuery() { } 14 | 15 | @Override 16 | protected String getQueryActionString() { 17 | return CLEAR; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/BinaryOperator.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * The SPARQL binary operators 5 | */ 6 | enum BinaryOperator implements SparqlOperator { 7 | EQUALS("="), 8 | GREATER_THAN(">"), 9 | GREATER_THAN_EQUALS(">="), 10 | LESS_THAN("<"), 11 | LESS_THAN_EQUALS("<="), 12 | NOT_EQUALS("!="); 13 | 14 | private String operator; 15 | 16 | private BinaryOperator(String operator) { 17 | this.operator = operator; 18 | } 19 | 20 | @Override 21 | public String getQueryString() { 22 | return operator; 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/ConnectiveOperator.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * The SPARQL connective operators 5 | */ 6 | enum ConnectiveOperator implements SparqlOperator { 7 | // Logical 8 | AND("&&"), 9 | OR("||"), 10 | 11 | // Arithmetic 12 | ADD("+"), 13 | DIVIDE("/"), 14 | MULTIPLY("*"), 15 | SUBTRACT("-"); 16 | 17 | private String operator; 18 | 19 | private ConnectiveOperator(String operator) { 20 | this.operator = operator; 21 | } 22 | 23 | @Override 24 | public String getQueryString() { 25 | return operator; 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfPredicate.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | /** 6 | * Denotes an element that can represent a predicate in a 7 | * {@link com.anqit.spanqit.graphpattern.TriplePattern} 8 | */ 9 | public interface RdfPredicate extends QueryElement { 10 | /** 11 | * The built-in predicate shortcut for rdf:type 12 | * 13 | * @see 14 | * RDF Type abbreviation 15 | */ 16 | public static RdfPredicate a = () -> "a"; 17 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Base.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.rdf.Iri; 4 | 5 | /** 6 | * A SPARQL Base declaration 7 | * 8 | * @see 10 | * SPARQL Relative IRIs 11 | */ 12 | public class Base implements QueryElement { 13 | private static final String BASE = "BASE "; 14 | 15 | private Iri iri; 16 | 17 | Base(Iri iri) { 18 | this.iri = iri; 19 | } 20 | 21 | @Override 22 | public String getQueryString() { 23 | return BASE + iri.getQueryString(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/PrefixDeclarations.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * A collection of SPARQL Prefix declarations 5 | * 6 | * @see 8 | * SPARQL Prefix 9 | */ 10 | public class PrefixDeclarations extends StandardQueryElementCollection { 11 | /** 12 | * Add prefix declarations to this collection 13 | * 14 | * @param prefixes 15 | * @return this 16 | */ 17 | public PrefixDeclarations addPrefix(Prefix... prefixes) { 18 | return addElements(prefixes); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/GraphPattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | /** 6 | * Denotes a SPARQL Graph Pattern 7 | * 8 | * @see 10 | * SPARQL Graph Patterns 11 | */ 12 | public interface GraphPattern extends QueryElement { 13 | /** 14 | * @return if this pattern is a collection of GraphPatterns (ie., Group or 15 | * Alternative patterns), returns if the collection contains any 16 | * patterns 17 | */ 18 | default public boolean isEmpty() { return true; } 19 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Assignable.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * A marker interface to denote objects which are bind-able in 5 | * a SPARQL assignment expression. 6 | * 7 | * @see 9 | * SPARQL Assignments 10 | * 11 | * 12 | */ 13 | public interface Assignable extends QueryElement { 14 | /** 15 | * Create a SPARQL assignment from this object 16 | * 17 | * @param var 18 | * the variable to bind the expression value to 19 | * @return an Assignment object 20 | */ 21 | default public Assignment as(Variable var) { 22 | return Spanqit.as(this, var); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Assignment.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * A SPARQL expression-to-variable assignment 5 | * 6 | * @see 8 | * SPARQL Assignments 9 | */ 10 | public class Assignment implements Projectable, Groupable { 11 | private static final String AS = " AS "; 12 | private Assignable expression; 13 | private Variable var; 14 | 15 | Assignment(Assignable exp, Variable var) { 16 | this.expression = exp; 17 | this.var = var; 18 | } 19 | 20 | @Override 21 | public String getQueryString() { 22 | return SpanqitUtils.getParenthesizedString(expression.getQueryString() + AS + var.getQueryString()); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/UnaryOperation.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | import com.anqit.spanqit.core.SpanqitUtils; 4 | 5 | /** 6 | * Represents a SPARQL operation that takes exactly 1 argument 7 | */ 8 | class UnaryOperation extends Operation { 9 | UnaryOperation(UnaryOperator operator) { 10 | super(operator, 1); 11 | } 12 | 13 | @Override 14 | public String getQueryString() { 15 | if(isAtOperatorLimit()) { 16 | StringBuilder expression = new StringBuilder(); 17 | 18 | expression.append(operator.getQueryString()); 19 | String op = getOperand(0).getQueryString(); 20 | expression.append(SpanqitUtils.getParenthesizedString(op)); 21 | 22 | return expression.toString(); 23 | } else { 24 | return ""; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Orderable.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * Denotes an orederable SPARQL query element (can be used in a 5 | * ORDER BY clause) 6 | * 7 | * @see 9 | * SPARQL Order By Clause 10 | */ 11 | public interface Orderable extends QueryElement { 12 | /** 13 | * @return an ascending {@link OrderCondition} instance for this {@link Orderable} object 14 | */ 15 | default public OrderCondition asc() { 16 | return Spanqit.asc(this); 17 | } 18 | 19 | /** 20 | * @return an descending {@link OrderCondition} instance for this {@link Orderable} object 21 | */ 22 | default public OrderCondition desc() { 23 | return Spanqit.desc(this); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/GroupBy.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * A SPARQL Group By clause 7 | * 8 | * @see 10 | * SPARQL Group By Clause 11 | */ 12 | public class GroupBy extends StandardQueryElementCollection { 13 | private static final String GROUP_BY = "GROUP BY"; 14 | private static final String DELIMETER = " "; 15 | 16 | GroupBy() { 17 | super(GROUP_BY, DELIMETER, new ArrayList()); 18 | printNameIfEmpty(false); 19 | } 20 | 21 | /** 22 | * Add group conditions 23 | * 24 | * @param groupables 25 | * the group conditions 26 | * @return this 27 | */ 28 | public GroupBy by(Groupable... groupables) { 29 | return addElements(groupables); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/OrderBy.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * A SPARQL Order By clause 7 | * 8 | * @see 10 | * SPARQL Order By Clause 11 | */ 12 | public class OrderBy extends StandardQueryElementCollection { 13 | private static final String ORDER_BY = "ORDER BY"; 14 | private static final String DELIMETER = " "; 15 | 16 | OrderBy() { 17 | super(ORDER_BY, DELIMETER, new ArrayList()); 18 | printNameIfEmpty(false); 19 | } 20 | 21 | /** 22 | * Add order conditions 23 | * 24 | * @param conditions 25 | * the conditions to add 26 | * @return this 27 | */ 28 | public OrderBy by(Orderable... conditions) { 29 | return addElements(conditions); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/SparqlAggregate.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * The built-in SPARQL aggregates. Keeping this public until 5 | * {@link Expressions} is completed. 6 | * 7 | * @see 9 | * SPARQL Function Definitions 10 | */ 11 | @SuppressWarnings("javadoc") // acceptable, as this won't be public for long 12 | public enum SparqlAggregate implements SparqlOperator { 13 | AVG("AVG"), 14 | COUNT("COUNT"), 15 | GROUP_CONCAT("GROUP_CONCAT"), 16 | MAX("MAX"), 17 | MIN("MIN"), 18 | SAMPLE("SAMPLE"), 19 | SUM("SUM"); 20 | 21 | private String function; 22 | 23 | private SparqlAggregate(String function) { 24 | this.function = function; 25 | } 26 | 27 | @Override 28 | public String getQueryString() { 29 | return function; 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/TriplesTemplate.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.Collections; 4 | 5 | import com.anqit.spanqit.graphpattern.TriplePattern; 6 | 7 | /** 8 | * Represents a collection of triple patterns 9 | */ 10 | public class TriplesTemplate extends QueryElementCollection { 11 | TriplesTemplate(TriplePattern... triples) { 12 | super(" .\n"); 13 | and(triples); 14 | } 15 | 16 | /** 17 | * add triples to this template 18 | * 19 | * @param triples the triples to add 20 | * 21 | * @return this TriplesTemplate instance 22 | */ 23 | public TriplesTemplate and(TriplePattern... triples) { 24 | Collections.addAll(elements, triples); 25 | 26 | return this; 27 | } 28 | 29 | @Override 30 | public String getQueryString() { 31 | return SpanqitUtils.getBracedString(super.getQueryString()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/Function.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * A SPARQL Function. Consists of a function name and a parenthesized, 5 | * comma-separated list of arguments. 6 | * 7 | * @see SPARQL 8 | * Filters 9 | *
10 | * 12 | * SPARQL Function Definitions 13 | */ 14 | class Function extends Expression { 15 | Function(SparqlFunction function) { 16 | super(function, ", "); 17 | parenthesize(); 18 | } 19 | 20 | @Override 21 | public String getQueryString() { 22 | StringBuilder function = new StringBuilder(); 23 | 24 | function.append(operator.getQueryString()).append(super.getQueryString()); 25 | 26 | return function.toString(); 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/BNodeTriplePattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.rdf.RdfBlankNode.PropertiesBlankNode; 4 | import com.anqit.spanqit.rdf.RdfPredicateObjectList; 5 | 6 | /** 7 | * A triple pattern formed by a property-list blank node 8 | * 9 | * @see 10 | * blank node syntax 11 | */ 12 | class BNodeTriplePattern implements TriplePattern { 13 | private PropertiesBlankNode bnode; 14 | 15 | BNodeTriplePattern(PropertiesBlankNode subject) { 16 | this.bnode = subject; 17 | } 18 | 19 | @Override 20 | public BNodeTriplePattern andHas(RdfPredicateObjectList... lists) { 21 | bnode.andHas(lists); 22 | 23 | return this; 24 | } 25 | 26 | @Override 27 | public String getQueryString() { 28 | return bnode.getQueryString() + SUFFIX; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Having.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.anqit.spanqit.constraint.Expression; 6 | 7 | /** 8 | * A SPARQL Having clause 9 | * 10 | * @see 11 | * SPARQL Having Clause 12 | */ 13 | public class Having extends StandardQueryElementCollection> { 14 | private static final String HAVING = "HAVING"; 15 | private static final String DELIMETER = " "; 16 | 17 | Having() { 18 | super(HAVING, DELIMETER, SpanqitUtils::getParenthesizedString, new ArrayList>()); 19 | printBodyIfEmpty(true); 20 | } 21 | 22 | /** 23 | * Add having conditions 24 | * 25 | * @param expressions 26 | * the conditions to add 27 | * @return this 28 | */ 29 | public Having having(Expression... expressions) { 30 | return addElements(expressions); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Dataset.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.Arrays; 4 | 5 | import com.anqit.spanqit.rdf.Iri; 6 | 7 | /** 8 | * A SPARQL dataset specification 9 | * 10 | * @see 12 | * RDF Datasets 13 | */ 14 | public class Dataset extends StandardQueryElementCollection { 15 | /** 16 | * Add graph references to this dataset 17 | * 18 | * @param graphs 19 | * the datasets to add 20 | * @return this object 21 | */ 22 | public Dataset from(From... graphs) { 23 | return addElements(graphs); 24 | } 25 | 26 | /** 27 | * Add unnamed graph references to this dataset 28 | * 29 | * @param iris the IRI's of the graphs to add 30 | * @return this 31 | */ 32 | public Dataset from(Iri... iris) { 33 | return from(Arrays.stream(iris).map(Spanqit::from).toArray(From[]::new)); 34 | } 35 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.anqit.spanqit 6 | spanqit 7 | 1.1 8 | 9 | 10 | 11 | 12 | org.apache.maven.plugins 13 | maven-compiler-plugin 14 | 3.1 15 | 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | org.apache.maven.plugins 22 | maven-javadoc-plugin 23 | 3.0.0-M1 24 | 25 | private 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/From.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.rdf.Iri; 4 | 5 | /** 6 | * A SPARQL Dataset specifier. 7 | * 8 | * @see 10 | * Specifying RDF Datasets 11 | */ 12 | public class From implements QueryElement { 13 | private static final String FROM = "FROM"; 14 | private static final String NAMED = "NAMED"; 15 | private Iri iri; 16 | private boolean isNamed; 17 | 18 | From(Iri iri) { 19 | this(iri, false); 20 | } 21 | 22 | From(Iri iri, boolean isNamed) { 23 | this.iri = iri; 24 | this.isNamed = isNamed; 25 | } 26 | 27 | @Override 28 | public String getQueryString() { 29 | StringBuilder fromClause = new StringBuilder(); 30 | 31 | fromClause.append(FROM).append(" "); 32 | if (isNamed) { 33 | fromClause.append(NAMED).append(" "); 34 | } 35 | fromClause.append(iri.getQueryString()); 36 | 37 | return fromClause.toString(); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/GraphManagementQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.core.QueryElement; 4 | 5 | abstract class GraphManagementQuery> implements QueryElement { 6 | private static final String SILENT = "SILENT"; 7 | 8 | private boolean silent = false; 9 | 10 | GraphManagementQuery() { } 11 | 12 | /** 13 | * Set the SILENT option to true on this query 14 | * 15 | * @return this query instance 16 | */ 17 | public T silent() { 18 | return silent(true); 19 | } 20 | 21 | /** 22 | * Specify if the SILENT option should be on for this query 23 | * 24 | * @param isSilent if this should be a SILENT operation or not 25 | * 26 | * @return this query instance 27 | */ 28 | @SuppressWarnings("unchecked") 29 | public T silent(boolean isSilent) { 30 | this.silent = isSilent; 31 | 32 | return (T) this; 33 | } 34 | 35 | protected void appendSilent(StringBuilder builder) { 36 | if (silent) { 37 | builder.append(SILENT).append(" "); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/FilterExistsGraphPattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | /** 4 | * A SPARQL Graph Pattern Filter 5 | * 6 | * @see 8 | * Filtering using Graph Pattern 9 | */ 10 | class FilterExistsGraphPattern extends GroupGraphPattern { 11 | private static final String FILTER = "FILTER"; 12 | private static final String NOT = "NOT"; 13 | private static final String EXISTS = "EXISTS"; 14 | 15 | private boolean exists = true; 16 | 17 | FilterExistsGraphPattern() { 18 | super(); 19 | } 20 | 21 | FilterExistsGraphPattern exists(boolean exists) { 22 | this.exists = exists; 23 | 24 | return this; 25 | } 26 | 27 | @Override 28 | public String getQueryString() { 29 | StringBuilder filterExists = new StringBuilder(); 30 | 31 | filterExists.append(FILTER).append(" "); 32 | if (!exists) { 33 | filterExists.append(NOT).append(" "); 34 | } 35 | filterExists.append(EXISTS).append(" "); 36 | 37 | return filterExists.append(super.getQueryString()).toString(); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/CreateQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.rdf.Iri; 4 | 5 | /** 6 | * A SPARQL CREATE Query 7 | * 8 | * @see 9 | * SPARQL CREATE Query 10 | */ 11 | public class CreateQuery extends GraphManagementQuery { 12 | private static final String CREATE = "CREATE"; 13 | private static final String GRAPH = "GRAPH"; 14 | 15 | private Iri graph; 16 | 17 | CreateQuery() { } 18 | 19 | /** 20 | * Specify the graph to create 21 | * 22 | * @param graph the IRI identifier for the new graph 23 | * 24 | * @return this CreateQuery instance 25 | */ 26 | public CreateQuery graph(Iri graph) { 27 | this.graph = graph; 28 | 29 | return this; 30 | } 31 | 32 | @Override 33 | public String getQueryString() { 34 | StringBuilder create = new StringBuilder(); 35 | 36 | create.append(CREATE).append(" "); 37 | 38 | appendSilent(create); 39 | 40 | create.append(GRAPH).append(" ").append(graph.getQueryString()); 41 | 42 | return create.toString(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spanqit 2 | 3 | *** 4 | ## Exciting update! 5 | Spanqit has been merged into the Eclipse Foundation project [rdf4j](http://rdf4j.org/)! As such, further development will continue there first, and perhaps backported here. Check out links to [docs](https://rdf4j.org/documentation/tutorials/sparqlbuilder/) and the [source code](https://github.com/eclipse/rdf4j/tree/main/core/sparqlbuilder) 6 | *** 7 | 8 | 9 | A Java-based SPARQL query generator 10 | 11 | Spanqit is an open source, fluent Java library to programatically create SPARQL queries. See the [wiki](https://github.com/anqit/spanqit/wiki) and javadocs (coming soon) for more info. 12 | 13 | 14 | ### New with version 1.1: 15 | - Support for all of the [Update Queries](https://www.w3.org/TR/sparql11-update/)!! 16 | - No more need for adapters, all RDF elements can be created from with Spanqit, including IRI's and blank nodes 17 | - support for more SPARQL syntax constructs like predicate-object lists in triple patterns and blank nodes 18 | - more convenience methods 19 | - some bug fixes and javadocs 20 | Check out the updated [examples project](https://github.com/anqit/spanqit-examples) for detailed usage 21 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfPredicateObjectList.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import java.util.Collections; 4 | 5 | import com.anqit.spanqit.core.QueryElementCollection; 6 | 7 | /** 8 | * A Predicate-Object List 9 | * 10 | * @see 11 | * SPARQL Predicate-Object List 12 | */ 13 | public class RdfPredicateObjectList extends QueryElementCollection { 14 | private RdfPredicate predicate; 15 | 16 | RdfPredicateObjectList(RdfPredicate predicate, RdfObject... objects) { 17 | super(", "); 18 | this.predicate = predicate; 19 | and(objects); 20 | } 21 | 22 | /** 23 | * Add {@link RdfObject} instances to this predicate-object list 24 | * 25 | * @param objects the objects to add to this list 26 | * 27 | * @return this {@link RdfPredicateObjectList} instance 28 | */ 29 | public RdfPredicateObjectList and(RdfObject... objects) { 30 | Collections.addAll(elements, objects); 31 | 32 | return this; 33 | } 34 | 35 | @Override 36 | public String getQueryString() { 37 | return predicate.getQueryString() + " " + super.getQueryString(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/QueryElementCollection.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.Collection; 4 | import java.util.HashSet; 5 | import java.util.stream.Collectors; 6 | 7 | /** 8 | * A logical collection of query elements. Provides common functionality for 9 | * elements which are collections of other elements, especially in printing. 10 | * Would have loved to have avoided making this public. 11 | * 12 | * @param 13 | * the type of elements in the collection 14 | */ 15 | public abstract class QueryElementCollection implements QueryElement { 16 | protected Collection elements; 17 | private String delimeter; 18 | 19 | protected QueryElementCollection() { 20 | this("\n"); 21 | } 22 | 23 | protected QueryElementCollection(String delimeter) { 24 | this(delimeter, new HashSet()); 25 | } 26 | 27 | protected QueryElementCollection(String delimeter, Collection elements) { 28 | this.elements = elements; 29 | this.delimeter = delimeter; 30 | } 31 | 32 | /** 33 | * @return if this collection is empty 34 | */ 35 | public boolean isEmpty() { 36 | return elements.isEmpty(); 37 | } 38 | 39 | @Override 40 | public String getQueryString() { 41 | return elements.stream().map(QueryElement::getQueryString).collect(Collectors.joining(delimeter)); 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/Operation.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * A SPARQL Operation. Differs from a {@link Function} in the way operators and 5 | * arguments are printed. 6 | * 7 | * @param The type of operation. Used to support fluency. 8 | */ 9 | abstract class Operation> extends Expression { 10 | protected int operandLimit; 11 | 12 | Operation(SparqlOperator operator) { 13 | this(operator, -1); 14 | } 15 | 16 | Operation(SparqlOperator operator, int operandLimit) { 17 | super(operator); 18 | this.operandLimit = operandLimit; 19 | parenthesize(); 20 | } 21 | 22 | @SuppressWarnings("unchecked") 23 | T addOperand(Operand operand) /* throws Exception */ { 24 | if (isBelowOperatorLimit()) { 25 | return super.addOperand(operand); 26 | } 27 | // TODO: throw exception for out of bounds 28 | // throw new Exception(); 29 | return (T) this; 30 | } 31 | 32 | @Override 33 | public String getQueryString() { 34 | return isAtOperatorLimit() ? super.getQueryString() : ""; 35 | } 36 | 37 | protected boolean isBelowOperatorLimit() { 38 | return operandLimit < 0 || elements.size() < operandLimit; 39 | } 40 | 41 | protected boolean isAtOperatorLimit() { 42 | return operandLimit < 0 || elements.size() == operandLimit; 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/AlternativeGraphPattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.core.QueryElementCollection; 4 | 5 | /** 6 | * A SPARQL Alternative Graph Pattern. 7 | * 8 | * @see 10 | * SPARQL Alternative Graph Patterns 11 | */ 12 | class AlternativeGraphPattern extends QueryElementCollection 13 | implements GraphPattern { 14 | private static final String UNION = "UNION"; 15 | private static final String DELIMETER = " " + UNION + " "; 16 | 17 | AlternativeGraphPattern() { 18 | super(DELIMETER); 19 | } 20 | 21 | AlternativeGraphPattern(GraphPattern original) { 22 | super(DELIMETER); 23 | 24 | if (original instanceof AlternativeGraphPattern) { 25 | copy((AlternativeGraphPattern) original); 26 | } else if (original != null && !original.isEmpty()) { 27 | elements.add(new GroupGraphPattern(original)); 28 | } 29 | } 30 | 31 | private void copy(AlternativeGraphPattern original) { 32 | this.elements = original.elements; 33 | } 34 | 35 | AlternativeGraphPattern union(GraphPattern... patterns) { 36 | for (GraphPattern pattern : patterns) { 37 | elements.add(new GroupGraphPattern(pattern)); 38 | } 39 | 40 | return this; 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/Filter.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.constraint.Expression; 6 | import com.anqit.spanqit.core.QueryElement; 7 | import com.anqit.spanqit.core.SpanqitUtils; 8 | 9 | /** 10 | * A SPARQL Filter Clause 11 | * 12 | * @see SPARQL 13 | * Filter 14 | */ 15 | class Filter implements QueryElement { 16 | private static final String FILTER = "FILTER"; 17 | private Optional> constraint = Optional.empty(); 18 | 19 | Filter() { 20 | this(null); 21 | } 22 | 23 | Filter(Expression expression) { 24 | filter(expression); 25 | } 26 | 27 | /** 28 | * Set the constraint for this Filter clause 29 | * 30 | * @param expression 31 | * the constraint to set 32 | * @return this 33 | */ 34 | public Filter filter(Expression expression) { 35 | constraint = Optional.ofNullable(expression); 36 | 37 | return this; 38 | } 39 | 40 | @Override 41 | public String getQueryString() { 42 | StringBuilder filter = new StringBuilder(); 43 | 44 | filter.append(FILTER).append(" "); 45 | String exp = constraint.map(QueryElement::getQueryString).orElse(""); 46 | filter.append(SpanqitUtils.getParenthesizedString(exp)); 47 | 48 | return filter.toString(); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/UpdateDataQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.core.Spanqit; 6 | import com.anqit.spanqit.core.TriplesTemplate; 7 | import com.anqit.spanqit.graphpattern.GraphName; 8 | import com.anqit.spanqit.graphpattern.TriplePattern; 9 | 10 | @SuppressWarnings("unchecked") 11 | abstract class UpdateDataQuery> extends UpdateQuery { 12 | protected TriplesTemplate triplesTemplate = Spanqit.triplesTemplate(); 13 | protected Optional graphName = Optional.empty(); 14 | 15 | protected T addTriples(TriplePattern... triples) { 16 | triplesTemplate.and(triples); 17 | 18 | return (T) this; 19 | } 20 | 21 | protected T setTriplesTemplate(TriplesTemplate triplesTemplate) { 22 | this.triplesTemplate = triplesTemplate; 23 | 24 | return (T) this; 25 | } 26 | 27 | public T graph(GraphName graph) { 28 | graphName = Optional.ofNullable(graph); 29 | 30 | return (T) this; 31 | } 32 | 33 | protected abstract String getPrefix(); 34 | 35 | @Override 36 | protected String getQueryActionString() { 37 | StringBuilder updateDataQuery = new StringBuilder(); 38 | 39 | updateDataQuery.append(getPrefix()).append(" "); 40 | appendNamedTriplesTemplates(updateDataQuery, graphName, triplesTemplate); 41 | 42 | return updateDataQuery.toString(); 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/ConstructQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.core.GraphTemplate; 4 | import com.anqit.spanqit.core.Spanqit; 5 | import com.anqit.spanqit.graphpattern.TriplePattern; 6 | 7 | /** 8 | * The SPARQL CONSTRUCT query 9 | * 10 | * @see 12 | * SPARQL CONSTRUCT Query 13 | */ 14 | public class ConstructQuery extends OuterQuery { 15 | // package-protect instantiation of this class 16 | ConstructQuery() { } 17 | 18 | private GraphTemplate construct = Spanqit.construct(); 19 | 20 | /** 21 | * Add triples to this query's graph template 22 | * 23 | * @param patterns 24 | * the triples to include in the graph template 25 | * @return this 26 | */ 27 | public ConstructQuery construct(TriplePattern... patterns) { 28 | construct.construct(patterns); 29 | 30 | return this; 31 | } 32 | 33 | /** 34 | * Set this query's graph template 35 | * 36 | * @param construct 37 | * the {@link GraphTemplate} to set 38 | * @return this 39 | */ 40 | public ConstructQuery construct(GraphTemplate construct) { 41 | this.construct = construct; 42 | 43 | return this; 44 | } 45 | 46 | @Override 47 | protected String getQueryActionString() { 48 | return construct.getQueryString(); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/TriplesSameSubject.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.rdf.Rdf; 4 | import com.anqit.spanqit.rdf.RdfObject; 5 | import com.anqit.spanqit.rdf.RdfPredicate; 6 | import com.anqit.spanqit.rdf.RdfPredicateObjectList; 7 | import com.anqit.spanqit.rdf.RdfPredicateObjectListCollection; 8 | import com.anqit.spanqit.rdf.RdfSubject; 9 | 10 | /** 11 | * A SPARQL Triple Pattern. 12 | * 13 | * @see 15 | * Triple pattern syntax 16 | */ 17 | class TriplesSameSubject implements TriplePattern { 18 | private RdfSubject subject; 19 | private RdfPredicateObjectListCollection predicateObjectLists = Rdf.predicateObjectListCollection(); 20 | 21 | TriplesSameSubject(RdfSubject subject, RdfPredicate predicate, RdfObject... objects) { 22 | this.subject = subject; 23 | andHas(predicate, objects); 24 | } 25 | 26 | TriplesSameSubject(RdfSubject subject, RdfPredicateObjectList... lists) { 27 | this.subject = subject; 28 | andHas(lists); 29 | } 30 | 31 | @Override 32 | public TriplesSameSubject andHas(RdfPredicateObjectList... lists) { 33 | predicateObjectLists.andHas(lists); 34 | 35 | return this; 36 | } 37 | 38 | @Override 39 | public String getQueryString() { 40 | return subject.getQueryString() + " " + predicateObjectLists.getQueryString() + SUFFIX; 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/GraphTemplate.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.graphpattern.TriplePattern; 4 | 5 | /** 6 | * A SPARQL Graph Template, used in Construct queries 7 | * 8 | * @see 10 | * SPARQL CONSTRUCT Query 11 | */ 12 | public class GraphTemplate implements QueryElement { 13 | private static final String CONSTRUCT = "CONSTRUCT"; 14 | private TriplesTemplate triplesTemplate = Spanqit.triplesTemplate(); 15 | 16 | GraphTemplate() { } 17 | 18 | /** 19 | * Add triple patterns to this graph template 20 | * 21 | * @param triples 22 | * the patterns to add 23 | * @return this 24 | */ 25 | public GraphTemplate construct(TriplePattern... triples) { 26 | triplesTemplate.and(triples); 27 | 28 | return this; 29 | } 30 | 31 | /** 32 | * Set, rather than augment, this graph template's triples template 33 | * @param triplesTemplate 34 | * the {@link TriplesTemplate} instance to set 35 | * @return this graph template 36 | */ 37 | public GraphTemplate construct(TriplesTemplate triplesTemplate) { 38 | this.triplesTemplate = triplesTemplate; 39 | 40 | return this; 41 | } 42 | 43 | @Override 44 | public String getQueryString() { 45 | StringBuilder graphTemplate = new StringBuilder(); 46 | 47 | graphTemplate.append(CONSTRUCT).append(" ").append(triplesTemplate.getQueryString()); 48 | 49 | return graphTemplate.toString(); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/InsertDataQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.core.TriplesTemplate; 4 | import com.anqit.spanqit.graphpattern.GraphName; 5 | import com.anqit.spanqit.graphpattern.TriplePattern; 6 | 7 | /** 8 | * The SPARQL Insert Data Query 9 | * 10 | * @see 11 | * SPARQL INSERT DATA Query 12 | * 13 | */ 14 | public class InsertDataQuery extends UpdateDataQuery { 15 | private static final String INSERT_DATA = "INSERT DATA"; 16 | 17 | /** 18 | * Add triples to be inserted 19 | * 20 | * @param triples the triples to add to this insert data query 21 | * 22 | * @return this Insert Data query instance 23 | */ 24 | public InsertDataQuery insertData(TriplePattern... triples) { 25 | return addTriples(triples); 26 | } 27 | 28 | /** 29 | * Set this query's triples template 30 | * 31 | * @param triplesTemplate 32 | * the {@link TriplesTemplate} instance to set 33 | * 34 | * @return this instance 35 | */ 36 | public InsertDataQuery insertData(TriplesTemplate triplesTemplate) { 37 | return setTriplesTemplate(triplesTemplate); 38 | } 39 | /** 40 | * Specify a graph to insert the data into 41 | * 42 | * @param graph the identifier of the graph 43 | * 44 | * @return this Insert Data query instance 45 | */ 46 | public InsertDataQuery into(GraphName graph) { 47 | return graph(graph); 48 | } 49 | 50 | @Override 51 | public String getPrefix() { 52 | return INSERT_DATA; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/DeleteDataQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.core.TriplesTemplate; 4 | import com.anqit.spanqit.graphpattern.GraphName; 5 | import com.anqit.spanqit.graphpattern.TriplePattern; 6 | 7 | /** 8 | * The SPARQL Delete Data Query 9 | * 10 | * @see SPARQL 11 | * DELETE DATA Query 12 | * 13 | */ 14 | public class DeleteDataQuery extends UpdateDataQuery { 15 | private static final String DELETE_DATA = "DELETE DATA"; 16 | 17 | /** 18 | * Add triples to be deleted 19 | * 20 | * @param triples the triples to add to this delete data query 21 | * 22 | * @return this Delete Data query instance 23 | */ 24 | public DeleteDataQuery deleteData(TriplePattern... triples) { 25 | return addTriples(triples); 26 | } 27 | 28 | /** 29 | * Set this query's triples template 30 | * 31 | * @param triplesTemplate 32 | * the {@link TriplesTemplate} instance to set 33 | * 34 | * @return this instance 35 | */ 36 | public DeleteDataQuery deleteData(TriplesTemplate triplesTemplate) { 37 | return setTriplesTemplate(triplesTemplate); 38 | } 39 | 40 | /** 41 | * Specify a graph to delete the data from 42 | * 43 | * @param graph the identifier of the graph 44 | * 45 | * @return this Delete Data query instance 46 | */ 47 | public DeleteDataQuery from(GraphName graph) { 48 | return graph(graph); 49 | } 50 | 51 | @Override 52 | protected String getPrefix() { 53 | return DELETE_DATA; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/OrderCondition.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | /** 4 | * An ascending or descending order condition 5 | * 6 | * @see 8 | * SPARQL Order By Clause 9 | */ 10 | public class OrderCondition implements Orderable { 11 | private static final String ASC = "ASC"; 12 | private static final String DESC = "DESC"; 13 | private Orderable orderOn; 14 | private boolean isAscending; 15 | 16 | OrderCondition(Orderable orderOn) { 17 | this(orderOn, true); 18 | } 19 | 20 | OrderCondition(Orderable orderOn, boolean ascending) { 21 | this.orderOn = orderOn; 22 | if (ascending) { 23 | asc(); 24 | } else { 25 | desc(); 26 | } 27 | } 28 | 29 | /** 30 | * Set this order condition to be ascending 31 | * 32 | * @return this 33 | */ 34 | public OrderCondition asc() { 35 | this.isAscending = true; 36 | 37 | return this; 38 | } 39 | 40 | /** 41 | * Set this order condition to be descending 42 | * 43 | * @return this 44 | */ 45 | public OrderCondition desc() { 46 | this.isAscending = false; 47 | 48 | return this; 49 | } 50 | 51 | @Override 52 | public String getQueryString() { 53 | StringBuilder condition = new StringBuilder(); 54 | 55 | if (orderOn != null) { 56 | if (isAscending) { 57 | condition.append(ASC); 58 | } else { 59 | condition.append(DESC); 60 | } 61 | 62 | condition.append(SpanqitUtils.getParenthesizedString(orderOn.getQueryString())); 63 | } 64 | 65 | return condition.toString(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Variable.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.constraint.Operand; 4 | import com.anqit.spanqit.graphpattern.GraphName; 5 | import com.anqit.spanqit.rdf.RdfObject; 6 | import com.anqit.spanqit.rdf.RdfPredicate; 7 | import com.anqit.spanqit.rdf.RdfSubject; 8 | 9 | /** 10 | * A SPARQL query variable 11 | * 12 | * @see 14 | * SPARQL Variable Syntax 15 | */ 16 | public class Variable implements Projectable, RdfSubject, 17 | RdfPredicate, RdfObject, Operand, Orderable, 18 | Groupable, GraphName, Assignable { 19 | private String alias; 20 | 21 | Variable(String varName) { 22 | this.alias = varName; 23 | } 24 | 25 | @Override 26 | public String getQueryString() { 27 | return "?" + alias; 28 | } 29 | 30 | @Override 31 | public boolean equals(Object obj) { 32 | if (this == obj) { 33 | return true; 34 | } 35 | if (obj == null) { 36 | return false; 37 | } 38 | if (!(obj instanceof Variable)) { 39 | return false; 40 | } 41 | 42 | Variable other = (Variable) obj; 43 | if (alias == null) { 44 | if (other.alias != null) { 45 | return false; 46 | } 47 | } else if (!alias.equals(other.alias)) { 48 | return false; 49 | } 50 | 51 | return true; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | final int prime = 31; 57 | int result = 1; 58 | result = prime * result + ((alias == null) ? 0 : alias.hashCode()); 59 | return result; 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/LoadQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.core.SpanqitUtils; 6 | import com.anqit.spanqit.rdf.Iri; 7 | 8 | /** 9 | * A SPARQL LOAD Query 10 | * 11 | * @see 12 | * SPARQL LOAD Query 13 | */ 14 | public class LoadQuery extends GraphManagementQuery { 15 | private static final String LOAD = "LOAD"; 16 | private static final String INTO_GRAPH = "INTO GRAPH"; 17 | 18 | private Iri from; 19 | private Optional to = Optional.empty(); 20 | 21 | LoadQuery() { } 22 | 23 | /** 24 | * Specify which graph to load form 25 | * 26 | * @param from the IRI identifying the graph to load triples from 27 | * 28 | * @return this LoadQuery instance 29 | */ 30 | public LoadQuery from(Iri from) { 31 | this.from = from; 32 | 33 | return this; 34 | } 35 | 36 | /** 37 | * Specify which graph to load into, if not the default graph 38 | * 39 | * @param to the IRI identifying the graph to load into 40 | * 41 | * @return this LoadQuery instance 42 | */ 43 | public LoadQuery to(Iri to) { 44 | this.to = Optional.ofNullable(to); 45 | 46 | return this; 47 | } 48 | 49 | @Override 50 | public String getQueryString() { 51 | StringBuilder load = new StringBuilder(); 52 | load.append(LOAD).append(" "); 53 | 54 | appendSilent(load); 55 | 56 | load.append(from.getQueryString()); 57 | 58 | SpanqitUtils.appendQueryElementIfPresent(to, load, " " + INTO_GRAPH + " ", null); 59 | 60 | return load.toString(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfPredicateObjectListCollection.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import java.util.Collections; 4 | 5 | import com.anqit.spanqit.core.QueryElementCollection; 6 | 7 | /** 8 | * An RDF predicate-object list collection 9 | * 10 | * @see 11 | * Predicate-Object Lists 12 | * @see 13 | * Object Lists 14 | */ 15 | public class RdfPredicateObjectListCollection extends QueryElementCollection { 16 | private static final String DELIMITER = " ;\n "; 17 | 18 | RdfPredicateObjectListCollection() { 19 | super(DELIMITER); 20 | }; 21 | 22 | /** 23 | * add predicate-object lists to this collection 24 | * 25 | * @param predicate the predicate of the predicate-object list to add 26 | * @param objects the object or objects to add 27 | * 28 | * @return this instance 29 | */ 30 | public RdfPredicateObjectListCollection andHas(RdfPredicate predicate, RdfObject... objects) { 31 | return andHas(Rdf.predicateObjectList(predicate, objects)); 32 | } 33 | 34 | /** 35 | * add predicate-object lists to this collection 36 | * 37 | * @param lists the {@link RdfPredicateObjectList}'s to add to this collection 38 | * @return this instance 39 | */ 40 | public RdfPredicateObjectListCollection andHas(RdfPredicateObjectList... lists) { 41 | Collections.addAll(elements, lists); 42 | 43 | return this; 44 | } 45 | 46 | // TODO add suffix for if elements.size > 1; here or in triplessamesubject 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/QueryPattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.graphpattern.GraphPattern; 4 | import com.anqit.spanqit.graphpattern.GraphPatternNotTriple; 5 | import com.anqit.spanqit.graphpattern.GraphPatterns; 6 | 7 | /** 8 | * A SPARQL Query Pattern (WHERE clause) 9 | * 10 | * @see 12 | * Query Pattern Definition 13 | */ 14 | public class QueryPattern implements QueryElement { 15 | private static final String WHERE = "WHERE"; 16 | 17 | private GraphPatternNotTriple where = GraphPatterns.and(); 18 | 19 | QueryPattern() { } 20 | 21 | /** 22 | * Add graph patterns to this query pattern. Adds the given patterns into 23 | * this query pattern's group graph pattern 24 | * 25 | * @param patterns 26 | * the patterns to add 27 | * @return this 28 | */ 29 | public QueryPattern where(GraphPattern... patterns) { 30 | where.and(patterns); 31 | 32 | return this; 33 | } 34 | 35 | /** 36 | * Set this query pattern's where clause 37 | * @param where 38 | * the {@link GraphPatternNotTriple} instance to set the where clause to 39 | * @return 40 | * this QueryPattern instance 41 | */ 42 | public QueryPattern where(GraphPatternNotTriple where) { 43 | this.where = GraphPatterns.and(where); 44 | 45 | return this; 46 | } 47 | 48 | @Override 49 | public String getQueryString() { 50 | StringBuilder whereClause = new StringBuilder(); 51 | 52 | whereClause.append(WHERE).append(" ").append(where.getQueryString()); 53 | 54 | return whereClause.toString(); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/SparqlFunction.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | /** 4 | * The built-in SPARQL Functions. Keeping this public until 5 | * {@link Expressions} is completed. 6 | * 7 | * @see 9 | * SPARQL Function Definitions 10 | */ 11 | @SuppressWarnings("javadoc") // acceptable, as this won't be public for long 12 | public enum SparqlFunction implements SparqlOperator { 13 | ABS("ABS"), 14 | BNODE("BNODE"), 15 | BOUND("BOUND"), 16 | CEIL("CEIL"), 17 | COALESCE("COALESCE"), 18 | CONCAT("CONCAT"), 19 | CONTAINS("CONTAINS"), 20 | DATATYPE("DATATYPE"), 21 | DAY("DAY"), 22 | ENCODE_FOR_URI("ENCODE_FOR_URI"), 23 | FLOOR("FLOOR"), 24 | HOURS("HOURS"), 25 | IF("IF"), 26 | IRI("IRI"), 27 | IS_BLANK("isBLANK"), 28 | IS_IRI("isIRI"), 29 | IS_LITERAL("isLITERAL"), 30 | IS_NUMERIC("isNUMERIC"), 31 | IS_URI("isURI"), 32 | LANG("LANG"), 33 | LANGMATCHES("LANGMATCHES"), 34 | LCASE("LCASE"), 35 | MD5("MD5"), 36 | MINUTES("MINUTES"), 37 | MONTH("MONTH"), 38 | NOW("NOW"), 39 | RAND("RAND"), 40 | REGEX("REGEX"), 41 | REPLACE("REPLACE"), 42 | ROUND("ROUND"), 43 | SAME_TERM("sameTerm"), 44 | SECONDS("SECONDS"), 45 | SHA1("SHA1"), 46 | SHA256("SHA256"), 47 | SHA384("SHA384"), 48 | SHA512("SHA512"), 49 | STRAFTER("STRAFTER"), 50 | STRBEFORE("STRBEFORE"), 51 | STRDT("STRDT"), 52 | STRENDS("STRENDS"), 53 | STRING("STR"), 54 | STRLANG("STRLANG"), 55 | STRLEN("STRLEN"), 56 | STRSTARTS("STRSTARTS"), 57 | STRUUID("STRUUID"), 58 | SUBSTR("SUBSTR"), 59 | TIMEZONE("TIMEZONE"), 60 | TZ("TZ"), 61 | UCASE("UCASE"), 62 | URI("URI"), 63 | UUID("UUID"), 64 | YEAR("YEAR"); 65 | 66 | private String function; 67 | 68 | private SparqlFunction(String function) { 69 | this.function = function; 70 | } 71 | 72 | @Override 73 | public String getQueryString() { 74 | return function; 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Prefix.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.rdf.Iri; 4 | 5 | /** 6 | * A SPARQL Prefix declaration 7 | * 8 | * @see 10 | * SPARQL Prefix 11 | */ 12 | public class Prefix implements QueryElement { 13 | private static final String PREFIX = "PREFIX"; 14 | private String label; 15 | private Iri iri; 16 | 17 | Prefix(String alias, Iri iri) { 18 | this.label = alias; 19 | this.iri = iri; 20 | } 21 | 22 | /** 23 | * Create a prefixed IRI reference from this prefix 24 | * 25 | * @param localName 26 | * the local part of the prefixed IRI 27 | * @return a prefixed IRI reference, with this prefix's label as the base, 28 | * and the given string for the local part 29 | */ 30 | public Iri iri(String localName) { 31 | return () -> label + ":" + localName; 32 | } 33 | 34 | @Override 35 | public String getQueryString() { 36 | return PREFIX + " " + label + ": " + iri.getQueryString(); 37 | } 38 | 39 | @Override 40 | public boolean equals(Object obj) { 41 | if (this == obj) { 42 | return true; 43 | } 44 | 45 | if (obj == null) { 46 | return false; 47 | } 48 | 49 | if (!(obj instanceof Prefix)) { 50 | return false; 51 | } 52 | 53 | Prefix other = (Prefix) obj; 54 | if (label == null) { 55 | if (other.label != null) { 56 | return false; 57 | } 58 | } else if (!label.equals(other.label)) { 59 | return false; 60 | } 61 | if (iri == null) { 62 | if (other.iri != null) { 63 | return false; 64 | } 65 | } else if (!iri.equals(other.iri)) { 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | @Override 73 | public int hashCode() { 74 | final int prime = 31; 75 | int result = 1; 76 | result = prime * result + ((label == null) ? 0 : label.hashCode()); 77 | result = prime * result + ((iri == null) ? 0 : iri.hashCode()); 78 | return result; 79 | } 80 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/TargetedGraphManagementQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.rdf.Iri; 6 | 7 | @SuppressWarnings("javadoc") 8 | public abstract class TargetedGraphManagementQuery> extends GraphManagementQuery> { 9 | private static final String GRAPH = "GRAPH"; 10 | private static final String DEFAULT = "DEFAULT"; 11 | private static final String NAMED = "NAMED"; 12 | private static final String ALL = "ALL"; 13 | 14 | private String target = DEFAULT; 15 | private Optional graph = Optional.empty(); 16 | 17 | /** 18 | * Specify which graph to target 19 | * 20 | * @param graph the IRI identifying the graph to target 21 | * 22 | * @return this query instance 23 | */ 24 | @SuppressWarnings("unchecked") 25 | public T graph(Iri graph) { 26 | this.graph = Optional.ofNullable(graph); 27 | 28 | return (T) this; 29 | } 30 | 31 | /** 32 | * Target the default graph 33 | * 34 | * @return this query instance 35 | */ 36 | public T def() { 37 | return target(DEFAULT); 38 | } 39 | 40 | /** 41 | * Target all named graphs 42 | * 43 | * @return this query instance 44 | */ 45 | public T named() { 46 | return target(NAMED); 47 | } 48 | 49 | /** 50 | * Target all graphs 51 | * 52 | * @return this query instance 53 | */ 54 | public T all() { 55 | return target(ALL); 56 | } 57 | 58 | @SuppressWarnings("unchecked") 59 | private T target(String target) { 60 | this.target = target; 61 | graph = Optional.empty(); 62 | 63 | return (T) this; 64 | } 65 | 66 | protected abstract String getQueryActionString(); 67 | 68 | @Override 69 | public String getQueryString() { 70 | StringBuilder query = new StringBuilder(); 71 | 72 | query.append(getQueryActionString()).append(" "); 73 | 74 | appendSilent(query); 75 | 76 | String targetString = graph.map(iri -> GRAPH + " " + iri.getQueryString()).orElse(target); 77 | query.append(targetString); 78 | 79 | return query.toString(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/StandardQueryElementCollection.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.Optional; 6 | import java.util.function.Function; 7 | 8 | abstract class StandardQueryElementCollection, T extends QueryElement> 9 | extends QueryElementCollection { 10 | private String operatorName; 11 | private Function wrapperMethod; 12 | 13 | private boolean printBodyIfEmpty = false; 14 | private boolean printNameIfEmpty = true; 15 | 16 | StandardQueryElementCollection() { 17 | this(null, null); 18 | } 19 | 20 | StandardQueryElementCollection(String operatorName, Function wrapperMethod) { 21 | super(); 22 | initialize(operatorName, wrapperMethod); 23 | } 24 | 25 | StandardQueryElementCollection(String operatorName, String delimiter, Collection collection) { 26 | super(delimiter, collection); 27 | initialize(operatorName, null); 28 | } 29 | 30 | StandardQueryElementCollection(String operatorName, String delimiter, Function wrapperMethod, 31 | Collection collection) { 32 | super(delimiter, collection); 33 | initialize(operatorName, wrapperMethod); 34 | } 35 | 36 | private void initialize(String operatorName, Function wrapperMethod) { 37 | this.operatorName = Optional.ofNullable(operatorName).map(s -> s + " ").orElse(""); 38 | this.wrapperMethod = Optional.ofNullable(wrapperMethod).orElse(Function.identity()); 39 | } 40 | 41 | @SuppressWarnings("unchecked") 42 | protected C addElements(T... queryElements) { 43 | Collections.addAll(elements, queryElements); 44 | 45 | return (C) this; 46 | } 47 | 48 | @SuppressWarnings("unchecked") 49 | protected C printBodyIfEmpty(boolean printBodyIfEmpty) { 50 | this.printBodyIfEmpty = printBodyIfEmpty; 51 | 52 | return (C) this; 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | protected C printNameIfEmpty(boolean printNameIfEmpty) { 57 | this.printNameIfEmpty = printNameIfEmpty; 58 | 59 | return (C) this; 60 | } 61 | 62 | @Override 63 | public String getQueryString() { 64 | StringBuilder queryString = new StringBuilder(); 65 | 66 | if(printNameIfEmpty || !isEmpty()) { 67 | queryString.append(operatorName); 68 | } 69 | if (printBodyIfEmpty || !isEmpty()) { 70 | queryString.append(wrapperMethod.apply(super.getQueryString())); 71 | } 72 | 73 | return queryString.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/SpanqitUtils.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Supplier; 5 | import java.util.function.UnaryOperator; 6 | 7 | @SuppressWarnings("javadoc") 8 | public class SpanqitUtils { 9 | private static final String PAD = " "; 10 | 11 | public static Optional getOrCreateAndModifyOptional(Optional optional, Supplier getter, UnaryOperator operator) { 12 | return Optional.of(operator.apply(optional.orElseGet(getter))); 13 | } 14 | 15 | public static void appendAndNewlineIfPresent(Optional elementOptional, StringBuilder builder) { 16 | appendQueryElementIfPresent(elementOptional, builder, null, "\n"); 17 | } 18 | 19 | public static void appendQueryElementIfPresent(Optional queryElementOptional, StringBuilder builder, String prefix, String suffix) { 20 | appendStringIfPresent(queryElementOptional.map(QueryElement::getQueryString), builder, prefix, suffix); 21 | } 22 | 23 | public static void appendStringIfPresent(Optional stringOptional, StringBuilder builder, String prefix, String suffix) { 24 | Optional preOpt = Optional.ofNullable(prefix); 25 | Optional sufOpt = Optional.ofNullable(suffix); 26 | 27 | stringOptional.ifPresent(string -> { 28 | preOpt.ifPresent(p -> builder.append(p)); 29 | builder.append(string); 30 | sufOpt.ifPresent(s -> builder.append(s)); 31 | }); 32 | } 33 | 34 | public static String getBracedString(String contents) { 35 | return getEnclosedString("{", "}", contents); 36 | } 37 | 38 | public static String getBracketedString(String contents) { 39 | return getEnclosedString("[", "]", contents); 40 | } 41 | 42 | public static String getParenthesizedString(String contents) { 43 | return getEnclosedString("(", ")", contents); 44 | } 45 | 46 | public static String getQuotedString(String contents) { 47 | return getEnclosedString("\"", "\"", contents, false); 48 | } 49 | 50 | /** 51 | * For string literals that contain single- or double-quotes 52 | * 53 | * @see 54 | * RDF Literal Syntax 55 | * @param contents 56 | * @return a "long quoted" string 57 | */ 58 | public static String getLongQuotedString(String contents) { 59 | return getEnclosedString("'''", "'''", contents, false); 60 | } 61 | 62 | private static String getEnclosedString(String open, String close, 63 | String contents) { 64 | return getEnclosedString(open, close, contents, true); 65 | } 66 | 67 | private static String getEnclosedString(String open, String close, 68 | String contents, boolean pad) { 69 | StringBuilder es = new StringBuilder(); 70 | 71 | es.append(open); 72 | if (contents != null && !contents.isEmpty()) { 73 | es.append(contents); 74 | if (pad) { 75 | es.insert(open.length(), PAD).append(PAD); 76 | } 77 | } else { 78 | es.append(PAD); 79 | } 80 | es.append(close); 81 | 82 | return es.toString(); 83 | } 84 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/Expression.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.anqit.spanqit.core.Assignable; 6 | import com.anqit.spanqit.core.Groupable; 7 | import com.anqit.spanqit.core.Orderable; 8 | import com.anqit.spanqit.core.QueryElementCollection; 9 | import com.anqit.spanqit.core.SpanqitUtils; 10 | 11 | /** 12 | * A SPARQL expression. Used by filters, having clauses, order and group by 13 | * clauses, assignments, and as arguments to other expressions. 14 | * 15 | * @param 16 | * the type of Expression (ie, Function or Operation). Used to 17 | * support fluency 18 | * 19 | * @see SPARQL 21 | * Filters 22 | *
23 | * 24 | * SPARQL HAVING 25 | *
26 | * SPARQL ORDER BY 29 | *
30 | * 32 | * SPARQL GROUP BY 33 | *
34 | * 36 | * SPARQL Assignments 37 | */ 38 | public abstract class Expression> extends 39 | QueryElementCollection implements Operand, 40 | Orderable, Groupable, Assignable { 41 | protected SparqlOperator operator; 42 | private boolean parenthesize; 43 | 44 | Expression(SparqlOperator operator) { 45 | this(operator, " " + operator.getQueryString() + " "); 46 | } 47 | 48 | Expression(SparqlOperator operator, String delimeter) { 49 | super(delimeter, new ArrayList()); 50 | this.operator = operator; 51 | parenthesize(false); 52 | } 53 | 54 | @SuppressWarnings("unchecked") 55 | T addOperand(Operand... operands) { 56 | for (Operand operand : operands) { 57 | elements.add(operand); 58 | } 59 | 60 | return (T) this; 61 | } 62 | 63 | /** 64 | * Indicate that this expression should be wrapped in parentheses 65 | * when converted to a query string 66 | * 67 | * @return this 68 | */ 69 | public T parenthesize() { 70 | return parenthesize(true); 71 | } 72 | 73 | /** 74 | * Indicate if this expression should be wrapped in parentheses 75 | * when converted to a query string 76 | * 77 | * @param parenthesize 78 | * @return this 79 | */ 80 | @SuppressWarnings("unchecked") 81 | public T parenthesize(boolean parenthesize) { 82 | this.parenthesize = parenthesize; 83 | 84 | return (T) this; 85 | } 86 | 87 | Operand getOperand(int index) { 88 | return ((ArrayList) elements).get(index); 89 | } 90 | 91 | @Override 92 | public String getQueryString() { 93 | String queryString = super.getQueryString(); 94 | 95 | return parenthesize ? SpanqitUtils.getParenthesizedString(queryString) : queryString; 96 | } 97 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/UpdateQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import static com.anqit.spanqit.core.SpanqitUtils.getOrCreateAndModifyOptional; 4 | 5 | import java.util.Optional; 6 | 7 | import com.anqit.spanqit.core.Base; 8 | import com.anqit.spanqit.core.Prefix; 9 | import com.anqit.spanqit.core.PrefixDeclarations; 10 | import com.anqit.spanqit.core.QueryElement; 11 | import com.anqit.spanqit.core.Spanqit; 12 | import com.anqit.spanqit.core.SpanqitUtils; 13 | import com.anqit.spanqit.core.TriplesTemplate; 14 | import com.anqit.spanqit.graphpattern.GraphName; 15 | import com.anqit.spanqit.rdf.Iri; 16 | 17 | /** 18 | * A SPARQL Update query 19 | * 20 | * @param The type of update query. Used to support fluency. 21 | * 22 | * @see 24 | * SPARQL Update Query 25 | */ 26 | @SuppressWarnings("unchecked") 27 | abstract class UpdateQuery> implements QueryElement { 28 | private Optional base = Optional.empty(); 29 | private Optional prefixes = Optional.empty(); 30 | 31 | UpdateQuery() { } 32 | 33 | /** 34 | * Set the base IRI of this query 35 | * 36 | * @param iri 37 | * the base IRI 38 | * @return this 39 | */ 40 | public T base(Iri iri) { 41 | this.base = Optional.of(Spanqit.base(iri)); 42 | 43 | return (T) this; 44 | } 45 | 46 | /** 47 | * Set the Base clause of this query 48 | * 49 | * @param base 50 | * the {@link Base} clause to set 51 | * @return this 52 | */ 53 | public T base(Base base) { 54 | this.base = Optional.of(base); 55 | 56 | return (T) this; 57 | } 58 | 59 | /** 60 | * Add prefix declarations to this query 61 | * 62 | * @param prefixes 63 | * the prefixes to add 64 | * @return this 65 | */ 66 | public T prefix(Prefix... prefixes) { 67 | this.prefixes = getOrCreateAndModifyOptional(this.prefixes, Spanqit::prefixes, p -> p.addPrefix(prefixes)); 68 | 69 | return (T) this; 70 | } 71 | 72 | /** 73 | * Set the Prefix declarations of this query 74 | * 75 | * @param prefixes 76 | * the {@link PrefixDeclarations} to set 77 | * @return this 78 | */ 79 | public T prefix(PrefixDeclarations prefixes) { 80 | this.prefixes = Optional.of(prefixes); 81 | 82 | return (T) this; 83 | } 84 | 85 | protected abstract String getQueryActionString(); 86 | 87 | @Override 88 | public String getQueryString() { 89 | StringBuilder query = new StringBuilder(); 90 | 91 | SpanqitUtils.appendAndNewlineIfPresent(base, query); 92 | SpanqitUtils.appendAndNewlineIfPresent(prefixes, query); 93 | 94 | query.append(getQueryActionString()); 95 | 96 | return query.toString(); 97 | } 98 | 99 | protected void appendNamedTriplesTemplates(StringBuilder queryString, Optional graphName, TriplesTemplate triples) { 100 | queryString.append(graphName.map(graph -> 101 | SpanqitUtils.getBracedString("GRAPH " + graph.getQueryString() + " " + triples.getQueryString())) 102 | .orElseGet(() ->triples.getQueryString())); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/Aggregate.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | import com.anqit.spanqit.core.SpanqitUtils; 4 | 5 | /** 6 | * A SPARQL aggregate expression. 7 | * 8 | * @see 9 | * SPARQL Aggregates 10 | */ 11 | public class Aggregate extends Expression { 12 | private static final String DISTINCT = "DISTINCT"; 13 | private static final Object SEPARATOR = "SEPARATOR"; 14 | 15 | private String separator; 16 | private boolean isDistinct = false; 17 | private boolean countAll = false; 18 | 19 | Aggregate(SparqlAggregate aggregate) { 20 | super(aggregate); 21 | } 22 | 23 | /** 24 | * Specify this aggregate expression to be distinct 25 | * 26 | * @return this aggregate instance 27 | */ 28 | public Aggregate distinct() { 29 | return distinct(true); 30 | } 31 | 32 | /** 33 | * Specify if this aggregate expression should be distinct or not 34 | * 35 | * @param isDistinct 36 | * if this aggregate should be distinct 37 | * 38 | * @return this aggregate instance 39 | */ 40 | public Aggregate distinct(boolean isDistinct) { 41 | this.isDistinct = isDistinct; 42 | 43 | return this; 44 | } 45 | 46 | /** 47 | * If this is a {@code count} aggregate expressions, specify that it should count all 48 | * 49 | * @return this aggregate instance 50 | */ 51 | public Aggregate countAll() { 52 | return countAll(true); 53 | } 54 | 55 | /** 56 | * If this is a {@code count} aggregate expressions, specify if it should count all 57 | * 58 | * @param countAll if this should count all arguments or not 59 | * 60 | * @return this aggregate instance 61 | */ 62 | public Aggregate countAll(boolean countAll) { 63 | this.countAll = countAll; 64 | 65 | return this; 66 | } 67 | 68 | /** 69 | * If this is a {@code group_concat} aggregate expression, specify the separator to use 70 | * 71 | * @param separator the separator to use 72 | * 73 | * @return this aggregate instance 74 | * 75 | * @see 76 | * group_concat() 77 | */ 78 | public Aggregate separator(String separator) { 79 | this.separator = separator; 80 | 81 | return this; 82 | } 83 | 84 | @Override 85 | public String getQueryString() { 86 | StringBuilder aggregate = new StringBuilder(); 87 | StringBuilder params = new StringBuilder(); 88 | 89 | aggregate.append(operator.getQueryString()); 90 | 91 | if(isDistinct) { 92 | params.append(DISTINCT).append(" "); 93 | } 94 | 95 | // Yeah. I know... 96 | if(operator == SparqlAggregate.COUNT && countAll) { 97 | params.append("*"); 98 | } else { 99 | params.append(super.getQueryString()); 100 | } 101 | 102 | // Yep, I still know... 103 | if(operator == SparqlAggregate.GROUP_CONCAT && separator != null) { 104 | params.append(" ").append(";").append(" ").append(SEPARATOR) 105 | .append(" ").append("=").append(" ").append(separator); 106 | } 107 | 108 | return aggregate.append(SpanqitUtils.getParenthesizedString(params.toString())).toString(); 109 | } 110 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/OuterQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import static com.anqit.spanqit.core.SpanqitUtils.appendAndNewlineIfPresent; 4 | import static com.anqit.spanqit.core.SpanqitUtils.getOrCreateAndModifyOptional; 5 | 6 | import java.util.Optional; 7 | 8 | import com.anqit.spanqit.core.Base; 9 | import com.anqit.spanqit.core.Dataset; 10 | import com.anqit.spanqit.core.From; 11 | import com.anqit.spanqit.core.Prefix; 12 | import com.anqit.spanqit.core.PrefixDeclarations; 13 | import com.anqit.spanqit.core.Spanqit; 14 | import com.anqit.spanqit.rdf.Iri; 15 | 16 | /** 17 | * A non-subquery query. 18 | * 19 | * @param 20 | * The query type. Used to support fluency. 21 | */ 22 | @SuppressWarnings("unchecked") 23 | public abstract class OuterQuery> extends Query { 24 | protected Optional base = Optional.empty(); 25 | protected Optional prefixes = Optional.empty(); 26 | protected Optional from = Optional.empty(); 27 | 28 | /** 29 | * Set the base IRI of this query 30 | * 31 | * @param iri 32 | * the base IRI 33 | * @return this 34 | */ 35 | public T base(Iri iri) { 36 | this.base = Optional.of(Spanqit.base(iri)); 37 | 38 | return (T) this; 39 | } 40 | 41 | /** 42 | * Set the Base clause of this query 43 | * 44 | * @param base 45 | * the {@link Base} clause to set 46 | * @return this 47 | */ 48 | public T base(Base base) { 49 | this.base = Optional.of(base); 50 | 51 | return (T) this; 52 | } 53 | 54 | /** 55 | * Add prefix declarations to this query 56 | * 57 | * @param prefixes 58 | * the prefixes to add 59 | * @return this 60 | */ 61 | public T prefix(Prefix... prefixes) { 62 | this.prefixes = getOrCreateAndModifyOptional(this.prefixes, Spanqit::prefixes, p -> p.addPrefix(prefixes)); 63 | 64 | return (T) this; 65 | } 66 | 67 | /** 68 | * Set the Prefix declarations of this query 69 | * 70 | * @param prefixes 71 | * the {@link PrefixDeclarations} to set 72 | * @return this 73 | */ 74 | public T prefix(PrefixDeclarations prefixes) { 75 | this.prefixes = Optional.of(prefixes); 76 | 77 | return (T) this; 78 | } 79 | 80 | /** 81 | * Add datasets to this query 82 | * 83 | * @param graphs 84 | * the graph specifiers to add 85 | * @return this 86 | */ 87 | public T from(From... graphs) { 88 | from = getOrCreateAndModifyOptional(from, Spanqit::dataset, f -> f.from(graphs)); 89 | 90 | return (T) this; 91 | } 92 | 93 | /** 94 | * Set the Dataset clause for this query 95 | * 96 | * @param from 97 | * the {@link Dataset} clause to set 98 | * @return this 99 | */ 100 | public T from(Dataset from) { 101 | this.from = Optional.of(from); 102 | 103 | return (T) this; 104 | } 105 | 106 | @Override 107 | public String getQueryString() { 108 | StringBuilder query = new StringBuilder(); 109 | 110 | appendAndNewlineIfPresent(base, query); 111 | appendAndNewlineIfPresent(prefixes, query); 112 | appendAndNewlineIfPresent(from, query); 113 | 114 | query.append(super.getQueryString()); 115 | 116 | return query.toString(); 117 | } 118 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/DestinationSourceManagementQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.rdf.Iri; 6 | 7 | /** 8 | * A SPARQL Update Query that has a source and a destination 9 | * 10 | * @param the type of the query; used to support fluency 11 | */ 12 | public abstract class DestinationSourceManagementQuery> extends GraphManagementQuery> { 13 | private static String DEFAULT = "DEFAULT"; 14 | private static String TO = "TO"; 15 | 16 | private Optional from = Optional.empty(); 17 | private Optional to = Optional.empty(); 18 | private boolean fromDefault = false, toDefault = false; 19 | 20 | /** 21 | * Specify the query source graph 22 | * 23 | * @param from the Iri identifying the source graph 24 | * 25 | * @return this query instance 26 | */ 27 | public T from(Iri from) { 28 | this.from = Optional.ofNullable(from); 29 | 30 | return fromDefault(false); 31 | } 32 | 33 | /** 34 | * Specify the query destination graph 35 | * 36 | * @param to the Iri identifying the destination graph 37 | * 38 | * @return this query instance 39 | */ 40 | public T to(Iri to) { 41 | this.to = Optional.ofNullable(to); 42 | 43 | return toDefault(false); 44 | } 45 | 46 | /** 47 | * Specify that the source graph of this query should be the default graph 48 | * 49 | * @return this query instance 50 | */ 51 | public T fromDefault() { 52 | return fromDefault(true); 53 | } 54 | 55 | /** 56 | * Specify if this query's source should be the default graph 57 | * 58 | * @param fromDefault if this query's source should be the default graph 59 | * 60 | * @return this query instance 61 | */ 62 | @SuppressWarnings("unchecked") 63 | public T fromDefault(boolean fromDefault) { 64 | this.fromDefault = fromDefault; 65 | 66 | return (T) this; 67 | } 68 | 69 | /** 70 | * Specify that the destination graph of this query should be the default graph 71 | * 72 | * @return this query instance 73 | */ 74 | public T toDefault() { 75 | return toDefault(true); 76 | } 77 | 78 | /** 79 | * Specify if this query's destination should be the default graph 80 | * 81 | * @param toDefault if this query's destination should be the default graph 82 | * 83 | * @return this query instance 84 | */ 85 | @SuppressWarnings("unchecked") 86 | public T toDefault(boolean toDefault) { 87 | this.toDefault = toDefault; 88 | 89 | return (T) this; 90 | } 91 | 92 | protected abstract String getQueryActionString(); 93 | 94 | @Override 95 | public String getQueryString() { 96 | StringBuilder query = new StringBuilder(); 97 | query.append(getQueryActionString()).append(" "); 98 | 99 | appendSilent(query); 100 | 101 | if(fromDefault) { 102 | query.append(DEFAULT); 103 | } else { 104 | query.append(from.map(Iri::getQueryString).orElse(DEFAULT)); 105 | } 106 | 107 | query.append(" ").append(TO).append(" "); 108 | 109 | if(toDefault) { 110 | query.append(DEFAULT); 111 | } else { 112 | query.append(to.map(Iri::getQueryString).orElse(DEFAULT)); 113 | } 114 | 115 | return query.toString(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Projection.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * A SPARQL Projection 7 | * 8 | * @see 10 | * SPARQL Projections 11 | */ 12 | public class Projection extends QueryElementCollection { 13 | private static final String SELECT = "SELECT"; 14 | private static final String DISTINCT = "DISTINCT"; 15 | private static final String DELIMETER = " "; 16 | 17 | private boolean isDistinct, selectAll; 18 | 19 | Projection() { 20 | this(false); 21 | } 22 | 23 | Projection(boolean isDistinct) { 24 | super(DELIMETER, new ArrayList()); 25 | all(false); 26 | distinct(isDistinct); 27 | } 28 | 29 | /** 30 | * Specify this projection to be distinct 31 | * 32 | * @return this 33 | * 34 | * @see 36 | * SPARQL Distinct modifier 37 | */ 38 | public Projection distinct() { 39 | return distinct(true); 40 | } 41 | 42 | /** 43 | * Specify if this projection should be distinct or not 44 | * 45 | * @param isDistinct 46 | * if this projection should be distinct 47 | * @return this 48 | * 49 | * @see 51 | * SPARQL Distinct modifier 52 | */ 53 | public Projection distinct(boolean isDistinct) { 54 | this.isDistinct = isDistinct; 55 | 56 | return this; 57 | } 58 | 59 | /** 60 | * Specify that this projection should select all in-scope expressions 61 | * 62 | * @return this 63 | * 64 | * @see 66 | * SPARQL Select 67 | */ 68 | public Projection all() { 69 | return all(true); 70 | } 71 | 72 | /** 73 | * Specify if this projection should select all in-scope expressions or not 74 | * 75 | * @param selectAll 76 | * if this projection should select all expressions 77 | * @return this 78 | * 79 | * @see 81 | * SPARQL Select 82 | */ 83 | public Projection all(boolean selectAll) { 84 | this.selectAll = selectAll; 85 | 86 | return this; 87 | } 88 | 89 | /** 90 | * Add expressions for this projection to select 91 | * 92 | * @param projectables 93 | * the projectable expressions to add 94 | * @return this 95 | */ 96 | public Projection select(Projectable... projectables) { 97 | for (Projectable variable : projectables) { 98 | elements.add(variable); 99 | } 100 | 101 | return this; 102 | } 103 | 104 | @Override 105 | public String getQueryString() { 106 | StringBuilder selectStatement = new StringBuilder(); 107 | selectStatement.append(SELECT).append(DELIMETER); 108 | 109 | if (isDistinct) { 110 | selectStatement.append(DISTINCT).append(DELIMETER); 111 | } 112 | 113 | if (selectAll || isEmpty()) { 114 | selectStatement.append("*").append(DELIMETER); 115 | } else { 116 | selectStatement.append(super.getQueryString()); 117 | } 118 | 119 | return selectStatement.toString(); 120 | } 121 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfLiteral.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.core.SpanqitUtils; 6 | 7 | import static com.anqit.spanqit.core.SpanqitUtils.appendQueryElementIfPresent; 8 | import static com.anqit.spanqit.core.SpanqitUtils.appendStringIfPresent; 9 | 10 | /** 11 | * Denotes an RDF literal 12 | * 13 | * @param the datatype of the literal 14 | * 15 | * @see 17 | * RDF Literals 18 | * @see 20 | * RDF Literal Syntax 21 | */ 22 | public abstract class RdfLiteral implements RdfValue { 23 | protected T value; 24 | 25 | private RdfLiteral(T value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public String getQueryString() { 31 | return String.valueOf(value); 32 | } 33 | 34 | @Override 35 | public boolean equals(Object obj) { 36 | if(obj == null) { 37 | return false; 38 | } 39 | 40 | if(!(obj instanceof RdfLiteral)) { 41 | return false; 42 | } 43 | 44 | RdfLiteral other = (RdfLiteral) obj; 45 | if(value == null) { 46 | return other.value == null; 47 | } else { 48 | return value.equals(other.value); 49 | } 50 | } 51 | 52 | @Override 53 | public int hashCode() { 54 | final int prime = 31; 55 | int result = 1; 56 | result = prime * result + ((value == null) ? 0 : value.hashCode()); 57 | 58 | return result; 59 | } 60 | 61 | /** 62 | * Represents an RDF string literal 63 | */ 64 | public static class StringLiteral extends RdfLiteral { 65 | private static final String DATATYPE_SPECIFIER = "^^"; 66 | private static final String LANG_TAG_SPECIFIER = "@"; 67 | 68 | private Optional dataType = Optional.empty(); 69 | private Optional languageTag = Optional.empty(); 70 | 71 | StringLiteral(String stringValue) { 72 | super(stringValue); 73 | } 74 | 75 | StringLiteral(String stringValue, Iri dataType) { 76 | super(stringValue); 77 | this.dataType = Optional.ofNullable(dataType); 78 | } 79 | 80 | StringLiteral(String stringValue, String languageTag) { 81 | super(stringValue); 82 | this.languageTag = Optional.ofNullable(languageTag); 83 | } 84 | 85 | @Override 86 | public String getQueryString() { 87 | StringBuilder literal = new StringBuilder(); 88 | 89 | if(value.contains("'") || value.contains("\"")) { 90 | literal.append(SpanqitUtils.getLongQuotedString(value)); 91 | } else { 92 | literal.append(SpanqitUtils.getQuotedString(value)); 93 | } 94 | 95 | appendQueryElementIfPresent(dataType, literal, DATATYPE_SPECIFIER, null); 96 | appendStringIfPresent(languageTag, literal, LANG_TAG_SPECIFIER, null); 97 | 98 | return literal.toString(); 99 | } 100 | } 101 | 102 | /** 103 | * Represents an RDF number literal 104 | */ 105 | public static class NumericLiteral extends RdfLiteral { 106 | NumericLiteral(Number numbervalue) { 107 | super(numbervalue); 108 | } 109 | } 110 | 111 | /** 112 | * Represents an RDF boolean literal 113 | */ 114 | public static class BooleanLiteral extends RdfLiteral { 115 | BooleanLiteral(Boolean boolValue) { 116 | super(boolValue); 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/TriplePattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import static com.anqit.spanqit.rdf.Rdf.toRdfLiteralArray; 4 | 5 | import com.anqit.spanqit.rdf.Rdf; 6 | import com.anqit.spanqit.rdf.RdfObject; 7 | import com.anqit.spanqit.rdf.RdfPredicate; 8 | import com.anqit.spanqit.rdf.RdfPredicateObjectList; 9 | 10 | /** 11 | * Denotes a SPARQL Triple Pattern 12 | * 13 | * @see 15 | * Triple pattern syntax 16 | * @see 17 | * blank node syntax 18 | */ 19 | public interface TriplePattern extends GraphPattern { 20 | @SuppressWarnings("javadoc") 21 | static String SUFFIX = " ."; 22 | 23 | /** 24 | * Add predicate-object lists describing this triple pattern's subject 25 | * 26 | * @param predicate the predicate to use to describe this triple pattern's subject 27 | * @param objects the corresponding object(s) 28 | * 29 | * @return this triple pattern 30 | */ 31 | default public TriplePattern andHas(RdfPredicate predicate, RdfObject... objects) { 32 | return andHas(Rdf.predicateObjectList(predicate, objects)); 33 | } 34 | 35 | /** 36 | * Add predicate-object lists describing this triple pattern's subject 37 | * 38 | * @param lists 39 | * the {@link RdfPredicateObjectList}(s) to add 40 | * 41 | * @return this triple pattern 42 | */ 43 | public TriplePattern andHas(RdfPredicateObjectList... lists); 44 | 45 | /** 46 | * Convenience version of {@link #andHas(RdfPredicate, RdfObject...)} that takes Strings 47 | * and converts them to StringLiterals 48 | * 49 | * @param predicate the predicate to use to describe this triple pattern's subject 50 | * @param objects the corresponding object(s) 51 | * 52 | * @return this triple pattern 53 | */ 54 | default TriplePattern andHas(RdfPredicate predicate, String... objects) { 55 | return andHas(predicate, toRdfLiteralArray(objects)); 56 | }; 57 | 58 | /** 59 | * Convenience version of {@link #andHas(RdfPredicate, RdfObject...)} that takes Boolean 60 | * and converts them to BooleanLiterals 61 | * 62 | * @param predicate the predicate to use to describe this triple pattern's subject 63 | * @param objects the corresponding object(s) 64 | * 65 | * @return this triple pattern 66 | */ 67 | default TriplePattern andHas(RdfPredicate predicate, Boolean... objects) { 68 | return andHas(predicate, toRdfLiteralArray(objects)); 69 | }; 70 | 71 | /** 72 | * Convenience version of {@link #andHas(RdfPredicate, RdfObject...)} that takes Numbers 73 | * and converts them to NumberLiterals 74 | * 75 | * @param predicate the predicate to use to describe this triple pattern's subject 76 | * @param objects the corresponding object(s) 77 | * 78 | * @return this triple pattern 79 | */ 80 | default TriplePattern andHas(RdfPredicate predicate, Number... objects) { 81 | return andHas(predicate, toRdfLiteralArray(objects)); 82 | }; 83 | 84 | /** 85 | * Use the built-in RDF shortcut {@code a} for {@code rdf:type} to specify the subject's type 86 | * 87 | * @param object the object describing this triple pattern's subject's {@code rdf:type} 88 | * 89 | * @return this triple pattern 90 | * 91 | * @see 92 | * RDF Type abbreviation 93 | */ 94 | default TriplePattern andIsA(RdfObject object) { 95 | return andHas(RdfPredicate.a, object); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/GroupGraphPattern.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.constraint.Expression; 6 | import com.anqit.spanqit.core.QueryElementCollection; 7 | import com.anqit.spanqit.core.SpanqitUtils; 8 | 9 | import static com.anqit.spanqit.core.SpanqitUtils.appendQueryElementIfPresent; 10 | 11 | /** 12 | * A SPARQL Group Graph Pattern 13 | * 14 | * @see 16 | * SPARQL Group Graph Patterns 17 | */ 18 | class GroupGraphPattern extends QueryElementCollection implements 19 | GraphPattern { 20 | private static final String OPTIONAL = "OPTIONAL"; 21 | // private static final String DELIMITER = " . "; 22 | private static final String GRAPH = "GRAPH "; 23 | 24 | private Optional from = Optional.empty(); 25 | private Optional filter = Optional.empty(); 26 | protected boolean isOptional = false; 27 | 28 | GroupGraphPattern() { 29 | this(false); 30 | } 31 | 32 | GroupGraphPattern(boolean isOptional) { 33 | // super(DELIMITER); 34 | this.isOptional = isOptional; 35 | } 36 | 37 | GroupGraphPattern(GraphPattern original) { 38 | // super(DELIMITER); 39 | 40 | if (original instanceof GroupGraphPattern) { 41 | copy((GroupGraphPattern) original); 42 | } else if (original != null && !original.isEmpty()) { 43 | elements.add(original); 44 | } 45 | } 46 | 47 | protected void copy(GroupGraphPattern original) { 48 | this.elements = original.elements; 49 | this.isOptional = original.isOptional; 50 | this.from = original.from; 51 | this.filter = original.filter; 52 | } 53 | 54 | GroupGraphPattern and(GraphPattern... patterns) { 55 | for (GraphPattern pattern : patterns) { 56 | elements.add(pattern); 57 | } 58 | 59 | return this; 60 | } 61 | 62 | GroupGraphPattern optional(boolean isOptional) { 63 | this.isOptional = isOptional; 64 | 65 | return this; 66 | } 67 | 68 | GroupGraphPattern from(GraphName name) { 69 | from = Optional.of(name); 70 | 71 | return this; 72 | } 73 | 74 | GroupGraphPattern filter(Expression constraint) { 75 | if (!filter.isPresent()) { 76 | filter = Optional.of(new Filter()); 77 | } 78 | filter.get().filter(constraint); 79 | 80 | return this; 81 | } 82 | 83 | @Override 84 | public boolean isEmpty() { 85 | return super.isEmpty(); 86 | } 87 | 88 | @Override 89 | public String getQueryString() { 90 | StringBuilder pattern = new StringBuilder(); 91 | StringBuilder innerPattern = new StringBuilder(); 92 | 93 | // Prevent extra brackets being added in the case of this graph pattern 94 | // containing only one group graph pattern. Resulting syntax is 95 | // logically equivalent and easier to read (and hopefully parse by query 96 | // parsers) 97 | boolean bracketize = !(elements.size() == 1 && elements.toArray()[0] instanceof GroupGraphPattern); 98 | 99 | if (isOptional) { 100 | pattern.append(OPTIONAL).append(" "); 101 | } 102 | 103 | appendQueryElementIfPresent(from, pattern, GRAPH, " "); 104 | 105 | innerPattern.append(super.getQueryString()); 106 | 107 | appendQueryElementIfPresent(filter, innerPattern, "\n", null); 108 | 109 | if (bracketize) { 110 | pattern.append(SpanqitUtils.getBracedString(innerPattern 111 | .toString())); 112 | } else { 113 | pattern.append(innerPattern.toString()); 114 | } 115 | 116 | return pattern.toString(); 117 | } 118 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/SelectQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.core.Projectable; 4 | import com.anqit.spanqit.core.Projection; 5 | import com.anqit.spanqit.core.Spanqit; 6 | 7 | /** 8 | * A SPARQL Select query 9 | * 10 | * @see 11 | * SPARQL Select Query 12 | */ 13 | public class SelectQuery extends OuterQuery { 14 | private Projection select = Spanqit.select(); 15 | 16 | // package-protect instantiation of this class 17 | SelectQuery() { } 18 | 19 | /** 20 | * Specify the query's projection to be distinct 21 | * 22 | * @return this 23 | * 24 | * @see com.anqit.spanqit.core.Projection#distinct() 25 | */ 26 | public SelectQuery distinct() { 27 | return distinct(true); 28 | } 29 | 30 | /** 31 | * Specify if the query's projection should be distinct or not 32 | * 33 | * @param isDistinct 34 | * if this query's projection should be distinct 35 | * @return this 36 | * 37 | * @see com.anqit.spanqit.core.Projection#distinct(boolean) 38 | */ 39 | public SelectQuery distinct(boolean isDistinct) { 40 | select.distinct(isDistinct); 41 | 42 | return this; 43 | } 44 | 45 | /** 46 | * Specify that this query's projection should select all in-scope 47 | * expressions 48 | *

49 | * NOTE: setting this takes precedence over any expressions added to the 50 | * projection via {@link #select(Projectable...)} or {@link #select(Projection)} when printing 51 | * 52 | * @return this 53 | * 54 | * @see Projection#all() 55 | */ 56 | public SelectQuery all() { 57 | return all(true); 58 | } 59 | 60 | /** 61 | * Specify if this query's projection should select all in-scope expressions 62 | * or not. 63 | *

64 | * NOTE: if called with true, this setting will take precedence 65 | * over any expressions added to the projection via 66 | * {@link #select(Projectable...)} or {@link #select(Projection)} when 67 | * converting to string via {@link #getQueryString()} 68 | * 69 | * @param selectAll 70 | * if all in-scope expressions should be selected 71 | * @return this 72 | * 73 | * @see Projection#all(boolean) 74 | */ 75 | public SelectQuery all(boolean selectAll) { 76 | select.all(selectAll); 77 | 78 | return this; 79 | } 80 | 81 | /** 82 | * Add expressions to the query's projection 83 | *

84 | * NOTE: if SELECT * has been specified (by {@link #all()} or calling 85 | * {@link #all(boolean)} with true), that will take precedence 86 | * over specified expressions when converting to string via {@link #getQueryString()} 87 | * 88 | * @param projectables 89 | * expressions to add 90 | * @return this 91 | * 92 | * @see Projection#select(Projectable...) 93 | */ 94 | public SelectQuery select(Projectable... projectables) { 95 | select.select(projectables); 96 | 97 | return this; 98 | } 99 | 100 | /** 101 | * Set this query's projection 102 | *

103 | * NOTE: if SELECT * has been specified (by {@link #all()} or calling 104 | * {@link #all(boolean)} with true), that will take precedence 105 | * over specified expressions when converting to string via 106 | * {@link #getQueryString()} 107 | * 108 | * @param select 109 | * the {@link Projection} to set 110 | * @return this 111 | */ 112 | public SelectQuery select(Projection select) { 113 | this.select = select; 114 | 115 | return this; 116 | } 117 | 118 | @Override 119 | protected String getQueryActionString() { 120 | return select.getQueryString(); 121 | } 122 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfBlankNode.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import com.anqit.spanqit.core.SpanqitUtils; 4 | import com.anqit.spanqit.graphpattern.GraphPatterns; 5 | import com.anqit.spanqit.graphpattern.TriplePattern; 6 | 7 | /** 8 | * Denotes an RDF Blank Node 9 | */ 10 | public interface RdfBlankNode extends RdfResource { 11 | /** 12 | * a labeled blank node, of the form "_:label" 13 | */ 14 | public static class LabeledBlankNode implements RdfBlankNode { 15 | private String label; 16 | 17 | LabeledBlankNode(String label) { 18 | this.label = label; 19 | } 20 | 21 | @Override 22 | public String getQueryString() { 23 | return "_:" + label; 24 | } 25 | } 26 | 27 | /** 28 | * an anonymous blank node 29 | * @see 30 | * Blank node syntax 31 | */ 32 | public static class AnonymousBlankNode implements RdfBlankNode { 33 | @Override 34 | public String getQueryString() { 35 | return SpanqitUtils.getBracketedString(" "); 36 | } 37 | } 38 | 39 | /** 40 | * A blank node representing a resource that matches the contained set of predicate-object lists 41 | * 42 | * @see 43 | * Blank node syntax 44 | */ 45 | public static class PropertiesBlankNode implements RdfBlankNode { 46 | private RdfPredicateObjectListCollection predicateObjectLists = Rdf.predicateObjectListCollection(); 47 | 48 | PropertiesBlankNode(RdfPredicate predicate, RdfObject... objects) { 49 | andHas(predicate, objects); 50 | } 51 | 52 | /** 53 | * Using the predicate-object and object list mechanisms, expand this blank node's pattern to include 54 | * triples consisting of this blank node as the subject, and the given predicate and object(s) 55 | * 56 | * @param predicate the predicate of the triple to add 57 | * @param objects the object or objects of the triple to add 58 | * 59 | * @return this blank node 60 | * 61 | * @see 62 | * Predicate-Object Lists 63 | * @see 64 | * Object Lists 65 | */ 66 | public PropertiesBlankNode andHas(RdfPredicate predicate, RdfObject... objects) { 67 | predicateObjectLists.andHas(predicate, objects); 68 | 69 | return this; 70 | } 71 | 72 | /** 73 | * Add predicate-object lists to this blank node's pattern 74 | * 75 | * @param lists 76 | * the {@link RdfPredicateObjectList}(s) to add 77 | * @return this blank node 78 | * 79 | * @see 80 | * Predicate-Object Lists 81 | * @see 82 | * Object Lists 83 | */ 84 | public PropertiesBlankNode andHas(RdfPredicateObjectList... lists) { 85 | predicateObjectLists.andHas(lists); 86 | 87 | return this; 88 | } 89 | /** 90 | * convert this blank node to a triple pattern 91 | * 92 | * @return the triple pattern identified by this blank node 93 | * 94 | * @see 95 | * blank node syntax 96 | */ 97 | public TriplePattern toTp() { 98 | return GraphPatterns.tp(this); 99 | } 100 | 101 | @Override 102 | public String getQueryString() { 103 | return SpanqitUtils.getBracketedString(predicateObjectLists.getQueryString()); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/RdfSubject.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import static com.anqit.spanqit.rdf.Rdf.toRdfLiteralArray; 4 | 5 | import com.anqit.spanqit.core.QueryElement; 6 | import com.anqit.spanqit.graphpattern.GraphPatterns; 7 | import com.anqit.spanqit.graphpattern.TriplePattern; 8 | 9 | /** 10 | * Denotes an element that can represent a subject in a 11 | * {@link com.anqit.spanqit.graphpattern.TriplePattern} 12 | */ 13 | public interface RdfSubject extends QueryElement { 14 | /** 15 | * Create a triple pattern from this subject and the given predicate and 16 | * object 17 | * 18 | * @param predicate 19 | * the predicate of the triple pattern 20 | * @param objects 21 | * the object(s) of the triple pattern 22 | * @return a new {@link TriplePattern} with this subject, and the given predicate and object(s) 23 | * 24 | * @see 26 | * Triple pattern syntax 27 | */ 28 | default public TriplePattern has(RdfPredicate predicate, RdfObject... objects) { 29 | return GraphPatterns.tp(this, predicate, objects); 30 | } 31 | 32 | /** 33 | * Create a triple pattern from this subject and the given predicate-object list(s) 34 | * @param lists 35 | * the {@link RdfPredicateObjectList}(s) to describing this subject 36 | * @return a new {@link TriplePattern} with this subject, and the given predicate-object list(s) 37 | */ 38 | default public TriplePattern has(RdfPredicateObjectList... lists) { 39 | return GraphPatterns.tp(this, lists); 40 | } 41 | 42 | /** 43 | * Wrapper for {@link #has(RdfPredicate, RdfObject...)} that converts String objects into RdfLiteral instances 44 | * 45 | * @param predicate 46 | * the predicate of the triple pattern 47 | * @param objects 48 | * the String object(s) of the triple pattern 49 | * @return a new {@link TriplePattern} with this subject, and the given predicate and object(s) 50 | */ 51 | default public TriplePattern has(RdfPredicate predicate, String... objects) { 52 | return GraphPatterns.tp(this, predicate, toRdfLiteralArray(objects)); 53 | } 54 | 55 | /** 56 | * Wrapper for {@link #has(RdfPredicate, RdfObject...)} that converts Number objects into RdfLiteral instances 57 | * 58 | * @param predicate 59 | * the predicate of the triple pattern 60 | * @param objects 61 | * the Number object(s) of the triple pattern 62 | * @return a new {@link TriplePattern} with this subject, and the given predicate and object(s) 63 | */ 64 | default public TriplePattern has(RdfPredicate predicate, Number... objects) { 65 | return GraphPatterns.tp(this, predicate, toRdfLiteralArray(objects)); 66 | } 67 | 68 | /** 69 | * Wrapper for {@link #has(RdfPredicate, RdfObject...)} that converts Boolean objects into RdfLiteral instances 70 | * 71 | * @param predicate 72 | * the predicate of the triple pattern 73 | * @param objects 74 | * the Boolean object(s) of the triple pattern 75 | * @return a new {@link TriplePattern} with this subject, and the given predicate and object(s) 76 | */ 77 | default public TriplePattern has(RdfPredicate predicate, Boolean... objects) { 78 | return GraphPatterns.tp(this, predicate, toRdfLiteralArray(objects)); 79 | } 80 | 81 | /** 82 | * Use the built-in shortcut "a" for rdf:type to build a triple with this subject and the given objects 83 | * @param objects the objects to use to describe the rdf:type of this subject 84 | * 85 | * @return a {@link TriplePattern} object with this subject, the "a" shortcut predicate, and the given objects 86 | * 87 | * @see 88 | * RDF Type abbreviation 89 | */ 90 | default public TriplePattern isA(RdfObject... objects) { 91 | return has(RdfPredicate.a, objects); 92 | } 93 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/SubSelect.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.core.Projectable; 4 | import com.anqit.spanqit.core.Projection; 5 | import com.anqit.spanqit.core.Spanqit; 6 | import com.anqit.spanqit.core.SpanqitUtils; 7 | import com.anqit.spanqit.core.query.Query; 8 | 9 | /** 10 | * A SPARQL subquery 11 | * 12 | * @see 14 | * SPARQL Subquery 15 | */ 16 | public class SubSelect extends Query implements GraphPattern { 17 | private Projection select = Spanqit.select(); 18 | 19 | /* 20 | * If someone has any ideas how I can eliminate the need for repeating the 21 | * following methods from SelectQuery without inheriting the methods that 22 | * don't apply to SubSelect (prologue and dataset stuff), that would be 23 | * awesome. 24 | */ 25 | 26 | /** 27 | * Specify the query's projection to be distinct 28 | * 29 | * @return this 30 | * 31 | * @see com.anqit.spanqit.core.Projection#distinct() 32 | */ 33 | public SubSelect distinct() { 34 | return distinct(true); 35 | } 36 | 37 | /** 38 | * Specify if the query's projection should be distinct or not 39 | * 40 | * @param isDistinct 41 | * if this query's projection should be distinct 42 | * @return this 43 | * 44 | * @see com.anqit.spanqit.core.Projection#distinct(boolean) 45 | */ 46 | public SubSelect distinct(boolean isDistinct) { 47 | select.distinct(isDistinct); 48 | 49 | return this; 50 | } 51 | 52 | /** 53 | * Specify that this query's projection should select all in-scope 54 | * expressions 55 | *

56 | * NOTE: setting this takes precedence over any expressions added to the 57 | * projection via {@link #select(Projectable...)} when printing 58 | * 59 | * @return this 60 | * 61 | * @see Projection#all() 62 | */ 63 | public SubSelect all() { 64 | return all(true); 65 | } 66 | 67 | /** 68 | * Specify if this query's projection should select all in-scope expressions 69 | * or not. 70 | *

71 | * NOTE: if called with true, this setting will take precedence 72 | * over any expressions added to the projection via 73 | * {@link #select(Projectable...)} when printing 74 | * 75 | * @param selectAll 76 | * if all in-scope expressions should be selected 77 | * @return this 78 | * 79 | * @see Projection#all(boolean) 80 | */ 81 | public SubSelect all(boolean selectAll) { 82 | select.all(selectAll); 83 | 84 | return this; 85 | } 86 | 87 | /** 88 | * Add expressions to the query's projection 89 | *

90 | * NOTE: if SELECT * has been specified (by {@link #all()} or calling 91 | * {@link #all(boolean)} with true), that will take precedence 92 | * over specified expressions when converting to string via 93 | * {@link #getQueryString()} 94 | * 95 | * @param projectables 96 | * expressions to add 97 | * @return this 98 | * 99 | * @see Projection#select(Projectable...) 100 | */ 101 | public SubSelect select(Projectable... projectables) { 102 | select.select(projectables); 103 | 104 | return this; 105 | } 106 | 107 | /** 108 | * Set this query's projection 109 | * 110 | * @param select 111 | * the {@link Projection} to set 112 | * @return this 113 | */ 114 | public SubSelect select(Projection select) { 115 | this.select = select; 116 | 117 | return this; 118 | } 119 | 120 | @Override 121 | public boolean isEmpty() { 122 | return false; 123 | } 124 | 125 | // TODO: Values 126 | 127 | @Override 128 | protected String getQueryActionString() { 129 | return select.getQueryString(); 130 | } 131 | 132 | @Override 133 | public String getQueryString() { 134 | StringBuilder subSelect = new StringBuilder(); 135 | 136 | subSelect.append(super.getQueryString()); 137 | 138 | // TODO: VALUES 139 | // subselect.append(values.getQueryString()); 140 | 141 | return SpanqitUtils.getBracedString(subSelect.toString()); 142 | } 143 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/GraphPatterns.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import com.anqit.spanqit.core.Projectable; 4 | import com.anqit.spanqit.rdf.RdfBlankNode.PropertiesBlankNode; 5 | import com.anqit.spanqit.rdf.RdfObject; 6 | import com.anqit.spanqit.rdf.RdfPredicate; 7 | import com.anqit.spanqit.rdf.RdfPredicateObjectList; 8 | import com.anqit.spanqit.rdf.RdfSubject; 9 | 10 | /** 11 | * A class with static methods to create graph patterns. 12 | * 13 | * @see SPARQL 15 | * Graph Pattern 16 | */ 17 | public class GraphPatterns { 18 | // prevent instantiation of this class 19 | private GraphPatterns() { } 20 | 21 | /** 22 | * Create a triple pattern with the given subject, predicate, and object(s) 23 | * 24 | * @param subject 25 | * @param predicate 26 | * @param objects 27 | * 28 | * @return a new {@link TriplePattern} 29 | * 30 | * @see 32 | * Triple pattern syntax 33 | */ 34 | public static TriplePattern tp(RdfSubject subject, RdfPredicate predicate, RdfObject... objects) { 35 | return new TriplesSameSubject(subject, predicate, objects); 36 | } 37 | 38 | /** 39 | * Create a triple pattern with the given subject and predicate-object list(s) 40 | * 41 | * @param subject 42 | * @param lists 43 | * 44 | * @return a new {@link TriplePattern} 45 | * 46 | * @see 48 | * Triple pattern syntax 49 | */ 50 | public static TriplePattern tp(RdfSubject subject, RdfPredicateObjectList... lists) { 51 | return new TriplesSameSubject(subject, lists); 52 | } 53 | /** 54 | * Create a triple pattern from a property-list blank node 55 | * @param bnode the PropertiesBlankNode instance to convert to a triple pattern 56 | * 57 | * @return the triple pattern represented by the expansion of this blank node 58 | * 59 | * @see 60 | * blank node syntax 61 | */ 62 | public static TriplePattern tp(PropertiesBlankNode bnode) { 63 | return new BNodeTriplePattern(bnode); 64 | } 65 | 66 | /** 67 | * Create a group graph pattern containing the given graph patterns 68 | * 69 | * @param patterns 70 | * the patterns to include in the group graph a pattern 71 | * @return a new group graph pattern 72 | * 73 | * @see SPARQL 75 | * Group Graph Pattern 76 | */ 77 | public static GraphPatternNotTriple and(GraphPattern... patterns) { 78 | return new GraphPatternNotTriple().and(patterns); 79 | } 80 | 81 | /** 82 | * Create an alternative graph pattern containing the union of the given 83 | * graph patterns:
84 | * 85 | *

 86 | 	 * { { pattern1 } UNION { pattern2 } UNION ... UNION { patternN } }
 87 | 	 * 
88 | * 89 | * @param patterns 90 | * the patterns to include in the union 91 | * @return a new alternative graph pattern 92 | * 93 | * @see 95 | * SPARQL Alternative Graph Patterns 96 | */ 97 | public static GraphPatternNotTriple union(GraphPattern... patterns) { 98 | return new GraphPatternNotTriple().union(patterns); 99 | } 100 | 101 | /** 102 | * Create an optional group graph pattern containing the given graph 103 | * patterns:
104 | * 105 | *
106 | 	 * {
107 | 	 *   OPTIONAL {
108 | 	 *     pattern1 .
109 | 	 *     pattern2 .
110 | 	 *     ... .
111 | 	 *     patternN
112 | 	 *   }
113 | 	 * }
114 | 	 * 
115 | * 116 | * @param patterns 117 | * the patterns to include in the optional graph pattern 118 | * @return a new optional graph pattern 119 | * 120 | * @see 122 | * SPARQL Optional Graph Patterns 123 | */ 124 | public static GraphPatternNotTriple optional(GraphPattern... patterns) { 125 | return and(patterns).optional(); 126 | } 127 | 128 | /** 129 | * Create a SPARQL subquery, including the given elements in its projection. 130 | * 131 | * @param projectables 132 | * the elements to include in the projection of the subquery 133 | * @return a new subquery 134 | * 135 | * @see 137 | * SPARQL Subquery 138 | */ 139 | public static SubSelect select(Projectable... projectables) { 140 | return new SubSelect().select(projectables); 141 | } 142 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/ModifyQuery.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import java.util.Optional; 4 | 5 | import com.anqit.spanqit.core.QueryPattern; 6 | import com.anqit.spanqit.core.Spanqit; 7 | import com.anqit.spanqit.core.TriplesTemplate; 8 | import com.anqit.spanqit.graphpattern.GraphName; 9 | import com.anqit.spanqit.graphpattern.GraphPattern; 10 | import com.anqit.spanqit.graphpattern.TriplePattern; 11 | import com.anqit.spanqit.rdf.Iri; 12 | 13 | import static com.anqit.spanqit.core.SpanqitUtils.getOrCreateAndModifyOptional; 14 | 15 | /** 16 | * The SPARQL Modify Queries 17 | * 18 | * @see 19 | * SPARQL DELETE/INSERT Query 20 | */ 21 | public class ModifyQuery extends UpdateQuery { 22 | private static final String INSERT = "INSERT"; 23 | private static final String DELETE = "DELETE"; 24 | private static final String WITH = "WITH"; 25 | private static final String USING = "USING"; 26 | private static final String NAMED = "NAMED"; 27 | 28 | private Optional with = Optional.empty(); 29 | private Optional using = Optional.empty(); 30 | private boolean usingNamed = false; 31 | 32 | private Optional deleteTriples = Optional.empty(); 33 | private Optional insertTriples = Optional.empty(); 34 | private Optional deleteGraph = Optional.empty(); 35 | private Optional insertGraph = Optional.empty(); 36 | 37 | private QueryPattern where = Spanqit.where(); 38 | 39 | ModifyQuery() { } 40 | 41 | /** 42 | * Define the graph that will be modified or matched against in the absence of more explicit graph definitions 43 | * 44 | * @param iri the IRI identifying the desired graph 45 | * 46 | * @return this modify query instance 47 | */ 48 | public ModifyQuery with(Iri iri) { 49 | with = Optional.ofNullable(iri); 50 | 51 | return this; 52 | } 53 | 54 | /** 55 | * Specify triples to delete (or leave empty for DELETE WHERE shortcut) 56 | * 57 | * @param triples the triples to delete 58 | * 59 | * @return this modify query instance 60 | * 61 | * @see 62 | * SPARQL DELETE WHERE shortcut 63 | */ 64 | public ModifyQuery delete(TriplePattern... triples) { 65 | deleteTriples = getOrCreateAndModifyOptional(deleteTriples, Spanqit::triplesTemplate, tt -> tt.and(triples)); 66 | 67 | return this; 68 | } 69 | 70 | /** 71 | * Specify the graph to delete triples from 72 | * 73 | * @param graphName the identifier of the graph 74 | * 75 | * @return this modify query instance 76 | */ 77 | public ModifyQuery from(GraphName graphName) { 78 | this.deleteGraph = Optional.ofNullable(graphName); 79 | 80 | return this; 81 | } 82 | 83 | /** 84 | * Specify triples to insert 85 | * 86 | * @param triples the triples to insert 87 | * 88 | * @return this modify query instance 89 | */ 90 | public ModifyQuery insert(TriplePattern... triples) { 91 | insertTriples = getOrCreateAndModifyOptional(insertTriples, Spanqit::triplesTemplate, tt -> tt.and(triples)); 92 | 93 | return this; 94 | } 95 | 96 | /** 97 | * Specify the graph to insert triples into 98 | * 99 | * @param graphName the identifier of the graph 100 | * 101 | * @return this modify query instance 102 | */ 103 | public ModifyQuery into(GraphName graphName) { 104 | insertGraph = Optional.ofNullable(graphName); 105 | 106 | return this; 107 | } 108 | 109 | /** 110 | * Specify the graph used when evaluating the WHERE clause 111 | * 112 | * @param iri the IRI identifying the desired graph 113 | * 114 | * @return this modify query instance 115 | */ 116 | public ModifyQuery using(Iri iri) { 117 | using = Optional.ofNullable(iri); 118 | 119 | return this; 120 | } 121 | 122 | /** 123 | * Specify a named graph to use to when evaluating the WHERE clause 124 | * 125 | * @param iri the IRI identifying the desired graph 126 | * 127 | * @return this modify query instance 128 | */ 129 | public ModifyQuery usingNamed(Iri iri) { 130 | usingNamed = true; 131 | 132 | return using(iri); 133 | } 134 | 135 | /** 136 | * Add graph patterns to this query's query pattern 137 | * 138 | * @param patterns the patterns to add 139 | * 140 | * @return this modify query instance 141 | */ 142 | public ModifyQuery where(GraphPattern... patterns) { 143 | where.where(patterns); 144 | 145 | return this; 146 | } 147 | 148 | @Override 149 | protected String getQueryActionString() { 150 | StringBuilder modifyQuery = new StringBuilder(); 151 | 152 | with.ifPresent(withIri -> modifyQuery.append(WITH).append(" ").append(withIri.getQueryString()).append("\n")); 153 | 154 | deleteTriples.ifPresent(delTriples -> { 155 | modifyQuery.append(DELETE).append(" "); 156 | 157 | // DELETE WHERE shortcut 158 | // https://www.w3.org/TR/sparql11-update/#deleteWhere 159 | if(!delTriples.isEmpty()) { 160 | appendNamedTriplesTemplates(modifyQuery, deleteGraph, delTriples); 161 | } 162 | modifyQuery.append("\n"); 163 | }); 164 | 165 | insertTriples.ifPresent(insTriples -> { 166 | modifyQuery.append(INSERT).append(" "); 167 | appendNamedTriplesTemplates(modifyQuery, insertGraph, insTriples); 168 | modifyQuery.append("\n"); 169 | }); 170 | 171 | using.ifPresent(usingIri -> { 172 | modifyQuery.append(USING).append(" "); 173 | 174 | if(usingNamed) { 175 | modifyQuery.append(NAMED).append(" "); 176 | } 177 | 178 | modifyQuery.append(usingIri.getQueryString()); 179 | modifyQuery.append("\n"); 180 | }); 181 | 182 | modifyQuery.append(where.getQueryString()); 183 | 184 | return modifyQuery.toString(); 185 | } 186 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/Query.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import static com.anqit.spanqit.core.SpanqitUtils.appendAndNewlineIfPresent; 4 | import static com.anqit.spanqit.core.SpanqitUtils.getOrCreateAndModifyOptional; 5 | 6 | import java.util.Optional; 7 | 8 | import com.anqit.spanqit.constraint.Expression; 9 | import com.anqit.spanqit.core.GroupBy; 10 | import com.anqit.spanqit.core.Groupable; 11 | import com.anqit.spanqit.core.Having; 12 | import com.anqit.spanqit.core.OrderBy; 13 | import com.anqit.spanqit.core.Orderable; 14 | import com.anqit.spanqit.core.QueryElement; 15 | import com.anqit.spanqit.core.QueryPattern; 16 | import com.anqit.spanqit.core.Spanqit; 17 | import com.anqit.spanqit.core.Variable; 18 | import com.anqit.spanqit.graphpattern.GraphPattern; 19 | 20 | /** 21 | * The base class for all SPARQL Queries. Contains elements and methods common 22 | * to all queries. 23 | * 24 | * @param 25 | * They type of query. Used to support fluency. 26 | */ 27 | @SuppressWarnings("unchecked") 28 | public abstract class Query> implements QueryElement { 29 | protected static final String LIMIT = "LIMIT"; 30 | protected static final String OFFSET = "OFFSET"; 31 | 32 | protected QueryPattern where = Spanqit.where(); 33 | protected Optional groupBy = Optional.empty(); 34 | protected Optional orderBy = Optional.empty(); 35 | protected Optional having = Optional.empty(); 36 | protected int limit = -1, offset = -1, varCount = -1; 37 | 38 | /** 39 | * Add graph patterns to this query's query pattern 40 | * 41 | * @param queryPatterns 42 | * the patterns to add 43 | * @return this 44 | * 45 | * @see QueryPattern 46 | */ 47 | public T where(GraphPattern... queryPatterns) { 48 | where.where(queryPatterns); 49 | 50 | return (T) this; 51 | } 52 | 53 | /** 54 | * Set the query pattern of this query 55 | * 56 | * @param where 57 | * the query pattern to set 58 | * @return this 59 | */ 60 | public T where(QueryPattern where) { 61 | this.where = where; 62 | 63 | return (T) this; 64 | } 65 | 66 | /** 67 | * Add grouping specifiers for the query results. 68 | * 69 | * @param groupables 70 | * the objects to group on, in order (appended to the end of any 71 | * existing grouping specifiers) 72 | * @return this 73 | * 74 | * @see GroupBy 75 | */ 76 | public T groupBy(Groupable... groupables) { 77 | groupBy = getOrCreateAndModifyOptional(groupBy, Spanqit::groupBy, gb -> gb.by(groupables)); 78 | 79 | return (T) this; 80 | } 81 | 82 | /** 83 | * Set this query's Group By clause 84 | * 85 | * @param groupBy 86 | * the {@link GroupBy} clause to set 87 | * @return this 88 | */ 89 | public T groupBy(GroupBy groupBy) { 90 | this.groupBy = Optional.of(groupBy); 91 | 92 | return (T) this; 93 | } 94 | 95 | /** 96 | * Specify orderings for the query results 97 | * 98 | * @param conditions 99 | * the objects to order on, in order 100 | * @return this 101 | * 102 | * @see OrderBy 103 | */ 104 | public T orderBy(Orderable... conditions) { 105 | orderBy = getOrCreateAndModifyOptional(orderBy, Spanqit::orderBy, ob -> ob.by(conditions)); 106 | 107 | return (T) this; 108 | } 109 | 110 | /** 111 | * Set this query's Order By clause 112 | * 113 | * @param orderBy 114 | * the {@link OrderBy} clause to set 115 | * @return this 116 | */ 117 | public T orderBy(OrderBy orderBy) { 118 | this.orderBy = Optional.of(orderBy); 119 | 120 | return (T) this; 121 | } 122 | 123 | /** 124 | * Specify constraints for this query's Having clause. 125 | * 126 | * @param constraints 127 | * the constraints to add to the clause 128 | * @return this 129 | * 130 | * @see Having 131 | */ 132 | public T having(Expression... constraints) { 133 | having = getOrCreateAndModifyOptional(having, Spanqit::having, h -> h.having(constraints)); 134 | 135 | return (T) this; 136 | } 137 | 138 | /** 139 | * Set this query's Having clause 140 | * 141 | * @param having 142 | * the Having clause to set 143 | * @return this 144 | */ 145 | public T having(Having having) { 146 | this.having = Optional.of(having); 147 | 148 | return (T) this; 149 | } 150 | 151 | /** 152 | * Set a limit on the number of results returned by this query. 153 | * 154 | * @param limit 155 | * @return this 156 | * 157 | * @see 159 | * Limits in SPARQL Queries 160 | */ 161 | public T limit(int limit) { 162 | this.limit = limit; 163 | 164 | return (T) this; 165 | } 166 | 167 | /** 168 | * Specify an offset in query results. 169 | * 170 | * @param offset 171 | * @return this 172 | * 173 | * @see Offsets 175 | * in SPARQL Queries 176 | */ 177 | public T offset(int offset) { 178 | this.offset = offset; 179 | 180 | return (T) this; 181 | } 182 | 183 | /** 184 | * A shortcut. Each call to this method returns a new {@link Variable} 185 | * that is unique (i.e., has a unique alias) to this query instance. 186 | * 187 | * @return a SparqlVariable object that is unique to this query instance 188 | */ 189 | public Variable var() { 190 | return Spanqit.var("x" + ++varCount); 191 | } 192 | 193 | protected abstract String getQueryActionString(); 194 | 195 | @Override 196 | public String getQueryString() { 197 | StringBuilder query = new StringBuilder(); 198 | 199 | query.append(getQueryActionString()).append("\n"); 200 | query.append(where.getQueryString()).append("\n"); 201 | 202 | appendAndNewlineIfPresent(groupBy, query); 203 | appendAndNewlineIfPresent(having, query); 204 | appendAndNewlineIfPresent(orderBy, query); 205 | 206 | if (limit >= 0) { 207 | query.append(LIMIT + " ").append(limit).append("\n"); 208 | } 209 | 210 | if (offset >= 0) { 211 | query.append(OFFSET + " ").append(offset).append("\n"); 212 | } 213 | 214 | return query.toString(); 215 | } 216 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/Spanqit.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core; 2 | 3 | import com.anqit.spanqit.constraint.Expression; 4 | import com.anqit.spanqit.graphpattern.GraphPattern; 5 | import com.anqit.spanqit.graphpattern.TriplePattern; 6 | import com.anqit.spanqit.rdf.Iri; 7 | 8 | /** 9 | * A class to with static methods to create SPARQL query elements. 10 | */ 11 | public class Spanqit { 12 | // prevent instantiation of this class 13 | private Spanqit() { } 14 | 15 | /** 16 | * Create a SPARQL variable with a specific alias. 17 | * 18 | * @param varName 19 | * the alias of the variable 20 | * @return a new SPARQL variable 21 | */ 22 | public static Variable var(String varName) { 23 | return new Variable(varName); 24 | } 25 | 26 | /** 27 | * Create a SPARQL assignment 28 | * 29 | * @param exp 30 | * the expression to evaluate 31 | * @param var 32 | * the variable to bind the expression value to 33 | * @return an Assignment object 34 | */ 35 | public static Assignment as(Assignable exp, Variable var) { 36 | return new Assignment(exp, var); 37 | } 38 | 39 | /** 40 | * Create a SPARQL Base declaration 41 | * 42 | * @param iri 43 | * the base iri 44 | * @return a Base object 45 | */ 46 | public static Base base(Iri iri) { 47 | return new Base(iri); 48 | } 49 | 50 | /** 51 | * Create a SPARQL Prefix declaration 52 | * 53 | * @param alias 54 | * the alias of the prefix 55 | * @param iri 56 | * the iri the alias refers to 57 | * @return a Prefix object 58 | */ 59 | public static Prefix prefix(String alias, Iri iri) { 60 | return new Prefix(alias, iri); 61 | } 62 | 63 | /** 64 | * Create a SPARQL default Prefix declaration 65 | * 66 | * @param iri 67 | * the default iri prefix 68 | * @return a Prefix object 69 | */ 70 | public static Prefix prefix(Iri iri) { 71 | return prefix("", iri); 72 | } 73 | 74 | /** 75 | * Create a SPARQL Prefix clause 76 | * 77 | * @param prefixes 78 | * prefix declarations to add to this Prefix clause 79 | * @return a new 80 | */ 81 | public static PrefixDeclarations prefixes(Prefix... prefixes) { 82 | return new PrefixDeclarations().addPrefix(prefixes); 83 | } 84 | 85 | /** 86 | * Create a default graph reference 87 | * 88 | * @param iri 89 | * the source of the graph 90 | * @return a From clause 91 | * 92 | * @see 94 | * RDF Datasets 95 | */ 96 | public static From from(Iri iri) { 97 | return new From(iri); 98 | } 99 | 100 | /** 101 | * Create a named graph reference 102 | * 103 | * @param iri 104 | * the source of the graph 105 | * @return a named From clause 106 | * 107 | * @see 109 | * RDF Datasets 110 | */ 111 | public static From fromNamed(Iri iri) { 112 | return new From(iri, true); 113 | } 114 | 115 | /** 116 | * Create a dataset declaration 117 | * 118 | * @param graphs 119 | * @return a new dataset clause 120 | * 121 | * @see 123 | * RDF Datasets 124 | */ 125 | public static Dataset dataset(From... graphs) { 126 | return new Dataset().from(graphs); 127 | } 128 | 129 | /** 130 | * Create a SPARQL projection 131 | * 132 | * @param projectables 133 | * projectable elements to add to the projection 134 | * @return a Projection 135 | */ 136 | public static Projection select(Projectable... projectables) { 137 | return new Projection().select(projectables); 138 | } 139 | 140 | /** 141 | * Create a SPARQL graph template 142 | * 143 | * @param triples 144 | * triples to add to the template 145 | * @return a new SPARQL graph template 146 | */ 147 | public static GraphTemplate construct(TriplePattern... triples) { 148 | return new GraphTemplate().construct(triples); 149 | } 150 | 151 | /** 152 | * Create a SPARQL query pattern 153 | * 154 | * @param patterns 155 | * graph patterns to add to the query pattern 156 | * @return a new Query Pattern 157 | */ 158 | public static QueryPattern where(GraphPattern... patterns) { 159 | return new QueryPattern().where(patterns); 160 | } 161 | 162 | /** 163 | * Create a SPARQL Group By clause 164 | * 165 | * @param groupables 166 | * the group conditions 167 | * @return a Group By clause 168 | */ 169 | public static GroupBy groupBy(Groupable... groupables) { 170 | return new GroupBy().by(groupables); 171 | } 172 | 173 | /** 174 | * Create a SPARQL Order clause 175 | * 176 | * @param conditions 177 | * the order conditions 178 | * @return an Order By clause 179 | */ 180 | public static OrderBy orderBy(Orderable... conditions) { 181 | return new OrderBy().by(conditions); 182 | } 183 | 184 | /** 185 | * Create a SPARQL Having clause 186 | * 187 | * @param expressions 188 | * the having conditions 189 | * @return a Having clause 190 | */ 191 | public static Having having(Expression... expressions) { 192 | return new Having().having(expressions); 193 | } 194 | 195 | /** 196 | * Create an ascending SPARQL order condition 197 | * 198 | * @param orderOn 199 | * the order comparator 200 | * @return an ASC() order condition 201 | */ 202 | public static OrderCondition asc(Orderable orderOn) { 203 | return new OrderCondition(orderOn, true); 204 | } 205 | 206 | /** 207 | * Create a descending SPARQL order condition 208 | * 209 | * @param orderOn 210 | * the order comparator 211 | * @return a DESC() order condition 212 | */ 213 | public static OrderCondition desc(Orderable orderOn) { 214 | return new OrderCondition(orderOn, false); 215 | } 216 | 217 | /** 218 | * Create a TriplesTemplate instance, for use with Construct and Update queries 219 | * 220 | * @param triples 221 | * the triples to include in the triples template 222 | * @return a TriplesTemplate of the given triples 223 | */ 224 | public static TriplesTemplate triplesTemplate(TriplePattern... triples) { 225 | return new TriplesTemplate(triples); 226 | } 227 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/core/query/Queries.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.core.query; 2 | 3 | import com.anqit.spanqit.core.GraphTemplate; 4 | import com.anqit.spanqit.core.Projectable; 5 | import com.anqit.spanqit.core.Projection; 6 | import com.anqit.spanqit.core.TriplesTemplate; 7 | import com.anqit.spanqit.graphpattern.TriplePattern; 8 | 9 | /** 10 | * A class with static methods to create SPARQL queries 11 | * 12 | * @see 13 | * SPARQL Query Language 14 | */ 15 | public class Queries { 16 | // prevent instantiation of this class 17 | private Queries() { } 18 | 19 | /** 20 | * Create a SPARQL Select query 21 | * 22 | * @param projectables 23 | * the initial set of {@link Projectable}(s), if any, to select 24 | * 25 | * @return a new {@link SelectQuery} 26 | * 27 | * @see SPARQL 29 | * Select Query 30 | */ 31 | public static SelectQuery SELECT(Projectable... projectables) { 32 | return new SelectQuery().select(projectables); 33 | } 34 | 35 | /** 36 | * Create a SPARQL Select query 37 | * 38 | * @param select 39 | * the {@link Projection} to set initially 40 | * @return a new {@link SelectQuery} 41 | * 42 | * @see SPARQL 44 | * Select Query 45 | */ 46 | public static SelectQuery SELECT(Projection select) { 47 | return new SelectQuery().select(select); 48 | } 49 | 50 | /** 51 | * Create a SPARQL Construct query 52 | * 53 | * @param patterns 54 | * the initial set of {@link TriplePattern}(s), if any, to construct 55 | * @return a new {@link ConstructQuery} 56 | * 57 | * @see SPARQL 59 | * Construct Query 60 | */ 61 | public static ConstructQuery CONSTRUCT(TriplePattern... patterns) { 62 | return new ConstructQuery().construct(patterns); 63 | } 64 | 65 | /** 66 | * Create a SPARQL Construct query 67 | * 68 | * @param construct 69 | * the {@link GraphTemplate} to set initially 70 | * @return a new {@link ConstructQuery} 71 | * 72 | * @see SPARQL 74 | * Construct Query 75 | */ 76 | public static ConstructQuery CONSTRUCT(GraphTemplate construct) { 77 | return new ConstructQuery().construct(construct); 78 | } 79 | /** 80 | * Create a SPARQL INSERT DATA query 81 | * 82 | * @param triples 83 | * the initial set of {@link TriplePattern}(s), if any, to use 84 | * 85 | * @return a new {@link InsertDataQuery} 86 | * 87 | * @see 88 | * SPARQL INSERT DATA Query 89 | */ 90 | public static InsertDataQuery INSERT_DATA(TriplePattern... triples) { 91 | return new InsertDataQuery().insertData(triples); 92 | } 93 | 94 | /** 95 | * Create a SPARQL INSERT DATA query 96 | * 97 | * @param triplesTemplate 98 | * the {@link TriplesTemplate} to set initially 99 | * 100 | * @return a new {@link InsertDataQuery} 101 | * 102 | * @see 103 | * SPARQL INSERT DATA Query 104 | */ 105 | public static InsertDataQuery INSERT_DATA(TriplesTemplate triplesTemplate) { 106 | return new InsertDataQuery().insertData(triplesTemplate); 107 | } 108 | 109 | /** 110 | * Create a SPARQL DELETE DATA query 111 | * 112 | * @param triples 113 | * the initial set of {@link TriplePattern}(s), if any, to use 114 | * 115 | * @return a new {@link DeleteDataQuery} 116 | * 117 | * @see 118 | * SPARQL DELETE DATA Query 119 | */ 120 | public static DeleteDataQuery DELETE_DATA(TriplePattern... triples) { 121 | return new DeleteDataQuery().deleteData(triples); 122 | } 123 | 124 | /** 125 | * Create a SPARQL DELETE DATA query 126 | * 127 | * @param triplesTemplate 128 | * the {@link TriplesTemplate} to set initially 129 | * 130 | * @return a new {@link DeleteDataQuery} 131 | * 132 | * @see 133 | * SPARQL DELETE DATA Query 134 | */ 135 | public static DeleteDataQuery DELETE_DATA(TriplesTemplate triplesTemplate) { 136 | return new DeleteDataQuery().deleteData(triplesTemplate); 137 | } 138 | 139 | /** 140 | * Creates a SPARQL Modify query 141 | * 142 | * @return a new {@link ModifyQuery} 143 | * 144 | * @see 145 | * SPARQL Modify Query 146 | */ 147 | public static ModifyQuery MODIFY() { 148 | return new ModifyQuery(); 149 | } 150 | 151 | /** 152 | * Creates a SPARQL LOAD query 153 | * 154 | * @return a new {@link LoadQuery} 155 | * 156 | * @see 157 | * SPARQL LOAD Query 158 | */ 159 | public static LoadQuery LOAD() { 160 | return new LoadQuery(); 161 | } 162 | 163 | /** 164 | * Creates a SPARQL CLEAR Query 165 | * 166 | * @return a new {@link ClearQuery} 167 | * 168 | * @see 169 | * SPARQL CLEAR Query 170 | */ 171 | public static ClearQuery CLEAR() { 172 | return new ClearQuery(); 173 | } 174 | 175 | /** 176 | * Creates a SPARQL CREATE Query 177 | * 178 | * @return a new {@link CreateQuery} 179 | * 180 | * @see 181 | * SPARQL CREATE Query 182 | */ 183 | public static CreateQuery CREATE() { 184 | return new CreateQuery(); 185 | } 186 | 187 | /** 188 | * Creates a SPARQL DROP Query 189 | * 190 | * @return a new {@link DropQuery} 191 | * 192 | * @see 193 | * SPARQL DROP Query 194 | */ 195 | public static DropQuery DROP() { 196 | return new DropQuery(); 197 | } 198 | 199 | /** 200 | * Creates a SPARQL COPY Query 201 | * 202 | * @return a new {@link CopyQuery} 203 | * 204 | * @see 205 | * SPARQL COPY Query 206 | */ 207 | public static CopyQuery COPY() { 208 | return new CopyQuery(); 209 | } 210 | 211 | /** 212 | * Creates a SPARQL MOVE Query 213 | * 214 | * @return a new {@link MoveQuery} 215 | * 216 | * @see 217 | * SPARQL MOVE Query 218 | */ 219 | public static MoveQuery MOVE() { 220 | return new MoveQuery(); 221 | } 222 | 223 | /** 224 | * Creates a new SPARQL ADD Query 225 | * 226 | * @return a new {@link AddQuery} 227 | * 228 | * @see 229 | * SPARQL ADD Query 230 | */ 231 | public static AddQuery ADD() { 232 | return new AddQuery(); 233 | } 234 | } -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/rdf/Rdf.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.rdf; 2 | 3 | import java.util.Arrays; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | import java.util.stream.Stream; 7 | 8 | import com.anqit.spanqit.rdf.RdfBlankNode.AnonymousBlankNode; 9 | import com.anqit.spanqit.rdf.RdfBlankNode.LabeledBlankNode; 10 | import com.anqit.spanqit.rdf.RdfBlankNode.PropertiesBlankNode; 11 | import com.anqit.spanqit.rdf.RdfLiteral.BooleanLiteral; 12 | import com.anqit.spanqit.rdf.RdfLiteral.NumericLiteral; 13 | import com.anqit.spanqit.rdf.RdfLiteral.StringLiteral; 14 | 15 | /** 16 | * A class with static methods to create basic RDF objects 17 | */ 18 | public class Rdf { 19 | // not sure if other protocols are generally used in RDF iri's? 20 | private static final Set IRI_PROTOCOLS = Stream.of("http://", "https://", "mailto:").collect(Collectors.toSet()); 21 | 22 | private Rdf() { } 23 | 24 | /** 25 | * Create a Spanqit Iri instance from a String iri 26 | * 27 | * @param iriString the String representing the iri 28 | * @return the {@link Iri} instance 29 | */ 30 | public static Iri iri(String iriString) { 31 | return () -> IRI_PROTOCOLS.stream().anyMatch(iriString.toLowerCase()::startsWith) ? 32 | "<" + iriString + ">" : iriString; 33 | } 34 | 35 | /** 36 | * Create a Spanqit Iri instance from a namespace and local name 37 | * @param namespace 38 | * the namespace of the Iri 39 | * @param localName 40 | * the local name of the Iri 41 | * @return a {@link Iri} instance 42 | */ 43 | public static Iri iri(String namespace, String localName) { 44 | return iri(namespace + localName); 45 | } 46 | 47 | /** 48 | * creates a labeled blank node 49 | * 50 | * @param label the label of the blank node 51 | * 52 | * @return a new {@link LabeledBlankNode} instance 53 | */ 54 | public static LabeledBlankNode bNode(String label) { 55 | return new LabeledBlankNode(label); 56 | } 57 | 58 | /** 59 | * creates a label-less blank node, identified by the supplied predicate-object lists 60 | * 61 | * @param predicate the predicate of the initial predicate-object list to populate this blank node with 62 | * @param objects the objects of the initial predicate-object list to populate this blank node with 63 | * 64 | * @return a new {@link PropertiesBlankNode} instance 65 | * 66 | * @see 67 | * Blank node syntax 68 | */ 69 | public static PropertiesBlankNode bNode(RdfPredicate predicate, RdfObject... objects) { 70 | return new PropertiesBlankNode(predicate, objects); 71 | } 72 | 73 | /** 74 | * create an empty anonymous blank node 75 | * @return an empty {@link AnonymousBlankNode} instance 76 | */ 77 | public static AnonymousBlankNode bNode() { 78 | return new AnonymousBlankNode(); 79 | } 80 | 81 | /** 82 | * create an RDF string literal 83 | * 84 | * @param stringValue the String instance to create a literal from 85 | * @return a StringLiteral instance representing the given String 86 | */ 87 | public static StringLiteral literalOf(String stringValue) { 88 | return new StringLiteral(stringValue); 89 | } 90 | 91 | /** 92 | * create a literal with a datatype 93 | * 94 | * @param stringValue the literal string 95 | * @param dataType the datatype tag 96 | * 97 | * @return a StringLiteral instance representing the given String and datatype 98 | */ 99 | public static StringLiteral literalOfType(String stringValue, Iri dataType) { 100 | return new StringLiteral(stringValue, dataType); 101 | } 102 | 103 | /** 104 | * create a literal with a language tag 105 | * 106 | * @param stringValue the literal string 107 | * @param language the language tag 108 | * 109 | * @return a StringLiteral instance representing the given String and language 110 | */ 111 | public static StringLiteral literalOfLanguage(String stringValue, String language) { 112 | return new StringLiteral(stringValue, language); 113 | } 114 | 115 | /** 116 | * create an RDF numeric literal 117 | * 118 | * @param numberValue the Number instance to create a literal from 119 | * @return a NumberLiteral instance representing the given Number 120 | */ 121 | public static NumericLiteral literalOf(Number numberValue) { 122 | return new NumericLiteral(numberValue); 123 | } 124 | 125 | /** 126 | * create an RDF boolean literal 127 | * 128 | * @param boolValue the boolean to create a literal from 129 | * @return a BooleanLiteral instance representing the given boolean 130 | */ 131 | public static BooleanLiteral literalOf(Boolean boolValue) { 132 | return new BooleanLiteral(boolValue); 133 | } 134 | 135 | /** 136 | * Create a {@link RdfPredicateObjectList} 137 | * 138 | * @param predicate the {@link RdfPredicate} of the predicate-object list 139 | * @param objects the {@link RdfObject}(s) of the list 140 | * 141 | * @return a new {@link RdfPredicateObjectList} 142 | */ 143 | public static RdfPredicateObjectList predicateObjectList(RdfPredicate predicate, RdfObject... objects) { 144 | return new RdfPredicateObjectList(predicate, objects); 145 | } 146 | 147 | /** 148 | * Create a {@link RdfPredicateObjectListCollection} with an initial {@link RdfPredicateObjectList} 149 | * 150 | * @param predicate the {@link RdfPredicate} of the initial {@link RdfPredicateObjectList} 151 | * @param objects the {@link RdfObject}(s) of the initial {@link RdfPredicateObjectList} 152 | * 153 | * @return a new {@link RdfPredicateObjectListCollection} 154 | */ 155 | public static RdfPredicateObjectListCollection predicateObjectListCollection(RdfPredicate predicate, RdfObject... objects) { 156 | return new RdfPredicateObjectListCollection().andHas(predicate, objects); 157 | } 158 | 159 | /** 160 | * Create a {@link RdfPredicateObjectListCollection} with the given {@link RdfPredicateObjectList}(s) 161 | * 162 | * @param predicateObjectLists the {@link RdfPredicateObjectList}(s) to add to the collection 163 | * 164 | * @return a new {@link RdfPredicateObjectListCollection} 165 | */ 166 | public static RdfPredicateObjectListCollection predicateObjectListCollection(RdfPredicateObjectList... predicateObjectLists) { 167 | return new RdfPredicateObjectListCollection().andHas(predicateObjectLists); 168 | } 169 | 170 | /** 171 | * Convert an array of {@link String}s to an array of {@link StringLiteral}s 172 | * 173 | * @param literals the {@link String}s to convert 174 | * 175 | * @return an array of the corresponding {@link StringLiteral}s 176 | */ 177 | public static StringLiteral[] toRdfLiteralArray(String... literals) { 178 | return Arrays.stream(literals).map(Rdf::literalOf).toArray(StringLiteral[]::new); 179 | } 180 | 181 | /** 182 | * Convert an array of {@link Boolean}s to an array of {@link BooleanLiteral}s 183 | * 184 | * @param literals the {@link Boolean}s to convert 185 | * 186 | * @return an array of the corresponding {@link BooleanLiteral}s 187 | */ 188 | public static BooleanLiteral[] toRdfLiteralArray(Boolean... literals) { 189 | return Arrays.stream(literals).map(Rdf::literalOf).toArray(BooleanLiteral[]::new); 190 | } 191 | 192 | /** 193 | * Convert an array of {@link Number}s to an array of {@link NumericLiteral}s 194 | * 195 | * @param literals the {@link Number}s to convert 196 | * 197 | * @return an array of the corresponding {@link NumericLiteral}s 198 | */ 199 | public static NumericLiteral[] toRdfLiteralArray(Number... literals) { 200 | return Arrays.stream(literals).map(Rdf::literalOf).toArray(NumericLiteral[]::new); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/graphpattern/GraphPatternNotTriple.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.graphpattern; 2 | 3 | import java.util.Arrays; 4 | import java.util.function.Consumer; 5 | 6 | import com.anqit.spanqit.constraint.Expression; 7 | 8 | /** 9 | * A SPARQL Graph Pattern that is not a triple pattern. 10 | * 11 | * @see 13 | * SPARQL Graph Patterns 14 | */ 15 | public class GraphPatternNotTriple implements GraphPattern { 16 | private GraphPattern pattern; 17 | 18 | GraphPatternNotTriple() { 19 | this(new GroupGraphPattern()); 20 | } 21 | 22 | GraphPatternNotTriple(GraphPattern other) { 23 | this.pattern = extractPattern(other); 24 | } 25 | 26 | /** 27 | * Convert this graph pattern into a group graph pattern, combining this 28 | * graph pattern with the given patterns:
29 | * 30 | *
 31 | 	 * {
 32 | 	 *   thisPattern .
 33 | 	 *   pattern1 .
 34 | 	 *   pattern2 .
 35 | 	 *   ...
 36 | 	 *   patternN
 37 | 	 * }
 38 | 	 * 
39 | * 40 | * @param patterns 41 | * the patterns to add 42 | * @return this 43 | * 44 | * @see SPARQL 46 | * Group Graph Pattern 47 | */ 48 | public GraphPatternNotTriple and(GraphPattern... patterns) { 49 | if (patterns != null && patterns.length > 0) { 50 | GroupGraphPattern groupPattern = new GroupGraphPattern(pattern); 51 | extractAndAddPatterns(groupPattern::and, patterns); 52 | 53 | pattern = groupPattern; 54 | } 55 | 56 | return this; 57 | } 58 | 59 | /** 60 | * Convert this graph pattern into an alternative graph pattern, combining 61 | * this graph pattern with the given patterns:
62 | * 63 | *
 64 | 	 * {
 65 | 	 *   { thisPattern } UNION
 66 | 	 *   { pattern1 } UNION
 67 | 	 *   { pattern2 } UNION
 68 | 	 *   ...
 69 | 	 *   { patternN }
 70 | 	 * }
 71 | 	 * 
72 | * 73 | * @param patterns 74 | * the patterns to add 75 | * @return this 76 | * 77 | * @see SPARQL 79 | * Alternative Graph Pattern 80 | */ 81 | public GraphPatternNotTriple union(GraphPattern... patterns) { 82 | AlternativeGraphPattern alternativePattern = new AlternativeGraphPattern(pattern); 83 | extractAndAddPatterns(alternativePattern::union, patterns); 84 | 85 | pattern = alternativePattern; 86 | 87 | return this; 88 | } 89 | 90 | /** 91 | * Convert this graph pattern into an optional group graph pattern:
92 | * 93 | *
 94 | 	 * OPTIONAL {thisPattern}
 95 | 	 * 
96 | * 97 | * @return this 98 | * 99 | * @see 101 | * SPARQL Optional Graph Patterns 102 | */ 103 | public GraphPatternNotTriple optional() { 104 | return optional(true); 105 | } 106 | 107 | /** 108 | * Specify if this graph pattern should be optional. 109 | * 110 | *

111 | * NOTE: This converts this graph pattern into a group graph pattern. 112 | * 113 | * @param isOptional 114 | * if this graph pattern should be optional or not 115 | * @return this 116 | * 117 | * @see 119 | * SPARQL Optional Graph Patterns 120 | */ 121 | public GraphPatternNotTriple optional(boolean isOptional) { 122 | pattern = new GroupGraphPattern(pattern).optional(isOptional); 123 | 124 | return this; 125 | } 126 | 127 | /** 128 | * Convert this graph pattern into a group graph pattern and add a filter:
129 | * 130 | *

131 | 	 * {
132 | 	 *   thisPattern
133 | 	 *   FILTER { constraint }
134 | 	 * }
135 | 	 * 
136 | * 137 | * @param constraint 138 | * the filter constraint 139 | * @return this 140 | * 141 | * @see 142 | * SPARQL Filter 143 | */ 144 | public GraphPatternNotTriple filter(Expression constraint) { 145 | pattern = new GroupGraphPattern(pattern).filter(constraint); 146 | 147 | return this; 148 | } 149 | 150 | /** 151 | * Create an EXISTS{} filter expression with the given graph 152 | * patterns and add it to this graph pattern (converting this to a group 153 | * graph pattern in the process):
154 | * 155 | *
156 | 	 * {
157 | 	 * 	thisPattern
158 | 	 * 	FILTER EXISTS { patterns }
159 | 	 * }
160 | 	 * 
161 | * 162 | * @param patterns 163 | * the patterns to pass as arguments to the EXISTS 164 | * expression 165 | * 166 | * @return this 167 | * 168 | * @see 170 | * Filtering using Graph Pattern 171 | */ 172 | public GraphPatternNotTriple filterExists(GraphPattern... patterns) { 173 | filterExists(true, patterns); 174 | 175 | return this; 176 | } 177 | 178 | /** 179 | * Create a NOT EXISTS{} filter expression with the given graph 180 | * patterns and add it to this graph pattern (converting this to a group 181 | * graph pattern in the process):
182 | * 183 | *
184 | 	 * {
185 | 	 * 	thisPattern
186 | 	 * 	FILTER NOT EXISTS { patterns }
187 | 	 * }
188 | 	 * 
189 | * 190 | * @param patterns 191 | * the patterns to pass as arguments to the 192 | * NOT EXISTS expression 193 | * 194 | * @return this 195 | * 196 | * @see 198 | * Filtering using Graph Pattern 199 | */ 200 | public GraphPatternNotTriple filterNotExists(GraphPattern... patterns) { 201 | filterExists(false, patterns); 202 | 203 | return this; 204 | } 205 | 206 | /** 207 | * Create a MINUS graph pattern with the given graph patterns 208 | * and add it to this graph pattern (converting this to a group graph 209 | * pattern in the process):
210 | * 211 | *
212 | 	 * {
213 | 	 * 	thisPattern
214 | 	 * 	MINUS { patterns }
215 | 	 * }
216 | 	 * 
217 | * 218 | * @param patterns 219 | * the patterns to construct the MINUS graph pattern 220 | * with 221 | * @return this 222 | * 223 | * @see 225 | * SPARQL MINUS Graph Pattern 226 | */ 227 | public GraphPatternNotTriple minus(GraphPattern... patterns) { 228 | MinusGraphPattern minus = new MinusGraphPattern(); 229 | extractAndAddPatterns(minus::and, patterns); 230 | 231 | pattern = new GroupGraphPattern(pattern).and(minus); 232 | 233 | return this; 234 | } 235 | 236 | /** 237 | * Convert this graph pattern into a named group graph pattern:
238 | * 239 | *
240 | 	 * GRAPH graphName { thisPattern }
241 | 	 * 
242 | * 243 | * @param name 244 | * the name to specify 245 | * @return this 246 | * 247 | * @see 249 | * Specifying Datasets in SPARQL Queries 250 | */ 251 | public GraphPatternNotTriple from(GraphName name) { 252 | pattern = new GroupGraphPattern(pattern).from(name); 253 | 254 | return this; 255 | } 256 | 257 | @Override 258 | public boolean isEmpty() { 259 | return pattern.isEmpty(); 260 | } 261 | 262 | private void filterExists(boolean exists, GraphPattern... patterns) { 263 | FilterExistsGraphPattern filterExists = new FilterExistsGraphPattern().exists(exists); 264 | extractAndAddPatterns(filterExists::and, patterns); 265 | 266 | pattern = new GroupGraphPattern(pattern).and(filterExists); 267 | } 268 | 269 | private void extractAndAddPatterns(Consumer action, GraphPattern... patterns) { 270 | Arrays.stream(patterns).map(this::extractPattern).forEach(action); 271 | } 272 | 273 | private GraphPattern extractPattern(GraphPattern pattern) { 274 | if (pattern instanceof GraphPatternNotTriple) { 275 | return ((GraphPatternNotTriple) pattern).pattern; 276 | } else { 277 | return pattern; 278 | } 279 | } 280 | 281 | @Override 282 | public String getQueryString() { 283 | return pattern.getQueryString(); 284 | } 285 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/main/java/com/anqit/spanqit/constraint/Expressions.java: -------------------------------------------------------------------------------- 1 | package com.anqit.spanqit.constraint; 2 | 3 | import static com.anqit.spanqit.constraint.SparqlFunction.ABS; 4 | import static com.anqit.spanqit.constraint.SparqlFunction.BNODE; 5 | import static com.anqit.spanqit.constraint.SparqlFunction.BOUND; 6 | import static com.anqit.spanqit.constraint.SparqlFunction.CEIL; 7 | import static com.anqit.spanqit.constraint.SparqlFunction.COALESCE; 8 | import static com.anqit.spanqit.constraint.SparqlFunction.CONCAT; 9 | import static com.anqit.spanqit.constraint.SparqlFunction.REGEX; 10 | 11 | import com.anqit.spanqit.core.Variable; 12 | import com.anqit.spanqit.rdf.Rdf; 13 | import com.anqit.spanqit.rdf.RdfLiteral; 14 | 15 | /** 16 | * A class with static methods to create SPARQL expressions. 17 | * Obviously there's some more flushing out TODO still 18 | * 19 | * @see 21 | * SPARQL Function Definitions 22 | */ 23 | public class Expressions { 24 | // prevent instantiation of this class 25 | private Expressions() { } 26 | 27 | /** 28 | * ABS(operand) 29 | * 30 | * @param operand 31 | * the argument to the absolute value function 32 | * @return an ABS() function 33 | * 34 | * @see 36 | * SPARQL ABS Function 37 | */ 38 | public static Expression abs(Number operand) { 39 | return abs(Rdf.literalOf(operand)); 40 | } 41 | 42 | /** 43 | * ABS(operand) 44 | * 45 | * @param operand 46 | * the argument to the absolute value function 47 | * @return an ABS() function 48 | * 49 | * @see 51 | * SPARQL ABS Function 52 | */ 53 | public static Expression abs(Operand operand) { 54 | return function(ABS, operand); 55 | } 56 | 57 | /** 58 | * BNODE() 59 | * 60 | * @return a no-arg BNODE() function 61 | * 62 | * @see 64 | * SPARQL BNODE Function 65 | */ 66 | public static Expression bnode() { 67 | return function(BNODE, (Operand) null); 68 | } 69 | 70 | /** 71 | * BNODE(operand) 72 | * 73 | * @param literal 74 | * the RDF literal argument to the function 75 | * @return a BNODE() function 76 | * 77 | * @see 79 | * SPARQL BNODE Function 80 | */ 81 | public static Expression bnode(RdfLiteral literal) { 82 | return function(BNODE, literal); 83 | } 84 | 85 | /** 86 | * BNODE(operand) 87 | * 88 | * @param literal 89 | * the String literal argument to the function 90 | * @return a BNODE() function 91 | * 92 | * @see 94 | * SPARQL BNODE Function 95 | */ 96 | public static Expression bnode(String literal) { 97 | return function(BNODE, Rdf.literalOf(literal)); 98 | } 99 | 100 | /** 101 | * BOUND(operand) 102 | * 103 | * @param var 104 | * the SPARQL variable argument to the function 105 | * @return a BOUND() function 106 | * 107 | * @see 109 | * SPARQL BOUND Function 110 | */ 111 | public static Expression bound(Variable var) { 112 | return function(BOUND, var); 113 | } 114 | 115 | /** 116 | * CEIL(operand) 117 | * 118 | * @param operand 119 | * the argument to the function 120 | * @return a CEIL() function 121 | * 122 | * @see 124 | * SPARQL CEIL Function 125 | */ 126 | public static Expression ceil(Operand operand) { 127 | return function(CEIL, operand); 128 | } 129 | 130 | /** 131 | * COALESCE(operand1, operand2, ... , operandN) 132 | * 133 | * @param operands 134 | * the arguments to the function 135 | * @return a COALESCE() function 136 | * 137 | * @see 139 | * SPARQL COALESCE Function 140 | */ 141 | public static Expression coalesce(Operand... operands) { 142 | return function(COALESCE, operands); 143 | } 144 | 145 | /** 146 | * CONCAT(operand1, operand2, ... , operandN) 147 | * 148 | * @param operands 149 | * the arguments to the function 150 | * @return a CONCAT() function 151 | * 152 | * @see 154 | * SPARQL CONCAT Function 155 | */ 156 | public static Expression concat(Operand... operands) { 157 | return function(CONCAT, operands); 158 | } 159 | 160 | /** 161 | * REGEX(testString, pattern) 162 | * 163 | * @param testString 164 | * the text to match against 165 | * @param pattern 166 | * the regex pattern to match 167 | * @return a REGEX() function 168 | * 169 | * @see 171 | * SPARQL REGEX Function 172 | */ 173 | public static Expression regex(Operand testString, String pattern) { 174 | return regex(testString, Rdf.literalOf(pattern)); 175 | } 176 | 177 | /** 178 | * REGEX(testString, pattern, flags) 179 | * 180 | * @param testString 181 | * the text to match against 182 | * @param pattern 183 | * the regular expression pattern to match 184 | * @param flags 185 | * flags to specify matching options 186 | * @return a REGEX() function 187 | * 188 | * @see 190 | * SPARQL REGEX Function 191 | */ 192 | public static Expression regex(Operand testString, String pattern, 193 | String flags) { 194 | return regex(testString, Rdf.literalOf(pattern), Rdf.literalOf(flags)); 195 | } 196 | 197 | /** 198 | * REGEX(testString, pattern) 199 | * 200 | * @param testString 201 | * the text to match against 202 | * @param pattern 203 | * the regex pattern to match 204 | * @return a REGEX() function 205 | * 206 | * @see 208 | * SPARQL REGEX Function 209 | */ 210 | public static Expression regex(Operand testString, 211 | Operand pattern) { 212 | return function(REGEX, testString, pattern); 213 | } 214 | 215 | /** 216 | * REGEX(testString, pattern, flags) 217 | * 218 | * @param testString 219 | * the text to match against 220 | * @param pattern 221 | * the regular expression pattern to match 222 | * @param flags 223 | * flags to specify matching options 224 | * @return a REGEX() function 225 | * 226 | * @see 228 | * SPARQL REGEX Function 229 | */ 230 | public static Expression regex(Operand testString, 231 | Operand pattern, Operand flags) { 232 | return function(REGEX, testString, pattern, flags); 233 | } 234 | 235 | /** 236 | * {@code STR(literal)} or {@code STR(iri)} 237 | * 238 | * @param operand the arg to convert to a string 239 | * 240 | * @return a {@code STR()} function 241 | * 242 | * @see 243 | * SPARQL STR Function 244 | */ 245 | public static Expression str(Operand operand) { 246 | return function(SparqlFunction.STRING, operand); 247 | } 248 | 249 | // public static Expression custom(IRI functionIri, ExpressionOperand... operands) { 250 | // return function(functionIri, operands); 251 | // } 252 | 253 | // ... etc... 254 | 255 | /** 256 | * Too lazy at the moment. Make the rest of the functions this way for now. 257 | * 258 | * @param function 259 | * a SPARQL Function 260 | * @param operands 261 | * arguments to the function 262 | * @return a function object of the given function type and 263 | * operands 264 | */ 265 | public static Expression function(SparqlFunction function, 266 | Operand... operands) { 267 | return new Function(function).addOperand(operands); 268 | } 269 | 270 | /** 271 | * !operand 272 | * 273 | * @param operand 274 | * argument to the function 275 | * @return logical not operation 276 | * 277 | * @see SPARQL 279 | * Operators 280 | */ 281 | public static Expression not(Operand operand) { 282 | return unaryExpression(UnaryOperator.NOT, operand); 283 | } 284 | 285 | /** 286 | * +operand 287 | * 288 | * @param operand 289 | * argument to the function 290 | * @return unary plus operation 291 | * 292 | * @see SPARQL 294 | * Operators 295 | */ 296 | public static Expression plus(Operand operand) { 297 | return unaryExpression(UnaryOperator.UNARY_PLUS, operand); 298 | } 299 | 300 | /** 301 | * -operand 302 | * 303 | * @param operand 304 | * argument to the function 305 | * @return unary minus operation 306 | * 307 | * @see SPARQL 309 | * Operators 310 | */ 311 | public static Expression minus(Operand operand) { 312 | return unaryExpression(UnaryOperator.UNARY_MINUS, operand); 313 | } 314 | 315 | private static UnaryOperation unaryExpression(UnaryOperator operator, 316 | Operand operand) { 317 | return new UnaryOperation(operator).addOperand(operand); 318 | } 319 | 320 | /** 321 | * left = right 322 | * 323 | * @param left 324 | * the left operand 325 | * @param right 326 | * the right operand 327 | * @return logical equals operation 328 | * @see SPARQL 330 | * Operators 331 | */ 332 | public static Expression equals(Operand left, 333 | Operand right) { 334 | return binaryExpression(BinaryOperator.EQUALS, left, right); 335 | } 336 | 337 | /** 338 | * left != right 339 | * 340 | * @param left 341 | * the left operand 342 | * @param right 343 | * the right operand 344 | * @return logical not equals operation 345 | * @see SPARQL 347 | * Operators 348 | */ 349 | public static Expression notEquals(Operand left, 350 | Operand right) { 351 | return binaryExpression(BinaryOperator.NOT_EQUALS, left, right); 352 | } 353 | 354 | /** 355 | * left > right 356 | * 357 | * @param left 358 | * the left operand 359 | * @param right 360 | * the right operand 361 | * @return logical greater than operation 362 | * @see SPARQL 364 | * Operators 365 | */ 366 | public static Expression gt(Number left, Number right) { 367 | return binaryExpression(BinaryOperator.GREATER_THAN, Rdf.literalOf(left), 368 | Rdf.literalOf(right)); 369 | } 370 | 371 | /** 372 | * left > right 373 | * 374 | * @param left 375 | * the left operand 376 | * @param right 377 | * the right operand 378 | * @return logical greater than operation 379 | * @see SPARQL 381 | * Operators 382 | */ 383 | public static Expression gt(Number left, Operand right) { 384 | return binaryExpression(BinaryOperator.GREATER_THAN, Rdf.literalOf(left), 385 | right); 386 | } 387 | 388 | /** 389 | * left > right 390 | * 391 | * @param left 392 | * the left operand 393 | * @param right 394 | * the right operand 395 | * @return logical greater than operation 396 | * @see SPARQL 398 | * Operators 399 | */ 400 | public static Expression gt(Operand left, Number right) { 401 | return binaryExpression(BinaryOperator.GREATER_THAN, left, 402 | Rdf.literalOf(right)); 403 | } 404 | 405 | /** 406 | * left > right 407 | * 408 | * @param left 409 | * the left operand 410 | * @param right 411 | * the right operand 412 | * @return logical greater than operation 413 | * @see SPARQL 415 | * Operators 416 | */ 417 | public static Expression gt(Operand left, 418 | Operand right) { 419 | return binaryExpression(BinaryOperator.GREATER_THAN, left, right); 420 | } 421 | 422 | /** 423 | * left >= right 424 | * 425 | * @param left 426 | * the left operand 427 | * @param right 428 | * the right operand 429 | * @return logical greater than or equals operation 430 | * @see SPARQL 432 | * Operators 433 | */ 434 | public static Expression gte(Operand left, 435 | Operand right) { 436 | return binaryExpression(BinaryOperator.GREATER_THAN_EQUALS, left, right); 437 | } 438 | 439 | /** 440 | * left < right 441 | * 442 | * @param left 443 | * the left operand 444 | * @param right 445 | * the right operand 446 | * @return logical less than operation 447 | * @see SPARQL 449 | * Operators 450 | */ 451 | public static Expression lt(Number left, Number right) { 452 | return binaryExpression(BinaryOperator.LESS_THAN, Rdf.literalOf(left), 453 | Rdf.literalOf(right)); 454 | } 455 | 456 | /** 457 | * left < right 458 | * 459 | * @param left 460 | * the left operand 461 | * @param right 462 | * the right operand 463 | * @return logical less than operation 464 | * @see SPARQL 466 | * Operators 467 | */ 468 | public static Expression lt(Number left, Operand right) { 469 | return binaryExpression(BinaryOperator.LESS_THAN, Rdf.literalOf(left), 470 | right); 471 | } 472 | 473 | /** 474 | * left < right 475 | * 476 | * @param left 477 | * the left operand 478 | * @param right 479 | * the right operand 480 | * @return logical less than operation 481 | * @see SPARQL 483 | * Operators 484 | */ 485 | public static Expression lt(Operand left, Number right) { 486 | return binaryExpression(BinaryOperator.LESS_THAN, left, 487 | Rdf.literalOf(right)); 488 | } 489 | 490 | /** 491 | * left < right 492 | * 493 | * @param left 494 | * the left operand 495 | * @param right 496 | * the right operand 497 | * @return logical less than operation 498 | * @see SPARQL 500 | * Operators 501 | */ 502 | public static Expression lt(Operand left, 503 | Operand right) { 504 | return binaryExpression(BinaryOperator.LESS_THAN, left, right); 505 | } 506 | 507 | /** 508 | * left <= right 509 | * 510 | * @param left 511 | * the left operand 512 | * @param right 513 | * the right operand 514 | * @return logical less than or equals operation 515 | * 516 | * @see SPARQL 518 | * Operators 519 | */ 520 | public static Expression lte(Operand left, 521 | Operand right) { 522 | return binaryExpression(BinaryOperator.LESS_THAN_EQUALS, left, right); 523 | } 524 | 525 | private static BinaryOperation binaryExpression(BinaryOperator operator, 526 | Operand op1, Operand op2) { 527 | BinaryOperation op = new BinaryOperation(operator); 528 | 529 | op.addOperand(op1).addOperand(op2); 530 | 531 | return op; 532 | } 533 | 534 | /** 535 | * operand1 && operand2 && ... operandN 536 | * 537 | * @param operands 538 | * the arguments 539 | * @return logical and operation 540 | * 541 | * @see SPARQL 543 | * Operators 544 | */ 545 | public static Expression and(Operand... operands) { 546 | return connectiveExpression(ConnectiveOperator.AND, operands); 547 | } 548 | 549 | /** 550 | * operand1 || operand2 || ... || operandN 551 | * 552 | * @param operands 553 | * the arguments 554 | * @return logical or operation 555 | * 556 | * @see SPARQL 558 | * Operators 559 | */ 560 | public static Expression or(Operand... operands) { 561 | return connectiveExpression(ConnectiveOperator.OR, operands); 562 | } 563 | 564 | /** 565 | * operand1 + operand2 + ... + operandN 566 | * 567 | * @param operands 568 | * the arguments 569 | * @return arithmetic addition operation 570 | * 571 | * @see SPARQL 573 | * Operators 574 | */ 575 | public static Expression add(Operand... operands) { 576 | return connectiveExpression(ConnectiveOperator.ADD, operands); 577 | } 578 | 579 | /** 580 | * operand1 - operand2 - ... - operandN 581 | * 582 | * @param operands 583 | * the arguments 584 | * @return arithmetic subtraction operation 585 | * 586 | * @see SPARQL 588 | * Operators 589 | */ 590 | public static Expression subtract(Operand... operands) { 591 | return connectiveExpression(ConnectiveOperator.SUBTRACT, operands); 592 | } 593 | 594 | /** 595 | * operand1 * operand2 * ... * operandN 596 | * 597 | * @param operands 598 | * the arguments 599 | * @return arithmetic multiplication operation 600 | * 601 | * @see SPARQL 603 | * Operators 604 | */ 605 | public static Expression multiply(Operand... operands) { 606 | return connectiveExpression(ConnectiveOperator.MULTIPLY, operands); 607 | } 608 | 609 | /** 610 | * operand1 / operand2 / ... / operandN 611 | * 612 | * @param operands 613 | * the arguments 614 | * @return arithmetic division operation 615 | * 616 | * @see SPARQL 618 | * Operators 619 | */ 620 | public static Expression divide(Operand... operands) { 621 | return connectiveExpression(ConnectiveOperator.DIVIDE, operands); 622 | } 623 | 624 | private static ConnectiveOperation connectiveExpression(ConnectiveOperator operator, Operand... operands) { 625 | ConnectiveOperation op = new ConnectiveOperation(operator); 626 | 627 | for (Operand operand : operands) { 628 | op.addOperand(operand); 629 | } 630 | 631 | return op; 632 | } 633 | 634 | /** 635 | * Aggregates 636 | */ 637 | 638 | /** 639 | * 640 | * @param operand 641 | * @return 642 | */ 643 | public static Aggregate avg(Operand operand) { 644 | return new Aggregate(SparqlAggregate.AVG).addOperand(operand); 645 | } 646 | 647 | /** 648 | * 649 | * @param operand 650 | * @return 651 | */ 652 | public static Aggregate count(Operand operand) { 653 | return new Aggregate(SparqlAggregate.COUNT).addOperand(operand); 654 | } 655 | 656 | public static Aggregate countAll() { 657 | return new Aggregate(SparqlAggregate.COUNT).countAll(); 658 | } 659 | 660 | public static Aggregate group_concat(Operand... operands) { 661 | return new Aggregate(SparqlAggregate.GROUP_CONCAT).addOperand(operands); 662 | } 663 | 664 | public static Aggregate group_concat(String separator, Operand... operands) { 665 | return new Aggregate(SparqlAggregate.GROUP_CONCAT).addOperand(operands).separator(separator); 666 | } 667 | 668 | public static Aggregate max(Operand operand) { 669 | return new Aggregate(SparqlAggregate.MAX).addOperand(operand); 670 | } 671 | 672 | public static Aggregate min(Operand operand) { 673 | return new Aggregate(SparqlAggregate.MIN).addOperand(operand); 674 | } 675 | 676 | public static Aggregate sample(Operand operand) { 677 | return new Aggregate(SparqlAggregate.SAMPLE).addOperand(operand); 678 | } 679 | 680 | public static Aggregate sum(Operand operand) { 681 | return new Aggregate(SparqlAggregate.SUM).addOperand(operand); 682 | } 683 | } --------------------------------------------------------------------------------