KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > search > basic > BasicExpressionCompiler


1 /*
2  * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/search/basic/BasicExpressionCompiler.java,v 1.10 2004/07/28 09:35:02 ib Exp $
3  * $Revision: 1.10 $
4  * $Date: 2004/07/28 09:35:02 $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23 package org.apache.slide.search.basic;
24
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import org.apache.slide.content.NodeProperty.NamespaceCache;
32 import org.apache.slide.search.BadQueryException;
33 import org.apache.slide.search.PropertyProvider;
34 import org.jdom.Element;
35
36 /**
37  * The implementation of the {@link org.apache.slide.search.basic.IBasicExpressionCompiler
38  * IBasicExpressionCompiler} interface.
39  *
40  * @version $Revision: 1.10 $
41  *
42  **/

43 public class BasicExpressionCompiler implements IBasicExpressionCompiler{
44     
45     /**
46      * The IBasicQuery that provides some general information about the query.
47      */

48     protected IBasicQuery query = null;
49     
50     /**
51      * The PropertyProvider to use (if set).
52      */

53     protected PropertyProvider propertyProvider = null;
54     
55     /**
56      * The default IBasicExpressionFactory to use.
57      */

58     protected IBasicExpressionFactory genericExpressionFactory = null;
59     
60     /**
61      * The store specific IBasicExpressionFactory for property expressions
62      * to use (if one exists).
63      */

64     protected IBasicExpressionFactory propertiesExpressionFactory = null;
65     
66     /**
67      * The store specific IBasicExpressionFactory for content expressions
68      * to use (if one exists).
69      */

70     protected IBasicExpressionFactory contentExpressionFactory = null;
71     
72     /**
73      * Inidicates if it has already been tried to instantiate the
74      * {@link #storeSpecificExpressionFactory storeSpecificExpressionFactory}.
75      */

76     protected boolean alreadyTriedToInstantiate = false;
77     
78     
79     
80     /**
81      * Creates the BasicExpressionCompiler, loads and inits the expression
82      * factories. If no store / indexer specific factory is defined, the
83      * generic expression factory is used.
84      *
85      * @param query the IBasicQuery.
86      * @param propertyProvider the PropertyProvider to use (may be
87      * <code>null</code>).
88      */

89     public BasicExpressionCompiler (IBasicQuery query, PropertyProvider propertyProvider) throws BadQueryException {
90         this.query = query;
91         this.propertyProvider = propertyProvider;
92         
93         genericExpressionFactory = new BasicExpressionFactory();
94         
95         propertiesExpressionFactory = query.getPropertiesExpressionFactory() == null ?
96             genericExpressionFactory : query.getPropertiesExpressionFactory();
97         
98         contentExpressionFactory = query.getContentExpressionFactory() == null ?
99             genericExpressionFactory : query.getContentExpressionFactory();
100
101         propertiesExpressionFactory.init(query, propertyProvider);
102         contentExpressionFactory.init(query, propertyProvider);
103         genericExpressionFactory.init(query, propertyProvider);
104     }
105     
106
107     
108     /**
109      * Compiles an IBasicExpression (-tree) from the given <code>expressionElement</code>.
110      *
111      * @param expressionElement the (root) expression Element to compile
112      * into an IBasicExpression.
113      *
114      * @return the compiled IBasicExpression.
115      *
116      * @throws BadQueryException if compiling the expression failed.
117      */

118     public IBasicExpression compile(Element expressionElement) throws BadQueryException {
119         
120         if (isMergeExpression(expressionElement)) {
121             
122             List JavaDoc expressionsToMerge = new ArrayList JavaDoc();
123             Iterator JavaDoc iterator = expressionElement.getChildren().iterator();
124             while (iterator.hasNext()) {
125                 expressionsToMerge.add(compile((Element)iterator.next()));
126             }
127             return createMergeExpression(expressionElement.getName(),
128                                          expressionElement.getNamespaceURI(),
129                                          expressionsToMerge);
130         }
131         else {
132             return createExpression(expressionElement);
133         }
134     }
135     
136     /**
137      * Creates a MergeExpression for the given element (AND, OR). The given children
138      * are the expressions to merge.
139      * If there are expressions of different factories (content, properties or
140      * generic), all expressions of one factory are merged using its factory,
141      * then the remaining nodes are merged using generic factory.
142      *
143      * @param name the name of the Element describing the merge expression.
144      * @param namespace the namespace of the Element describing the merge expression.
145      * @param expressionsToMerge the expressions to merge.
146      *
147      * @return an IBasicExpression
148      *
149      * @throws BadQueryException
150      */

151     private IBasicExpression createMergeExpression (String JavaDoc name, String JavaDoc namespace,
152                                                     List JavaDoc expressionsToMerge)
153         throws BadQueryException
154     {
155         
156         Map JavaDoc expressionsByFactory = new HashMap JavaDoc ();
157         IBasicExpression mergeExpression = null;
158         Iterator JavaDoc it = expressionsToMerge.iterator();
159         
160         // collect all expressions by factory (should be max 2 different factories)
161
while (it.hasNext()) {
162             IBasicExpression exp = (IBasicExpression)it.next();
163             IBasicExpressionFactory fac = exp.getFactory();
164             List JavaDoc expList = (List JavaDoc)expressionsByFactory.get(fac);
165             if (expList == null) {
166                 expList = new ArrayList JavaDoc();
167                 expressionsByFactory.put (fac, expList);
168             }
169             
170             expList.add (exp);
171         }
172         
173         // merge all expressions of each factory
174
it = expressionsByFactory.keySet().iterator();
175         while (it.hasNext()) {
176             IBasicExpressionFactory fac = (IBasicExpressionFactory)it.next();
177             List JavaDoc expList = (List JavaDoc)expressionsByFactory.get (fac);
178             
179             
180             if (expList.size() > 1) {
181                 // merge all expressions
182
expressionsByFactory.put
183                     (fac, fac.createMergeExpression (name, namespace, expList));
184             }
185             else {
186                 // we're interested in the one and only expression
187
expressionsByFactory.put (fac, expList.get(0));
188             }
189         }
190         
191         // if there is more than one entry in the map (expressions of different
192
// factories), merge them with GenericFactory
193
Collection JavaDoc exprToMerge = expressionsByFactory.values();
194         
195         if (expressionsByFactory.size() > 1) {
196             
197             mergeExpression =
198                 genericExpressionFactory.createMergeExpression (name, namespace,
199                                                                 exprToMerge);
200         }
201         else {
202             it = expressionsByFactory.values().iterator();
203             if (it.hasNext())
204                 mergeExpression = (IBasicExpression)it.next();
205         }
206         
207         return mergeExpression;
208     }
209     
210     /**
211      * Creates a (non-merge) expression (compare...) for the given Element.
212      * Falls back to generic factory if no store / indexer specific factory
213      * defined. Uses generic factory if specific factory does not implement
214      * the expression.
215      *
216      * @param expressionElement an Element describing the expression.
217      *
218      * @return an IBasicExpression
219      *
220      * @throws BadQueryException
221      */

222     private IBasicExpression createExpression (Element expressionElement)
223         throws BadQueryException
224     {
225         IBasicExpression expression = null;
226         
227         if (isContentExpression (expressionElement)) {
228             expression = contentExpressionFactory.createExpression(expressionElement);
229         }
230         else {
231             expression = propertiesExpressionFactory.createExpression(expressionElement);
232         }
233
234         if (expression == null) {
235             expression = genericExpressionFactory.createExpression (expressionElement);
236         }
237         
238         return expression;
239     }
240     
241     
242     /**
243      * Returns <code>true</code> if the given <code>expressionElement</code>
244      * describes a merge expression.
245      *
246      * @param expressionElement the Element that describes the expression.
247      *
248      * @return <code>true</code> if the given <code>expressionElement</code>
249      * describes a merge expression.
250      */

251     public static boolean isMergeExpression(Element expressionElement) {
252         
253         boolean isMerge = false;
254         if ( (expressionElement != null) &&
255             NamespaceCache.DEFAULT_URI.equals(expressionElement.getNamespaceURI()) ) {
256             
257             isMerge = Literals.AND.equals(expressionElement.getName()) ||
258                 Literals.OR.equals(expressionElement.getName());
259         }
260         return isMerge;
261     }
262     
263     
264     /**
265      * Checks, if an expression is a contains expression.
266      *
267      * TODO: ask the contentIndexer, if it knows this expression (to allow
268      * proprietary extensions to DASL, for example <RDFContains>, <xpath>)
269      *
270      * @param expressionElement an Element
271      *
272      * @return a boolean
273      *
274      */

275     public static boolean isContentExpression (Element expressionElement) {
276         boolean isContent = false;
277         if ( (expressionElement != null) &&
278             NamespaceCache.DEFAULT_URI.equals(expressionElement.getNamespaceURI()) ) {
279             
280             isContent = Literals.CONTAINS.equals(expressionElement.getName());
281         }
282         return isContent;
283     }
284 }
285
286
Popular Tags