code: public void processDocument(BufferedReader document, Wordsi wordsi) {
          Queue<String> prevWords = new ArrayDeque<String>();
          Queue<String> nextWords = new ArrayDeque<String>();
  
          Iterator<String> it = IteratorFactory.tokenizeOrdered(document);
  
          // Skip empty documents.
          if (!it.hasNext())
              return;
  
          // Read the header and use it as the secondary key for wordsi, if told
          // to do so.
          String header = null;
          if (readHeader)
              header = it.next();
  
          // Fill up the words after the context so that when the real processing
          // starts, the context is fully prepared.
          for (int i = 0 ; i < windowSize && it.hasNext(); ++i)
              nextWords.offer(it.next());
  
          // Iterate through each of the words in the context, generating context
          // vectors for each acceptable word.
          String focus = null;
          while (!nextWords.isEmpty()) {
              focus = nextWords.remove();
              String secondaryKey = (header == null) ? focus : header;
  
              // Advance the sliding window to the right.
              if (it.hasNext())
                  nextWords.offer(it.next());
  
              // Represent the word if wordsi is willing to process it.
              if (wordsi.acceptWord(focus)) {
                  SparseDoubleVector contextVector = generator.generateContext(
                          prevWords, nextWords);
                  wordsi.handleContextVector(focus, secondaryKey, contextVector);
              }
  
              // Advance the sliding window to the right.
              prevWords.offer(focus);
              if (prevWords.size() > windowSize)
                  prevWords.remove();
          }
      }
docs: {@inheritDoc}