blob: 9c9f87305871578eeb9adec4e5d9c7b1eb6b74b3 [file] [log] [blame]
/*
* 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.sse.writers;
import java.io.OutputStream ;
import java.util.Iterator ;
import java.util.List ;
import org.apache.jena.atlas.io.IndentedWriter ;
import org.apache.jena.graph.Triple ;
import org.apache.jena.query.Query ;
import org.apache.jena.query.SortCondition ;
import org.apache.jena.shared.PrefixMapping ;
import org.apache.jena.sparql.ARQConstants ;
import org.apache.jena.sparql.algebra.Op ;
import org.apache.jena.sparql.algebra.OpPrefixesUsed ;
import org.apache.jena.sparql.algebra.OpVisitor ;
import org.apache.jena.sparql.algebra.op.* ;
import org.apache.jena.sparql.algebra.table.TableEmpty;
import org.apache.jena.sparql.algebra.table.TableUnit ;
import org.apache.jena.sparql.core.* ;
import org.apache.jena.sparql.expr.Expr ;
import org.apache.jena.sparql.expr.ExprAggregator ;
import org.apache.jena.sparql.expr.ExprList ;
import org.apache.jena.sparql.pfunction.PropFuncArg ;
import org.apache.jena.sparql.serializer.SerializationContext ;
import org.apache.jena.sparql.sse.Tags ;
import org.apache.jena.sparql.util.FmtUtils ;
// ToDo extract write of:
// Table
// Triple and quads
public class WriterOp
{
private static final int NL = WriterLib.NL ;
private static final int NoNL = WriterLib.NoNL ; // No newline, with space
private static final int NoSP = WriterLib.NoSP ;
public static void output(Op op)
{ output(System.out, op) ; }
public static void output(Op op, PrefixMapping pMap)
{ output(System.out, op, pMap) ; }
public static void output(Op op, Prologue prologue)
{ output(System.out, op, prologue) ; }
public static void output(OutputStream out, Op op)
{ output(out, op, (PrefixMapping)null) ; }
public static void output(OutputStream out, Op op, PrefixMapping pMap)
{ output(new IndentedWriter(out), op, pMap) ; }
public static void output(OutputStream out, Op op, Prologue prologue)
{ output(new IndentedWriter(out), op, prologue) ; }
public static void output(IndentedWriter iWriter, Op op)
{ output(iWriter, op, (PrefixMapping)null) ; }
public static void output(IndentedWriter iWriter, Op op, PrefixMapping pMap) {
if ( pMap == null )
pMap = OpPrefixesUsed.used(op, ARQConstants.getGlobalPrefixMap()) ;
SerializationContext sCxt = new SerializationContext(pMap) ;
output(iWriter, op, sCxt) ;
}
public static void output(IndentedWriter iWriter, Op op, Prologue prologue) {
SerializationContext sCxt = new SerializationContext(prologue) ;
output(iWriter, op, sCxt) ;
}
public static void output(OutputStream out, Op op, SerializationContext sCxt) {
output(new IndentedWriter(out), op, sCxt) ;
}
// Actual work
public static void output(final IndentedWriter iWriter, final Op op, SerializationContext sCxt) {
if ( sCxt == null )
sCxt = new SerializationContext() ;
final SerializationContext sCxt2 = sCxt ;
WriterBasePrefix.Fmt fmt = new WriterBasePrefix.Fmt() {
@Override
public void format() {
op.visit(new OpWriterWorker(iWriter, sCxt2)) ;
}
} ;
WriterBasePrefix.output(iWriter, fmt, sCxt2.getPrologue()) ;
}
// Without the base/prefix wrapper.
static void outputNoPrologue(final IndentedWriter iWriter, final Op op, final SerializationContext sCxt) {
OpWriterWorker v = new OpWriterWorker(iWriter, sCxt) ;
op.visit(v) ;
}
public static class OpWriterWorker implements OpVisitor {
private IndentedWriter out ;
private SerializationContext sContext ;
public OpWriterWorker(IndentedWriter out, SerializationContext sCxt) {
this.sContext = sCxt ;
this.out = out ;
}
private void visitOpN(OpN op) {
start(op, NL) ;
for ( Iterator<Op> iter = op.iterator() ; iter.hasNext() ; ) {
Op sub = iter.next() ;
out.ensureStartOfLine() ;
printOp(sub) ;
}
finish(op) ;
}
private void visitOp2(Op2 op, ExprList exprs) {
start(op, NL) ;
printOp(op.getLeft()) ;
out.ensureStartOfLine() ;
printOp(op.getRight()) ;
if ( exprs != null ) {
out.ensureStartOfLine() ;
WriterExpr.output(out, exprs, sContext) ;
}
finish(op) ;
}
private void visitOp1(Op1 op) {
start(op, NL) ;
printOp(op.getSubOp()) ;
finish(op) ;
}
@Override
public void visit(OpBGP opBGP) {
if ( opBGP.getPattern().size() == 1 ) {
start(opBGP, NoNL) ;
write(opBGP.getPattern(), true) ;
finish(opBGP) ;
return ;
}
start(opBGP, NL) ;
write(opBGP.getPattern(), false) ;
finish(opBGP) ;
}
@Override
public void visit(OpQuadPattern opQuadP) {
QuadPattern quads = opQuadP.getPattern() ;
if ( quads.size() == 1 ) {
start(opQuadP, NoNL) ;
formatQuad(quads.get(0)) ;
finish(opQuadP) ;
return ;
}
start(opQuadP, NL) ;
write(quads, false) ;
finish(opQuadP) ;
}
@Override
public void visit(OpQuadBlock opQuads) {
QuadPattern quads = opQuads.getPattern() ;
if ( quads.size() == 1 ) {
start(opQuads, NoNL) ;
formatQuad(quads.get(0)) ;
finish(opQuads) ;
return ;
}
start(opQuads, NL) ;
write(quads, false) ;
finish(opQuads) ;
}
private void write(BasicPattern pattern, boolean oneLine) {
boolean first = true ;
for ( Triple t : pattern ) {
formatTriple(t) ;
if ( oneLine ) {
if ( !first )
out.print(" ") ;
} else
out.println() ;
first = false ;
}
}
private void write(QuadPattern quads, boolean oneLine) {
boolean first = true ;
for ( Quad t : quads ) {
formatQuad(t) ;
if ( oneLine ) {
if ( !first )
out.print(" ") ;
} else
out.println() ;
first = false ;
}
}
@Override
public void visit(OpTriple opTriple) {
formatTriple(opTriple.getTriple()) ;
}
@Override
public void visit(OpQuad opQuad) {
formatQuad(opQuad.getQuad()) ;
}
@Override
public void visit(OpPath opPath) {
// start(opPath, NoNL) ;
formatTriplePath(opPath.getTriplePath()) ;
// finish(opPath) ;
}
@Override
public void visit(OpFind opFind) {
start(opFind, NoNL) ;
out.print(opFind.getVar());
out.print(" ");
formatTriple(opFind.getTriple()) ;
out.println() ;
finish(opFind) ;
}
@Override
public void visit(OpProcedure opProc) {
start(opProc, NoNL) ;
WriterNode.output(out, opProc.getProcId(), sContext) ;
out.println() ;
WriterExpr.output(out, opProc.getArgs(), true, false, sContext) ;
out.println() ;
printOp(opProc.getSubOp()) ;
finish(opProc) ;
}
@Override
public void visit(OpPropFunc opPropFunc) {
start(opPropFunc, NoNL) ;
out.print(FmtUtils.stringForNode(opPropFunc.getProperty(), sContext)) ;
out.println() ;
outputPF(opPropFunc.getSubjectArgs()) ;
out.print(" ") ;
outputPF(opPropFunc.getObjectArgs()) ;
out.println() ;
printOp(opPropFunc.getSubOp()) ;
finish(opPropFunc) ;
}
private void outputPF(PropFuncArg pfArg) {
if ( pfArg.isNode() ) {
WriterNode.output(out, pfArg.getArg(), sContext) ;
return ;
}
WriterNode.output(out, pfArg.getArgList(), sContext) ;
}
@Override
public void visit(OpJoin opJoin) {
visitOp2(opJoin, null) ;
}
@Override
public void visit(OpSequence opSequence) {
visitOpN(opSequence) ;
}
@Override
public void visit(OpDisjunction opDisjunction) {
visitOpN(opDisjunction) ;
}
@Override
public void visit(OpLeftJoin opLeftJoin) {
visitOp2(opLeftJoin, opLeftJoin.getExprs()) ;
}
@Override
public void visit(OpDiff opDiff) {
visitOp2(opDiff, null) ;
}
@Override
public void visit(OpMinus opMinus) {
visitOp2(opMinus, null) ;
}
@Override
public void visit(OpUnion opUnion) {
visitOp2(opUnion, null) ;
}
@Override
public void visit(OpConditional opCondition) {
visitOp2(opCondition, null) ;
}
@Override
public void visit(OpFilter opFilter) {
start(opFilter, NoNL) ;
ExprList exprs = opFilter.getExprs() ;
if ( exprs == null ) {
start() ;
finish() ;
} else
WriterExpr.output(out, exprs, sContext) ;
out.println() ;
printOp(opFilter.getSubOp()) ;
finish(opFilter) ;
}
@Override
public void visit(OpGraph opGraph) {
start(opGraph, NoNL) ;
out.println(FmtUtils.stringForNode(opGraph.getNode(), sContext)) ;
opGraph.getSubOp().visit(this) ;
finish(opGraph) ;
}
@Override
public void visit(OpService opService) {
start(opService, NoNL) ;
if ( opService.getSilent() )
out.println("silent ") ;
out.println(FmtUtils.stringForNode(opService.getService(), sContext)) ;
opService.getSubOp().visit(this) ;
finish(opService) ;
}
@Override
public void visit(OpTable opTable) {
if ( TableUnit.isTableUnit(opTable.getTable()) ) {
start(opTable, NoNL) ;
out.print("unit") ;
finish(opTable) ;
return ;
}
if ( TableEmpty.isTableEmpty(opTable.getTable()) ) {
start(opTable, NoNL) ;
out.print("empty") ;
finish(opTable) ;
return ;
}
start(opTable, NoNL) ;
WriterNode.outputVars(out, opTable.getTable().getVars(), sContext) ;
if ( ! opTable.getTable().isEmpty() ) {
out.println();
WriterTable.outputPlain(out, opTable.getTable(), sContext) ;
}
finish(opTable) ;
}
@Override
public void visit(OpDatasetNames dsNames) {
start(dsNames, NoNL) ;
WriterNode.output(out, dsNames.getGraphNode(), sContext) ;
finish(dsNames) ;
}
@Override
public void visit(OpExt opExt) {
// start(opExt, NL) ;
opExt.output(out, sContext) ;
// finish(opExt) ;
}
@Override
public void visit(OpNull opNull) {
start(opNull, NoSP) ;
finish(opNull) ;
}
@Override
public void visit(OpLabel opLabel) {
String x = FmtUtils.stringForString(opLabel.getObject().toString()) ;
if ( opLabel.hasSubOp() ) {
start(opLabel, NL) ;
out.println(x) ;
printOp(opLabel.getSubOp()) ;
finish(opLabel) ;
} else {
start(opLabel, NoNL) ;
out.print(x) ;
finish(opLabel) ;
}
}
@Override
public void visit(OpList opList) {
visitOp1(opList) ;
}
@Override
public void visit(OpGroup opGroup) {
start(opGroup, NoNL) ;
writeNamedExprList(opGroup.getGroupVars()) ;
if ( !opGroup.getAggregators().isEmpty() ) {
// --- Aggregators
out.print(" ") ;
start() ;
out.incIndent() ;
boolean first = true ;
for ( ExprAggregator agg : opGroup.getAggregators() ) {
if ( !first ) {
out.print(" ") ;
}
first = false ;
Var v = agg.getVar() ;
String str = agg.getAggregator().toPrefixString() ;
start() ;
out.print(v.toString()) ;
out.print(" ") ;
out.print(str) ;
finish() ;
}
finish() ;
out.decIndent() ;
}
out.println() ;
printOp(opGroup.getSubOp()) ;
finish(opGroup) ;
}
@Override
public void visit(OpOrder opOrder) {
start(opOrder, NoNL) ;
// Write conditions
start() ;
boolean first = true ;
for ( SortCondition sc : opOrder.getConditions() ) {
if ( !first )
out.print(" ") ;
first = false ;
formatSortCondition(sc) ;
}
finish() ;
out.newline() ;
printOp(opOrder.getSubOp()) ;
finish(opOrder) ;
}
@Override
public void visit(OpTopN opTop) {
start(opTop, NoNL) ;
// Write conditions
start() ;
writeIntOrDefault(opTop.getLimit()) ;
out.print(" ") ;
boolean first = true ;
for ( SortCondition sc : opTop.getConditions() ) {
if ( !first )
out.print(" ") ;
first = false ;
formatSortCondition(sc) ;
}
finish() ;
out.newline() ;
printOp(opTop.getSubOp()) ;
finish(opTop) ;
}
// Neater would be a pair of explicit SortCondition formatters
private void formatSortCondition(SortCondition sc) {
boolean close = true ;
String tag = null ;
if ( sc.getDirection() != Query.ORDER_DEFAULT ) {
if ( sc.getDirection() == Query.ORDER_ASCENDING ) {
tag = Tags.tagAsc ;
WriterLib.start(out, tag, NoNL) ;
}
if ( sc.getDirection() == Query.ORDER_DESCENDING ) {
tag = Tags.tagDesc ;
WriterLib.start(out, tag, NoNL) ;
}
}
WriterExpr.output(out, sc.getExpression(), sContext) ;
if ( tag != null )
WriterLib.finish(out, tag) ;
}
@Override
public void visit(OpProject opProject) {
start(opProject, NoNL) ;
writeVarList(opProject.getVars()) ;
out.println() ;
printOp(opProject.getSubOp()) ;
finish(opProject) ;
}
@Override
public void visit(OpDistinct opDistinct) {
visitOp1(opDistinct) ;
}
@Override
public void visit(OpReduced opReduced) {
visitOp1(opReduced) ;
}
@Override
public void visit(OpAssign opAssign) {
start(opAssign, NoNL) ;
writeNamedExprList(opAssign.getVarExprList()) ;
out.println() ;
printOp(opAssign.getSubOp()) ;
finish(opAssign) ;
}
@Override
public void visit(OpExtend opExtend) {
start(opExtend, NoNL) ;
writeNamedExprList(opExtend.getVarExprList()) ;
out.println() ;
printOp(opExtend.getSubOp()) ;
finish(opExtend) ;
}
@Override
public void visit(OpSlice opSlice) {
start(opSlice, NoNL) ;
writeIntOrDefault(opSlice.getStart()) ;
out.print(" ") ;
writeIntOrDefault(opSlice.getLength()) ;
out.println() ;
printOp(opSlice.getSubOp()) ;
finish(opSlice) ;
}
private void writeIntOrDefault(long value) {
String x = "_" ;
if ( value != Query.NOLIMIT )
x = Long.toString(value) ;
out.print(x) ;
}
private void start(Op op, int newline) {
WriterLib.start(out, op.getName(), newline) ;
}
private void finish(Op op) {
WriterLib.finish(out, op.getName()) ;
}
private void start() {
WriterLib.start(out) ;
}
private void finish() {
WriterLib.finish(out) ;
}
private void printOp(Op op) {
if ( op == null ) {
WriterLib.start(out, Tags.tagNull, NoSP) ;
WriterLib.finish(out, Tags.tagNull) ;
} else
op.visit(this) ;
}
private void writeVarList(List<Var> vars) {
start() ;
boolean first = true ;
for ( Var var : vars ) {
if ( !first )
out.print(" ") ;
first = false ;
out.print(var.toString()) ;
}
finish() ;
}
private void writeNamedExprList(VarExprList project) {
start() ;
boolean first = true ;
for ( Var v : project.getVars() ) {
if ( !first )
out.print(" ") ;
first = false ;
Expr expr = project.getExpr(v) ;
if ( expr != null ) {
start() ;
out.print(v.toString()) ;
out.print(" ") ;
WriterExpr.output(out, expr, sContext) ;
finish() ;
} else
out.print(v.toString()) ;
}
finish() ;
}
private void formatTriple(Triple tp) {
WriterNode.output(out, tp, sContext) ;
}
private void formatQuad(Quad qp) {
WriterNode.output(out, qp, sContext) ;
}
private void formatTriplePath(TriplePath tp) {
WriterPath.output(out, tp, sContext) ;
}
}
}