@Override
 public int nextDoc() throws IOException {
   assertThread("Sorted doc values", creationThread);
   int docID = in.nextDoc();
   assert docID > lastDocID;
   assert docID == NO_MORE_DOCS || docID < maxDoc;
   assert docID == in.docID();
   lastDocID = docID;
   return docID;
 }
 private int[] sortDocValues(int maxDoc, Sorter.DocMap sortMap, SortedDocValues oldValues)
     throws IOException {
   int[] ords = new int[maxDoc];
   Arrays.fill(ords, -1);
   int docID;
   while ((docID = oldValues.nextDoc()) != NO_MORE_DOCS) {
     int newDocID = sortMap.oldToNew(docID);
     ords[newDocID] = oldValues.ordValue();
   }
   return ords;
 }
 @Override
 public int advance(int target) throws IOException {
   assertThread("Sorted doc values", creationThread);
   assert target >= 0;
   assert target >= in.docID();
   int docID = in.advance(target);
   assert docID >= target;
   assert docID == NO_MORE_DOCS || docID < maxDoc;
   lastDocID = docID;
   return docID;
 }
 @Override
 public BytesRef binaryValue() {
   assertThread("Sorted doc values", creationThread);
   final BytesRef result = in.binaryValue();
   assert result.isValid();
   return result;
 }
 @Override
 public int getValueCount() {
   assertThread("Sorted doc values", creationThread);
   int valueCount = in.getValueCount();
   assert valueCount == this.valueCount; // should not change
   return valueCount;
 }
 @Override
 public int ordValue() {
   assertThread("Sorted doc values", creationThread);
   int ord = in.ordValue();
   assert ord >= -1 && ord < valueCount;
   return ord;
 }
 @Override
 public long cost() {
   assertThread("Sorted doc values", creationThread);
   long cost = in.cost();
   assert cost >= 0;
   return cost;
 }
 @Override
 public BytesRef lookupOrd(int ord) {
   assertThread("Sorted doc values", creationThread);
   assert ord >= 0 && ord < valueCount;
   final BytesRef result = in.lookupOrd(ord);
   assert result.isValid();
   return result;
 }
 @Override
 public int lookupTerm(BytesRef key) {
   assertThread("Sorted doc values", creationThread);
   assert key.isValid();
   int result = in.lookupTerm(key);
   assert result < valueCount;
   assert key.isValid();
   return result;
 }
  public void testSorted() throws Exception {
    Directory dir = newDirectory();
    Document doc = new Document();
    Field field = new SortedDocValuesField("bytes", new BytesRef());
    doc.add(field);

    IndexWriterConfig iwc = newIndexWriterConfig(random(), null);
    iwc.setMergePolicy(newLogMergePolicy());
    RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc);

    int numDocs = TEST_NIGHTLY ? atLeast(500) : atLeast(50);
    for (int i = 0; i < numDocs; i++) {
      BytesRef ref = new BytesRef(TestUtil.randomUnicodeString(random()));
      field.setBytesValue(ref);
      if (random().nextInt(7) == 0) {
        iw.addDocument(new Document());
      }
      iw.addDocument(doc);
      if (random().nextInt(17) == 0) {
        iw.commit();
      }
    }
    DirectoryReader ir = iw.getReader();
    iw.forceMerge(1);
    DirectoryReader ir2 = iw.getReader();
    LeafReader merged = getOnlyLeafReader(ir2);
    iw.close();

    SortedDocValues multi = MultiDocValues.getSortedValues(ir, "bytes");
    SortedDocValues single = merged.getSortedDocValues("bytes");
    assertEquals(single.getValueCount(), multi.getValueCount());
    for (int i = 0; i < numDocs; i++) {
      // check ord
      assertEquals(single.getOrd(i), multi.getOrd(i));
      // check value
      final BytesRef expected = BytesRef.deepCopyOf(single.get(i));
      final BytesRef actual = multi.get(i);
      assertEquals(expected, actual);
    }
    ir.close();
    ir2.close();
    dir.close();
  }
 @Override
 public int docID() {
   assertThread("Sorted doc values", creationThread);
   return in.docID();
 }
 public AssertingSortedDocValues(SortedDocValues in, int maxDoc) {
   this.in = in;
   this.maxDoc = maxDoc;
   this.valueCount = in.getValueCount();
   assert valueCount >= 0 && valueCount <= maxDoc;
 }