KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > search > impl > lucene > LuceneQueryParser


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.search.impl.lucene;
18
19 import java.io.IOException JavaDoc;
20 import java.io.StringReader JavaDoc;
21 import java.util.HashSet JavaDoc;
22
23 import org.alfresco.repo.search.SearcherException;
24 import org.alfresco.repo.search.impl.lucene.query.PathQuery;
25 import org.alfresco.service.cmr.dictionary.AspectDefinition;
26 import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
27 import org.alfresco.service.cmr.dictionary.DictionaryService;
28 import org.alfresco.service.cmr.dictionary.PropertyDefinition;
29 import org.alfresco.service.cmr.dictionary.TypeDefinition;
30 import org.alfresco.service.namespace.NamespacePrefixResolver;
31 import org.alfresco.service.namespace.QName;
32 import org.apache.log4j.Logger;
33 import org.apache.lucene.analysis.Analyzer;
34 import org.apache.lucene.analysis.TokenStream;
35 import org.apache.lucene.index.Term;
36 import org.apache.lucene.search.BooleanQuery;
37 import org.apache.lucene.search.Query;
38 import org.apache.lucene.search.RangeQuery;
39 import org.apache.lucene.search.TermQuery;
40 import org.saxpath.SAXPathException;
41
42 import com.werken.saxpath.XPathReader;
43
44 public class LuceneQueryParser extends QueryParser
45 {
46     private static Logger s_logger = Logger.getLogger(LuceneQueryParser.class);
47
48     private NamespacePrefixResolver namespacePrefixResolver;
49
50     private DictionaryService dictionaryService;
51
52     /**
53      * Parses a query string, returning a {@link org.apache.lucene.search.Query}.
54      *
55      * @param query
56      * the query string to be parsed.
57      * @param field
58      * the default field for query terms.
59      * @param analyzer
60      * used to find terms in the query text.
61      * @throws ParseException
62      * if the parsing fails
63      */

64     static public Query parse(String JavaDoc query, String JavaDoc field, Analyzer analyzer,
65             NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, int defaultOperator)
66             throws ParseException
67     {
68         if (s_logger.isDebugEnabled())
69         {
70             s_logger.debug("Using Alfresco Lucene Query Parser for query: " + query);
71         }
72         LuceneQueryParser parser = new LuceneQueryParser(field, analyzer);
73         parser.setOperator(defaultOperator);
74         parser.setNamespacePrefixResolver(namespacePrefixResolver);
75         parser.setDictionaryService(dictionaryService);
76         return parser.parse(query);
77     }
78
79     public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
80     {
81         this.namespacePrefixResolver = namespacePrefixResolver;
82     }
83
84     public LuceneQueryParser(String JavaDoc arg0, Analyzer arg1)
85     {
86         super(arg0, arg1);
87     }
88
89     public LuceneQueryParser(CharStream arg0)
90     {
91         super(arg0);
92     }
93
94     public LuceneQueryParser(QueryParserTokenManager arg0)
95     {
96         super(arg0);
97     }
98
99     protected Query getFieldQuery(String JavaDoc field, String JavaDoc queryText) throws ParseException
100     {
101         try
102         {
103             if (field.equals("PATH"))
104             {
105                 XPathReader reader = new XPathReader();
106                 LuceneXPathHandler handler = new LuceneXPathHandler();
107                 handler.setNamespacePrefixResolver(namespacePrefixResolver);
108                 handler.setDictionaryService(dictionaryService);
109                 reader.setXPathHandler(handler);
110                 reader.parse(queryText);
111                 PathQuery pathQuery = handler.getQuery();
112                 pathQuery.setRepeats(false);
113                 return pathQuery;
114             }
115             else if (field.equals("PATH_WITH_REPEATS"))
116             {
117                 XPathReader reader = new XPathReader();
118                 LuceneXPathHandler handler = new LuceneXPathHandler();
119                 handler.setNamespacePrefixResolver(namespacePrefixResolver);
120                 handler.setDictionaryService(dictionaryService);
121                 reader.setXPathHandler(handler);
122                 reader.parse(queryText);
123                 PathQuery pathQuery = handler.getQuery();
124                 pathQuery.setRepeats(true);
125                 return pathQuery;
126             }
127             else if (field.equals("ID"))
128             {
129                 TermQuery termQuery = new TermQuery(new Term(field, queryText));
130                 return termQuery;
131             }
132             else if (field.equals("TX"))
133             {
134                 TermQuery termQuery = new TermQuery(new Term(field, queryText));
135                 return termQuery;
136             }
137             else if (field.equals("PARENT"))
138             {
139                 TermQuery termQuery = new TermQuery(new Term(field, queryText));
140                 return termQuery;
141             }
142             else if (field.equals("PRIMARYPARENT"))
143             {
144                 TermQuery termQuery = new TermQuery(new Term(field, queryText));
145                 return termQuery;
146             }
147             else if (field.equals("QNAME"))
148             {
149                 XPathReader reader = new XPathReader();
150                 LuceneXPathHandler handler = new LuceneXPathHandler();
151                 handler.setNamespacePrefixResolver(namespacePrefixResolver);
152                 handler.setDictionaryService(dictionaryService);
153                 reader.setXPathHandler(handler);
154                 reader.parse("//" + queryText);
155                 return handler.getQuery();
156             }
157             else if (field.equals("TYPE"))
158             {
159                 TypeDefinition target = dictionaryService.getType(QName.createQName(queryText));
160                 if (target == null)
161                 {
162                     throw new SearcherException("Invalid type: " + queryText);
163                 }
164                 QName targetQName = target.getName();
165                 HashSet JavaDoc<QName> subclasses = new HashSet JavaDoc<QName>();
166                 for (QName classRef : dictionaryService.getAllTypes())
167                 {
168                     TypeDefinition current = dictionaryService.getType(classRef);
169                     while ((current != null) && !current.getName().equals(targetQName))
170                     {
171                         current = (current.getParentName() == null) ? null : dictionaryService.getType(current
172                                 .getParentName());
173                     }
174                     if (current != null)
175                     {
176                         subclasses.add(classRef);
177                     }
178                 }
179                 BooleanQuery booleanQuery = new BooleanQuery();
180                 for (QName qname : subclasses)
181                 {
182                     TermQuery termQuery = new TermQuery(new Term(field, qname.toString()));
183                     booleanQuery.add(termQuery, false, false);
184                 }
185                 return booleanQuery;
186             }
187             else if (field.equals("ASPECT"))
188             {
189                 AspectDefinition target = dictionaryService.getAspect(QName.createQName(queryText));
190                 QName targetQName = target.getName();
191                 HashSet JavaDoc<QName> subclasses = new HashSet JavaDoc<QName>();
192                 for (QName classRef : dictionaryService.getAllAspects())
193                 {
194                     AspectDefinition current = dictionaryService.getAspect(classRef);
195                     while ((current != null) && !current.getName().equals(targetQName))
196                     {
197                         current = (current.getParentName() == null) ? null : dictionaryService.getAspect(current
198                                 .getParentName());
199                     }
200                     if (current != null)
201                     {
202                         subclasses.add(classRef);
203                     }
204                 }
205
206                 BooleanQuery booleanQuery = new BooleanQuery();
207                 for (QName qname : subclasses)
208                 {
209                     TermQuery termQuery = new TermQuery(new Term(field, qname.toString()));
210                     booleanQuery.add(termQuery, false, false);
211                 }
212                 return booleanQuery;
213             }
214             else if (field.startsWith("@"))
215             {
216
217                 String JavaDoc expandedFieldName = field;
218                 // Check for any prefixes and expand to the full uri
219
if (field.charAt(1) != '{')
220                 {
221                     int colonPosition = field.indexOf(':');
222                     if (colonPosition == -1)
223                     {
224                         // use the default namespace
225
expandedFieldName = "@{"
226                             + namespacePrefixResolver.getNamespaceURI("") + "}" + field.substring(1);
227                     }
228                     else
229                     {
230                         // find the prefix
231
expandedFieldName = "@{"
232                                 + namespacePrefixResolver.getNamespaceURI(field.substring(1, colonPosition)) + "}"
233                                 + field.substring(colonPosition + 1);
234                     }
235                 }
236                 
237                 if(expandedFieldName.endsWith(".mimetype"))
238                 {
239                     QName propertyQName = QName.createQName(expandedFieldName.substring(1, expandedFieldName.length()-9));
240                     PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName);
241                     if((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)))
242                     {
243                         TermQuery termQuery = new TermQuery(new Term(expandedFieldName, queryText));
244                         return termQuery;
245                     }
246                             
247                 }
248                 
249                 // Already in expanded form
250
return super.getFieldQuery(expandedFieldName, queryText);
251                
252
253             }
254             else
255             {
256                 return super.getFieldQuery(field, queryText);
257             }
258         }
259         catch (SAXPathException e)
260         {
261             throw new ParseException("Failed to parse XPath...\n" + e.getMessage());
262         }
263
264     }
265
266     /**
267      * @exception ParseException
268      * throw in overridden method to disallow
269      */

270     protected Query getRangeQuery(String JavaDoc field, String JavaDoc part1, String JavaDoc part2, boolean inclusive) throws ParseException
271     {
272         if (field.startsWith("@"))
273         {
274             String JavaDoc fieldName = field;
275             // Check for any prefixes and expand to the full uri
276
if (field.charAt(1) != '{')
277             {
278                 int colonPosition = field.indexOf(':');
279                 if (colonPosition == -1)
280                 {
281                     // use the default namespace
282
fieldName = "@{" + namespacePrefixResolver.getNamespaceURI("") + "}" + field.substring(1);
283                 }
284                 else
285                 {
286                     // find the prefix
287
fieldName = "@{"
288                             + namespacePrefixResolver.getNamespaceURI(field.substring(1, colonPosition)) + "}"
289                             + field.substring(colonPosition + 1);
290                 }
291             }
292             return new RangeQuery(new Term(fieldName, getToken(fieldName, part1)), new Term(fieldName, getToken(
293                     fieldName, part2)), inclusive);
294
295         }
296         else
297         {
298             return super.getRangeQuery(field, part1, part2, inclusive);
299         }
300
301     }
302
303     private String JavaDoc getToken(String JavaDoc field, String JavaDoc value)
304     {
305         TokenStream source = analyzer.tokenStream(field, new StringReader JavaDoc(value));
306         org.apache.lucene.analysis.Token t;
307         String JavaDoc tokenised = null;
308
309         while (true)
310         {
311             try
312             {
313                 t = source.next();
314             }
315             catch (IOException JavaDoc e)
316             {
317                 t = null;
318             }
319             if (t == null)
320                 break;
321             tokenised = t.termText();
322         }
323         try
324         {
325             source.close();
326         }
327         catch (IOException JavaDoc e)
328         {
329
330         }
331         return tokenised;
332
333     }
334
335     public void setDictionaryService(DictionaryService dictionaryService)
336     {
337         this.dictionaryService = dictionaryService;
338     }
339
340 }
341
Popular Tags