org.apache.jena.sparql.path.PathWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-arq Show documentation
Show all versions of jena-arq Show documentation
ARQ is a SPARQL 1.1 query engine for Apache Jena
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.sparql.path;
import static org.apache.jena.sparql.path.P_Mod.UNSET ;
import java.util.List ;
import org.apache.jena.atlas.io.IndentedLineBuffer ;
import org.apache.jena.atlas.io.IndentedWriter ;
import org.apache.jena.graph.Node ;
import org.apache.jena.sparql.ARQException ;
import org.apache.jena.sparql.core.Prologue ;
import org.apache.jena.sparql.util.FmtUtils ;
public class PathWriter {
public static void write(Path path, Prologue prologue) {
write(IndentedWriter.stdout, path, prologue) ;
}
public static void write(IndentedWriter out, Path path, Prologue prologue) {
PathWriterWorker w = new PathWriterWorker(out, prologue) ;
path.visit(w) ;
out.flush() ;
}
public static String asString(Path path) {
return asString(path, null) ;
}
public static String asString(Path path, Prologue prologue) {
IndentedLineBuffer buff = new IndentedLineBuffer() ;
PathWriterWorker w = new PathWriterWorker(buff, prologue) ;
path.visit(w) ;
w.out.flush() ;
return buff.asString() ;
}
static class PathWriterWorker implements PathVisitor {
private IndentedWriter out ;
private Prologue prologue ;
private static boolean alwaysInnerParens = true ;
private boolean needParens = false ;
PathWriterWorker(IndentedWriter indentedWriter, Prologue prologue) {
this.out = indentedWriter ;
this.prologue = prologue ;
}
private void visitPath(Path path) {
visitPath(path, true) ;
}
private void visitPath(Path path, boolean needParensThisTime) {
if ( alwaysInnerParens )
needParensThisTime = true ;
boolean b = needParens ;
needParens = needParensThisTime ;
path.visit(this) ;
needParens = b ;
}
private void output(Node node) {
out.print(FmtUtils.stringForNode(node, prologue)) ;
}
private void output(P_Path0 path0) {
if ( !path0.isForward() )
out.print("^") ;
out.print(FmtUtils.stringForNode(path0.getNode(), prologue)) ;
}
@Override
public void visit(P_Link pathNode) {
output(pathNode.getNode()) ;
}
@Override
public void visit(P_ReverseLink pathNode) {
out.println("^") ;
output(pathNode.getNode()) ;
}
@Override
public void visit(P_NegPropSet pathNotOneOf) {
List props = pathNotOneOf.getNodes() ;
if ( props.size() == 0 )
throw new ARQException("Bad path element: NotOneOf found with no elements") ;
out.print("!") ;
if ( props.size() == 1 )
output(props.get(0)) ;
else {
out.print("(") ;
boolean first = true ;
for ( P_Path0 p : props ) {
if ( !first )
out.print("|") ;
first = false ;
output(p) ;
}
out.print(")") ;
}
}
@Override
public void visit(P_Alt pathAlt) {
visit2(pathAlt, "|", true) ;
}
@Override
public void visit(P_Seq pathSeq) {
visit2(pathSeq, "/", false) ;
}
// Should pass around precedence numbers.
private void visit2(P_Path2 path2, String sep, boolean isSeq) {
if ( needParens )
out.print("(") ;
visitPath(path2.getLeft()) ;
out.print(sep) ;
// Don't need parens if same as before.
if ( isSeq ) {
// Make / and ^ chains look nice
if ( path2.getRight() instanceof P_Seq )
visitPath(path2.getRight(), needParens) ;
else
visitPath(path2.getRight(), true) ;
} else
visitPath(path2.getRight(), true) ;
if ( needParens )
out.print(")") ;
}
@Override
public void visit(P_Mod pathMod) {
if ( needParens )
out.print("(") ;
if ( alwaysInnerParens )
out.print("(") ;
pathMod.getSubPath().visit(this) ;
if ( alwaysInnerParens )
out.print(")") ;
out.print("{") ;
if ( pathMod.getMin() != UNSET )
out.print(Long.toString(pathMod.getMin())) ;
out.print(",") ;
if ( pathMod.getMax() != UNSET )
out.print(Long.toString(pathMod.getMax())) ;
out.print("}") ;
if ( needParens )
out.print(")") ;
}
@Override
public void visit(P_FixedLength pFixedLength) {
if ( needParens )
out.print("(") ;
if ( alwaysInnerParens )
out.print("(") ;
pFixedLength.getSubPath().visit(this) ;
if ( alwaysInnerParens )
out.print(")") ;
out.print("{") ;
out.print(Long.toString(pFixedLength.getCount())) ;
out.print("}") ;
if ( needParens )
out.print(")") ;
}
@Override
public void visit(P_Distinct pathDistinct) {
out.print("DISTINCT(") ;
pathDistinct.getSubPath().visit(this) ;
out.print(")") ;
}
@Override
public void visit(P_Multi pathMulti) {
out.print("MULTI(") ;
pathMulti.getSubPath().visit(this) ;
out.print(")") ;
}
@Override
public void visit(P_Shortest path) {
out.print("SHORTEST(") ;
path.getSubPath().visit(this) ;
out.print(")") ;
}
@Override
public void visit(P_ZeroOrOne path)
{ printPathMod("?", path.getSubPath()) ; }
@Override
public void visit(P_ZeroOrMore1 path)
{ printPathMod("*", path.getSubPath()) ; }
@Override
public void visit(P_ZeroOrMoreN path)
{ printPathMod("{*}", path.getSubPath()) ; }
@Override
public void visit(P_OneOrMore1 path)
{ printPathMod("+", path.getSubPath()) ; }
@Override
public void visit(P_OneOrMoreN path)
{ printPathMod("{+}", path.getSubPath()) ; }
private void printPathMod(String mod, Path path) {
boolean doParens = (needParens || alwaysInnerParens) ;
if ( doParens )
out.print("(") ;
path.visit(this) ;
if ( doParens )
out.print(")") ;
out.print(mod) ;
}
// Need to consider binary ^ (not part of SPARQL)
@Override
public void visit(P_Inverse inversePath) {
out.print("^") ;
Path p = inversePath.getSubPath() ;
boolean parens = true ;
if ( p instanceof P_Link )
parens = false ;
visitPath(p, parens) ;
}
}
}