/*
 * 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() ;
        usePrologueFrom(prologue) ;
    }

    // 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);
    }
}
