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

import java.io.OutputStream ;
import java.util.* ;

import org.apache.jena.atlas.io.IndentedLineBuffer ;
import org.apache.jena.atlas.io.IndentedWriter ;
import org.apache.jena.atlas.io.Printable ;
import org.apache.jena.atlas.logging.Log ;
import org.apache.jena.graph.Node ;
import org.apache.jena.sparql.ARQConstants ;
import org.apache.jena.sparql.algebra.table.TableData ;
import org.apache.jena.sparql.core.* ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.expr.Expr ;
import org.apache.jena.sparql.expr.ExprAggregator ;
import org.apache.jena.sparql.expr.ExprTransform ;
import org.apache.jena.sparql.expr.ExprVar ;
import org.apache.jena.sparql.expr.aggregate.Aggregator ;
import org.apache.jena.sparql.serializer.QuerySerializerFactory ;
import org.apache.jena.sparql.serializer.SerializerRegistry ;
import org.apache.jena.sparql.syntax.Element ;
import org.apache.jena.sparql.syntax.PatternVars ;
import org.apache.jena.sparql.syntax.Template ;
import org.apache.jena.sparql.syntax.syntaxtransform.* ;
import org.apache.jena.sparql.util.FmtUtils ;
import org.apache.jena.sys.JenaSystem ;

/** The data structure for a query as presented externally.
 *  There are two ways of creating a query - use the parser to turn
 *  a string description of the query into the executable form, and
 *  the programmatic way (the parser is calling the programmatic
 *  operations driven by the query string).  The declarative approach
 *  of passing in a string is preferred.
 *
 * Once a query is built, it can be passed to the QueryFactory to produce a query execution engine.
 * @see QueryExecutionFactory
 * @see ResultSet
 */

public class Query extends Prologue implements Cloneable, Printable
{
    static { JenaSystem.init() ; /* Ensure everything has started properly */ }

    // Old constants. Retain for compatibility.
    public static final int QueryTypeUnknown    = -123 ;
    public static final int QueryTypeSelect     = 111 ;
    public static final int QueryTypeConstruct  = 222 ;
    public static final int QueryTypeDescribe   = 333 ;
    public static final int QueryTypeAsk        = 444 ;
    public static final int QueryTypeJson       = 555 ;

    private QueryType queryType = QueryType.UNKNOWN;

    // If no model is provided explicitly, the query engine will load
    // a model from the URL.  Never a list of zero items.

    private List<String> graphURIs = new ArrayList<>() ;
    private List<String> namedGraphURIs = new ArrayList<>() ;

    // The WHERE clause
    private Element queryPattern = null ;

    // Query syntax
    private Syntax syntax = Syntax.syntaxSPARQL ; // Default

    // LIMIT/OFFSET
    public static final long  NOLIMIT = Long.MIN_VALUE ;
    private long resultLimit   = NOLIMIT ;
    private long resultOffset  = NOLIMIT ;

    // ORDER BY
    private List<SortCondition> orderBy       = null ;
    public static final int ORDER_ASCENDING           = 1 ;
    public static final int ORDER_DESCENDING          = -1 ;
    public static final int ORDER_DEFAULT             = -2 ;    // Not explicitly given.
    public static final int ORDER_UNKNOW              = -3 ;

    // VALUES trailing clause
    protected TableData valuesDataBlock = null ;

    protected boolean strictQuery = true ;

    // SELECT * seen
    protected boolean queryResultStar        = false ;

    protected boolean distinct               = false ;
    protected boolean reduced                = false ;

    // CONSTRUCT
    protected Template constructTemplate  = null ;

    // DESCRIBE
    // Any URIs/QNames in the DESCRIBE clause
    // Also uses resultVars
    protected List<Node> resultNodes               = new ArrayList<>() ;     // Type in list: Node

    /**
     * Creates a new empty query
     */
    public Query()
    {
        syntax = Syntax.syntaxSPARQL ;
    }

    /**
     * Creates a new empty query with the given prologue
     */
    public Query(Prologue prologue)
    {
        this() ;
        Prologue p2 = prologue.copy();
        prefixMap = p2.getPrefixMapping();
        seenBaseURI = false ;
        resolver = p2.getResolver();
    }

    // Allocate variables that are unique to this query.
    private VarAlloc varAlloc = new VarAlloc(ARQConstants.allocQueryVariables) ;
    private Var allocInternVar() { return varAlloc.allocVar() ; }

    public void setQuerySelectType()            { queryType = QueryType.SELECT ; }
    public void setQueryConstructType()         { queryType = QueryType.CONSTRUCT ; queryResultStar = true ; }
    public void setQueryDescribeType()          { queryType = QueryType.DESCRIBE; }
    public void setQueryAskType()               { queryType = QueryType.ASK; }
    public void setQueryJsonType()              { queryType = QueryType.CONSTRUCT_JSON; }

    /** Return the {@link QueryType} */
    public QueryType queryType()                       { return queryType ; }

    /** @deprecated Use {@link #queryType()} which returns an {@link QueryType} */
    @Deprecated
    public int getQueryType() {
        // Old constants.
        switch(queryType) {
            case SELECT :           return QueryTypeSelect;
            case ASK :              return QueryTypeAsk;
            case CONSTRUCT :        return QueryTypeConstruct;
            case CONSTRUCT_JSON :   return QueryTypeJson;
            case CONSTRUCT_QUADS :  return QueryTypeConstruct;
            case DESCRIBE :         return QueryTypeDescribe;
            default :               return QueryTypeUnknown;
        }
    }

    public boolean isSelectType()               { return queryType == QueryType.SELECT; }

    public boolean isConstructType()            { return queryType == QueryType.CONSTRUCT ; }

    public boolean isDescribeType()             { return queryType == QueryType.DESCRIBE ; }

    public boolean isAskType()                  { return queryType == QueryType.ASK ; }

    public boolean isJsonType()                 { return queryType == QueryType.CONSTRUCT_JSON ; }

    public boolean isUnknownType()              { return queryType == QueryType.UNKNOWN ; }

    public boolean isConstructQuad() {
        return (isConstructType() && constructTemplate.containsRealQuad())
            || queryType == QueryType.CONSTRUCT_QUADS;
    }

    // It was a mistake to extend Prologue ... but what is done is done.
    public Prologue getPrologue()               { return this ; }

    public void setStrict(boolean isStrict)
    {
        strictQuery = isStrict ;

        if ( strictQuery )
            initStrict() ;
        else
            initLax() ;
    }

    public boolean isStrict()                { return strictQuery ; }

    private void initStrict()
    {
//        if ( prefixMap.getGlobalPrefixMapping() == globalPrefixMap )
//            prefixMap.setGlobalPrefixMapping(null) ;
    }

    private void initLax()
    {
//        if ( prefixMap.getGlobalPrefixMapping() == null )
//            prefixMap.setGlobalPrefixMapping(globalPrefixMap) ;
    }

    public void setDistinct(boolean b) { distinct = b ; }
    public boolean isDistinct()        { return distinct ; }

    public void setReduced(boolean b) { reduced = b ; }
    public boolean isReduced()        { return reduced ; }

    /** @return Returns the syntax. */
    public Syntax getSyntax()         { return syntax ; }

    /** @param syntax The syntax to set. */
    public void setSyntax(Syntax syntax)
    {
        this.syntax = syntax ;
        if ( syntax != Syntax.syntaxSPARQL )
            strictQuery = false ;
    }

    // ---- Limit/offset

    public long getLimit()             { return resultLimit ; }
    public void setLimit(long limit)   { resultLimit = limit ; }
    public boolean hasLimit()          { return resultLimit != NOLIMIT ; }

    public long getOffset()            { return resultOffset ; }
    public void setOffset(long offset) { resultOffset = offset ; }
    public boolean hasOffset()         { return resultOffset != NOLIMIT ; }

    // ---- Order By

    public boolean hasOrderBy()        { return orderBy != null && orderBy.size() > 0 ; }

    public boolean isOrdered()         { return hasOrderBy() ; }

    public void addOrderBy(SortCondition condition)
    {
        if ( orderBy == null )
            orderBy = new ArrayList<>() ;

        orderBy.add(condition) ;
    }
    public void addOrderBy(Expr expr, int direction)
    {
        SortCondition sc = new SortCondition(expr, direction) ;
        addOrderBy(sc) ;
    }

    public void addOrderBy(Node var, int direction)
    {
        if ( ! var.isVariable() )
            throw new QueryException("Not a variable: "+var) ;
        SortCondition sc = new SortCondition(var, direction) ;
        addOrderBy(sc) ;
    }

    public void addOrderBy(String varName, int direction)
    {
        varName = Var.canonical(varName) ;
        SortCondition sc = new SortCondition(new ExprVar(varName), direction) ;
        addOrderBy(sc) ;
    }

    public List<SortCondition> getOrderBy()           { return orderBy ; }

    // ----

    /** Answer whether the query had SELECT/DESCRIBE/CONSTRUCT *
     * @return boolean as to whether a * result form was seen
     */
    public boolean isQueryResultStar() { return queryResultStar ; }

    /** Set whether the query had SELECT/DESCRIBE *
     *
     * @param isQueryStar
     */
    public void setQueryResultStar(boolean isQueryStar)
    {
        queryResultStar = isQueryStar ;
        if ( isQueryStar )
            resultVarsSet = false ;
    }

    public void setQueryPattern(Element elt)
    {
        queryPattern = elt ;
    }

    public Element getQueryPattern() { return queryPattern ; }

     /** Location of the source for the data.  If the model is not set,
     *  then the QueryEngine will attempt to load the data from these URIs
     *  into the default (unamed) graph.
     */
    public void addGraphURI(String s)
    {
        if ( graphURIs == null )
            graphURIs = new ArrayList<>() ;
        graphURIs.add(s) ;
    }

    /** Location of the source for the data.  If the model is not set,
     *  then the QueryEngine will attempt to load the data from these URIs
     *  as named graphs in the dataset.
     */
    public void addNamedGraphURI(String uri)
    {
        if ( namedGraphURIs == null )
            namedGraphURIs = new ArrayList<>() ;
        if ( namedGraphURIs.contains(uri) )
            throw new QueryException("URI already in named graph set: "+uri) ;
        else
            namedGraphURIs.add(uri) ;
    }

    /** Return the list of URIs (strings) for the unnamed graph
     *
     * @return List of strings
     */

    public List<String> getGraphURIs() { return graphURIs ; }

    /** Test whether the query mentions a URI in forming the default graph (FROM clause)
     *
     * @param uri
     * @return boolean  True if the URI used in a FROM clause
     */
    public boolean usesGraphURI(String uri) { return graphURIs.contains(uri) ; }

    /** Return the list of URIs (strings) for the named graphs (FROM NAMED clause)
     *
     * @return List of strings
     */

    public List<String> getNamedGraphURIs() { return namedGraphURIs ; }

    /** Test whether the query mentions a URI for a named graph.
     *
     * @param uri
     * @return True if the URI used in a FROM NAMED clause
     */
    public boolean usesNamedGraphURI(String uri) { return namedGraphURIs.contains(uri) ; }

    /** Return true if the query has either some graph
     * URIs or some named graph URIs in its description.
     * This does not mean these URIs will be used - just that
     * they are noted as part of the query.
     */

    public boolean hasDatasetDescription()
    {
        if ( getGraphURIs() != null && getGraphURIs().size() > 0 )
            return true ;
        if ( getNamedGraphURIs() != null && getNamedGraphURIs().size() > 0 )
            return true ;
        return false ;
    }

    /** Return a dataset description (FROM/FROM NAMED clauses) for the query. */
    public DatasetDescription getDatasetDescription()
    {
        if ( ! hasDatasetDescription() )
            return null;

        DatasetDescription description = new DatasetDescription() ;

        description.addAllDefaultGraphURIs(getGraphURIs()) ;
        description.addAllNamedGraphURIs(getNamedGraphURIs()) ;
        return description ;
    }

    // ---- SELECT

    protected VarExprList projectVars = new VarExprList() ;

    /** Return a list of the variables requested (SELECT) */
    public List<String> getResultVars()
    {
        // Ensure "SELECT *" processed
        setResultVars() ;
        return Var.varNames(projectVars.getVars()) ;
    }

    /** Return a list of the variables requested (SELECT) */
    public List<Var> getProjectVars()
    {
        // Ensure "SELECT *" processed
        setResultVars() ;
        return projectVars.getVars() ;
    }

    public VarExprList getProject()
    {
        return projectVars ;
    }

    /** Add a collection of projection variables to a SELECT query */
    public void addProjectVars(Collection<?> vars)
    {
        for ( Object obj : vars )
        {
            if ( obj instanceof String )
            {
                this.addResultVar( (String) obj );
                continue;
            }
            if ( obj instanceof Var )
            {
                this.addResultVar( (Var) obj );
                continue;
            }
            throw new QueryException( "Not a variable or variable name: " + obj );
        }
        resultVarsSet = true ;
    }


    /** Add a projection variable to a SELECT query */
    public void addResultVar(String varName)
    {
        varName = Var.canonical(varName) ;
        _addResultVar(varName) ;
    }

    public void addResultVar(Node v)
    {
        if ( !v.isVariable() )
            throw new QueryException("Not a variable: "+v) ;
        _addResultVar(v.getName()) ;
    }

    public void addResultVar(Node v, Expr expr)
    {
        Var var = null ;
        if ( v == null )
            var = allocInternVar() ;
        else
        {
            if ( !v.isVariable() )
                throw new QueryException("Not a variable: "+v) ;
            var = Var.alloc(v) ;
        }
        _addVarExpr(projectVars, var, expr) ;
    }

    /** Add an to a SELECT query (a name will be created for it) */
    public void addResultVar(Expr expr)
    {
        _addVarExpr(projectVars, allocInternVar(), expr) ;
    }

    /** Add a named expression to a SELECT query */
    public void addResultVar(String varName, Expr expr)
    {
        Var var = null ;
        if ( varName == null )
            var = allocInternVar() ;
        else
        {
            varName = Var.canonical(varName) ;
            var = Var.alloc(varName) ;
        }
        _addVarExpr(projectVars, var, expr) ;
    }

    // Add raw name.
    private void _addResultVar(String varName)
    {
        Var v = Var.alloc(varName) ;
        _addVar(projectVars, v) ;
        resultVarsSet = true ;
    }

    private static void _addVar(VarExprList varExprList, Var v)
    {
        if ( varExprList.contains(v) )
        {
            Expr expr = varExprList.getExpr(v) ;
            if ( expr != null )
                // SELECT (?a+?b AS ?x) ?x
                throw new QueryBuildException("Duplicate variable (had an expression) in result projection '"+v+"'") ;
            // SELECT ?x ?x
            if ( ! ARQ.allowDuplicateSelectColumns )
                return ;
            // else drop through and have two variables of the same name.
        }
        varExprList.add(v) ;
    }

    private static void _addVarExpr(VarExprList varExprList, Var v, Expr expr)
    {
        if ( varExprList.contains(v) )
            // SELECT ?x (?a+?b AS ?x)
            // SELECT (2*?a AS ?x) (?a+?b AS ?x)
            throw new QueryBuildException("Duplicate variable in result projection '"+v+"'") ;
        varExprList.add(v, expr) ;
    }

    protected VarExprList groupVars = new VarExprList() ;
    protected List<Expr> havingExprs = new ArrayList<>() ;  // Expressions : Make an ExprList?

    public boolean hasGroupBy()     { return ! groupVars.isEmpty() || getAggregators().size() > 0 ; }
    public boolean hasHaving()      { return havingExprs != null && havingExprs.size() > 0 ; }

    public VarExprList getGroupBy()      { return groupVars ; }

    public List<Expr> getHavingExprs()    { return havingExprs ; }

    public void addGroupBy(String varName)
    {
        varName = Var.canonical(varName) ;
        addGroupBy(Var.alloc(varName)) ;
    }

    public void addGroupBy(Node v)
    {
        _addVar(groupVars, Var.alloc(v)) ;
    }

    public void addGroupBy(Expr expr) { addGroupBy(null, expr) ; }

    public void addGroupBy(Var v, Expr expr)
    {
        if ( v == null )
            v = allocInternVar() ;

        if ( expr.isVariable() && v.isAllocVar() )
        {
            // It was (?x) with no AS - keep the name by adding by variable.
            addGroupBy(expr.asVar()) ;
            return ;
        }

        groupVars.add(v, expr) ;
    }

    public void addHavingCondition(Expr expr)
    {
        havingExprs.add(expr) ;
    }

    // SELECT JSON

    private Map<String, Node> jsonMapping = new LinkedHashMap<>();

    public void addJsonMapping(String key, Node value) {
        jsonMapping.put(key, value);
    }

    public Map<String, Node> getJsonMapping() {
        return Collections.unmodifiableMap(jsonMapping);
    }

    // ---- Aggregates

    // Record allocated aggregations.
    // Later: The same aggregation expression used in a query
    // will always lead to the same aggregator.
    // For now, allocate a fresh one each time (cause the calculation
    // to be done multiple times but (1) it's unusual to have repeated
    // aggregators normally and (2) the actual calculation is cheap.

    // Unlike SELECT expressions, here the expression itself (E_Aggregator) knows its variable
    // Commonality?

    private List<ExprAggregator> aggregators = new ArrayList<>() ;
    private Map<Var, ExprAggregator> aggregatorsMap = new HashMap<>() ;

    // Note any E_Aggregator created for reuse.
    private Map<String, Var> aggregatorsAllocated = new HashMap<>() ;

    public boolean hasAggregators() { return aggregators.size() != 0  ; }
    public List<ExprAggregator> getAggregators() { return aggregators ; }

    public Expr allocAggregate(Aggregator agg)
    {
        // We need to track the aggregators in case one aggregator is used twice, e.g. in HAVING and in SELECT expression
        // (is that much harm to do twice?  Yes, if distinct.)
        String key = agg.key() ;

        Var v = aggregatorsAllocated.get(key);
        if ( v != null )
        {
            ExprAggregator eAgg = aggregatorsMap.get(v) ;
            if ( ! agg.equals(eAgg.getAggregator()) )
                Log.warn(Query.class, "Internal inconsistency: Aggregator: "+agg) ;
            return eAgg ;
        }
        // Allocate.
        v = allocInternVar() ;
        ExprAggregator aggExpr = new ExprAggregator(v, agg) ;
        aggregatorsAllocated.put(key, v) ;
        aggregatorsMap.put(v, aggExpr) ;
        aggregators.add(aggExpr) ;
        return aggExpr ;
    }

    // ---- VALUES

    /** Does the query have a VALUES trailing block? */
    public boolean hasValues()                { return valuesDataBlock != null ; }

    /** Variables from a VALUES trailing block */
    public List<Var> getValuesVariables()     { return valuesDataBlock==null ? null : valuesDataBlock.getVars() ; }

    /** Data from a VALUES trailing block. null for a Node means undef */
    public List<Binding> getValuesData()      { return valuesDataBlock==null ? null : valuesDataBlock.getRows() ; }

    public void setValuesDataBlock(List<Var> variables, List<Binding> values)
    {
        checkDataBlock(variables, values) ;
        valuesDataBlock = new TableData(variables, values) ;
    }

    private static void checkDataBlock(List<Var> variables, List<Binding> values)
    {
        // Check.
        int N = variables.size() ;
        for ( Binding valueRow : values )
        {
            Iterator<Var> iter= valueRow.vars() ;
            for ( ; iter.hasNext() ; )
            {
                Var v = iter.next() ;
                if ( ! variables.contains(v) )
                    throw new QueryBuildException("Variable "+v+" not found in "+variables) ;
            }
        }
    }

    // ---- CONSTRUCT

    /** Get the template pattern for a construct query */
    public Template getConstructTemplate()
    {
        return constructTemplate ;
    }

    /** Set triple patterns for a construct query */
    public void setConstructTemplate(Template templ)  { constructTemplate = templ ; }

    // ---- DESCRIBE

    public void addDescribeNode(Node node)
    {
        if ( node.isVariable() ) { addResultVar(node) ; return ; }
        if ( node.isURI() || node.isBlank() )
        {
            if ( !resultNodes.contains(node) )
                resultNodes.add(node);
            return ;
        }
        if ( node.isLiteral() )
            throw new QueryException("Result node is a literal: "+FmtUtils.stringForNode(node)) ;
        throw new QueryException("Result node not recognized: "+node) ;
    }


    /** Get the result list (things wanted - not the results themselves)
     *  of a DESCRIBE query. */
    public List<Node> getResultURIs() { return resultNodes ; }

    private boolean resultVarsSet = false ;
    /**
     * Set the results variables if necessary, when the query has "*" ({@code SELECT *}
     * or {@code DESCRIBE *}) and for a construct query. This operation is idempotent and can
     * be called to ensure the results variables have been set.
     */
    public void setResultVars()
    {
        if ( resultVarsSet )
            return ;
        synchronized(this) {
            if ( resultVarsSet )
                return;
            // Synchronized in case this query is used in a multithreaded
            // situation calling setResultVars(). JENA-1861.
            resetResultVars();
            resultVarsSet = true ;
        }
    }

    /**
     * If modifying a query, it may be necessary to reset the calculate of the result
     * variables of the query for {@code SELECT *} and {@code DESCRIBE *} and {@code CONSTRUCT}.
     */
    public void resetResultVars() {
        if  ( isQueryResultStar() )
            projectVars.clear();
        
        if ( getQueryPattern() == null )
        {
            if ( ! this.isDescribeType() )
                Log.warn(this, "setResultVars(): no query pattern") ;
            return ;
        }

        if ( isSelectType() )
        {
            if ( isQueryResultStar() )
                findAndAddNamedVars() ;
            return ;
        }

        if ( isConstructType() )
        {
            // All named variables are in-scope
            findAndAddNamedVars() ;
            return ;
        }

        if ( isDescribeType() )
        {
            if ( isQueryResultStar() )
                findAndAddNamedVars() ;
            return ;
        }
//        if ( isAskType() )
//        {}
    }

    private void findAndAddNamedVars()
    {
        Iterator<Var> varIter = null ;
        if ( hasGroupBy() )
            varIter = groupVars.getVars().iterator() ;
        else
        {
            // Binding variables -- in patterns, not in filters and not in EXISTS
            LinkedHashSet<Var> queryVars = new LinkedHashSet<>() ;
            PatternVars.vars(queryVars, this.getQueryPattern()) ;
            if ( this.hasValues() )
                queryVars.addAll(getValuesVariables()) ;
//            if ( this.hasValues() )
//                queryVars.addAll(getValuesVariables()) ;
            varIter = queryVars.iterator() ;
        }

        // All query variables, including ones from bNodes in the query.

        for ( ; varIter.hasNext() ; )
        {
            Var var = varIter.next() ;
            if ( var.isNamedVar() )
                addResultVar(var) ;
        }
    }

    public void visit(QueryVisitor visitor)
    {
        visitor.startVisit(this) ;
        visitor.visitResultForm(this) ;
        visitor.visitPrologue(this) ;
        if ( this.isSelectType() )
            visitor.visitSelectResultForm(this) ;
        if ( this.isConstructType() )
            visitor.visitConstructResultForm(this) ;
        if ( this.isDescribeType() )
            visitor.visitDescribeResultForm(this) ;
        if ( this.isAskType() )
            visitor.visitAskResultForm(this) ;
        if ( this.isJsonType() )
            visitor.visitJsonResultForm(this) ;
        visitor.visitDatasetDecl(this) ;
        visitor.visitQueryPattern(this) ;
        visitor.visitGroupBy(this) ;
        visitor.visitHaving(this) ;
        visitor.visitOrderBy(this) ;
        visitor.visitOffset(this) ;
        visitor.visitLimit(this) ;
        visitor.visitValues(this) ;
        visitor.finishVisit(this) ;
    }

    @Override
    public Object clone() { return cloneQuery() ; }

    /**
     * Makes a copy of this query using the syntax transform machinery.
     * @return Copy of this query
     */
    public Query cloneQuery() {
        ElementTransform eltTransform = new ElementTransformCopyBase(true);
        ExprTransform exprTransform = new ExprTransformApplyElementTransform(eltTransform, true);

        Query result = QueryTransformOps.transform(this, eltTransform, exprTransform);
        return result;
    }

    // ---- Query canonical syntax

    // Reverse of parsing : should produce a string that parses to an equivalent query
    // "Equivalent" => gives the same results on any model
    @Override
    public String toString()
    { return serialize() ; }

    public String toString(Syntax syntax)
    { return serialize(syntax) ; }


    /** Must align with .equals */
    private int hashcode = -1 ;

    @Override
    public int hashCode()
    {
        if ( hashcode == -1 )
        {
            hashcode = QueryHashCode.calc(this) ;
            if ( hashcode == -1 )
                hashcode = Integer.MIN_VALUE/2 ;
        }
        return hashcode ;
    }

    /** Are two queries equals - tests shape and details.
     * Equality means that the queries do the same thing, including
     * same variables, in the same places.  Being unequals does
     * <b>not</b> mean the queries do different things.
     *
     * For example, reordering a group or union
     * means that a query is different.
     *
     * Two instances of a query parsed from the same string are equal.
     */

    @Override
    public boolean equals(Object other)
    {
        if ( ! ( other instanceof Query ) )
            return false ;
        if ( this == other ) return true ;
        return QueryCompare.equals(this, (Query)other) ;
    }

//    public static boolean sameAs(Query query1, Query query2)
//    { return query1.sameAs(query2) ; }

    @Override
    public void output(IndentedWriter out)
    {
        serialize(out) ;
    }

    /** Convert the query to a string */

    public String serialize()
    {
        IndentedLineBuffer buff = new IndentedLineBuffer() ;
        serialize(buff) ;
        return buff.toString();
    }

    /** Convert the query to a string in the given syntax
     * @param syntax
     */

    public String serialize(Syntax syntax)
    {
        IndentedLineBuffer buff = new IndentedLineBuffer() ;
        serialize(buff, syntax) ;
        return buff.toString();
    }

    /** Output the query
     * @param out  OutputStream
     */
    public void serialize(OutputStream out) { serialize(out, syntax); }

    /** Output the query
     *
     * @param out     OutputStream
     * @param syntax  Syntax URI
     */

    public void serialize(OutputStream out, Syntax syntax) {
        IndentedWriter writer = new IndentedWriter(out) ;
        serialize(writer, syntax) ;
        writer.flush() ;
        try { out.flush() ; } catch (Exception ex) { }
    }

    /** Format the query into the buffer
     *
     * @param buff    IndentedLineBuffer
     */

    public void serialize(IndentedLineBuffer buff) {
        serialize(buff, syntax);
    }

    /** Format the query
     *
     * @param buff       IndentedLineBuffer in which to place the unparsed query
     * @param outSyntax  Syntax URI
     */

    public void serialize(IndentedLineBuffer buff, Syntax outSyntax) {
        serialize((IndentedWriter)buff, outSyntax);
    }

    /** Format the query
     *
     * @param writer  IndentedWriter
     */

    public void serialize(IndentedWriter writer) {
        serialize(writer, syntax);
    }

    /** Format the query
     *
     * @param writer     IndentedWriter
     * @param outSyntax  Syntax URI
     */

    public void serialize(IndentedWriter writer, Syntax outSyntax)
    {
        // Try to use a serializer factory if available
        QuerySerializerFactory factory = SerializerRegistry.get().getQuerySerializerFactory(outSyntax);
        QueryVisitor serializer = factory.create(outSyntax, this, writer);
        this.visit(serializer);
    }
}
