public static <O> Optional<O> getOrCreateAndModifyOptional(Optional<O> optional, Supplier<O> getter, UnaryOperator<O> operator) {
	return Optional.of(operator.apply(optional.orElseGet(getter)));
} public class Base implements QueryElement {
	private static final String BASE = "BASE ";

	private Iri iri;

	Base(Iri iri) {
		this.iri = iri;
	}

	@Override
	public String getQueryString() {
		return BASE + iri.getQueryString();
	}
} public class Prefix implements QueryElement {
	private static final String PREFIX = "PREFIX";
	private String label;
	private Iri iri;

	Prefix(String alias, Iri iri) {
		this.label = alias;
		this.iri = iri;
	}

	/**
	 * Create a prefixed IRI reference from this prefix
	 * 
	 * @param localName
	 *            the local part of the prefixed IRI
	 * @return a prefixed IRI reference, with this prefix's label as the base,
	 *         and the given string for the local part
	 */
	public Iri iri(String localName) {		
		return () -> label + ":" + localName;
	}

	@Override
	public String getQueryString() {
		return PREFIX + " " + label + ": " + iri.getQueryString();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj == null) {
			return false;
		}

		if (!(obj instanceof Prefix)) {
			return false;
		}

		Prefix other = (Prefix) obj;
		if (label == null) {
			if (other.label != null) {
				return false;
			}
		} else if (!label.equals(other.label)) {
			return false;
		}
		if (iri == null) {
			if (other.iri != null) {
				return false;
			}
		} else if (!iri.equals(other.iri)) {
			return false;
		}

		return true;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((label == null) ? 0 : label.hashCode());
		result = prime * result + ((iri == null) ? 0 : iri.hashCode());
		return result;
	}
} public class PrefixDeclarations extends StandardQueryElementCollection<PrefixDeclarations, Prefix> {
	/**
	 * Add prefix declarations to this collection
	 * 
	 * @param prefixes
	 * @return this
	 */
	public PrefixDeclarations addPrefix(Prefix... prefixes) {
		return addElements(prefixes);
	}
} public interface QueryElement {
	/**
	 * @return the String representing the SPARQL syntax of this element
	 */
	public String getQueryString();
} public class Spanqit {
	// prevent instantiation of this class
	private Spanqit() { }

	/**
	 * Create a SPARQL variable with a specific alias.
	 * 
	 * @param varName
	 *            the alias of the variable
	 * @return a new SPARQL variable
	 */
	public static Variable var(String varName) {
		return new Variable(varName);
	}
	
	/**
	 * Create a SPARQL assignment
	 * 
	 * @param exp
	 *            the expression to evaluate
	 * @param var
	 *            the variable to bind the expression value to
	 * @return an Assignment object
	 */
	public static Assignment as(Assignable exp, Variable var) {
		return new Assignment(exp, var);
	}

	/**
	 * Create a SPARQL Base declaration
	 * 
	 * @param iri
	 *            the base iri
	 * @return a Base object
	 */
	public static Base base(Iri iri) {
		return new Base(iri);
	}

	/**
	 * Create a SPARQL Prefix declaration
	 * 
	 * @param alias
	 *            the alias of the prefix
	 * @param iri
	 *            the iri the alias refers to
	 * @return a Prefix object
	 */
	public static Prefix prefix(String alias, Iri iri) {
		return new Prefix(alias, iri);
	}

	/**
	 * Create a SPARQL default Prefix declaration
	 * 
	 * @param iri
	 *            the default iri prefix
	 * @return a Prefix object
	 */
	public static Prefix prefix(Iri iri) {
		return prefix("", iri);
	}
	
	/**
	 * Create a SPARQL Prefix clause
	 * 
	 * @param prefixes
	 *            prefix declarations to add to this Prefix clause
	 * @return a new
	 */
	public static PrefixDeclarations prefixes(Prefix... prefixes) {
		return new PrefixDeclarations().addPrefix(prefixes);
	}

	/**
	 * Create a default graph reference
	 * 
	 * @param iri
	 *            the source of the graph
	 * @return a From clause
	 * 
	 * @see <a
	 *      href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rdfDataset">
	 *      RDF Datasets</a>
	 */
	public static From from(Iri iri) {
		return new From(iri);
	}

	/**
	 * Create a named graph reference
	 *
	 * @param iri
	 *            the source of the graph
	 * @return a named From clause
	 * 
	 * @see <a
	 *      href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rdfDataset">
	 *      RDF Datasets</a>
	 */
	public static From fromNamed(Iri iri) {
		return new From(iri, true);
	}

	/**
	 * Create a dataset declaration
	 * 
	 * @param graphs
	 * @return a new dataset clause
	 * 
	 * @see <a
	 *      href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rdfDataset">
	 *      RDF Datasets</a>
	 */
	public static Dataset dataset(From... graphs) {
		return new Dataset().from(graphs);
	}

	/**
	 * Create a SPARQL projection
	 * 
	 * @param projectables
	 *            projectable elements to add to the projection
	 * @return a Projection
	 */
	public static Projection select(Projectable... projectables) {
		return new Projection().select(projectables);
	}

	/**
	 * Create a SPARQL graph template
	 * 
	 * @param triples
	 *            triples to add to the template
	 * @return a new SPARQL graph template
	 */
	public static GraphTemplate construct(TriplePattern... triples) {
		return new GraphTemplate().construct(triples);
	}

	/**
	 * Create a SPARQL query pattern
	 * 
	 * @param patterns
	 *            graph patterns to add to the query pattern
	 * @return a new Query Pattern
	 */
	public static QueryPattern where(GraphPattern... patterns) {
		return new QueryPattern().where(patterns);
	}

	/**
	 * Create a SPARQL Group By clause
	 * 
	 * @param groupables
	 *            the group conditions
	 * @return a Group By clause
	 */
	public static GroupBy groupBy(Groupable... groupables) {
		return new GroupBy().by(groupables);
	}

	/**
	 * Create a SPARQL Order clause
	 * 
	 * @param conditions
	 *            the order conditions
	 * @return an Order By clause
	 */
	public static OrderBy orderBy(Orderable... conditions) {
		return new OrderBy().by(conditions);
	}

	/**
	 * Create a SPARQL Having clause
	 * 
	 * @param expressions
	 *            the having conditions
	 * @return a Having clause
	 */
	public static Having having(Expression<?>... expressions) {
		return new Having().having(expressions);
	}

	/**
	 * Create an ascending SPARQL order condition
	 * 
	 * @param orderOn
	 *            the order comparator
	 * @return an ASC() order condition
	 */
	public static OrderCondition asc(Orderable orderOn) {
		return new OrderCondition(orderOn, true);
	}

	/**
	 * Create a descending SPARQL order condition
	 * 
	 * @param orderOn
	 *            the order comparator
	 * @return a DESC() order condition
	 */
	public static OrderCondition desc(Orderable orderOn) {
		return new OrderCondition(orderOn, false);
	}
	
	/**
	 * Create a TriplesTemplate instance, for use with Construct and Update queries
	 * 
	 * @param triples
	 * 			the triples to include in the triples template
	 * @return a TriplesTemplate of the given triples
	 */
	public static TriplesTemplate triplesTemplate(TriplePattern... triples) {
		return new TriplesTemplate(triples);
	}
} @SuppressWarnings("javadoc")
public class SpanqitUtils {
	private static final String PAD = " ";

	public static <O> Optional<O> getOrCreateAndModifyOptional(Optional<O> optional, Supplier<O> getter, UnaryOperator<O> operator) {
		return Optional.of(operator.apply(optional.orElseGet(getter)));
	}
	
	public static void appendAndNewlineIfPresent(Optional<? extends QueryElement> elementOptional, StringBuilder builder) {
		appendQueryElementIfPresent(elementOptional, builder, null, "\n");
	}
	
	public static void appendQueryElementIfPresent(Optional<? extends QueryElement> queryElementOptional, StringBuilder builder, String prefix, String suffix) {
		appendStringIfPresent(queryElementOptional.map(QueryElement::getQueryString), builder, prefix, suffix);
	}
	
	public static void appendStringIfPresent(Optional<String> stringOptional, StringBuilder builder, String prefix, String suffix) {
		Optional<String> preOpt = Optional.ofNullable(prefix);
		Optional<String> sufOpt = Optional.ofNullable(suffix);
		
		stringOptional.ifPresent(string -> {
			preOpt.ifPresent(p -> builder.append(p));
			builder.append(string);
			sufOpt.ifPresent(s -> builder.append(s));
		});
	}
	
	public static String getBracedString(String contents) {
		return getEnclosedString("{", "}", contents);
	}

	public static String getBracketedString(String contents) {
		return getEnclosedString("[", "]", contents);
	}
	
	public static String getParenthesizedString(String contents) {
		return getEnclosedString("(", ")", contents);
	}

	public static String getQuotedString(String contents) {
		return getEnclosedString("\"", "\"", contents, false);
	}

	/**
	 * For string literals that contain single- or double-quotes
	 * 
	 * @see <a href="https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#QSynLiterals">
	 * RDF Literal Syntax</a>
	 * @param contents
	 * @return a "long quoted" string
	 */
	public static String getLongQuotedString(String contents) {
		return getEnclosedString("'''", "'''", contents, false);
	}
	
	private static String getEnclosedString(String open, String close,
			String contents) {
		return getEnclosedString(open, close, contents, true);
	}

	private static String getEnclosedString(String open, String close,
			String contents, boolean pad) {
		StringBuilder es = new StringBuilder();

		es.append(open);
		if (contents != null && !contents.isEmpty()) {
			es.append(contents);
			if (pad) {
				es.insert(open.length(), PAD).append(PAD);
			}
		} else {
			es.append(PAD);
		}
		es.append(close);

		return es.toString();
	}
} public class TriplesTemplate extends QueryElementCollection<TriplePattern> {
	TriplesTemplate(TriplePattern... triples) {
		super(" .\n");
		and(triples);
	}

	/**
	 * add triples to this template
	 * 
	 * @param triples the triples to add
	 * 
	 * @return this TriplesTemplate instance
	 */
	public TriplesTemplate and(TriplePattern... triples) {
		Collections.addAll(elements, triples);
		
		return this;
	}
	
	@Override
	public String getQueryString() {
		return SpanqitUtils.getBracedString(super.getQueryString());
	}

} public interface GraphName extends QueryElement { } public interface Iri extends RdfResource, RdfPredicate, GraphName { }
import static com.anqit.spanqit.core.SpanqitUtils.getOrCreateAndModifyOptional;
import java.util.Optional;
import com.anqit.spanqit.core.Base;
import com.anqit.spanqit.core.Prefix;
import com.anqit.spanqit.core.PrefixDeclarations;
import com.anqit.spanqit.core.QueryElement;
import com.anqit.spanqit.core.Spanqit;
import com.anqit.spanqit.core.SpanqitUtils;
import com.anqit.spanqit.core.TriplesTemplate;
import com.anqit.spanqit.graphpattern.GraphName;
import com.anqit.spanqit.rdf.Iri;
package com.anqit.spanqit.core.query;




/**
 * A SPARQL Update query
 * 
 * @param <T> The type of update query. Used to support fluency. 
 *
 * @see <a
 * 		 href="https://www.w3.org/TR/sparql11-update/">
 * 		 SPARQL Update Query</a>
 */
@SuppressWarnings("unchecked")
abstract class UpdateQuery<T extends UpdateQuery<T>> implements QueryElement {
	private Optional<Base> base = Optional.empty();
	private Optional<PrefixDeclarations> prefixes = Optional.empty();
	
	UpdateQuery() {	}

	/**
	 * Set the base IRI of this query
	 * 
	 * @param iri
	 *            the base IRI
	 * @return this
	 */
	public T base(Iri iri) {
		this.base = Optional.of(Spanqit.base(iri));