luetzkendorf    2004/12/07 09:49:58

  Modified:    src/stores/org/apache/slide/index/lucene Index.java
                        IndexConfiguration.java
                        LuceneExpressionFactory.java
                        LucenePropertiesIndexer.java
               src/stores/org/apache/slide/index/lucene/expressions
                        AbstractLuceneExpression.java
                        BetweenExpression.java ContainsExpression.java
                        GtExpression.java IsCollectionExpression.java
                        IsDefinedExpression.java LikeExpression.java
                        LtExpression.java MergeExpression.java
                        PropcontainsExpression.java
                        PropertyContainsExpression.java
  Added:       src/stores/org/apache/slide/index/lucene/expressions
                        RangeOperator.java
  Log:
  some improvemens (negation handling, range query optimization, ...)
  
  Revision  Changes    Path
  1.8       +51 -29    
jakarta-slide/src/stores/org/apache/slide/index/lucene/Index.java
  
  Index: Index.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/Index.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Index.java        29 Nov 2004 18:38:46 -0000      1.7
  +++ Index.java        7 Dec 2004 17:49:57 -0000       1.8
  @@ -47,6 +47,7 @@
   import org.apache.lucene.store.Directory;
   import org.apache.lucene.store.FSDirectory;
   
  +import org.apache.slide.common.PropertyName;
   import org.apache.slide.common.Uri;
   import org.apache.slide.content.NodeProperty;
   import org.apache.slide.content.NodeRevisionDescriptor;
  @@ -69,6 +70,7 @@
       public static final String VERSION_FIELD_NAME = "SLIDE_VERSION";
       public static final String IS_DEFINED_FIELD_NAME = "SLIDE_ISDEFINED";
       public static final String CONTENT_FIELD_NAME = "SLIDE_CONTENT";
  +    public static final String NULL_FIELD_NAME = "SLIDE_NULL";
       
       protected static final SimpleDateFormat DATE_INDEX_FORMAT = 
           new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.UK);
  @@ -241,19 +243,18 @@
           // all other properties
           for(Enumeration e = descriptor.enumerateProperties(); 
e.hasMoreElements();) {
               NodeProperty property = (NodeProperty)e.nextElement();
  -            String name = property.getName();
  -            String namespace = property.getNamespace();
  +            PropertyName propertyName = property.getPropertyName();
               Object value = property.getValue();
               
               if (value == null) continue;
  -            if (!configuration.isIndexedProperty(namespace, name)) continue;
  +            if (!configuration.isIndexedProperty(propertyName)) continue;
               
  -            if (configuration.isStringProperty(namespace, name)) {
  +            if (configuration.isStringProperty(propertyName)) {
                   doc.add(unstoredString(configuration.generateFieldName(
                           property.getNamespace(), property.getName()), 
                           value.toString()));
               }
  -            if (configuration.isDateProperty(namespace, name)) {
  +            if (configuration.isDateProperty(propertyName)) {
                   Date date = IndexConfiguration.getDateValue(value);
                   if (date != null) {
                       doc.add(unstoredString(configuration.generateFieldName(
  @@ -261,7 +262,7 @@
                               configuration.dateToIndexString(date)));
                   }
               }
  -            if (configuration.isIntProperty(namespace, name)) {
  +            if (configuration.isIntProperty(propertyName)) {
                   try {
                       doc.add(unstoredString(configuration.generateFieldName(
                               property.getNamespace(), property.getName()),
  @@ -271,12 +272,12 @@
                       // TODO log warning
                   }
               }
  -            if (configuration.isTextProperty(namespace, name)) {
  +            if (configuration.isTextProperty(propertyName)) {
                   doc.add(textField(configuration.generateFieldName(
                           property.getNamespace(), property.getName()), 
                           value.toString()));
               }
  -            if (configuration.supportsIsDefined(namespace, name)) {
  +            if (configuration.supportsIsDefined(propertyName)) {
                   doc.add(unstoredString(Index.IS_DEFINED_FIELD_NAME, 
                           configuration.generateFieldName(
                                   property.getNamespace(), 
property.getName())));
  @@ -291,7 +292,7 @@
        */
       private Document createLuceneDocument(String uri, 
               NodeRevisionDescriptor descriptor, InputStream content) 
  -        throws IndexException
  +        throws IndexException, ExtractorException
       {
           Document doc = new Document();
           
  @@ -316,15 +317,11 @@
           List extractors = 
ExtractorManager.getInstance().getContentExtractors(
                   configuration.getNamespaceName(), uri, descriptor);
           
  -        try {
  -            for(Iterator i = extractors.iterator(); i.hasNext();) {
  -                ContentExtractor extractor = (ContentExtractor)i.next();
  -                doc.add(textField(Index.CONTENT_FIELD_NAME, 
  -                        extractor.extract(content)));
  -            }
  -        } catch (ExtractorException e) {
  -            throw new IndexException(e);
  -        } 
  +        for(Iterator i = extractors.iterator(); i.hasNext();) {
  +            ContentExtractor extractor = (ContentExtractor)i.next();
  +            doc.add(textField(Index.CONTENT_FIELD_NAME, 
  +                    extractor.extract(content)));
  +        }
           
           return doc;
       }
  @@ -359,35 +356,52 @@
       
       synchronized void executeIndexTransaction(Set removeJobs, Set addJobs) 
           throws IndexException  {
  +        
  +        IndexWriter writer = null;
  +        IndexReader reader = null;
           try {
               // execute delete jobs
               if (removeJobs.size() > 0) {
  -                IndexReader reader = IndexReader.open(getDirectory());
  +                reader = IndexReader.open(getDirectory());
                   for(Iterator i = removeJobs.iterator(); i.hasNext();) {
                       IndexJob job = (IndexJob)i.next();
  -                    logger.log("remove: " + job.key, LOG_CHANNEL, 
Logger.DEBUG);
  +                    if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
  +                        logger.log("remove: " + job.key, LOG_CHANNEL, 
Logger.DEBUG);
  +                    }
                       reader.delete(new Term(Index.KEY_FIELD_NAME, 
job.getKey()));
                       this.jobCounter++;
                   }
                   reader.close();
  +                reader = null;
               }
       
               // execute index jobs
               if (addJobs.size() > 0 || this.jobCounter >= 
configuration.getOptimizeThreshold()) {
  -                IndexWriter writer = new IndexWriter(getDirectory(), 
  -                        configuration.getAnalyzer(), false);
  +                 writer = new IndexWriter(getDirectory(), 
  +                         configuration.getAnalyzer(), false);
                   
                   for(Iterator i = addJobs.iterator(); i.hasNext(); ) {
                       IndexJob job = (IndexJob)i.next();
                       Document doc; 
                       if (job.content != null) {
  -                        logger.log("index content: " + job.key, LOG_CHANNEL, 
Logger.DEBUG);
  -                        doc = createLuceneDocument(job.uri, job.descriptor, 
job.content);
  +                        if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
  +                            logger.log("index content: " + job.key, 
LOG_CHANNEL, Logger.DEBUG);
  +                        }
  +                        try {
  +                            doc = createLuceneDocument(job.uri, 
job.descriptor, job.content);
  +                            writer.addDocument(doc);
  +                        } catch(ExtractorException e) {
  +                            logger.log("Error while extracting content: " + 
job.uri +
  +                                    " (" + e.toString() + ")", 
  +                                    LOG_CHANNEL, Logger.WARNING);
  +                        }
                       } else {
  -                        logger.log("index properties: " + job.key, 
LOG_CHANNEL, Logger.DEBUG);
  +                        if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
  +                            logger.log("index properties: " + job.key, 
LOG_CHANNEL, Logger.DEBUG);
  +                        }
                           doc = createLuceneDocument(job.uri, job.descriptor);
  +                        writer.addDocument(doc);
                       }
  -                    writer.addDocument(doc);
                       this.jobCounter++;
                   }
                   if (this.jobCounter > configuration.getOptimizeThreshold()) {
  @@ -396,9 +410,17 @@
                       this.jobCounter = 0;
                   }
                   writer.close();
  +                writer = null;
               }
           } catch (Exception e) {
               throw new IndexException(e);
  +        } finally {
  +            try {
  +                if (reader != null) reader.close();
  +                if (writer != null) writer.close();
  +            } catch (IOException e) {
  +                logger.log("Exception after executeIndexTransaction", e, 
LOG_CHANNEL, Logger.ERROR);
  +            }
           }
       }
       
  
  
  
  1.7       +55 -18    
jakarta-slide/src/stores/org/apache/slide/index/lucene/IndexConfiguration.java
  
  Index: IndexConfiguration.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/IndexConfiguration.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- IndexConfiguration.java   29 Nov 2004 18:38:46 -0000      1.6
  +++ IndexConfiguration.java   7 Dec 2004 17:49:57 -0000       1.7
  @@ -41,6 +41,7 @@
   import org.apache.lucene.analysis.SimpleAnalyzer;
   import org.apache.lucene.analysis.TokenStream;
   
  +import org.apache.slide.common.PropertyName;
   import org.apache.slide.content.NodeRevisionNumber;
   import org.apache.slide.search.IndexException;
   import org.apache.slide.util.conf.Configuration;
  @@ -70,56 +71,78 @@
       protected int priority = Thread.NORM_PRIORITY;
       
       public void addStringProperty(String namespace, String name) {
  -        String key = namespace + name;
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
           this.stringProperties.add(key);
           this.indexedProperties.add(key);
       }
  +    public boolean isStringProperty(PropertyName propertyName) {
  +        return this.stringProperties.contains(propertyName);
  +    }
       public boolean isStringProperty(String namespace, String name) {
  -        return this.stringProperties.contains(namespace + name);
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
  +        return this.stringProperties.contains(key);
       }
       
       public void addDateProperty(String namespace, String name) {
  -        String key = namespace + name;
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
           this.dateProperties.add(key);
           this.indexedProperties.add(key);
       }
  +    public boolean isDateProperty(PropertyName propertyName) {
  +        return this.dateProperties.contains(propertyName);
  +    }
       public boolean isDateProperty(String namespace, String name) {
  -        return this.dateProperties.contains(namespace + name);
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
  +        return this.dateProperties.contains(key);
       }
       
       
       public void addIntProperty(String namespace, String name) {
  -        String key = namespace + name;
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
           this.intProperties.add(key);
           this.indexedProperties.add(key);
       }
  +    public boolean isIntProperty(PropertyName propertyName) {
  +        return this.intProperties.contains(propertyName);
  +    }
       public boolean isIntProperty(String namespace, String name) {
  -        return this.intProperties.contains(namespace + name);
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
  +        return this.intProperties.contains(key);
       }
       
       public void addSupportsIsdefinedProperty(String namespace, String name) {
  -        String key = namespace + name;
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
           this.supportsIsdefinedProperties.add(key);
           this.indexedProperties.add(key);
       }
       
  +    public boolean supportsIsDefined(PropertyName propertyName) {
  +        return this.supportsIsdefinedProperties.contains(propertyName);
  +    }
       public boolean supportsIsDefined(String namespace, String name) {
  -        return this.supportsIsdefinedProperties.contains(namespace + name);
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
  +        return this.supportsIsdefinedProperties.contains(key);
       }
   
       public void addTextProperty(String namespace, String name, Analyzer 
analyzer) {
  -        String key = namespace + name;
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
           this.textProperties.put(key, analyzer);
           this.indexedProperties.add(key);
       }
  -    
  +    public boolean isTextProperty(PropertyName propertyName) {
  +        return this.textProperties.containsKey(propertyName);
  +    }
       public boolean isTextProperty(String namespace, String name) {
  -        return this.textProperties.containsKey(namespace + name);
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
  +        return this.textProperties.containsKey(key);
       }
   
  -    
  +    public boolean isIndexedProperty(PropertyName name) {
  +        return this.indexedProperties.contains(name);
  +    }
       public boolean isIndexedProperty(String namespace, String name) {
  -        return this.indexedProperties.contains(namespace + name);
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
  +        return this.indexedProperties.contains(key);
       }
       
       /**
  @@ -129,12 +152,16 @@
        * @return
        */
       public boolean isComparableProperty(String namespace, String name) {
  -        String key = namespace + name;
  +        PropertyName key = PropertyName.getPropertyName(name, namespace);
           return this.stringProperties.contains(key) ||
                  this.intProperties.contains(key) ||
                  this.dateProperties.contains(key);
       }
  -    
  +    public boolean isComparableProperty(PropertyName name) {
  +        return this.stringProperties.contains(name) ||
  +               this.intProperties.contains(name) ||
  +               this.dateProperties.contains(name);
  +    }
       
       public int getOptimizeThreshold() {
           return this.optimizeThreshold;
  @@ -341,7 +368,17 @@
           }
       }
       
  +    public String predecessor(String field, String value) {
  +        StringBuffer b = new StringBuffer(value);
  +        b.setCharAt(b.length()-1, (char)(b.charAt(b.length()-1)-1));
  +        return b.toString();
  +    }
       
  +    public String successor(String field, String value) {
  +        StringBuffer b = new StringBuffer(value);
  +        b.setCharAt(b.length()-1, (char)(b.charAt(b.length()-1)+1));
  +        return b.toString();
  +    }
       class AnalyzerImpl extends Analyzer {
           Analyzer defaultAnalyzer = new SimpleAnalyzer();
           Analyzer contentAnalyzer = null;
  
  
  
  1.7       +5 -5      
jakarta-slide/src/stores/org/apache/slide/index/lucene/LuceneExpressionFactory.java
  
  Index: LuceneExpressionFactory.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/LuceneExpressionFactory.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- LuceneExpressionFactory.java      29 Nov 2004 18:39:37 -0000      1.6
  +++ LuceneExpressionFactory.java      7 Dec 2004 17:49:57 -0000       1.7
  @@ -258,12 +258,12 @@
           // TODO not-between
           if (operator.equals("between")) {
               if (configuration.isComparableProperty(namespace, name)) {
  -                return new BetweenExpression(this.index, e, false);
  +                return new BetweenExpression(this.index, e, false, false);
               }
           }
           if (operator.equals("between-inclusive")) {
               if (configuration.isComparableProperty(namespace, name)) {
  -                return new BetweenExpression(this.index, e, true);
  +                return new BetweenExpression(this.index, e, true, false);
               }
           }
           if (operator.equals("property-contains")) {
  
  
  
  1.5       +2 -2      
jakarta-slide/src/stores/org/apache/slide/index/lucene/LucenePropertiesIndexer.java
  
  Index: LucenePropertiesIndexer.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/LucenePropertiesIndexer.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- LucenePropertiesIndexer.java      8 Nov 2004 09:45:10 -0000       1.4
  +++ LucenePropertiesIndexer.java      7 Dec 2004 17:49:57 -0000       1.5
  @@ -128,14 +128,14 @@
               // removed properties is to be indexed
               for(Enumeration e = 
revisionDescriptor.enumerateUpdatedProperties();e.hasMoreElements();) {
                   NodeProperty property = (NodeProperty)e.nextElement();
  -                
if(index.getConfiguration().isIndexedProperty(property.getNamespace(), 
property.getName())) {
  +                
if(index.getConfiguration().isIndexedProperty(property.getPropertyName())) {
                       needsUpdate = true; 
                       break;
                   }
               }
               for(Enumeration e = 
revisionDescriptor.enumerateRemovedProperties();!needsUpdate && 
e.hasMoreElements();) {
                   NodeProperty property = (NodeProperty)e.nextElement();
  -                
if(index.getConfiguration().isIndexedProperty(property.getNamespace(), 
property.getName())) {
  +                
if(index.getConfiguration().isIndexedProperty(property.getPropertyName())) {
                       needsUpdate = true; 
                       break;
                   }
  
  
  
  1.2       +18 -10    
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/AbstractLuceneExpression.java
  
  Index: AbstractLuceneExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/AbstractLuceneExpression.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractLuceneExpression.java     29 Nov 2004 18:38:16 -0000      1.1
  +++ AbstractLuceneExpression.java     7 Dec 2004 17:49:57 -0000       1.2
  @@ -90,7 +90,6 @@
       {
           this.factory = (LuceneExpressionFactory)factory;
       }
  -
       
       public IBasicResultSet execute() throws SearchException
       {
  @@ -109,9 +108,10 @@
   
           // add a scope restriction, this allows negated queries too
           BooleanQuery booleanQuery = new BooleanQuery();
  +        booleanQuery.add(luceneQuery, true, false);
           booleanQuery.add(new TermQuery(new Term(Index.SCOPE_FIELD_NAME, 
scope)), 
                   true, false);
  -        booleanQuery.add(luceneQuery, true, false);
  +        
           // add depth restriction
           switch (q.getScope().getDepth() ) {
               case QueryScope.DEPTH_INFINITY:
  @@ -137,15 +137,19 @@
   
           IndexSearcher searcher = null;
           try {
  -            index.getLogger().log("start query execution: " + 
  -                    luceneQuery.toString(), LOG_CHANNEL, Logger.DEBUG);
  +            if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
  +                index.getLogger().log("start query execution: " + 
  +                        luceneQuery.toString(), LOG_CHANNEL, Logger.DEBUG);
  +            }
               long start = System.currentTimeMillis();
       
               searcher = this.index.getSearcher();
               Hits hits = searcher.search(luceneQuery);
               
  -            index.getLogger().log("finished: " + hits.length() + " hits (" + 
  -                    (System.currentTimeMillis() - start) + "ms)" , 
LOG_CHANNEL, Logger.DEBUG);
  +            if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
  +                index.getLogger().log("finished: " + hits.length() + " hits 
(" + 
  +                        (System.currentTimeMillis() - start) + "ms)" , 
LOG_CHANNEL, Logger.DEBUG);
  +            }
   
               IBasicResultSet result = new BasicResultSetImpl(false);
   
  @@ -183,12 +187,16 @@
       protected Query negateQuery(Query query) {
           BooleanQuery booleanQuery = new BooleanQuery();
           booleanQuery.add(
  -                new TermQuery(new Term(Index.SCOPE_FIELD_NAME, "/")), 
  +                allQuery(), 
                   true, false);
           booleanQuery.add(
                   query, 
                   false, true);
           return booleanQuery;
  +    }
  +    
  +    protected Query allQuery() {
  +        return new TermQuery(new Term(Index.SCOPE_FIELD_NAME, "/"));
       }
   
       protected RequestedResource createResource(String uri) throws 
SearchException
  
  
  
  1.6       +67 -12    
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/BetweenExpression.java
  
  Index: BetweenExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/BetweenExpression.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- BetweenExpression.java    29 Nov 2004 18:38:16 -0000      1.5
  +++ BetweenExpression.java    7 Dec 2004 17:49:57 -0000       1.6
  @@ -23,6 +23,8 @@
   package org.apache.slide.index.lucene.expressions;
   
   import org.apache.lucene.index.Term;
  +import org.apache.lucene.search.BooleanQuery;
  +import org.apache.lucene.search.Query;
   import org.apache.lucene.search.RangeQuery;
   import org.apache.lucene.search.TermQuery;
   
  @@ -37,10 +39,11 @@
    * <code>between-inclusive</code> operators.
    * 
    * <p>
  - * With lucene <code>(between prop val1 val2)</code> will be much more 
efficient 
  + * With lucene <code>(between prop val1 val2)</code> will be more efficient 
    * than <code>(and (gt prop1 val1) (lt prop val2))</code>.
  - * 
  - * <p>TODO May be we could optimize such expressions by transformation.   
  + * <br>
  + * In the [EMAIL PROTECTED] 
org.apache.slide.index.lucene.expressions.MergeExpression} 
  + * such an optimization is implemented.
    * 
    * <p>Usage:
    * <pre>
  @@ -55,7 +58,7 @@
   public class BetweenExpression extends AbstractLuceneExpression
   {
   
  -    public BetweenExpression(Index index, Element element, boolean inclusive)
  +    public BetweenExpression(Index index, Element element, boolean 
inclusive, boolean negated)
           throws BadQueryException
       {
           super(index);
  @@ -83,23 +86,75 @@
               value2 = literal2.getTextTrim();
           }
           
  +        if (negated) {
  +            setQuery(createQuery(field, value1, value2, !inclusive));
  +            negateQuery(field);
  +        } else {
  +            setQuery(createQuery(field, value1, value2, inclusive));
  +        }
  +    }
  +
  +    public BetweenExpression(Index index, String field, String lowerValue, 
  +            String upperValue, boolean incluseLower, boolean incluseUpper,
  +            boolean negated) {
  +        super(index);
  +        if (incluseLower == incluseUpper) {
  +            if (negated) {
  +                setQuery(createQuery(field, lowerValue, upperValue, 
!incluseLower));
  +                negateQuery(field);
  +            } else {
  +                setQuery(createQuery(field, lowerValue, upperValue, 
incluseLower));
  +            }
  +        } else {
  +            // TODO what about negative integer values 
(predecessor,successor 
  +            // does not work with this)
  +            if (incluseLower) {
  +                setQuery(createQuery(field, 
  +                        lowerValue, 
  +                        index.getConfiguration().predecessor(field, 
upperValue), 
  +                        true));
  +            } else {
  +                setQuery(createQuery(field, 
  +                        index.getConfiguration().successor(field, 
lowerValue),
  +                        upperValue,
  +                        true));
  +            }
  +        }
  +    }
  +    
  +    private void negateQuery(String field)
  +    {
  +        BooleanQuery booleanQuery = new BooleanQuery();
  +        booleanQuery.add(
  +                new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, field)),
  +                true,  // required
  +                false);
  +        booleanQuery.add(getQuery(),
  +                false, 
  +                true); // prohibited
  +        setQuery(booleanQuery);
  +    }
  +
  +    private Query createQuery(String field, String value1, String value2, 
boolean inclusive)
  +    {
           int comp =  value1.compareTo(value2);
   
           if (comp == 0) {
               // value1 == value2
  -            setQuery(new TermQuery(new Term(field, value1)));
  +            return new TermQuery(new Term(field, value1));
           } else if (comp < 0) {
               // value1 < value2
  -            setQuery(new RangeQuery(
  +            return new RangeQuery(
                       new Term(field, value1),
                       new Term(field, value2),
  -                    inclusive)); // inclusive or not 
  +                    inclusive); // inclusive or not 
           } else {
               // value1 > value2
  -            setQuery(new RangeQuery(
  +            return new RangeQuery(
                       new Term(field, value2),
                       new Term(field, value1),
  -                    inclusive)); // inclusive or not 
  +                    inclusive); // inclusive or not 
           }
       }
  +
   }
  
  
  
  1.3       +4 -3      
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/ContainsExpression.java
  
  Index: ContainsExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/ContainsExpression.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ContainsExpression.java   29 Nov 2004 18:38:16 -0000      1.2
  +++ ContainsExpression.java   7 Dec 2004 17:49:57 -0000       1.3
  @@ -70,6 +70,7 @@
               termOrPhraseQuery(config, Index.CONTENT_FIELD_NAME, literal);
           }
           
  +        // TODO
           if (negated) {
               setQuery(negateQuery(getQuery()));
           }
  
  
  
  1.7       +47 -22    
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/GtExpression.java
  
  Index: GtExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/GtExpression.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- GtExpression.java 29 Nov 2004 18:38:16 -0000      1.6
  +++ GtExpression.java 7 Dec 2004 17:49:57 -0000       1.7
  @@ -35,40 +35,65 @@
   /**
    * Implements <code>gt</code> and <code>gte</code> expression.
    */
  -public class GtExpression extends AbstractLuceneExpression
  +public class GtExpression extends AbstractLuceneExpression implements 
RangeOperator
   {
  -    public GtExpression(Index index, Element element, boolean inclusive) 
  -        throws BadQueryException 
  +    private String field;
  +    private String value;
  +    private boolean inclusive;
  +
  +    public GtExpression(Index index, Element element, boolean inclusive)
  +            throws BadQueryException
       {
           super(index);
  +        this.inclusive = inclusive;
   
           IndexConfiguration config = index.getConfiguration();
           Element prop = getPropertyElement(element);
  -        String field = config.generateFieldName(prop.getNamespaceURI(), 
prop.getName());
  +        this.field = config.generateFieldName(prop.getNamespaceURI(), 
prop.getName());
           Element literal = getLiteralElement(element);
   
  -        String value;
           String upperBound;
           if (index.getConfiguration().isDateProperty(prop.getNamespaceURI(), 
prop.getName())) {
               Date date = 
IndexConfiguration.getDateValue(literal.getTextTrim());
  -            value = config.dateToIndexString(date);
  +            this.value = config.dateToIndexString(date);
               upperBound = Index.DATE_UPPER_BOUND;
  -        } 
  -        else if 
(index.getConfiguration().isIntProperty(prop.getNamespaceURI(), 
prop.getName())) { 
  -            value = 
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
  +        } else if 
(index.getConfiguration().isIntProperty(prop.getNamespaceURI(), 
prop.getName())) {
  +            this.value = 
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
               upperBound = Index.INT_UPPER_BOUND;
  -        } 
  -        else {
  -            value = literal.getTextTrim();
  +        } else {
  +            this.value = literal.getTextTrim();
               upperBound = Index.STRING_UPPER_BOUND;
           }
  -        
  -        
  +
           RangeQuery rangeQuery = new RangeQuery(
  -                new Term(field, value),
  -                new Term(field, upperBound),
  -                inclusive); // inclusive or not 
  -        
  +                new Term(this.field, this.value),
  +                new Term(this.field, upperBound), 
  +                inclusive); // inclusive or not
  +
           setQuery(rangeQuery);
       }
  -}
  +    
  +    public String getField() {
  +        return this.field;
  +    }
  +    
  +    public String getValue() {
  +        return this.value;
  +    }
  +    public boolean inclusive() {
  +        return this.inclusive;
  +    }
  +    
  +    public String toString() {
  +        StringBuffer b = new StringBuffer();
  +        
  +        b.append('(')
  +         .append(this.field)
  +         .append('>')
  +         .append(this.inclusive ? "=" : "")
  +         .append(this.value)
  +         .append(')');
  +        
  +        return b.toString();
  +    }
  +}
  \ No newline at end of file
  
  
  
  1.4       +4 -4      
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsCollectionExpression.java
  
  Index: IsCollectionExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsCollectionExpression.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IsCollectionExpression.java       29 Nov 2004 18:38:16 -0000      1.3
  +++ IsCollectionExpression.java       7 Dec 2004 17:49:57 -0000       1.4
  @@ -43,7 +43,7 @@
           setQuery(new TermQuery(new Term(config.generateFieldName(
                   NodeProperty.DEFAULT_NAMESPACE, "resourcetype"),
                   "collection")));
  -        
  +
           if (negated) {
               setQuery(negateQuery(getQuery()));
           }
  
  
  
  1.6       +12 -8     
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsDefinedExpression.java
  
  Index: IsDefinedExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsDefinedExpression.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- IsDefinedExpression.java  29 Nov 2004 18:38:16 -0000      1.5
  +++ IsDefinedExpression.java  7 Dec 2004 17:49:57 -0000       1.6
  @@ -37,7 +37,6 @@
    */
   public class IsDefinedExpression extends AbstractLuceneExpression
   {
  -
       public IsDefinedExpression(Index index, Element element, boolean 
negated) 
           throws BadQueryException
       {
  @@ -47,11 +46,16 @@
           Element prop = getPropertyElement(element);
           String field = config.generateFieldName(prop.getNamespaceURI(), 
prop.getName());
           
  -        
  -        if (config.supportsIsDefined(prop.getNamespaceURI(), 
prop.getName())) {
  -            setQuery(new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, 
field)));
  +        setQuery(new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, 
field)));
  +        if (negated) {
  +            setQuery(negateQuery(getQuery()));
           }
  -        
  +    }
  +    
  +    public IsDefinedExpression(Index index, String field, boolean negated) {
  +        super(index);
  +
  +        setQuery(new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, 
field)));
           if (negated) {
               setQuery(negateQuery(getQuery()));
           }
  
  
  
  1.5       +14 -4     
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LikeExpression.java
  
  Index: LikeExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LikeExpression.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- LikeExpression.java       29 Nov 2004 18:38:16 -0000      1.4
  +++ LikeExpression.java       7 Dec 2004 17:49:57 -0000       1.5
  @@ -23,7 +23,9 @@
   package org.apache.slide.index.lucene.expressions;
   
   import org.apache.lucene.index.Term;
  +import org.apache.lucene.search.BooleanQuery;
   import org.apache.lucene.search.PrefixQuery;
  +import org.apache.lucene.search.TermQuery;
   import org.apache.lucene.search.WildcardQuery;
   import org.apache.lucene.search.WildcardTermEnum;
   
  @@ -63,7 +65,15 @@
           }
           
           if (negated) {
  -            setQuery(negateQuery(getQuery()));
  +            BooleanQuery booleanQuery = new BooleanQuery();
  +            booleanQuery.add(
  +                    new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, 
field)),
  +                    true, // required
  +                    false);
  +            booleanQuery.add(getQuery(),
  +                    false, 
  +                    true); // prohibited
  +            setQuery(booleanQuery);
           }
       }
       
  
  
  
  1.6       +39 -11    
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LtExpression.java
  
  Index: LtExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LtExpression.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- LtExpression.java 29 Nov 2004 18:38:16 -0000      1.5
  +++ LtExpression.java 7 Dec 2004 17:49:57 -0000       1.6
  @@ -36,44 +36,72 @@
   /**
    * Implements <code>lt</code> and <code>lte</code> expression.
    */
  -public class LtExpression extends AbstractLuceneExpression
  +public class LtExpression extends AbstractLuceneExpression implements 
RangeOperator
   {
  +    private String field;
  +    private String value;
  +    private boolean inclusive;
       
       public LtExpression(Index index, Element element, boolean inclusive) 
           throws BadQueryException 
       {
           super(index);
  +        this.inclusive = inclusive;
   
           IndexConfiguration config = index.getConfiguration();
           Element prop = getPropertyElement(element);
  -        String field = config.generateFieldName(prop.getNamespaceURI(), 
prop.getName());
  +        this.field = config.generateFieldName(prop.getNamespaceURI(), 
prop.getName());
           Element literal = getLiteralElement(element);
   
  -        String value;
           String lowerBound;
           if (index.getConfiguration().isDateProperty(prop.getNamespaceURI(), 
prop.getName())) {
               Date date = 
IndexConfiguration.getDateValue(literal.getTextTrim());
               Calendar c = Calendar.getInstance();
               c.setTime(date);
               inclusive =  c.get(Calendar.SECOND) > 0;
  -            value = config.dateToIndexString(date);
  +            this.value = config.dateToIndexString(date);
               lowerBound = Index.DATE_LOWER_BOUND;
           } 
           else if 
(index.getConfiguration().isIntProperty(prop.getNamespaceURI(), 
prop.getName())) { 
  -            value = 
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
  +            this.value = 
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
               lowerBound = Index.INT_LOWER_BOUND;
           } 
           else {
  -            value = literal.getTextTrim();
  +            this.value = literal.getTextTrim();
               lowerBound = Index.STRING_LOWER_BOUND;
           }
           
           
           RangeQuery rangeQuery = new RangeQuery(
  -                new Term(field, lowerBound),
  -                new Term(field, value),
  +                new Term(this.field, lowerBound),
  +                new Term(this.field, this.value),
                   inclusive); // inclusive or not
           
           setQuery(rangeQuery);
  +    }
  +    
  +    public String getField() {
  +        return this.field;
  +    }
  +    
  +    public String getValue() {
  +        return this.value;
  +    }
  +    
  +    public boolean inclusive() {
  +        return this.inclusive;
  +    }
  +
  +    public String toString() {
  +        StringBuffer b = new StringBuffer();
  +        
  +        b.append('(')
  +         .append(this.field)
  +         .append('<')
  +         .append(this.inclusive ? "=" : "")
  +         .append(this.value)
  +         .append(')');
  +        
  +        return b.toString();
       }
   }
  
  
  
  1.4       +161 -9    
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/MergeExpression.java
  
  Index: MergeExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/MergeExpression.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MergeExpression.java      29 Nov 2004 18:39:38 -0000      1.3
  +++ MergeExpression.java      7 Dec 2004 17:49:57 -0000       1.4
  @@ -22,8 +22,12 @@
    */
   package org.apache.slide.index.lucene.expressions;
   
  +import java.util.ArrayList;
   import java.util.Collection;
  +import java.util.HashMap;
   import java.util.Iterator;
  +import java.util.List;
  +import java.util.Map;
   
   import org.apache.lucene.search.BooleanQuery;
   import org.apache.lucene.search.Query;
  @@ -47,14 +51,162 @@
       {
           super(index);
           
  -        BooleanQuery booleanQuery = new BooleanQuery();
  +        expressions = optimizeRanges(and, expressions);
           
  -        for(Iterator i = expressions.iterator(); i.hasNext();) {
  -            Object e = i.next();
  -            Query q = ((AbstractLuceneExpression)e).getQuery();
  -            booleanQuery.add(q, and, false);
  +        if (expressions.size() == 1) {
  +            AbstractLuceneExpression expression = 
  +                (AbstractLuceneExpression)expressions.iterator().next();
  +            setQuery(expression.getQuery());
  +            
  +        } else {
  +            BooleanQuery booleanQuery = new BooleanQuery();
  +            
  +            for(Iterator i = expressions.iterator(); i.hasNext();) {
  +                Object e = i.next();
  +                AbstractLuceneExpression expression = 
(AbstractLuceneExpression)e;
  +                Query q = expression.getQuery();
  +                booleanQuery.add(q, and, false);
  +            }
  +            setQuery(booleanQuery);
  +        }        
  +    }
  +    
  +    private Collection optimizeRanges(boolean and, Collection expressions) {
  +        Map fields = new HashMap();
  +        List result = new ArrayList(expressions.size());
  +        
  +        // search for comparision operators that work on same field
  +        
  +        for (Iterator i = expressions.iterator(); i.hasNext();) {
  +            Object o = i.next();
  +            if (o instanceof RangeOperator) {
  +                RangeOperator op = (RangeOperator)o;
  +                
  +                List ops = (List)fields.get(op.getField());
  +                if (ops == null) {
  +                    ops = new ArrayList();
  +                    fields.put(op.getField(), ops);
  +                }
  +                ops.add(op);
  +            } else {
  +                result.add(o);
  +            }
  +        }
  +        
  +        for (Iterator i = fields.entrySet().iterator(); i.hasNext();) {
  +            Map.Entry e = (Map.Entry)i.next();
  +            List ops = (List)e.getValue();
  +            
  +            if (ops.size() == 2) {
  +                AbstractLuceneExpression expr =  optBetween(
  +                        (RangeOperator)ops.get(0), 
  +                        (RangeOperator)ops.get(1), and);
  +                if (expr != null) {
  +                    result.add(expr);
  +                }
  +            } else {
  +                result.addAll(ops);
  +            }
           }
           
  -        setQuery(booleanQuery);
  +        return result;
  +    }
  +    
  +    private AbstractLuceneExpression optBetween(RangeOperator o1, 
RangeOperator o2, boolean and) {
  +        if (o1 instanceof GtExpression) {
  +            if (o2 instanceof LtExpression) {
  +                if (and) {
  +                    if (o1.getValue().compareTo(o2.getValue()) <= 0) {
  +                        //   ------o1>++++++<o2------
  +                        return new BetweenExpression(this.index, 
o1.getField(), 
  +                                o1.getValue(), o2.getValue(), 
  +                                o1.inclusive(), o2.inclusive(),
  +                                false);
  +                    } else {
  +                        //   ------<o2------o1>------
  +                        return null;
  +                    }
  +                } else {
  +                    if (o1.getValue().compareTo(o2.getValue()) >= 0) {
  +                        //   ++++++<o2------o1>++++++
  +                        return new BetweenExpression(this.index, 
o1.getField(), 
  +                                o2.getValue(), o1.getValue(), 
  +                                o2.inclusive(), o1.inclusive(), 
  +                                true); // negated
  +                    } else {
  +                        //   ++++++o1>+++++<o2+++++++
  +                        return new IsDefinedExpression(this.index, 
o1.getField(), false);
  +                    }
  +                }
  +            }   
  +            if (o2 instanceof GtExpression) {
  +                if (and) {
  +                    if (o1.getValue().compareTo(o2.getValue()) <= 0) {
  +                        // -----o1>-----o2>++++++
  +                        return (AbstractLuceneExpression)o2;
  +                    } else {
  +                        // -----o2>-----o1>++++++
  +                        return (AbstractLuceneExpression)o1;
  +                    }
  +                } else {
  +                    if (o1.getValue().compareTo(o2.getValue()) <= 0) {
  +                        // -----o1>+++++o2>++++++
  +                        return (AbstractLuceneExpression)o1;
  +                    } else {
  +                        // -----o2>+++++o1>++++++
  +                        return (AbstractLuceneExpression)o2;
  +                    }
  +                }
  +            }
  +            throw new RuntimeException();
  +        }
  +        if (o1 instanceof LtExpression) {
  +            if (o2 instanceof GtExpression) {
  +                if (and) {
  +                    if (o1.getValue().compareTo(o2.getValue()) <= 0) {
  +                        //   ------<o1------o2>------
  +                        return null;
  +                    } else {
  +                        //   ------o2>++++++<o1------
  +                        return new BetweenExpression(this.index, 
o1.getField(), 
  +                                o2.getValue(), o1.getValue(),  
  +                                o2.inclusive(), o1.inclusive(),
  +                                false);
  +                    }
  +                } else {
  +                    if (o1.getValue().compareTo(o2.getValue()) >= 0) {
  +                        //   ++++++o2>+++++<o1++++++
  +                        return new IsDefinedExpression(this.index, 
o1.getField(), false);
  +                    } else {
  +                        //   ++++++<o1-----o2>+++++++
  +                        return new BetweenExpression(this.index, 
o1.getField(), 
  +                                o1.getValue(), o2.getValue(), 
  +                                o1.inclusive(), o2.inclusive(), 
  +                                true); // negated
  +                    }
  +                }
  +            }
  +            if (o2 instanceof LtExpression) {
  +                if (and) {
  +                    if (o1.getValue().compareTo(o2.getValue()) <= 0) {
  +                        // +++++<o1-----<o2------
  +                        return (AbstractLuceneExpression)o1;
  +                    } else {
  +                        // +++++<o2-----<o1------
  +                        return (AbstractLuceneExpression)o2;
  +                    }
  +                } else {
  +                    if (o1.getValue().compareTo(o2.getValue()) <= 0) {
  +                        // +++++<o1+++++<o2------
  +                        return (AbstractLuceneExpression)o2;
  +                    } else {
  +                        // +++++<o2+++++<o1------
  +                        return (AbstractLuceneExpression)o1;
  +                    }
  +                }
  +            }
  +            throw new RuntimeException();
  +        }
  +        throw new RuntimeException();
       }
   }
  
  
  
  1.5       +14 -4     
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropcontainsExpression.java
  
  Index: PropcontainsExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropcontainsExpression.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- PropcontainsExpression.java       29 Nov 2004 18:38:16 -0000      1.4
  +++ PropcontainsExpression.java       7 Dec 2004 17:49:57 -0000       1.5
  @@ -23,6 +23,8 @@
   package org.apache.slide.index.lucene.expressions;
   
   import org.apache.lucene.index.Term;
  +import org.apache.lucene.search.BooleanQuery;
  +import org.apache.lucene.search.TermQuery;
   import org.apache.lucene.search.WildcardQuery;
   
   import org.apache.slide.index.lucene.Index;
  @@ -54,7 +56,15 @@
           setQuery(new WildcardQuery(new Term(field, "*" + text + "*")));
           
           if (negated) {
  -            setQuery(negateQuery(getQuery()));
  +            BooleanQuery booleanQuery = new BooleanQuery();
  +            booleanQuery.add(
  +                    new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, 
field)),
  +                    true,  // required 
  +                    false);
  +            booleanQuery.add(getQuery(),
  +                    false, 
  +                    true); // prohibited
  +            setQuery(booleanQuery);
           }
       }
   }
  
  
  
  1.5       +12 -4     
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropertyContainsExpression.java
  
  Index: PropertyContainsExpression.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropertyContainsExpression.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- PropertyContainsExpression.java   29 Nov 2004 18:38:16 -0000      1.4
  +++ PropertyContainsExpression.java   7 Dec 2004 17:49:57 -0000       1.5
  @@ -75,7 +75,15 @@
           }
           
           if (negated) {
  -            setQuery(negateQuery(getQuery()));
  +            BooleanQuery booleanQuery = new BooleanQuery();
  +            booleanQuery.add(
  +                    new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, 
field)),
  +                    true,  // required 
  +                    false);
  +            booleanQuery.add(getQuery(),
  +                    false, 
  +                    true); // prohibited
  +            setQuery(booleanQuery);
           }
       }
   
  
  
  
  1.1                  
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/RangeOperator.java
  
  Index: RangeOperator.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.slide.index.lucene.expressions;
  
  
  /**
   * @author Stefan L�tzkendorf
   */
  interface RangeOperator
  {
      public String getField();
      public String getValue();
      public boolean inclusive();
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to