// Copyright 2001 bob mcwhirter and James Strachan. All rights reserved.

package org.jaxen.expr;

import org.jaxen.Context;
import org.jaxen.JaxenException;
import org.jaxen.ContextGather;

import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

public class DefaultUnionExpr extends DefaultBinaryExpr implements UnionExpr
{
    public DefaultUnionExpr(Expr lhs,
                            Expr rhs)
    {
        super( lhs,
               rhs );
    }

    public String getOperator()
    {
        return "|";
    }

    public String toString()
    {
        return "[(DefaultUnionExpr): " + getLHS() + ", " + getRHS() + "]";
    }

    public Object evaluate(Context context) throws JaxenException
    {
        List results = new ArrayList();

        /*
         *  get the full list of nodes for ordering
         */

        List full = ContextGather.gather( context );

        List lhsResults = convertToList( getLHS().evaluate( context ) );
        List rhsResults = convertToList( getRHS().evaluate( context ) );

        /*
         *  if the ContextGather supports the object model, then
         *  we get a list back...
         */
        if ( full != null)
        {
            /*
             *  run through the list, in order, and
             *  see what was selected....
             */
            Iterator it = full.iterator();

            while( it.hasNext() )
            {
                Object o = it.next();

                if ( lhsResults.contains( o ) )
                {
                    results.add( o );
                }
                else if (rhsResults.contains( o ) )
                {
                    results.add( o );
                }
            }
        }
        else
        {
            /*
             *  the old way. Note this results in things
             *  being out of order...
             */

            Set unique = new HashSet();

            results.addAll( lhsResults );
            unique.addAll( lhsResults );

            Iterator rhsIter = rhsResults.iterator();
            Object   each    = null;

            while ( rhsIter.hasNext() )
            {
                each = rhsIter.next();

                if ( ! unique.contains( each ) )
                {
                   results.add( each );
                   unique.add( each );
                }
            }
        }

        return results;
    }
}