/* (non-Javadoc)
@see org.archive.util.iterator.LookaheadIterator#lookahead()
335055
protected boolean lookahead() {
        assert next == null : "looking ahead when next is already loaded";
        while(inner.hasNext()) {
            next = transform(inner.next());
            if(next!=null) {
                return true;
            }
        }
        noteExhausted();
        return false;
    }
999760
@Override
  public boolean hasNext() {
    while (!(iteratorList.isEmpty() || iteratorList.get(currentIteratorIndex).hasNext())) {
      Assert.isFalse(iteratorList.remove(currentIteratorIndex).hasNext(), "removing a non-empty Iterator");
      currentIteratorIndex = (iteratorList.isEmpty() ? 0 : (currentIteratorIndex % iteratorList.size()));
    }

    return !iteratorList.isEmpty();
  }
620612
private boolean _findMatches() throws IOException {
    // queue not empty
    if (!queueMatches.isEmpty()) {
      return true;
      // no more matches to be found
    } else if (currentPosition == NO_MORE_POSITIONS) {
      return false;
      // try to find matches
    } else {
      // subMatches: try to build matches while collecting
      Integer subMatchesStartPosition = null;
      Boolean subMatchesOptional = true;
      List<Match> subMatchesQueue = new ArrayList<>();
      // minimum startPosition previous, used to set lower boundary on
      // startPosition next
      Integer minStartPositionPrevious = null;
      // maximum endPosition previous, used to set upper boundary on
      // startPosition next
      Integer maxEndPositionPrevious = null;
      // other variables
      Integer minStartPositionNext = null;
      Integer minStartPosition = null;
      Integer minOptionalStartPosition = null;
      // adjusted minimum ignoreItem
      boolean adjustedMinimumIgnoreItem = false;
      // fill queue if necessary and possible
      for (int i = 0; i < queueSpans.size(); i++) {
        QueueItem item = queueSpans.get(i);
        // if span is optional, check docId
        if (!item.sequenceSpans.optional || (item.sequenceSpans.spans != null
            && item.sequenceSpans.spans.docID() == docId)) {
          // compute minimum startPosition until next non-optional item
          // used as lower boundary on endPosition next
          minStartPositionNext = null;
          for (int j = (i + 1); j < queueSpans.size(); j++) {

            // check for available lowestPosition
            if (!queueSpans.get(j).sequenceSpans.optional
                && queueSpans.get(j).lowestPosition != null) {
              minStartPositionNext = (minStartPositionNext == null)
                  ? queueSpans.get(j).lowestPosition
                  : Math.min(minStartPositionNext,
                      queueSpans.get(j).lowestPosition);
              // computing restrictions not possible
            } else {
              if (!queueSpans.get(j).sequenceSpans.optional) {
                minStartPositionNext = null;
              }
              break;
            }
          }
          // fill queue
          if ((minStartPositionPrevious == null) || subMatchesOptional) {
            fillQueue(item, null, maxEndPositionPrevious, minStartPositionNext);
          } else {
            fillQueue(item, minStartPositionPrevious, maxEndPositionPrevious,
                minStartPositionNext);
          }
          // try to adjust minimum ignoreItem
          if (!adjustedMinimumIgnoreItem && !item.sequenceSpans.optional
              && item.filledPosition) {
            if (minOptionalStartPosition != null) {
              ignoreItem.removeBefore(docId,
                  Math.min(minOptionalStartPosition, item.lowestPosition));
            } else {
              ignoreItem.removeBefore(docId, item.lowestPosition);
            }
            adjustedMinimumIgnoreItem = true;
          }
          // check for available positions
          if (!item.sequenceSpans.optional && item.noMorePositions
              && !item.filledPosition) {
            currentPosition = NO_MORE_POSITIONS;
            return false;
          }
          // build matches
          subMatchesQueue = _glue(subMatchesQueue, subMatchesOptional, item);
          // update subMatchesOptional
          if (!item.sequenceSpans.optional) {
            subMatchesOptional = false;
          }
          // check if matches are still achievable
          if (!subMatchesOptional && subMatchesQueue.isEmpty()) {
            // clean up previous queues
            if (subMatchesStartPosition != null) {
              int cleanStartPosition = subMatchesStartPosition;
              for (int j = 0; j <= i; j++) {
                queueSpans.get(j).del(cleanStartPosition);
                if (!queueSpans.get(j).sequenceSpans.optional) {
                  cleanStartPosition++;
                }
              }
            }
            return false;
          }
          // update subMatchesStartPosition
          if (subMatchesQueue.isEmpty()) {
            subMatchesStartPosition = null;
          } else {
            subMatchesStartPosition = subMatchesQueue.get(0).startPosition;
          }
          // compute minimum startPosition for next span
          if (item.lowestPosition != null) {
            minStartPositionPrevious = (minStartPositionPrevious == null)
                ? item.lowestPosition
                : Math.min(minStartPositionPrevious, item.lowestPosition);
          }
          // for optional spans
          if (item.sequenceSpans.optional) {
            // update stats
            if (item.lowestPosition != null) {
              minOptionalStartPosition = (minOptionalStartPosition == null)
                  ? item.lowestPosition
                  : Math.min(minOptionalStartPosition, item.lowestPosition);
            }
            // for not optional spans
          } else {
            // update stats, item.lowestPosition should be set
            minStartPosition = (minStartPosition == null) ? item.lowestPosition
                : Math.min(minStartPosition, item.lowestPosition);
            // reset maximum endPosition for next span
            maxEndPositionPrevious = null;
          }
          // compute maximum endPosition for next span
          if (item.lowestPosition != null) {
            for (Integer endPosition : item.queue.get(item.lowestPosition)) {
              maxEndPositionPrevious = (maxEndPositionPrevious == null)
                  ? endPosition : Math.max(maxEndPositionPrevious, endPosition);
            }
          }
        }
      }
      if (subMatchesQueue.isEmpty()) {
        // condition has only optional parts
        if (subMatchesOptional) {
          // check for
          boolean allFinished = true;
          for (int i = 0; i < queueSpans.size(); i++) {
            if (!queueSpans.get(i).noMorePositions) {
              allFinished = false;
              break;
            }
          }
          if (allFinished) {
            currentPosition = NO_MORE_POSITIONS;
          }
        }
        return false;
      } else if ((minOptionalStartPosition != null)
          && (minOptionalStartPosition < subMatchesStartPosition)) {
        for (int i = 0; i < queueSpans.size(); i++) {
          if (!queueSpans.get(i).sequenceSpans.optional) {
            break;
          } else {
            queueSpans.get(i).del(minOptionalStartPosition);
          }
        }
        return false;
      } else {
        for (int i = 0; i < queueSpans.size(); i++) {
          queueSpans.get(i).del(subMatchesStartPosition);
        }
        for (Match m : subMatchesQueue) {
          if (!queueMatches.contains(m)) {
            queueMatches.add(m);
          }
        }
        ignoreItem.removeBefore(docId, queueMatches.get(0).startPosition);
        return true;
      }
    }
  }
54986
public static Iterator iterator(final Matcher matcher) {
        matcher.reset();
        return new Iterator() {
            private boolean found /* = false */;
            private boolean done /* = false */;

            public boolean hasNext() {
                if (done) {
                    return false;
                }
                if (!found) {
                    found = matcher.find();
                    if (!found) {
                        done = true;
                    }
                }
                return found;
            }

            public Object next() {
                if (!found) {
                    if (!hasNext()) {
                        throw new NoSuchElementException();
                    }
                }
                found = false;

                if (hasGroup(matcher)) {
                    // are we using groups?
                    // yes, so return the specified group as list
                    List<String> list = new ArrayList<String>(matcher.groupCount());
                    for (int i = 0; i <= matcher.groupCount(); i++) {
                       list.add(matcher.group(i));
                    }
                    return list;
                } else {
                    // not using groups, so return the nth
                    // occurrence of the pattern
                    return matcher.group();
                 }
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
369543
@Override
  public int nextStartPosition() throws IOException {
    // no document
    if (docId == -1 || docId == NO_MORE_DOCS) {
      throw new IOException("no document");
      // finished
    } else if (noMorePositions) {
      return NO_MORE_POSITIONS;
      // littleSpans already at start match, because of check for matching
      // document
    } else if (!calledNextStartPosition) {
      calledNextStartPosition = true;
      return spans1.spans.startPosition();
      // compute next match
    } else {
      if (goToNextStartPosition()) {
        // match found
        return spans1.spans.startPosition();
      } else {
        // no more matches: document finished
        return NO_MORE_POSITIONS;
      }
    }
  }
881758
public char next() throws JSONException {

        if (m_useLastChar) {
            m_useLastChar = false;
            if (m_lastChar != 0) {
                m_index += 1;
            }
            return m_lastChar;
        }
        int c;
        try {
            c = m_reader.read();
        } catch (IOException exc) {
            throw new JSONException(exc);
        }

        if (c <= 0) { // End of stream
            m_lastChar = 0;
            return 0;
        }
        m_index += 1;
        m_lastChar = (char)c;
        return m_lastChar;
    }
116856
@Override
    public E next()
    {
        if (results != null && !results.isEmpty() && count < results.size())
        {
            current = results.get(count++);
            return current;
        }
        else
        {
            throw new NoSuchElementException(
                    "No object found in the iterator... Use hasNext() to check for valid next()");
        }
    }
916779
public Object read() throws IOException {
    char[] buffer = new char[BUFFER_LENGTH];
    reader.mark(BUFFER_LENGTH);
    int count = 0;
    int textEnd;

    while (true) {
      int r = reader.read(buffer, count, buffer.length - count);

      if (r == -1) {
        // the input is exhausted; return the remaining characters
        textEnd = count;
        break;
      }

      count += r;
      int possibleMarker = findPossibleMarker(buffer, count);

      if (possibleMarker != 0) {
        // return the characters that precede the marker
        textEnd = possibleMarker;
        break;
      }

      if (count < marker.length()) {
        // the buffer contains only the prefix of a marker so we must read more
        continue;
      }

      // we've read a marker so return the value that follows
      reader.reset();
      String json = reader.readLine().substring(marker.length());
      return jsonParser.parse(json);
    }

    if (count == 0) {
      return null;
    }

    // return characters
    reader.reset();
    count = reader.read(buffer, 0, textEnd);
    return new String(buffer, 0, count);
  }
125654
public E lookahead(int position) {
        int idx = offset + position - 1;
        if (idx < elements.length) {
            return elements[idx];
        }
        return null;
    }
1298913
@Override
  public int nextStartPosition() throws IOException {
    if (findMatches()) {
      currentMatch = queueMatches.get(0);
      queueMatches.remove(0);
      noMorePositions = false;
      return currentMatch.startPosition();
    } else {
      currentMatch = null;
      noMorePositions = true;
      return NO_MORE_POSITIONS;
    }
  }
1167337
public T getNext() throws IOException {
    try {
      return mapper.readValue(jsonParser, clazz);
    } catch (EOFException e) {
      return null;
    }
  }
469029
@Override
  public boolean hasNext() {
    if (!peekingIterator.hasNext()) {
      return false;
    }
    DirectionalRecord record = peekingIterator.peek();
    if (record.noResponseRecord) {
      // TODO: log as this is unsupported
      peekingIterator.next();
    }
    return true;
  }
370524
@Override
	public int lookupIndex(String str) {
		int ret = data.get(str);
		if (ret ==-1 && !frozen)	{
			ret = index.size();
			data.put(str, ret);
			index.put(ret, str);
		}
		return ret;
	}
39253
public T first() {
        Iterator<T> iterator = iterator();
        return (iterator.hasNext() ? iterator.next() : null);
    }
1255545
@Override
    public boolean checkRead()
    {
        //  Was the value prefetched already? If so, return.
        int h = queue.frontPos();
        if (h != r) {
            return true;
        }

        //  There's no prefetched value, so let us prefetch more values.
        //  Prefetching is to simply retrieve the
        //  pointer from c in atomic fashion. If there are no
        //  items to prefetch, set c to -1 (using compare-and-swap).
        if (c.compareAndSet(h, -1)) {
            // nothing to read, h == r must be the same
        }
        else {
            // something to have been written
            r = c.get();
        }

        //  If there are no elements prefetched, exit.
        //  During pipe's lifetime r should never be NULL, however,
        //  it can happen during pipe shutdown when items
        //  are being deallocated.
        if (h == r || r == -1) {
            return false;
        }

        //  There was at least one value prefetched.
        return true;
    }
14078
public static Iterator<String> iterator(Reader self) {
        final BufferedReader bufferedReader;
        if (self instanceof BufferedReader)
            bufferedReader = (BufferedReader) self;
        else
            bufferedReader = new BufferedReader(self);
        return new Iterator<String>() {
            String nextVal /* = null */;
            boolean nextMustRead = true;
            boolean hasNext = true;

            public boolean hasNext() {
                if (nextMustRead && hasNext) {
                    try {
                        nextVal = readNext();
                        nextMustRead = false;
                    } catch (IOException e) {
                        hasNext = false;
                    }
                }
                return hasNext;
            }

            public String next() {
                String retval = null;
                if (nextMustRead) {
                    try {
                        retval = readNext();
                    } catch (IOException e) {
                        hasNext = false;
                    }
                } else
                    retval = nextVal;
                nextMustRead = true;
                return retval;
            }

            private String readNext() throws IOException {
                String nv = bufferedReader.readLine();
                if (nv == null)
                    hasNext = false;
                return nv;
            }

            public void remove() {
                throw new UnsupportedOperationException("Cannot remove() from a Reader Iterator");
            }
        };
    }
619711
private static Iterator<String> getBaseIterator(BufferedReader reader,
                                                    boolean keepOrdering) {

        // The final iterator is how the stream will be tokenized after all the
        // tokenizing options have been applied.  This value is iteratively set
        // as the options are applied
        Iterator<String> finalIterator = new WordIterator(reader);

        // STEP 1: APPLY TOKEN REPLACEMENT
        if (replacementMap != null)
            finalIterator = 
                new WordReplacementIterator(finalIterator, replacementMap);

        // STEP 2: APPLY COMPOUND TOKENIZING
        if (compoundTokens != null) {
            // Because the initialization step for a CWI has some overhead, use
            // the reset to keep the same tokens.  However, multiple threads may
            // be each using their own CWI, so keep Thread-local storage of what
            // CWI is being used to avoid resetting another thread's iterator.
            CompoundWordIterator cwi = 
                compoundIterators.get(Thread.currentThread());
            if (cwi == null) {
                cwi = new CompoundWordIterator(finalIterator, compoundTokens);
                compoundIterators.put(Thread.currentThread(), cwi);
            } else {
                // NOTE: if the underlying set of valid compound words is ever
                // changed, the iterator returned from the compoundIterators map
                // will have been updated by the setProperties() call, so this
                // method is guaranteed to pick up the latest set of compound
                // words
                cwi.reset(finalIterator);
            }
            finalIterator = cwi;
        } 

        // STEP 3: APPLY TOKEN LIMITING
        if (wordLimit > 0)
            finalIterator = new LimitedIterator<String>(
                    finalIterator, wordLimit);

        // STEP 4: APPLY TOKEN FILTERING
        if (filter != null) {
            finalIterator = (keepOrdering)
                ? new OrderPreservingFilteredIterator(finalIterator, filter)
                : new FilteredIterator(finalIterator, filter);
        }

        // STEP 5: APPLY STEMMING
        if (stemmer != null) 
            finalIterator = new StemmingIterator(finalIterator, stemmer);

        return finalIterator;
    }