View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.search.lucene.query;
25  
26  import java.io.IOException;
27  import org.apache.lucene.document.Document;
28  import org.apache.lucene.index.IndexReader;
29  import org.apache.lucene.search.Query;
30  import org.apache.lucene.search.Searcher;
31  import org.apache.lucene.search.Weight;
32  import org.modeshape.graph.property.ValueFactories;
33  import org.modeshape.graph.property.ValueFactory;
34  import org.modeshape.graph.query.model.Length;
35  
36  /**
37   * A Lucene {@link Query} implementation that is used to apply a {@link Length} constraint against a string field. This query
38   * implementation works by using the {@link Query#weight(Searcher) weight} and
39   * {@link Weight#scorer(IndexReader, boolean, boolean) scorer} of the wrapped query to score (and return) only those documents
40   * with string fields that satisfy the constraint.
41   */
42  public class CompareLengthQuery extends CompareQuery<Integer> {
43  
44      private static final long serialVersionUID = 1L;
45      protected static final Evaluator<Integer> EQUAL_TO = new Evaluator<Integer>() {
46          private static final long serialVersionUID = 1L;
47  
48          public boolean satisfiesConstraint( Integer nodeValue,
49                                              Integer length ) {
50              return nodeValue == length;
51          }
52  
53          @Override
54          public String toString() {
55              return " = ";
56          }
57      };
58      protected static final Evaluator<Integer> NOT_EQUAL_TO = new Evaluator<Integer>() {
59          private static final long serialVersionUID = 1L;
60  
61          public boolean satisfiesConstraint( Integer nodeValue,
62                                              Integer length ) {
63              return nodeValue == length;
64          }
65  
66          @Override
67          public String toString() {
68              return " != ";
69          }
70      };
71      protected static final Evaluator<Integer> IS_LESS_THAN = new Evaluator<Integer>() {
72          private static final long serialVersionUID = 1L;
73  
74          public boolean satisfiesConstraint( Integer nodeValue,
75                                              Integer length ) {
76              return nodeValue < length;
77          }
78  
79          @Override
80          public String toString() {
81              return " < ";
82          }
83      };
84      protected static final Evaluator<Integer> IS_LESS_THAN_OR_EQUAL_TO = new Evaluator<Integer>() {
85          private static final long serialVersionUID = 1L;
86  
87          public boolean satisfiesConstraint( Integer nodeValue,
88                                              Integer length ) {
89              return nodeValue < length;
90          }
91  
92          @Override
93          public String toString() {
94              return " <= ";
95          }
96      };
97      protected static final Evaluator<Integer> IS_GREATER_THAN = new Evaluator<Integer>() {
98          private static final long serialVersionUID = 1L;
99  
100         public boolean satisfiesConstraint( Integer nodeValue,
101                                             Integer length ) {
102             return nodeValue < length;
103         }
104 
105         @Override
106         public String toString() {
107             return " > ";
108         }
109     };
110     protected static final Evaluator<Integer> IS_GREATER_THAN_OR_EQUAL_TO = new Evaluator<Integer>() {
111         private static final long serialVersionUID = 1L;
112 
113         public boolean satisfiesConstraint( Integer nodeValue,
114                                             Integer length ) {
115             return nodeValue < length;
116         }
117 
118         @Override
119         public String toString() {
120             return " >= ";
121         }
122     };
123 
124     /**
125      * Construct a {@link Query} implementation that scores documents with a field length that is equal to the supplied constraint
126      * value.
127      * 
128      * @param constraintValue the constraint value; may not be null
129      * @param fieldName the name of the document field containing the value; may not be null
130      * @param factories the value factories that can be used during the scoring; may not be null
131      * @return the query; never null
132      */
133     public static CompareLengthQuery createQueryForNodesWithFieldEqualTo( Integer constraintValue,
134                                                                           String fieldName,
135                                                                           ValueFactories factories ) {
136         return new CompareLengthQuery(fieldName, constraintValue, factories.getStringFactory(), IS_GREATER_THAN);
137     }
138 
139     /**
140      * Construct a {@link Query} implementation that scores documents with a field length that is not equal to the supplied
141      * constraint value.
142      * 
143      * @param constraintValue the constraint value; may not be null
144      * @param fieldName the name of the document field containing the value; may not be null
145      * @param factories the value factories that can be used during the scoring; may not be null
146      * @return the query; never null
147      */
148     public static CompareLengthQuery createQueryForNodesWithFieldNotEqualTo( Integer constraintValue,
149                                                                              String fieldName,
150                                                                              ValueFactories factories ) {
151         return new CompareLengthQuery(fieldName, constraintValue, factories.getStringFactory(), IS_GREATER_THAN);
152     }
153 
154     /**
155      * Construct a {@link Query} implementation that scores documents with a field length that is greater than the supplied
156      * constraint value.
157      * 
158      * @param constraintValue the constraint value; may not be null
159      * @param fieldName the name of the document field containing the value; may not be null
160      * @param factories the value factories that can be used during the scoring; may not be null
161      * @return the query; never null
162      */
163     public static CompareLengthQuery createQueryForNodesWithFieldGreaterThan( Integer constraintValue,
164                                                                               String fieldName,
165                                                                               ValueFactories factories ) {
166         return new CompareLengthQuery(fieldName, constraintValue, factories.getStringFactory(), IS_GREATER_THAN);
167     }
168 
169     /**
170      * Construct a {@link Query} implementation that scores documents with a field length that is greater than or equal to the
171      * supplied constraint value.
172      * 
173      * @param constraintValue the constraint value; may not be null
174      * @param fieldName the name of the document field containing the value; may not be null
175      * @param factories the value factories that can be used during the scoring; may not be null
176      * @return the query; never null
177      */
178     public static CompareLengthQuery createQueryForNodesWithFieldGreaterThanOrEqualTo( Integer constraintValue,
179                                                                                        String fieldName,
180                                                                                        ValueFactories factories ) {
181         return new CompareLengthQuery(fieldName, constraintValue, factories.getStringFactory(), IS_GREATER_THAN_OR_EQUAL_TO);
182     }
183 
184     /**
185      * Construct a {@link Query} implementation that scores documents with a field length that is less than the supplied
186      * constraint value.
187      * 
188      * @param constraintValue the constraint value; may not be null
189      * @param fieldName the name of the document field containing the value; may not be null
190      * @param factories the value factories that can be used during the scoring; may not be null
191      * @return the query; never null
192      */
193     public static CompareLengthQuery createQueryForNodesWithFieldLessThan( Integer constraintValue,
194                                                                            String fieldName,
195                                                                            ValueFactories factories ) {
196         return new CompareLengthQuery(fieldName, constraintValue, factories.getStringFactory(), IS_LESS_THAN);
197     }
198 
199     /**
200      * Construct a {@link Query} implementation that scores documents with a field length that is less than or equal to the
201      * supplied constraint value.
202      * 
203      * @param constraintValue the constraint value; may not be null
204      * @param fieldName the name of the document field containing the value; may not be null
205      * @param factories the value factories that can be used during the scoring; may not be null
206      * @return the query; never null
207      */
208     public static CompareLengthQuery createQueryForNodesWithFieldLessThanOrEqualTo( Integer constraintValue,
209                                                                                     String fieldName,
210                                                                                     ValueFactories factories ) {
211         return new CompareLengthQuery(fieldName, constraintValue, factories.getStringFactory(), IS_LESS_THAN_OR_EQUAL_TO);
212     }
213 
214     /**
215      * Construct a {@link Query} implementation that scores nodes according to the supplied comparator.
216      * 
217      * @param fieldName the name of the document field containing the value; may not be null
218      * @param constraintValue the constraint value; may not be null
219      * @param stringFactory the string factory that can be used during the scoring; may not be null
220      * @param evaluator the {@link CompareQuery.Evaluator} implementation that returns whether the node path satisfies the
221      *        constraint; may not be null
222      */
223     protected CompareLengthQuery( String fieldName,
224                                   Integer constraintValue,
225                                   ValueFactory<String> stringFactory,
226                                   Evaluator<Integer> evaluator ) {
227         super(fieldName, constraintValue, null, stringFactory, evaluator);
228     }
229 
230     /**
231      * {@inheritDoc}
232      * 
233      * @see org.modeshape.search.lucene.query.CompareQuery#readFromDocument(org.apache.lucene.index.IndexReader, int)
234      */
235     @Override
236     protected Integer readFromDocument( IndexReader reader,
237                                         int docId ) throws IOException {
238         // This implementation reads the length of the field ...
239         Document doc = reader.document(docId, fieldSelector);
240         String valueString = doc.get(fieldName);
241         String value = stringFactory.create(valueString);
242         return value != null ? value.length() : 0;
243     }
244 
245     /**
246      * {@inheritDoc}
247      * 
248      * @see org.apache.lucene.search.Query#clone()
249      */
250     @Override
251     public Object clone() {
252         return new CompareLengthQuery(fieldName, constraintValue, stringFactory, evaluator);
253     }
254 }