/*
 * 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.algebra ;

import java.util.* ;
import java.util.function.BiConsumer ;
import java.util.stream.Collectors ;

import org.apache.jena.atlas.lib.NotImplemented ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.Triple ;
import org.apache.jena.query.Query ;
import org.apache.jena.query.QueryFactory ;
import org.apache.jena.query.SortCondition ;
import org.apache.jena.query.Syntax ;
import org.apache.jena.sparql.ARQInternalErrorException ;
import org.apache.jena.sparql.ARQNotImplemented ;
import org.apache.jena.sparql.algebra.op.* ;
import org.apache.jena.sparql.core.BasicPattern ;
import org.apache.jena.sparql.core.Quad ;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.core.VarExprList ;
import org.apache.jena.sparql.engine.QueryIterator ;
import org.apache.jena.sparql.expr.* ;
import org.apache.jena.sparql.expr.aggregate.Aggregator ;
import org.apache.jena.sparql.pfunction.PropFuncArg ;
import org.apache.jena.sparql.syntax.* ;
import org.apache.jena.sparql.syntax.syntaxtransform.*;
import org.apache.jena.sparql.util.graph.GraphList ;
import org.apache.jena.vocabulary.RDF ;

/**
 * Convert an Op expression in SPARQL syntax, that is, the reverse of algebra
 * generation.
 * <p>
 * The contract is to return an "equivalent query" - generates the same answers -
 * to the original query that generated the algebra.
 * That may be the same query (the code aims for this, assuming the original query
 * didn't have additional, unnecessary {}),
 * different queries with the same alegra forms,
 * or different equivalent queries - same answers, different algebra -
 * usually where extra {} are added in and not easiely cleaned out.
 * <p>
 * Some attempt is made to handle algebra expressions with operators from the optimizer.
 * <p>
 * It is possible to build algrebra expressions directly for which there is no SPARQL query
 * that generates that algebra.  This code may produce an equivalent query but that is
 * not guaranteed.
 */
public class OpAsQuery {
    // Some things that can be done further:

    // TODO Optimization formats like OpTopN (which is an optimizer additional algebra operator).
    // TODO More group flattening. This is better presentation, not chanage in algebra.
    //    OPTIONAL (LeftJoin) unbundles the LHS to avoid { { P OPTIONAL{} } OPTIONAL{} }
    //    {   { ... } BIND } -- the inner { } is not necessary
    //       This is actually a general situation.
    //   Adding onto the end of a group when the item added can not merge into the existing last element.
    // e.g. BIND, VALUES.

    public static Query asQuery(Op op) {
        Converter converter = new Converter(op) ;
        return converter.convert() ;
    }

    static class /* struct */ QueryLevelDetails {
        // The stack of processing in a query is:
        // slice-distinct/reduce-project-order-filter[having]-extend*[AS and aggregate naming]-group-pattern

        OpSlice        opSlice    = null ;
        OpDistinct     opDistinct = null ;
        OpReduced      opReduced  = null ;
        OpProject      opProject  = null ;
        OpOrder        opOrder    = null ;
        OpFilter       opHaving   = null ;
        List<OpExtend> opExtends  = new ArrayList<>() ;
        OpGroup        opGroup    = null ;
        // End of the modifiers.
        // The pattern of the group or query itself if not grouped.
        Op             pattern    = null ;

        private QueryLevelDetails() {}

        // Debugging help.
        void info() {
            if ( opSlice != null )
                System.out.printf("slice: (%d, %d)\n", opSlice.getStart(), opSlice.getLength()) ;
            if ( opDistinct != null )
                System.out.printf("distinct\n") ;
            if ( opReduced != null )
                System.out.printf("reduced\n") ;
            if ( opProject != null )
                System.out.printf("project: %s\n", opProject.getVars()) ;
            if ( opOrder != null )
                System.out.printf("order: %s\n", opOrder.getConditions()) ;
            if ( opHaving != null )
                System.out.printf("having: %s\n", opHaving.getExprs()) ;
            if ( opExtends != null && !opExtends.isEmpty() ) {
                List<VarExprList> z = opExtends.stream().map(x -> x.getVarExprList()).collect(Collectors.toList()) ;
                System.out.printf("assigns: %s\n", z) ;
            }
            if ( opGroup != null ) {
                List<ExprAggregator> aggregators = opGroup.getAggregators() ;
                List<Var> aggVars = aggregators.stream().map(x -> x.getAggVar().asVar()).collect(Collectors.toList()) ;
                System.out.printf("group: %s |-| %s\n", opGroup.getGroupVars(), opGroup.getAggregators()) ;
                System.out.printf("group agg vars: %s\n", aggVars) ;
            }
        }

        static QueryLevelDetails analyse(Op operation) {
            // Walk inwards, collecting the query level information.
            // slice-distinct/reduce-project-order-filter[having]-extend*[AS and aggregate naming]-group-pattern
            QueryLevelDetails details = new QueryLevelDetails() ;

            Op op = operation ;
            if ( op instanceof OpSlice ) {
                details.opSlice = (OpSlice)op ;
                op = details.opSlice.getSubOp() ;
            }
            if ( op instanceof OpDistinct ) {
                details.opDistinct = (OpDistinct)op ;
                op = details.opDistinct.getSubOp() ;
            }
            if ( op instanceof OpReduced ) {
                details.opReduced = (OpReduced)op ;
                op = details.opReduced.getSubOp() ;
            }
            if ( op instanceof OpProject ) {
                details.opProject = (OpProject)op ;
                op = details.opProject.getSubOp() ;

            }
            if ( op instanceof OpOrder ) {
                details.opOrder = (OpOrder)op ;
                op = details.opOrder.getSubOp() ;
            }

            // Lookahead to see if an opGroup can be found.
            // If no group, leave and process as in WHERE clause.
            details.opGroup = getGroup(op) ;
            if ( details.opGroup == null ) {
                // If project, deal with as AS.
                // Else as regular WHERE
                if ( details.opProject != null ) {
                    op = processExtend(op, details.opExtends) ;
                    details.pattern = op ;
                } else
                    details.pattern = op ;
                return details ;
            }
            // (group) found.
            details.pattern = details.opGroup.getSubOp() ;
            if ( op instanceof OpFilter ) {
                details.opHaving = (OpFilter)op ;
                op = details.opHaving.getSubOp() ;
            }
            // Can't tell if it's an "aggregation" except by looking at the
            // assignment variables.

            // AS and aggregate renames.
            op = processExtend(op, details.opExtends) ;

            if ( !(op instanceof OpGroup) ) {
                System.out.println("Expected (group), got " + op.getName()) ;
            }

            return details ;
        }
    }

    public static class Converter implements OpVisitor {
        private Query               query ;
        private Op                  queryOp ;
        private Element             element      = null ;
        private ElementGroup        currentGroup = null ;
        private Deque<ElementGroup> stack        = new ArrayDeque<>() ;
        private boolean             hasRun       = false ;

        public Converter(Op op) {
            this.query = null ;
            this.queryOp = op ;
            currentGroup = new ElementGroup() ;
        }

        Query convert() {
            if ( !hasRun )
                try {
                    // Which may be broken, or null, if something went wrong.
                    query = convertInner() ;
                }
                finally {
                    this.hasRun = true ;
                }
            return query ;
        }

        Query convertInner() {
            this.query = QueryFactory.create() ;
            // Special case. SELECT * { ... BIND (  AS ...) }
            if ( queryOp instanceof OpExtend ) {
                List<OpExtend> assignments = new ArrayList<>() ;
                Op op = processExtend(queryOp, assignments) ;
                processQueryPattern(op, assignments) ;
                query.setQueryResultStar(true) ;
                query.resetResultVars();
                return query ;
            }

            // There is a projection.
            QueryLevelDetails level = QueryLevelDetails.analyse(queryOp) ;
            processQueryPattern(level) ;

            // Modifier stack.
            // slice-distinct/reduce-project-order-filter[having]-extend[AS]-extend[agg]-group-pattern
            // Do as executed (the reverse order) because e.g. extends have effects on project.

            // Substitution mapping
            Map<ExprVar, Expr> aggVarExprMap = new HashMap<>() ;

            if ( level.opGroup != null ) {
                query.getGroupBy().addAll(level.opGroup.getGroupVars()) ;
                level.opGroup.getAggregators().forEach(eAgg -> {
                    ExprVar v = eAgg.getAggVar() ;
                    Aggregator agg = eAgg.getAggregator() ;
                    aggVarExprMap.put(v, eAgg) ;
                }) ;
                query.getAggregators().addAll(level.opGroup.getAggregators()) ;
            }

            ExprTransform varToExpr = new ExprTransformCopy() {
                @Override
                public Expr transform(ExprVar nv) {
                    if ( aggVarExprMap.containsKey(nv) )
                        return aggVarExprMap.get(nv) ;
                    return nv ;
                }
            } ;

            // The assignments will become part of the project.
            Map<Var, Expr> assignments = new HashMap<>() ;
            if ( level.opExtends != null ) {
                processExtends(level.opExtends, (var,expr)->{
                    // Internal rename.
                    expr = rewrite(expr, varToExpr) ;
                    assignments.put(var, expr) ;
                }) ;

            }

            if ( level.opHaving != null ) {
                level.opHaving.getExprs().getList().forEach(expr -> {
                    expr = rewrite(expr, varToExpr) ;
                    query.getHavingExprs().add(expr) ;
                }) ;
            }

            if ( level.opOrder != null ) {
                level.opOrder.getConditions().forEach(sc -> {
                    Expr expr = sc.getExpression() ;
                    expr = rewrite(expr, varToExpr) ;
                    if ( expr == sc.getExpression() )
                        query.addOrderBy(sc) ;
                    else
                        query.addOrderBy(new SortCondition(expr, sc.getDirection())) ;
                }) ;
            }

            if ( level.opProject == null ) {
                query.setQueryResultStar(true) ;
                // No project, Make BINDs
                //processQueryPattern(op, assignments) ;


            } else {
                level.opProject.getVars().forEach(v -> {
                    if ( assignments.containsKey(v) ) {
                        query.addResultVar(v, assignments.get(v)) ;
                    } else
                        query.getProjectVars().add(v) ;

                }) ;
            }


            if ( level.opDistinct != null )
                query.setDistinct(true) ;
            if ( level.opReduced != null )
                query.setReduced(true) ;

            if ( level.opSlice != null ) {
                query.setOffset(level.opSlice.getStart()) ;
                query.setLimit(level.opSlice.getLength()) ;
            }
            query.resetResultVars() ;
            return query ;
        }

        /**
         * Collect the OpExtend in a stack of OpExtend into a list for later
         * processing. (Processing only uses opExtend in the list, not inner one
         * which wil also be in the list.)
         */
        private static Op processExtend(Op op, List<OpExtend> assignments) {
            while ( op instanceof OpExtend ) {
                OpExtend opExtend = (OpExtend)op ;
                // JENA-1843
                assignments.add(0, opExtend) ;
                op = opExtend.getSubOp() ;
            }
            return op ;
        }

        private static void processExtends(List<OpExtend> ext, BiConsumer<Var, Expr> action) {
            ext.forEach(extend->{
                extend.getVarExprList().forEachVarExpr(action) ;
            });
        }

        private static void processAssigns(List<OpAssign> assigns, BiConsumer<Var, Expr> action) {
            assigns.forEach(assign->{
                assign.getVarExprList().forEachExpr(action) ;
            });
        }

        private static Expr rewrite(Expr expr, ExprTransform transform) {
            return ExprTransformer.transform(transform, expr) ;
        }

        /**
         * Process for a single pattern below the modifiers.
         * Cleans up the ElementGroup produced.
         */
        private void processQueryPattern(QueryLevelDetails level) {
            Op op = level.pattern ;
            op.visit(this) ;
            ElementGroup eg = this.currentGroup ;
            Element e = fixupGroupsOfOne(eg) ;
            query.setQueryPattern(e) ;
            query.setQuerySelectType() ;
        }

        // Can't distinguish
        //    SELECT * { ... BIND ( ?v AS ...) }
        // from
        //    SELECT ( ?v AS ...) { ... }.
        // They have the same algebra.
        // This code chooses to use the second form.
        private void processQueryPattern(Op op, List<OpExtend> assignments) {
            op.visit(this) ;
            ElementGroup eg = this.currentGroup ;
            processExtends(assignments,(v,e)->eg.addElement(new ElementBind(v, e)) ) ;
            Element e = cleanupGroup(eg) ;
            query.setQueryPattern(e) ;
            query.setQuerySelectType() ;
        }

        private Element cleanupGroup(ElementGroup eg) {
            Element el = fixupGroupsOfOne(eg);
            // Other cleanups.
            return el;
        }
        
        private Element fixupGroupsOfOne(ElementGroup eg) {
            ElementTransform transform = new ElementTransformCleanGroupsOfOne() ;
            ExprTransform exprTransform = new ExprTransformApplyElementTransform(transform) ;
            Element el2 = ElementTransformer.transform(eg, transform, exprTransform) ;
            // Top level is always a group or a subquery.
            if ( ! ( el2 instanceof ElementGroup ) && ! ( el2 instanceof ElementSubQuery ) ) {
                ElementGroup eg2 = new ElementGroup() ;
                eg2.addElement(el2);
                el2 = eg2 ;
            }
            return el2 ;
        }

        private Element asElement(Op op) {
            ElementGroup g = asElementGroup(op) ;
            if ( g.size() == 1 )
                return g.get(0) ;
            return g ;
        }

        private ElementGroup asElementGroup(Op op) {
            startSubGroup() ;
            op.visit(this) ;
            return endSubGroup() ;
        }

        @Override
        public void visit(OpBGP opBGP) {
            currentGroup().addElement(process(opBGP.getPattern())) ;
        }

        @Override
        public void visit(OpTriple opTriple) {
            currentGroup().addElement(process(opTriple.getTriple())) ;
        }

        @Override
        public void visit(OpQuad opQuad) {
            throw new ARQNotImplemented("OpQuad") ;
        }

        @Override
        public void visit(OpFind opFind) {
            Element elt = new ElementFind(opFind.getVar(), opFind.getTriple());
            currentGroup().addElement(elt) ;
        }

        @Override
        public void visit(OpProcedure opProcedure) {
            throw new ARQNotImplemented("OpProcedure") ;
        }

        @Override
        public void visit(OpPropFunc opPropFunc) {
            Node s = processPropFuncArg(opPropFunc.getSubjectArgs()) ;
            Node o = processPropFuncArg(opPropFunc.getObjectArgs()) ;
            Triple t = new Triple(s, opPropFunc.getProperty(), o) ;
            currentGroup().addElement(process(t)) ;
        }

        private Node processPropFuncArg(PropFuncArg args) {
            if ( args.isNode() )
                return args.getArg() ;

            // List ...
            List<Node> list = args.getArgList() ;
            if ( list.size() == 0 )
                return RDF.Nodes.nil ;
            BasicPattern bgp = new BasicPattern() ;
            Node head = GraphList.listToTriples(list, bgp) ;
            currentGroup().addElement(process(bgp)) ;
            return head ;
        }

        // There is one special case to consider:
        // A path expression was expanded into a OpSequence during Algenra
        // generation. The simple path expressions become an OpSequence that could be
        // recombined into an ElementPathBlock.

        @Override
        public void visit(OpSequence opSequence) {
            ElementGroup g = currentGroup() ;
            boolean nestGroup = !g.isEmpty() ;
            if ( nestGroup ) {
                startSubGroup() ;
                g = currentGroup() ;
            }

            for ( Op op : opSequence.getElements() ) {
                Element e = asElement(op) ;
                insertIntoGroup(g, e) ;
            }

            if ( nestGroup )
                endSubGroup() ;
            return ;
        }

        @Override
        public void visit(OpDisjunction opDisjunction) {
            throw new ARQNotImplemented("OpDisjunction") ;
        }

        private Element process(BasicPattern pattern) {
            // The different SPARQL versions (1.0, 1.1) use different internal
            // structures for BGPs.
            if ( query.getSyntax() == Syntax.syntaxSPARQL_10 ) {
                ElementTriplesBlock e = new ElementTriplesBlock() ;
                for ( Triple t : pattern )
                    // Leave bNode variables as they are
                    // Query serialization will deal with them.
                    e.addTriple(t) ;
                return e ;
            }

            if ( query.getSyntax() == Syntax.syntaxSPARQL_11 || query.getSyntax() == Syntax.syntaxARQ ) {
                ElementPathBlock e = new ElementPathBlock() ;
                for ( Triple t : pattern )
                    // Leave bNode variables as they are
                    // Query serialization will deal with them.
                    e.addTriple(t) ;
                return e ;
            }

            throw new ARQInternalErrorException("Unrecognized syntax: " + query.getSyntax()) ;
        }

        private ElementTriplesBlock process(Triple triple) {
            // Unsubtle
            ElementTriplesBlock e = new ElementTriplesBlock() ;
            e.addTriple(triple) ;
            return e ;
        }

        @Override
        public void visit(OpQuadPattern quadPattern) {
            Node graphNode = quadPattern.getGraphNode() ;
            if ( graphNode.equals(Quad.defaultGraphNodeGenerated) ) {
                currentGroup().addElement(process(quadPattern.getBasicPattern())) ;
            } else {
                startSubGroup() ;
                Element e = asElement(new OpBGP(quadPattern.getBasicPattern())) ;
                endSubGroup() ;

                // If not element group make it one
                if ( !(e instanceof ElementGroup) ) {
                    ElementGroup g = new ElementGroup() ;
                    g.addElement(e) ;
                    e = g ;
                }

                Element graphElt = new ElementNamedGraph(graphNode, e) ;
                currentGroup().addElement(graphElt) ;
            }
        }

        @Override
        public void visit(OpQuadBlock quadBlock) {
            // Gather into OpQuadPatterns.
            throw new NotImplemented("OpQuadBlock") ;
        }

        @Override
        public void visit(OpPath opPath) {
            ElementPathBlock epb = new ElementPathBlock() ;
            epb.addTriplePath(opPath.getTriplePath()) ;
            ElementGroup g = currentGroup() ;
            g.addElement(epb) ;
        }

        @Override
        public void visit(OpJoin opJoin) {
            Element eLeft = asElement(opJoin.getLeft()) ;
            ElementGroup eRightGroup = asElementGroup(opJoin.getRight()) ;
            Element eRight = eRightGroup ;
            // Very special case. If the RHS is not something that risks
            // reparsing into a combined element of a group, strip the group-of-one.
            // See also ElementTransformCleanGroupsOfOne
            if ( eRightGroup.size() == 1 ) {
                // This always was a {} around it but it's unnecessary in a group of one.
                if ( eRightGroup.get(0) instanceof ElementSubQuery )
                    eRight = eRightGroup.get(0) ;
            }

            ElementGroup g = currentGroup() ;
            insertIntoGroup(g, eLeft) ;
            insertIntoGroup(g, eRight) ;
            return ;
        }

        @Override
        public void visit(OpLeftJoin opLeftJoin) {
            Element eLeft = asElement(opLeftJoin.getLeft()) ;
            ElementGroup eRight = asElementGroup(opLeftJoin.getRight()) ;

            // If the RHS is (filter) we need to protect it from becoming
            // part of the expr for the LeftJoin.
            // OPTIONAL {{ ?s ?p ?o FILTER (?o>34) }} is not the same as
            // OPTIONAL { ?s ?p ?o FILTER (?o>34) }

            boolean mustProtect = eRight.getElements().stream().anyMatch(el -> el instanceof ElementFilter ) ;

            if ( mustProtect ) {
                ElementGroup eRight2 = new ElementGroup() ;
                eRight2.addElement(eRight);
                eRight = eRight2 ;
            }

            if ( opLeftJoin.getExprs() != null ) {
                for ( Expr expr : opLeftJoin.getExprs() ) {
                    ElementFilter f = new ElementFilter(expr) ;
                    eRight.addElement(f) ;
                }
            }
            ElementGroup g = currentGroup() ;
            if ( !emptyGroup(eLeft) ) {
                if ( eLeft instanceof ElementGroup )
                    g.getElements().addAll(((ElementGroup)eLeft).getElements()) ;
                else
                    g.addElement(eLeft) ;
            }

            ElementOptional opt = new ElementOptional(eRight) ;
            g.addElement(opt) ;
        }

        @Override
        public void visit(OpDiff opDiff) {
            throw new ARQNotImplemented("OpDiff") ;
        }

        @Override
        public void visit(OpMinus opMinus) {
            Element eLeft = asElement(opMinus.getLeft()) ;
            Element eRight = asElementGroup(opMinus.getRight()) ;
            ElementMinus elMinus = new ElementMinus(eRight) ;
            ElementGroup g = currentGroup() ;
            if ( !emptyGroup(eLeft) )
                g.addElement(eLeft) ;
            g.addElement(elMinus) ;
        }

        @Override
        public void visit(OpUnion opUnion) {
            Element eLeft = asElementGroup(opUnion.getLeft()) ;
            Element eRight = asElementGroup(opUnion.getRight()) ;
            if ( eLeft instanceof ElementUnion ) {
                ElementUnion elUnion = (ElementUnion)eLeft ;
                elUnion.addElement(eRight) ;
                return ;
            }
            // Multiple unions.
            // if ( eRight instanceof ElementUnion )
            // {
            // ElementUnion elUnion = (ElementUnion)eRight ;
            // elUnion.getElements().add(0, eLeft) ;
            // return ;
            // }

            ElementUnion elUnion = new ElementUnion() ;
            elUnion.addElement(eLeft) ;
            elUnion.addElement(eRight) ;
            currentGroup().addElement(elUnion) ;
        }

        @Override
        public void visit(OpConditional opCondition) {
            throw new ARQNotImplemented("OpCondition") ;
        }

        @Override
        public void visit(OpFilter opFilter) {
            // (filter .. (filter ( ... )) (non-canonicalizing OpFilters)
            // Inner gets Grouped unnecessarily.
            Element e = asElement(opFilter.getSubOp()) ;
            if ( currentGroup() != e )
                currentGroup().addElement(e) ;
            element = currentGroup() ; // Was cleared by asElement.

            ExprList exprs = opFilter.getExprs() ;
            for ( Expr expr : exprs ) {
                ElementFilter f = new ElementFilter(expr) ;
                currentGroup().addElement(f) ;
            }
        }

        @Override
        public void visit(OpGraph opGraph) {
            startSubGroup() ;
            Element e = asElement(opGraph.getSubOp()) ;
            endSubGroup() ;

            // If not element group make it one
            if ( !(e instanceof ElementGroup) ) {
                ElementGroup g = new ElementGroup() ;
                g.addElement(e) ;
                e = g ;
            }

            Element graphElt = new ElementNamedGraph(opGraph.getNode(), e) ;
            currentGroup().addElement(graphElt) ;
        }

        @Override
        public void visit(OpService opService) {
            // Hmm - if the subnode has been optimized, we may fail.
            Op op = opService.getSubOp() ;
            Element x = asElement(opService.getSubOp()) ;
            Element elt = new ElementService(opService.getService(), x, opService.getSilent()) ;
            currentGroup().addElement(elt) ;
        }

        @Override
        public void visit(OpDatasetNames dsNames) {
            throw new ARQNotImplemented("OpDatasetNames") ;
        }

        @Override
        public void visit(OpTable opTable) {
            // This will go in a group so simply forget it.
            if ( opTable.isJoinIdentity() )
                return ;

            // Put in a VALUES
            // This may be related to the grpup of the overall query.

            ElementData el = new ElementData() ;
            el.getVars().addAll(opTable.getTable().getVars()) ;
            QueryIterator qIter = opTable.getTable().iterator(null) ;
            while (qIter.hasNext())
                el.getRows().add(qIter.next()) ;
            qIter.close() ;
            currentGroup().addElement(el) ;
        }

        @Override
        public void visit(OpExt opExt) {
            // Op op = opExt.effectiveOp() ;
            // // This does not work in all cases.
            // op.visit(this) ;
            throw new ARQNotImplemented("OpExt") ;
        }

        @Override
        public void visit(OpNull opNull) {
            throw new ARQNotImplemented("OpNull") ;
        }

        @Override
        public void visit(OpLabel opLabel) {
            if ( opLabel.hasSubOp() )
                opLabel.getSubOp().visit(this) ;
        }

        @Override
        public void visit(OpAssign opAssign) {
            Element e = asElement(opAssign.getSubOp()) ;
            // If (assign ... (table unit)), and first in group, don't add the empty group.
            insertIntoGroup(currentGroup(), e) ;
            processAssigns(Arrays.asList(opAssign), (var,expr)->{
                currentGroup().addElement(new ElementAssign(var,expr)) ;
            }) ;
        }

        @Override
        public void visit(OpExtend opExtend) {
            Element e = asElement(opExtend.getSubOp()) ;
            // If (extend ... (table unit)), and first in group, don't add the empty group.
            insertIntoGroup(currentGroup(), e) ;
            processExtends(Arrays.asList(opExtend), (var,expr)->{
                currentGroup().addElement(new ElementBind(var,expr)) ;
            }) ;
        }

        @Override
        public void visit(OpList opList) {
            opList.getSubOp().visit(this) ;
        }

        // When some modifers (e.g. OpDistinct) are met in a pattern, they signal
        // a new query level (new inner SELECT), where we switch back to
        // looking for the level start in

        private void newLevel(Op op) {
            convertAsSubQuery(op) ;
        }

        private void convertAsSubQuery(Op op) {
            Converter subConverter = new Converter(op) ;
            ElementSubQuery subQuery = new ElementSubQuery(subConverter.convert()) ;
            ElementGroup g = currentGroup() ;
            g.addElement(subQuery) ;
        }

        @Override
        public void visit(OpOrder opOrder) {
            newLevel(opOrder) ;
        }

        @Override
        public void visit(OpProject opProject) {
            newLevel(opProject) ;
        }

        @Override
        public void visit(OpReduced opReduced) {
            newLevel(opReduced) ;
        }

        @Override
        public void visit(OpDistinct opDistinct) {
            newLevel(opDistinct) ;
        }

        @Override
        public void visit(OpSlice opSlice) {
            newLevel(opSlice) ;
        }

        @Override
        public void visit(OpGroup opGroup) {
            newLevel(opGroup) ;
        }

        @Override
        public void visit(OpTopN opTop) {
            throw new ARQNotImplemented("OpTopN") ;
        }

        private static boolean emptyGroup(Element element) {
            if ( !(element instanceof ElementGroup) )
                return false ;
            ElementGroup eg = (ElementGroup)element ;
            return eg.isEmpty() ;
        }

        private static boolean groupOfOne(Element element) {
            if ( !(element instanceof ElementGroup) )
                return false ;
            ElementGroup eg = (ElementGroup)element ;
            return eg.size() == 1 ;
        }

        /** Insert into a group, skip initial empty subgroups; recombining ElementPathBlock */
        private static void insertIntoGroup(ElementGroup eg, Element e) {
            // Skip initial empty subgroup.
            if ( emptyGroup(e) && eg.isEmpty() )
                return ;

            // Empty group.
            if ( eg.isEmpty() ) {
                eg.addElement(e);
                return ;
            }

            Element eltTop = eg.getLast() ;
            if ( ! ( eltTop instanceof ElementPathBlock ) ) {
                // Not working on a ElementPathBlock - no need to group-of-one
                // when inserting ElementPathBlock.
                e = unwrapGroupOfOnePathBlock(e) ;
                eg.addElement(e);
                return ;
            }
            if ( ! ( e  instanceof ElementPathBlock ) ) {
                eg.addElement(e);
                return ;
            }
            // Combine.
            ElementPathBlock currentPathBlock = (ElementPathBlock)eltTop ;
            ElementPathBlock newPathBlock = (ElementPathBlock)e ;
            currentPathBlock.getPattern().addAll(newPathBlock.getPattern());
        }

        private static Element unwrapGroupOfOnePathBlock(Element e) {
            Element e2 = getElementOfGroupOfOne(e) ;
            if ( e2 != null )
                return e2 ;
            return e ;
        }

        private static Element getElementOfGroupOfOne(Element e) {
            if ( groupOfOne(e) ) {
                ElementGroup eg = (ElementGroup)e ;
                return eg.get(0) ;
            }
            return null ;
        }

        private Element lastElement() {
            ElementGroup g = currentGroup ;
            return g.getLast() ;
        }

        private void startSubGroup() {
            push(currentGroup) ;
            ElementGroup g = new ElementGroup() ;
            currentGroup = g ;
        }

        private ElementGroup endSubGroup() {
            ElementGroup g = pop() ;
            ElementGroup r = currentGroup ;
            currentGroup = g ;
            return r ;
        }

        private ElementGroup currentGroup() {
            // if ( currentGroup == null )
            // startSubGroup() ;
            return currentGroup ;
        }

        private ElementGroup peek() {
            if ( stack.size() == 0 )
                return null ;
            return stack.peek() ;
        }

        private ElementGroup pop() {
            return stack.pop() ;
        }

        private void push(ElementGroup el) {
            stack.push(el) ;
        }
    }
    

    /**
     * Allows multiple filters and any number of extend
     */
    private static OpGroup getGroup(Op op) {
        // Unwind tail recursion to protected against extreme queries.
        for ( ; ; ) {
            if ( op instanceof OpGroup )
                return (OpGroup)op ;
            if ( op instanceof OpFilter ) {
                OpFilter opFilter = (OpFilter)op ;
                op = opFilter.getSubOp() ;
                continue ;
            }
            if ( op instanceof OpExtend ) { // AS or Aggregate naming
                OpExtend opExtend = (OpExtend)op ;
                op = opExtend.getSubOp() ;
                continue ;
            }
            return null ;
        }
    }

    private static Op processExtend(Op op, List<OpExtend> assignments) {
        while (op instanceof OpExtend) {
            OpExtend opExtend = (OpExtend)op;
            assignments.add(opExtend);
            op = opExtend.getSubOp();
        }
        // JENA-1843
        if ( assignments.size() > 1 )
            Collections.reverse(assignments);

        return op;
    }
}
