LOG.debug("merging predicate values took " + (System.currentTimeMillis() - start) + "ms.");
    public Value eval( DocumentSet docs, NodeSet context, NodeProxy node ) {        ArraySet result = new ArraySet( 100 );        Expression first = getExpression( 0 );        if ( first == null )            return new ValueNodeSet( context );        switch ( first.returnsType() ) {            case Constants.TYPE_NODELIST:            {                NodeSet nodes =                    (NodeSet) super.eval( docs, context, null ).getNodeList();                long start = System.currentTimeMillis();                NodeProxy l;                NodeProxy parent;                boolean includeSelf =                	(context instanceof VirtualNodeSet ? false : true);                long pid;                for ( Iterator i = nodes.iterator(); i.hasNext();  ) {                    l = (NodeProxy) i.next();                    parent =                        context.parentWithChild( l, false, includeSelf );                    if ( parent != null) {                    	if(result.contains(parent.doc, parent.gid))                    		parent.addMatches(l.matches);                    	else {                    		parent.addMatches(l.matches);                    		result.add( parent );                        }                    }                }                LOG.debug("merging predicate values took " +                    (System.currentTimeMillis() - start) + "ms.");                break;            }            case Constants.TYPE_BOOL:            case Constants.TYPE_STRING:            {                //string has no special meaning                NodeProxy p;                NodeSet set;                DocumentSet dset;                Value v;                for ( Iterator i = context.iterator(); i.hasNext();  ) {                    p = (NodeProxy) i.next();                    set = new ArraySet( 1 );                    set.add( p );                    dset = new DocumentSet();                    dset.add( p.doc );                    v = first.eval( dset, set, p );                    if ( v.getBooleanValue() )                        result.add( p );                }                break;            }            case Constants.TYPE_NUM:            {                NodeProxy p;                NodeProxy n;                NodeSet set;                int level;                int count;                double pos;                long pid;                long last_pid = 0;                long f_gid;                long e_gid;                DocumentImpl doc;                DocumentImpl last_doc = null;                // evaluate predicate expression for each context node                for ( Iterator i = context.iterator(); i.hasNext();  ) {                    p = (NodeProxy) i.next();                    set = new ArraySet( 1 );                    set.add( p );                    pos = first.eval( docs, context, p ).getNumericValue();                    doc = (DocumentImpl) p.getDoc();                    level = doc.getTreeLevel( p.getGID() );                    pid = ( p.getGID() - doc.getLevelStartPoint( level ) ) /                        doc.getTreeLevelOrder( level )                         + doc.getLevelStartPoint( level - 1 );                    if ( pid == last_pid &&                        last_doc != null &&                        doc.getDocId() == last_doc.getDocId() )                        continue;                    last_pid = pid;                    last_doc = doc;                    f_gid = ( pid - doc.getLevelStartPoint( level - 1 ) ) *                        doc.getTreeLevelOrder( level ) +                        doc.getLevelStartPoint( level );                    e_gid = f_gid + doc.getTreeLevelOrder( level );                    count = 1;                    set = ( (ArraySet) context ).getRange( doc, f_gid, e_gid );                    for ( Iterator j = set.iterator(); j.hasNext(); count++ ) {                        n = (NodeProxy) j.next();                        if ( count == pos ) {                            result.add( n );                            break;                        }                    }                }            }        }        return new ValueNodeSet( result );    }