Save This Page
Home » lucene-2.4.1-src » org.apache » lucene » search » [javadoc | source]
    1   package org.apache.lucene.search;
    2   
    3   /**
    4    * Licensed to the Apache Software Foundation (ASF) under one or more
    5    * contributor license agreements.  See the NOTICE file distributed with
    6    * this work for additional information regarding copyright ownership.
    7    * The ASF licenses this file to You under the Apache License, Version 2.0
    8    * (the "License"); you may not use this file except in compliance with
    9    * the License.  You may obtain a copy of the License at
   10    *
   11    *     http://www.apache.org/licenses/LICENSE-2.0
   12    *
   13    * Unless required by applicable law or agreed to in writing, software
   14    * distributed under the License is distributed on an "AS IS" BASIS,
   15    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   16    * See the License for the specific language governing permissions and
   17    * limitations under the License.
   18    */
   19   
   20   import org.apache.lucene.index.IndexReader;
   21   import org.apache.lucene.index.Term;
   22   import org.apache.lucene.index.TermDocs;
   23   import org.apache.lucene.index.TermEnum;
   24   
   25   import java.io.IOException;
   26   import java.util.HashMap;
   27   import java.util.Locale;
   28   import java.util.Map;
   29   import java.util.WeakHashMap;
   30   
   31   /**
   32    * Expert: The default cache implementation, storing all values in memory.
   33    * A WeakHashMap is used for storage.
   34    *
   35    * <p>Created: May 19, 2004 4:40:36 PM
   36    *
   37    * @since   lucene 1.4
   38    * @version $Id: FieldCacheImpl.java 695514 2008-09-15 15:42:11Z otis $
   39    */
   40   class FieldCacheImpl
   41   implements FieldCache {
   42   	
   43     /** Expert: Internal cache. */
   44     abstract static class Cache {
   45       private final Map readerCache = new WeakHashMap();
   46       
   47       protected abstract Object createValue(IndexReader reader, Object key)
   48           throws IOException;
   49   
   50       public Object get(IndexReader reader, Object key) throws IOException {
   51         Map innerCache;
   52         Object value;
   53         synchronized (readerCache) {
   54           innerCache = (Map) readerCache.get(reader);
   55           if (innerCache == null) {
   56             innerCache = new HashMap();
   57             readerCache.put(reader, innerCache);
   58             value = null;
   59           } else {
   60             value = innerCache.get(key);
   61           }
   62           if (value == null) {
   63             value = new CreationPlaceholder();
   64             innerCache.put(key, value);
   65           }
   66         }
   67         if (value instanceof CreationPlaceholder) {
   68           synchronized (value) {
   69             CreationPlaceholder progress = (CreationPlaceholder) value;
   70             if (progress.value == null) {
   71               progress.value = createValue(reader, key);
   72               synchronized (readerCache) {
   73                 innerCache.put(key, progress.value);
   74               }
   75             }
   76             return progress.value;
   77           }
   78         }
   79         return value;
   80       }
   81     }
   82   
   83     static final class CreationPlaceholder {
   84       Object value;
   85     }
   86   
   87     /** Expert: Every composite-key in the internal cache is of this type. */
   88     static class Entry {
   89       final String field;        // which Fieldable
   90       final int type;            // which SortField type
   91       final Object custom;       // which custom comparator
   92       final Locale locale;       // the locale we're sorting (if string)
   93   
   94       /** Creates one of these objects. */
   95       Entry (String field, int type, Locale locale) {
   96         this.field = field.intern();
   97         this.type = type;
   98         this.custom = null;
   99         this.locale = locale;
  100       }
  101   
  102       /** Creates one of these objects for a custom comparator. */
  103       Entry (String field, Object custom) {
  104         this.field = field.intern();
  105         this.type = SortField.CUSTOM;
  106         this.custom = custom;
  107         this.locale = null;
  108       }
  109   
  110       /** Two of these are equal iff they reference the same field and type. */
  111       public boolean equals (Object o) {
  112         if (o instanceof Entry) {
  113           Entry other = (Entry) o;
  114           if (other.field == field && other.type == type) {
  115             if (other.locale == null ? locale == null : other.locale.equals(locale)) {
  116               if (other.custom == null) {
  117                 if (custom == null) return true;
  118               } else if (other.custom.equals (custom)) {
  119                 return true;
  120               }
  121             }
  122           }
  123         }
  124         return false;
  125       }
  126   
  127       /** Composes a hashcode based on the field and type. */
  128       public int hashCode() {
  129         return field.hashCode() ^ type ^ (custom==null ? 0 : custom.hashCode()) ^ (locale==null ? 0 : locale.hashCode());
  130       }
  131     }
  132   
  133     private static final ByteParser BYTE_PARSER = new ByteParser() {
  134       public byte parseByte(String value) {
  135         return Byte.parseByte(value);
  136       }
  137     };
  138   
  139     private static final ShortParser SHORT_PARSER = new ShortParser() {
  140       public short parseShort(String value) {
  141         return Short.parseShort(value);
  142       }
  143     };
  144   
  145     private static final IntParser INT_PARSER = new IntParser() {
  146         public int parseInt(String value) {
  147           return Integer.parseInt(value);
  148         }
  149     };
  150   
  151   
  152     private static final FloatParser FLOAT_PARSER = new FloatParser() {
  153         public float parseFloat(String value) {
  154           return Float.parseFloat(value);
  155         }
  156     };
  157   
  158     // inherit javadocs
  159     public byte[] getBytes (IndexReader reader, String field) throws IOException {
  160       return getBytes(reader, field, BYTE_PARSER);
  161     }
  162   
  163     // inherit javadocs
  164     public byte[] getBytes(IndexReader reader, String field, ByteParser parser)
  165         throws IOException {
  166       return (byte[]) bytesCache.get(reader, new Entry(field, parser));
  167     }
  168   
  169     Cache bytesCache = new Cache() {
  170   
  171       protected Object createValue(IndexReader reader, Object entryKey)
  172           throws IOException {
  173         Entry entry = (Entry) entryKey;
  174         String field = entry.field;
  175         ByteParser parser = (ByteParser) entry.custom;
  176         final byte[] retArray = new byte[reader.maxDoc()];
  177         TermDocs termDocs = reader.termDocs();
  178         TermEnum termEnum = reader.terms (new Term (field));
  179         try {
  180           do {
  181             Term term = termEnum.term();
  182             if (term==null || term.field() != field) break;
  183             byte termval = parser.parseByte(term.text());
  184             termDocs.seek (termEnum);
  185             while (termDocs.next()) {
  186               retArray[termDocs.doc()] = termval;
  187             }
  188           } while (termEnum.next());
  189         } finally {
  190           termDocs.close();
  191           termEnum.close();
  192         }
  193         return retArray;
  194       }
  195     };
  196     
  197     // inherit javadocs
  198     public short[] getShorts (IndexReader reader, String field) throws IOException {
  199       return getShorts(reader, field, SHORT_PARSER);
  200     }
  201   
  202     // inherit javadocs
  203     public short[] getShorts(IndexReader reader, String field, ShortParser parser)
  204         throws IOException {
  205       return (short[]) shortsCache.get(reader, new Entry(field, parser));
  206     }
  207   
  208     Cache shortsCache = new Cache() {
  209   
  210       protected Object createValue(IndexReader reader, Object entryKey)
  211           throws IOException {
  212         Entry entry = (Entry) entryKey;
  213         String field = entry.field;
  214         ShortParser parser = (ShortParser) entry.custom;
  215         final short[] retArray = new short[reader.maxDoc()];
  216         TermDocs termDocs = reader.termDocs();
  217         TermEnum termEnum = reader.terms (new Term (field));
  218         try {
  219           do {
  220             Term term = termEnum.term();
  221             if (term==null || term.field() != field) break;
  222             short termval = parser.parseShort(term.text());
  223             termDocs.seek (termEnum);
  224             while (termDocs.next()) {
  225               retArray[termDocs.doc()] = termval;
  226             }
  227           } while (termEnum.next());
  228         } finally {
  229           termDocs.close();
  230           termEnum.close();
  231         }
  232         return retArray;
  233       }
  234     };
  235     
  236     // inherit javadocs
  237     public int[] getInts (IndexReader reader, String field) throws IOException {
  238       return getInts(reader, field, INT_PARSER);
  239     }
  240   
  241     // inherit javadocs
  242     public int[] getInts(IndexReader reader, String field, IntParser parser)
  243         throws IOException {
  244       return (int[]) intsCache.get(reader, new Entry(field, parser));
  245     }
  246   
  247     Cache intsCache = new Cache() {
  248   
  249       protected Object createValue(IndexReader reader, Object entryKey)
  250           throws IOException {
  251         Entry entry = (Entry) entryKey;
  252         String field = entry.field;
  253         IntParser parser = (IntParser) entry.custom;
  254         final int[] retArray = new int[reader.maxDoc()];
  255         TermDocs termDocs = reader.termDocs();
  256         TermEnum termEnum = reader.terms (new Term (field));
  257         try {
  258           do {
  259             Term term = termEnum.term();
  260             if (term==null || term.field() != field) break;
  261             int termval = parser.parseInt(term.text());
  262             termDocs.seek (termEnum);
  263             while (termDocs.next()) {
  264               retArray[termDocs.doc()] = termval;
  265             }
  266           } while (termEnum.next());
  267         } finally {
  268           termDocs.close();
  269           termEnum.close();
  270         }
  271         return retArray;
  272       }
  273     };
  274   
  275   
  276     // inherit javadocs
  277     public float[] getFloats (IndexReader reader, String field)
  278       throws IOException {
  279       return getFloats(reader, field, FLOAT_PARSER);
  280     }
  281   
  282     // inherit javadocs
  283     public float[] getFloats(IndexReader reader, String field, FloatParser parser)
  284         throws IOException {
  285       return (float[]) floatsCache.get(reader, new Entry(field, parser));
  286     }
  287   
  288     Cache floatsCache = new Cache() {
  289   
  290       protected Object createValue(IndexReader reader, Object entryKey)
  291           throws IOException {
  292         Entry entry = (Entry) entryKey;
  293         String field = entry.field;
  294         FloatParser parser = (FloatParser) entry.custom;
  295         final float[] retArray = new float[reader.maxDoc()];
  296         TermDocs termDocs = reader.termDocs();
  297         TermEnum termEnum = reader.terms (new Term (field));
  298         try {
  299           do {
  300             Term term = termEnum.term();
  301             if (term==null || term.field() != field) break;
  302             float termval = parser.parseFloat(term.text());
  303             termDocs.seek (termEnum);
  304             while (termDocs.next()) {
  305               retArray[termDocs.doc()] = termval;
  306             }
  307           } while (termEnum.next());
  308         } finally {
  309           termDocs.close();
  310           termEnum.close();
  311         }
  312         return retArray;
  313       }
  314     };
  315   
  316     // inherit javadocs
  317     public String[] getStrings(IndexReader reader, String field)
  318         throws IOException {
  319       return (String[]) stringsCache.get(reader, field);
  320     }
  321   
  322     Cache stringsCache = new Cache() {
  323   
  324       protected Object createValue(IndexReader reader, Object fieldKey)
  325           throws IOException {
  326         String field = ((String) fieldKey).intern();
  327         final String[] retArray = new String[reader.maxDoc()];
  328         TermDocs termDocs = reader.termDocs();
  329         TermEnum termEnum = reader.terms (new Term (field));
  330         try {
  331           do {
  332             Term term = termEnum.term();
  333             if (term==null || term.field() != field) break;
  334             String termval = term.text();
  335             termDocs.seek (termEnum);
  336             while (termDocs.next()) {
  337               retArray[termDocs.doc()] = termval;
  338             }
  339           } while (termEnum.next());
  340         } finally {
  341           termDocs.close();
  342           termEnum.close();
  343         }
  344         return retArray;
  345       }
  346     };
  347   
  348     // inherit javadocs
  349     public StringIndex getStringIndex(IndexReader reader, String field)
  350         throws IOException {
  351       return (StringIndex) stringsIndexCache.get(reader, field);
  352     }
  353   
  354     Cache stringsIndexCache = new Cache() {
  355   
  356       protected Object createValue(IndexReader reader, Object fieldKey)
  357           throws IOException {
  358         String field = ((String) fieldKey).intern();
  359         final int[] retArray = new int[reader.maxDoc()];
  360         String[] mterms = new String[reader.maxDoc()+1];
  361         TermDocs termDocs = reader.termDocs();
  362         TermEnum termEnum = reader.terms (new Term (field));
  363         int t = 0;  // current term number
  364   
  365         // an entry for documents that have no terms in this field
  366         // should a document with no terms be at top or bottom?
  367         // this puts them at the top - if it is changed, FieldDocSortedHitQueue
  368         // needs to change as well.
  369         mterms[t++] = null;
  370   
  371         try {
  372           do {
  373             Term term = termEnum.term();
  374             if (term==null || term.field() != field) break;
  375   
  376             // store term text
  377             // we expect that there is at most one term per document
  378             if (t >= mterms.length) throw new RuntimeException ("there are more terms than " +
  379                     "documents in field \"" + field + "\", but it's impossible to sort on " +
  380                     "tokenized fields");
  381             mterms[t] = term.text();
  382   
  383             termDocs.seek (termEnum);
  384             while (termDocs.next()) {
  385               retArray[termDocs.doc()] = t;
  386             }
  387   
  388             t++;
  389           } while (termEnum.next());
  390         } finally {
  391           termDocs.close();
  392           termEnum.close();
  393         }
  394   
  395         if (t == 0) {
  396           // if there are no terms, make the term array
  397           // have a single null entry
  398           mterms = new String[1];
  399         } else if (t < mterms.length) {
  400           // if there are less terms than documents,
  401           // trim off the dead array space
  402           String[] terms = new String[t];
  403           System.arraycopy (mterms, 0, terms, 0, t);
  404           mterms = terms;
  405         }
  406   
  407         StringIndex value = new StringIndex (retArray, mterms);
  408         return value;
  409       }
  410     };
  411   
  412     /** The pattern used to detect integer values in a field */
  413     /** removed for java 1.3 compatibility
  414      protected static final Pattern pIntegers = Pattern.compile ("[0-9\\-]+");
  415      **/
  416   
  417     /** The pattern used to detect float values in a field */
  418     /**
  419      * removed for java 1.3 compatibility
  420      * protected static final Object pFloats = Pattern.compile ("[0-9+\\-\\.eEfFdD]+");
  421      */
  422   
  423   	// inherit javadocs
  424     public Object getAuto(IndexReader reader, String field) throws IOException {
  425       return autoCache.get(reader, field);
  426     }
  427   
  428     Cache autoCache = new Cache() {
  429   
  430       protected Object createValue(IndexReader reader, Object fieldKey)
  431           throws IOException {
  432         String field = ((String)fieldKey).intern();
  433         TermEnum enumerator = reader.terms (new Term (field));
  434         try {
  435           Term term = enumerator.term();
  436           if (term == null) {
  437             throw new RuntimeException ("no terms in field " + field + " - cannot determine sort type");
  438           }
  439           Object ret = null;
  440           if (term.field() == field) {
  441             String termtext = term.text().trim();
  442   
  443             /**
  444              * Java 1.4 level code:
  445   
  446              if (pIntegers.matcher(termtext).matches())
  447              return IntegerSortedHitQueue.comparator (reader, enumerator, field);
  448   
  449              else if (pFloats.matcher(termtext).matches())
  450              return FloatSortedHitQueue.comparator (reader, enumerator, field);
  451              */
  452   
  453             // Java 1.3 level code:
  454             try {
  455               Integer.parseInt (termtext);
  456               ret = getInts (reader, field);
  457             } catch (NumberFormatException nfe1) {
  458               try {
  459                   Float.parseFloat (termtext);
  460                   ret = getFloats (reader, field);
  461                 } catch (NumberFormatException nfe3) {
  462                   ret = getStringIndex (reader, field);
  463                 }
  464             }          
  465           } else {
  466             throw new RuntimeException ("field \"" + field + "\" does not appear to be indexed");
  467           }
  468           return ret;
  469         } finally {
  470           enumerator.close();
  471         }
  472       }
  473     };
  474   
  475     // inherit javadocs
  476     public Comparable[] getCustom(IndexReader reader, String field,
  477         SortComparator comparator) throws IOException {
  478       return (Comparable[]) customCache.get(reader, new Entry(field, comparator));
  479     }
  480   
  481     Cache customCache = new Cache() {
  482   
  483       protected Object createValue(IndexReader reader, Object entryKey)
  484           throws IOException {
  485         Entry entry = (Entry) entryKey;
  486         String field = entry.field;
  487         SortComparator comparator = (SortComparator) entry.custom;
  488         final Comparable[] retArray = new Comparable[reader.maxDoc()];
  489         TermDocs termDocs = reader.termDocs();
  490         TermEnum termEnum = reader.terms (new Term (field));
  491         try {
  492           do {
  493             Term term = termEnum.term();
  494             if (term==null || term.field() != field) break;
  495             Comparable termval = comparator.getComparable (term.text());
  496             termDocs.seek (termEnum);
  497             while (termDocs.next()) {
  498               retArray[termDocs.doc()] = termval;
  499             }
  500           } while (termEnum.next());
  501         } finally {
  502           termDocs.close();
  503           termEnum.close();
  504         }
  505         return retArray;
  506       }
  507     };
  508     
  509   }
  510   

Save This Page
Home » lucene-2.4.1-src » org.apache » lucene » search » [javadoc | source]