Index: lucene/src/test/org/apache/lucene/index/TestNorms.java =================================================================== --- lucene/src/test/org/apache/lucene/index/TestNorms.java (revision 1056691) +++ lucene/src/test/org/apache/lucene/index/TestNorms.java (working copy) @@ -236,4 +236,52 @@ return norm; } + class CustomNormEncodingSimilarity extends DefaultSimilarity { + @Override + public byte encodeNormValue(float f) { + return (byte) f; + } + + @Override + public float decodeNormValue(byte b) { + return (float) b; + } + + @Override + public float computeNorm(String field, FieldInvertState state) { + return (float) state.getLength(); + } + } + + // LUCENE-1260 + public void testCustomEncoder() throws Exception { + Directory dir = newDirectory(); + IndexWriterConfig config = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()); + config.setSimilarity(new CustomNormEncodingSimilarity()); + RandomIndexWriter writer = new RandomIndexWriter(random, dir, config); + Document doc = new Document(); + Field foo = newField("foo", "", Field.Store.NO, Field.Index.ANALYZED); + Field bar = newField("bar", "", Field.Store.NO, Field.Index.ANALYZED); + doc.add(foo); + doc.add(bar); + + for (int i = 0; i < 100; i++) { + bar.setValue("singleton"); + writer.addDocument(doc); + } + + IndexReader reader = writer.getReader(); + writer.close(); + + byte fooNorms[] = MultiNorms.norms(reader, "foo"); + for (int i = 0; i < reader.maxDoc(); i++) + assertEquals(0, fooNorms[i]); + + byte barNorms[] = MultiNorms.norms(reader, "bar"); + for (int i = 0; i < reader.maxDoc(); i++) + assertEquals(1, barNorms[i]); + + reader.close(); + dir.close(); + } } Index: lucene/src/java/org/apache/lucene/search/Similarity.java =================================================================== --- lucene/src/java/org/apache/lucene/search/Similarity.java (revision 1056691) +++ lucene/src/java/org/apache/lucene/search/Similarity.java (working copy) @@ -563,6 +563,11 @@ } /** Decodes a normalization factor stored in an index. + *
+ * WARNING: If you override this method, you should change the default + * Similarity to your implementation with {@link Similarity#setDefault(Similarity)}. + * Otherwise, your method may not always be called, especially if you omit norms + * for some fields. * @see #encodeNormValue(float) */ public float decodeNormValue(byte b) { @@ -641,7 +646,11 @@ * are rounded down to the largest representable value. Positive values too * small to represent are rounded up to the smallest positive representable * value. - * + *
+ * WARNING: If you override this method, you should change the default + * Similarity to your implementation with {@link Similarity#setDefault(Similarity)}. + * Otherwise, your method may not always be called, especially if you omit norms + * for some fields. * @see org.apache.lucene.document.Field#setBoost(float) * @see org.apache.lucene.util.SmallFloat */ Index: lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java =================================================================== --- lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java (revision 1056691) +++ lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java (working copy) @@ -73,7 +73,7 @@ norms = ArrayUtil.grow(norms, 1+upto); } final float norm = docState.similarity.computeNorm(fieldInfo.name, fieldState); - norms[upto] = Similarity.getDefault().encodeNormValue(norm); + norms[upto] = docState.similarity.encodeNormValue(norm); docIDs[upto] = docState.docID; upto++; } Index: lucene/src/java/org/apache/lucene/index/NormsWriter.java =================================================================== --- lucene/src/java/org/apache/lucene/index/NormsWriter.java (revision 1056691) +++ lucene/src/java/org/apache/lucene/index/NormsWriter.java (working copy) @@ -37,7 +37,7 @@ final class NormsWriter extends InvertedDocEndConsumer { - private static final byte defaultNorm = Similarity.getDefault().encodeNormValue(1.0f); + private final byte defaultNorm = Similarity.getDefault().encodeNormValue(1.0f); private FieldInfos fieldInfos; @Override public InvertedDocEndConsumerPerThread addThread(DocInverterPerThread docInverterPerThread) {