public StoreMessageResultIterator(
     MessageMapper<Id> mapper,
     Mailbox<Id> mailbox,
     MessageRange range,
     int batchSize,
     org.apache.james.mailbox.model.MessageResult.FetchGroup group) {
   this.mailbox = mailbox;
   this.group = group;
   this.mapper = mapper;
   this.from = range.getUidFrom();
   this.cursor = this.from;
   this.to = range.getUidTo();
   this.batchSize = batchSize;
   this.type = range.getType();
   this.ftype = getFetchType(group);
 }
 private void readBatch() throws MailboxException {
   MessageRange range;
   switch (type) {
     default:
     case ALL:
       // In case of all, we start on cursor and don't specify a to
       range = MessageRange.from(cursor);
       break;
     case FROM:
       range = MessageRange.from(cursor);
       break;
     case ONE:
       range = MessageRange.one(cursor);
       break;
     case RANGE:
       range = MessageRange.range(cursor, to);
       break;
   }
   next = mapper.findInMailbox(mailbox, range, ftype, batchSize);
   if (!next.hasNext()) {
     done = true;
   }
 }
  @Override
  public Iterator<Long> search(MailboxSession session, Mailbox<Id> mailbox, SearchQuery query)
      throws MailboxException {
    List<Criterion> crits = query.getCriterias();
    MessageMapper<Id> mapper = factory.getMessageMapper(session);

    // Ok we only search for a range so we can optimize the call
    if (crits.size() == 1 && crits.get(0) instanceof UidCriterion) {
      final List<Long> uids = new ArrayList<Long>();
      UidCriterion uidCrit = (UidCriterion) crits.get(0);
      NumericRange[] ranges = uidCrit.getOperator().getRange();
      for (int i = 0; i < ranges.length; i++) {
        NumericRange r = ranges[i];
        Iterator<Message<Id>> messages =
            mapper.findInMailbox(
                mailbox,
                MessageRange.range(r.getLowValue(), r.getHighValue()),
                FetchType.Metadata,
                -1);

        while (messages.hasNext()) {
          long uid = messages.next().getUid();
          if (uids.contains(uid) == false) {
            uids.add(uid);
          }
        }
      }
      Collections.sort(uids);
      return uids.iterator();

    } else {

      final List<Message<Id>> hits = new ArrayList<Message<Id>>();

      Iterator<Message<Id>> messages =
          mapper.findInMailbox(mailbox, MessageRange.all(), FetchType.Full, -1);
      while (messages.hasNext()) {
        Message<Id> m = messages.next();
        if (hits.contains(m) == false) {
          hits.add(m);
        }
      }
      Collections.sort(hits);

      Iterator<Message<?>> it =
          new Iterator<Message<?>>() {
            final Iterator<Message<Id>> it = hits.iterator();

            public boolean hasNext() {
              return it.hasNext();
            }

            public Message<?> next() {
              return it.next();
            }

            public void remove() {
              it.remove();
            }
          };

      if (session == null) {
        return new MessageSearches(it, query).iterator();
      } else {
        return new MessageSearches(it, query, session.getLog()).iterator();
      }
    }
  }