pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / misc / src / java / org / apache / lucene / index / FieldNormModifier.java
1 package org.apache.lucene.index;
2
3 /**
4  * Copyright 2006 The Apache Software Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 import java.io.IOException;
20 import java.io.File;
21 import java.util.Date;
22
23 import org.apache.lucene.search.Similarity;
24 import org.apache.lucene.store.Directory;
25 import org.apache.lucene.store.FSDirectory;
26 import org.apache.lucene.util.StringHelper;
27
28 /**
29  * Given a directory and a list of fields, updates the fieldNorms in place for every document.
30  * 
31  * If Similarity class is specified, uses its computeNorm method to set norms.
32  * If -n command line argument is used, removed field norms, as if 
33  * {@link org.apache.lucene.document.Field.Index}.NO_NORMS was used.
34  *
35  * <p>
36  * NOTE: This will overwrite any length normalization or field/document boosts.
37  * </p>
38  *
39  */
40 public class FieldNormModifier {
41
42   /**
43    * Command Line Execution method.
44    *
45    * <pre>
46    * Usage: FieldNormModifier /path/index &lt;package.SimilarityClassName | -n&gt; field1 field2 ...
47    * </pre>
48    */
49   public static void main(String[] args) throws IOException {
50     if (args.length < 3) {
51       System.err.println("Usage: FieldNormModifier <index> <package.SimilarityClassName | -n> <field1> [field2] ...");
52       System.exit(1);
53     }
54
55     Similarity s = null;
56     if (!args[1].equals("-n")) {
57       try {
58         s = Class.forName(args[1]).asSubclass(Similarity.class).newInstance();
59       } catch (Exception e) {
60         System.err.println("Couldn't instantiate similarity with empty constructor: " + args[1]);
61         e.printStackTrace(System.err);
62         System.exit(1);
63       }
64     }
65
66     Directory d = FSDirectory.open(new File(args[0]));
67     FieldNormModifier fnm = new FieldNormModifier(d, s);
68
69     for (int i = 2; i < args.length; i++) {
70       System.out.print("Updating field: " + args[i] + " " + (new Date()).toString() + " ... ");
71       fnm.reSetNorms(args[i]);
72       System.out.println(new Date().toString());
73     }
74     
75     d.close();
76   }
77   
78   
79   private Directory dir;
80   private Similarity sim;
81   
82   /**
83    * Constructor for code that wishes to use this class programmatically
84    * If Similarity is null, kill the field norms.
85    *
86    * @param d the Directory to modify
87    * @param s the Similarity to use (can be null)
88    */
89   public FieldNormModifier(Directory d, Similarity s) {
90     dir = d;
91     sim = s;
92   }
93
94   /**
95    * Resets the norms for the specified field.
96    *
97    * <p>
98    * Opens a new IndexReader on the Directory given to this instance,
99    * modifies the norms (either using the Similarity given to this instance, or by using fake norms,
100    * and closes the IndexReader.
101    * </p>
102    *
103    * @param field the field whose norms should be reset
104    */
105   public void reSetNorms(String field) throws IOException {
106     String fieldName = StringHelper.intern(field);
107     int[] termCounts = new int[0];
108     
109     IndexReader reader = null;
110     TermEnum termEnum = null;
111     TermDocs termDocs = null;
112     try {
113       reader = IndexReader.open(dir, true);
114       termCounts = new int[reader.maxDoc()];
115       try {
116         termEnum = reader.terms(new Term(field));
117         try {
118           termDocs = reader.termDocs();
119           do {
120             Term term = termEnum.term();
121             if (term != null && term.field().equals(fieldName)) {
122               termDocs.seek(termEnum.term());
123               while (termDocs.next()) {
124                 termCounts[termDocs.doc()] += termDocs.freq();
125               }
126             }
127           } while (termEnum.next());
128           
129         } finally {
130           if (null != termDocs) termDocs.close();
131         }
132       } finally {
133         if (null != termEnum) termEnum.close();
134       }
135     } finally {
136       if (null != reader) reader.close();
137     }
138     
139     try {
140       reader = IndexReader.open(dir, false); 
141       final FieldInvertState invertState = new FieldInvertState();
142       invertState.setBoost(1.0f);
143       for (int d = 0; d < termCounts.length; d++) {
144         if (! reader.isDeleted(d)) {
145           if (sim == null)
146             reader.setNorm(d, fieldName, Similarity.encodeNorm(1.0f));
147           else {
148             invertState.setLength(termCounts[d]);
149             reader.setNorm(d, fieldName, sim.encodeNormValue(sim.computeNorm(fieldName, invertState)));
150           }
151         }
152       }
153       
154     } finally {
155       if (null != reader) reader.close();
156     }
157   }
158   
159 }