NS_IMETHODIMP
nsUnionEnumerator::GetNext(nsISupports** aResult)
{
    NS_PRECONDITION(aResult != 0, "null ptr");
    if (! aResult)
        return NS_ERROR_NULL_POINTER;

    if (mConsumed)
        return NS_ERROR_UNEXPECTED;

    if (! mAtSecond)
        return mFirstEnumerator->GetNext(aResult);

    return mSecondEnumerator->GetNext(aResult);
}
nsMsgKey MsgMapiListContext::GetNext ()
{
  nsMsgKey key = nsMsgKey_None;
  PRBool    keepTrying = TRUE;
  
//  NS_ASSERTION (m_msgEnumerator && m_db, "need enumerator and db");
  if (m_msgEnumerator && m_db)
  {
    
    do 
    {
      keepTrying = FALSE;  
      nsCOMPtr <nsISupports> hdrISupports;
      nsCOMPtr <nsIMsgDBHdr> msgHdr;
      if (NS_SUCCEEDED(m_msgEnumerator->GetNext(getter_AddRefs(hdrISupports))) && hdrISupports)
      {
        msgHdr = do_QueryInterface(hdrISupports);
        msgHdr->GetMessageKey(&key);
        
        // Check here for IMAP message...if not, just return...
        if (!IsIMAPHost())
          return key;
        
        // If this is an IMAP message, we have to make sure we have a valid
        // body to work with.
        PRUint32  flags = 0;
        
        (void) msgHdr->GetFlags(&flags);
        if (flags & MSG_FLAG_OFFLINE) 
          return key;
        
        // Ok, if we get here, we have an IMAP message without a body!
        // We need to keep trying by calling the GetNext member recursively...
        keepTrying = TRUE;
      }
    } while (keepTrying);
  }
  
  return key;
}
NS_IMETHODIMP
ContainerEnumeratorImpl::HasMoreElements(bool* aResult)
{
    NS_ASSERTION(aResult != nullptr, "null ptr");
    if (! aResult)
        return NS_ERROR_NULL_POINTER;

    nsresult rv;

    // If we've already queued up a next value, then we know there are more elements.
    if (mResult) {
        *aResult = true;
        return NS_OK;
    }

    // Otherwise, we need to grovel

    // Figure out the upper bound so we'll know when we're done. Since it's
    // possible that we're targeting a composite datasource, we'll need to
    // "GetTargets()" and take the maximum value of "nextVal" to know the
    // upper bound.
    //
    // Remember that since nextVal is the next index that we'd assign
    // to an element in a container, it's *one more* than count of
    // elements in the container.
    int32_t max = 0;

    nsCOMPtr<nsISimpleEnumerator> targets;
    rv = mDataSource->GetTargets(mContainer, kRDF_nextVal, true, getter_AddRefs(targets));
    if (NS_FAILED(rv)) return rv;

    while (1) {
        bool hasmore;
        targets->HasMoreElements(&hasmore);
        if (! hasmore)
            break;

        nsCOMPtr<nsISupports> isupports;
        targets->GetNext(getter_AddRefs(isupports));

        nsCOMPtr<nsIRDFLiteral> nextValLiteral = do_QueryInterface(isupports);
        if (! nextValLiteral)
             continue;

         const char16_t *nextValStr;
         nextValLiteral->GetValueConst(&nextValStr);

         nsresult err;
         int32_t nextVal = nsAutoString(nextValStr).ToInteger(&err);

         if (nextVal > max)
             max = nextVal;
    }

    // Now pre-fetch our next value into mResult.
    while (mCurrent || mNextIndex < max) {

        // If mCurrent has been depleted, then conjure up a new one
        if (! mCurrent) {
            rv = gRDFC->IndexToOrdinalResource(mNextIndex, getter_AddRefs(mOrdinalProperty));
            if (NS_FAILED(rv)) return rv;

            rv = mDataSource->GetTargets(mContainer, mOrdinalProperty, true, getter_AddRefs(mCurrent));
            if (NS_FAILED(rv)) return rv;

            ++mNextIndex;
        }

        if (mCurrent) {
            bool hasMore;
            rv = mCurrent->HasMoreElements(&hasMore);
            if (NS_FAILED(rv)) return rv;

            // Is the current enumerator depleted? If so, iterate to
            // the next index.
            if (! hasMore) {
                mCurrent = nullptr;
                continue;
            }

            // "Peek" ahead and pull out the next target.
            nsCOMPtr<nsISupports> result;
            rv = mCurrent->GetNext(getter_AddRefs(result));
            if (NS_FAILED(rv)) return rv;

            mResult = do_QueryInterface(result, &rv);
            if (NS_FAILED(rv)) return rv;

            *aResult = true;
            return NS_OK;
        }
    }

    // If we get here, we ran out of elements. The cursor is empty.
    *aResult = false;
    return NS_OK;
}