GroupGraphPattern.java
/*******************************************************************************
* Copyright (c) 2018 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sparqlbuilder.graphpattern;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.rdf4j.sparqlbuilder.constraint.Expression;
import org.eclipse.rdf4j.sparqlbuilder.core.QueryElementCollection;
import org.eclipse.rdf4j.sparqlbuilder.util.SparqlBuilderUtils;
/**
* A SPARQL Group Graph Pattern
*
* @see <a href="http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#GroupPatterns"> SPARQL Group Graph Patterns</a>
*/
class GroupGraphPattern extends QueryElementCollection<GraphPattern> implements GraphPattern {
private static final String OPTIONAL = "OPTIONAL";
private static final String GRAPH = "GRAPH ";
private Optional<GraphName> from = Optional.empty();
private List<Filter> filters = new ArrayList<>();
protected boolean isOptional = false;
GroupGraphPattern() {
this(false);
}
GroupGraphPattern(boolean isOptional) {
this.isOptional = isOptional;
}
GroupGraphPattern(GraphPattern original) {
if (original instanceof GroupGraphPattern) {
copy((GroupGraphPattern) original);
} else if (original != null && !original.isEmpty()) {
elements.add(original);
}
}
protected void copy(GroupGraphPattern original) {
this.elements = original.elements;
this.isOptional = original.isOptional;
this.from = original.from;
this.filters = new ArrayList<>(original.filters);
}
@Override
public GroupGraphPattern and(GraphPattern... patterns) {
if (isEmpty() && patterns.length == 1 && (isGGP(patterns[0]))) {
copy(GraphPatterns.extractOrConvertToGGP(patterns[0]));
} else {
addElements(patterns);
}
return this;
}
@Override
public GroupGraphPattern optional(boolean isOptional) {
this.isOptional = isOptional;
return this;
}
@Override
public GroupGraphPattern from(GraphName name) {
from = Optional.of(name);
return this;
}
@Override
public GroupGraphPattern filter(Expression<?> constraint) {
filters.add(new Filter(constraint));
return this;
}
@Override
public boolean isEmpty() {
return super.isEmpty();
}
@Override
public String getQueryString() {
StringBuilder pattern = new StringBuilder();
StringBuilder innerPattern = new StringBuilder();
if (isOptional) {
pattern.append(OPTIONAL).append(" ");
}
SparqlBuilderUtils.appendQueryElementIfPresent(from, pattern, GRAPH, " ");
innerPattern.append(super.getQueryString());
filters.forEach(filter -> SparqlBuilderUtils.appendQueryElementIfPresent(
Optional.of(filter),
innerPattern, "\n", null));
if (bracketInner()) {
pattern.append(SparqlBuilderUtils.getBracedString(innerPattern.toString()));
} else {
pattern.append(innerPattern.toString());
}
return pattern.toString();
}
private static boolean isGGP(GraphPattern pattern) {
if (pattern instanceof GroupGraphPattern) {
return true;
}
if (pattern instanceof GraphPatternNotTriples) {
return ((GraphPatternNotTriples) pattern).gp instanceof GroupGraphPattern;
}
return false;
}
// Prevent extra brackets being added in the case of this graph pattern
// containing only one group graph pattern. Resulting syntax is
// logically equivalent and easier to read (and hopefully parse by query
// parsers) or make sure to add them if "modifiers" exist
private boolean bracketInner() {
return !(elements.size() == 1 && elements.iterator().next() instanceof GroupGraphPattern);
}
}