/**
  * Returns all context nodes associated with the nodes in this node set.
  *
  * @param contextId used to track context nodes when evaluating predicate expressions. If
  *     contextId != {@link Expression#NO_CONTEXT_ID}, the current context will be added to each
  *     result of the of the selection.
  */
 public NodeSet getContextNodes(int contextId) {
   NodeProxy current, context;
   ContextItem contextNode;
   NewArrayNodeSet result = new NewArrayNodeSet();
   DocumentImpl lastDoc = null;
   for (Iterator i = iterator(); i.hasNext(); ) {
     current = (NodeProxy) i.next();
     contextNode = current.getContext();
     while (contextNode != null) {
       if (contextNode.getContextId() == contextId) {
         context = contextNode.getNode();
         context.addMatches(current);
         // if (!result.contains(context)) {
         if (Expression.NO_CONTEXT_ID != contextId) context.addContextNode(contextId, context);
         if (lastDoc != null && lastDoc.getDocId() != context.getDocument().getDocId()) {
           lastDoc = context.getDocument();
           result.add(context, getSizeHint(lastDoc));
         } else result.add(context);
         // }
       }
       contextNode = contextNode.getNextDirect();
     }
   }
   return result;
 }
 /**
  * Return a new node set which represents the union of the current node set and the given node
  * set.
  *
  * @param other
  */
 public NodeSet union(NodeSet other) {
   NewArrayNodeSet result = new NewArrayNodeSet();
   result.addAll(other);
   NodeProxy p, c;
   for (Iterator i = iterator(); i.hasNext(); ) {
     p = (NodeProxy) i.next();
     if (other.contains(p)) {
       c = other.get(p);
       if (c != null) c.addMatches(p);
     } else result.add(p);
   }
   return result;
 }