/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.lucene.codecs;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.index.DocIDMerger;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.MergeState;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.SegmentWriteState;

Abstract API that consumes normalization values. Concrete implementations of this actually do "something" with the norms (write it into the index in a specific format).

The lifecycle is:

  1. NormsConsumer is created by NormsFormat.normsConsumer(SegmentWriteState).
  2. addNormsField is called for each field with normalization values. The API is a "pull" rather than "push", and the implementation is free to iterate over the values multiple times (Iterable.iterator()).
  3. After all fields are added, the consumer is Closeable.closed.
@lucene.experimental
/** * Abstract API that consumes normalization values. * Concrete implementations of this * actually do "something" with the norms (write it into * the index in a specific format). * <p> * The lifecycle is: * <ol> * <li>NormsConsumer is created by * {@link NormsFormat#normsConsumer(SegmentWriteState)}. * <li>{@link #addNormsField} is called for each field with * normalization values. The API is a "pull" rather * than "push", and the implementation is free to iterate over the * values multiple times ({@link Iterable#iterator()}). * <li>After all fields are added, the consumer is {@link #close}d. * </ol> * * @lucene.experimental */
public abstract class NormsConsumer implements Closeable {
Sole constructor. (For invocation by subclass constructors, typically implicit.)
/** Sole constructor. (For invocation by subclass * constructors, typically implicit.) */
protected NormsConsumer() {}
Writes normalization values for a field.
Params:
  • field – field information
  • normsProducer – NormsProducer of the numeric norm values
Throws:
/** * Writes normalization values for a field. * @param field field information * @param normsProducer NormsProducer of the numeric norm values * @throws IOException if an I/O error occurred. */
public abstract void addNormsField(FieldInfo field, NormsProducer normsProducer) throws IOException;
Merges in the fields from the readers in mergeState. The default implementation calls mergeNormsField for each field, filling segments with missing norms for the field with zeros. Implementations can override this method for more sophisticated merging (bulk-byte copying, etc).
/** Merges in the fields from the readers in * <code>mergeState</code>. The default implementation * calls {@link #mergeNormsField} for each field, * filling segments with missing norms for the field with zeros. * Implementations can override this method * for more sophisticated merging (bulk-byte copying, etc). */
public void merge(MergeState mergeState) throws IOException { for(NormsProducer normsProducer : mergeState.normsProducers) { if (normsProducer != null) { normsProducer.checkIntegrity(); } } for (FieldInfo mergeFieldInfo : mergeState.mergeFieldInfos) { if (mergeFieldInfo.hasNorms()) { mergeNormsField(mergeFieldInfo, mergeState); } } }
Tracks state of one numeric sub-reader that we are merging
/** Tracks state of one numeric sub-reader that we are merging */
private static class NumericDocValuesSub extends DocIDMerger.Sub { private final NumericDocValues values; public NumericDocValuesSub(MergeState.DocMap docMap, NumericDocValues values) { super(docMap); this.values = values; assert values.docID() == -1; } @Override public int nextDoc() throws IOException { return values.nextDoc(); } }
Merges the norms from toMerge.

The default implementation calls addNormsField, passing an Iterable that merges and filters deleted documents on the fly.

/** * Merges the norms from <code>toMerge</code>. * <p> * The default implementation calls {@link #addNormsField}, passing * an Iterable that merges and filters deleted documents on the fly. */
public void mergeNormsField(final FieldInfo mergeFieldInfo, final MergeState mergeState) throws IOException { // TODO: try to share code with default merge of DVConsumer by passing MatchAllBits ? addNormsField(mergeFieldInfo, new NormsProducer() { @Override public NumericDocValues getNorms(FieldInfo fieldInfo) throws IOException { if (fieldInfo != mergeFieldInfo) { throw new IllegalArgumentException("wrong fieldInfo"); } List<NumericDocValuesSub> subs = new ArrayList<>(); assert mergeState.docMaps.length == mergeState.docValuesProducers.length; for (int i=0;i<mergeState.docValuesProducers.length;i++) { NumericDocValues norms = null; NormsProducer normsProducer = mergeState.normsProducers[i]; if (normsProducer != null) { FieldInfo readerFieldInfo = mergeState.fieldInfos[i].fieldInfo(mergeFieldInfo.name); if (readerFieldInfo != null && readerFieldInfo.hasNorms()) { norms = normsProducer.getNorms(readerFieldInfo); } } if (norms != null) { subs.add(new NumericDocValuesSub(mergeState.docMaps[i], norms)); } } final DocIDMerger<NumericDocValuesSub> docIDMerger = DocIDMerger.of(subs, mergeState.needsIndexSort); return new NumericDocValues() { private int docID = -1; private NumericDocValuesSub current; @Override public int docID() { return docID; } @Override public int nextDoc() throws IOException { current = docIDMerger.next(); if (current == null) { docID = NO_MORE_DOCS; } else { docID = current.mappedDocID; } return docID; } @Override public int advance(int target) throws IOException { throw new UnsupportedOperationException(); } @Override public boolean advanceExact(int target) throws IOException { throw new UnsupportedOperationException(); } @Override public long cost() { return 0; } @Override public long longValue() throws IOException { return current.values.longValue(); } }; } @Override public void checkIntegrity() { } @Override public void close() { } @Override public long ramBytesUsed() { return 0; } }); } }