Index: PhrasePrefixQuery.java
===================================================================
RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/PhrasePrefixQuery.java,v
retrieving revision 1.3
diff -u -r1.3 PhrasePrefixQuery.java
--- PhrasePrefixQuery.java	7 Nov 2002 17:31:26 -0000	1.3
+++ PhrasePrefixQuery.java	20 Nov 2002 22:13:54 -0000
@@ -57,12 +57,14 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultipleTermPositions;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermEnum;
 import org.apache.lucene.index.TermPositions;
-import org.apache.lucene.search.Query;
 
 /**
  * PhrasePrefixQuery is a generalized version of PhraseQuery, with an added
@@ -79,13 +81,108 @@
     extends Query
 {
     private String _field;
-    private ArrayList _termArrays = new ArrayList();
+	private List _phraseTerms = new ArrayList();
 
     private float _idf = 0.0f;
     private float _weight = 0.0f;
 
     private int _slop = 0;
 
+	private 
+	class PhraseTerm
+	{
+		protected Term _term;
+		
+		PhraseTerm(Term t)
+		{
+			_term = t;
+		}
+		
+		void prepareScorer(IndexReader reader)
+		throws IOException
+		{
+		}
+		
+		float idf(Searcher searcher)
+		throws IOException
+		{
+			return searcher.getSimilarity().idf(_term, searcher);
+		}
+		
+		TermPositions termPositions(IndexReader reader)
+		throws IOException
+		{
+			return reader.termPositions(_term);
+		}
+		
+		public String toString()
+		{
+			return _term.text();
+		}
+	}
+
+	private 
+	class PhraseWildcardTerm
+	extends PhraseTerm
+	{
+		Term[] _terms = null;
+
+		PhraseWildcardTerm(Term t)
+		{
+			super(t);
+		}
+
+		void prepareScorer(IndexReader reader)
+		throws IOException
+		{
+            List result = new LinkedList();
+            String prefixText = _term.text();
+            String prefixField = _term.field();
+
+        	TermEnum termEnum = reader.terms(_term);
+
+            do 
+            {
+                Term term = termEnum.term();
+                if (term != null && 
+                	 term.text().startsWith(prefixText) &&
+                     term.field() == prefixField) 
+                {
+                	result.add(term);
+                } 
+                else 
+                    break;
+            } 
+            while (termEnum.next());                        
+
+            termEnum.close();               
+
+            _terms = (Term[])result.toArray(new Term[0]);
+		}
+		
+		float idf(Searcher searcher)
+		throws IOException
+		{
+			float result = 0;
+			
+		    for (int j=0; j<_terms.length; j++)
+				result += searcher.getSimilarity().idf(_terms[j], searcher);
+
+			return result;
+		}
+		
+		TermPositions termPositions(IndexReader reader)
+		throws IOException
+		{
+			return new MultipleTermPositions(reader, _terms);
+		}
+		
+		public String toString()
+		{
+			return _term.text() + "*";
+		}
+	}
+
     /**
      * Creates a new <code>PhrasePrefixQuery</code> instance.
      *
@@ -101,7 +198,7 @@
      */
     public void setSlop(int s)
     {
-	_slop = s;
+		_slop = s;
     }
 
     /**
@@ -114,6 +211,17 @@
 	return _slop;
     }
 
+
+	private void validateField(Term term)
+	{
+		if (_field == null)
+			_field = term.field();
+		else
+			if (term.field() != _field)
+				throw new IllegalArgumentException(
+				    "All phrase terms must be in the same field (" + _field + "): " + term);
+	}
+	
     /**
      * Describe <code>add</code> method here.
      *
@@ -121,7 +229,8 @@
      */
     public void add(Term term)
     {
-	add(new Term[]{term});
+		validateField(term);
+		_phraseTerms.add(new PhraseTerm(term));
     }
 
     /**
@@ -129,85 +238,55 @@
      *
      * @param terms a <code>Term[]</code> value
      */
-    public void add(Term[] terms)
+    public void addWildCardTerm(Term term)
     {
-	if (_termArrays.size() == 0)
-	    _field = terms[0].field();
-
-      	for (int i=0; i<terms.length; i++)
-	{
-	    if (terms[i].field() != _field)
-	    {
-		throw new IllegalArgumentException(
-		    "All phrase terms must be in the same field (" + _field + "): "
-		    + terms[i]);
-	    }
-	}
-
-	_termArrays.add(terms);
+		validateField(term);
+		_phraseTerms.add(new PhraseWildcardTerm(term));
     }
 
     Scorer scorer(IndexReader reader, Similarity similarity)
 	throws IOException
     {
-    	if (_termArrays.size() == 0)  // optimize zero-term case
-	    return null;
-
-	if (_termArrays.size() == 1)  // optimize one-term case
-	{
-	    Term[] terms = (Term[])_termArrays.get(0);
-
-	    BooleanQuery boq = new BooleanQuery();
-	    for (int i=0; i<terms.length; i++)
-		boq.add(new TermQuery(terms[i]), false, false);
-
-	    return boq.scorer(reader, similarity);
-    	}
-
-    	TermPositions[] tps = new TermPositions[_termArrays.size()];
-	for (int i=0; i<tps.length; i++)
-	{
-	    Term[] terms = (Term[])_termArrays.get(i);
+    	if (_phraseTerms.size() == 0)  // optimize zero-term case
+	    	return null;
 
-	    TermPositions p;
-	    if (terms.length > 1)
-		p = new MultipleTermPositions(reader, terms);
-	    else
-		p = reader.termPositions(terms[0]);
-
-	    if (p == null)
-		return null;
-
-	    tps[i] = p;
-	}
-
-	if (_slop == 0)
-	    return new ExactPhraseScorer(tps, similarity,
+    	TermPositions[] tps = new TermPositions[_phraseTerms.size()];
+		for (int i=0; i<tps.length; i++)
+		{
+			PhraseTerm pt = (PhraseTerm)_phraseTerms.get(i);
+			pt.prepareScorer(reader);
+	
+		    TermPositions p = pt.termPositions(reader);
+
+		    if (p == null)
+				return null;
+	
+		    tps[i] = p;
+		}
+	
+		if (_slop == 0)
+		    return new ExactPhraseScorer(tps, similarity,
                                          reader.norms(_field), _weight);
-	else
-	    return new SloppyPhraseScorer(tps, similarity, _slop,
+		else
+		    return new SloppyPhraseScorer(tps, similarity, _slop,
                                           reader.norms(_field), _weight);
     }
 
     float sumOfSquaredWeights(Searcher searcher)
 	throws IOException
     {
-	Iterator i = _termArrays.iterator();
-	while (i.hasNext())
-	{
-	    Term[] terms = (Term[])i.next();
-	    for (int j=0; j<terms.length; j++)
-		_idf += searcher.getSimilarity().idf(terms[j], searcher);
-	}
-
-	_weight = _idf * boost;
-	return _weight * _weight;
+		Iterator i = _phraseTerms.iterator();
+		while (i.hasNext())
+			_idf += ((PhraseTerm)i.next()).idf(searcher);
+	
+		_weight = _idf * boost;
+		return _weight * _weight;
     }
 
     void normalize(float norm)
     {
-	_weight *= norm;
-	_weight *= _idf;
+		_weight *= norm;
+		_weight *= _idf;
     }
 
     /**
@@ -221,34 +300,33 @@
      */
     public final String toString(String f)
     {
-	StringBuffer buffer = new StringBuffer();
-	if (!_field.equals(f))
-	{
-	    buffer.append(_field);
-	    buffer.append(":");
-	}
-
-	buffer.append("\"");
-	Iterator i = _termArrays.iterator();
-	while (i.hasNext())
-	{
-	    Term[] terms = (Term[])i.next();
-	    buffer.append(terms[0].text() + (terms.length > 0 ? "*" : ""));
-	}
-	buffer.append("\"");
-
-	if (_slop != 0)
-	{
-	    buffer.append("~");
-	    buffer.append(_slop);
-	}
-
-	if (boost != 1.0f)
-	{
-	    buffer.append("^");
-	    buffer.append(Float.toString(boost));
-	}
-
-	return buffer.toString();
+		StringBuffer buffer = new StringBuffer();
+		if (!_field.equals(f))
+		{
+		    buffer.append(_field);
+		    buffer.append(":");
+		}
+	
+		buffer.append("\"");
+
+		Iterator i = _phraseTerms.iterator();
+		while (i.hasNext())
+		    buffer.append(((PhraseTerm)i.next()).toString());
+
+		buffer.append("\"");
+	
+		if (_slop != 0)
+		{
+		    buffer.append("~");
+		    buffer.append(_slop);
+		}
+	
+		if (boost != 1.0f)
+		{
+		    buffer.append("^");
+		    buffer.append(Float.toString(boost));
+		}
+	
+		return buffer.toString();
     }
 }

