/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/search/basic/BasicExpressionCompiler.java,v 1.4.2.1 2004/02/05 16:05:10 mholz Exp $
* $Revision: 1.4.2.1 $
* $Date: 2004/02/05 16:05:10 $
*
* ====================================================================
*
* Copyright 1999 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.search.basic;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.slide.common.SlideRuntimeException;
import org.apache.slide.content.NodeProperty.NamespaceCache;
import org.apache.slide.search.BadQueryException;
import org.apache.slide.search.PropertyProvider;
import org.apache.slide.store.AbstractStore;
import org.jdom.Element;
/**
* The implementation of the {@link org.apache.slide.search.basic.IBasicExpressionCompiler
* IBasicExpressionCompiler} interface.
*
* @version $Revision: 1.4.2.1 $
*
* @author <a href="mailto:ralf.stuckert@softwareag.com">Ralf Stuckert</a>
**/
public class BasicExpressionCompiler implements IBasicExpressionCompiler{
/**
* The IBasicQuery that provides some general information about the query.
*/
protected IBasicQuery query = null;
/**
* The PropertyProvider to use (if set).
*/
protected PropertyProvider propertyProvider = null;
/**
* The default IBasicExpressionFactory to use.
*/
protected IBasicExpressionFactory defaultExpressionFactory = null;
/**
* The store specific IBasicExpressionFactory to use (if one exists).
*/
protected IBasicExpressionFactory storeSpecificExpressionFactory = null;
/**
* Inidicates if it has already been tried to instantiate the
* {@link #storeSpecificExpressionFactory storeSpecificExpressionFactory}.
*/
protected boolean alreadyTriedToInstantiate = false;
/**
* Creates the BasicExpressionCompiler.
*
* @param query the IBasicQuery.
* @param propertyProvider the PropertyProvider to use (may be
* <code>null</code>).
*/
public BasicExpressionCompiler (IBasicQuery query, PropertyProvider propertyProvider) throws BadQueryException {
this(query, propertyProvider, null);
}
/**
* Creates the BasicExpressionCompiler.
*
* @param query the IBasicQuery.
* @param propertyProvider the PropertyProvider to use (may be
* <code>null</code>).
* @param defaultExpressionFactory the default IBasicExpressionFactory to use.
*/
public BasicExpressionCompiler (IBasicQuery query,
PropertyProvider propertyProvider,
IBasicExpressionFactory defaultExpressionFactory)
throws BadQueryException
{
this.query = query;
this.propertyProvider = propertyProvider;
this.defaultExpressionFactory = defaultExpressionFactory;
storeSpecificExpressionFactory = query.getExpressionFactory();
storeSpecificExpressionFactory.init (query, propertyProvider);
}
/**
* Compiles an IBasicExpression (-tree) from the given <code>expressionElement</code>.
*
* @param expressionElement the (root) expression Element to compile
* into an IBasicExpression.
*
* @return the compiled IBasicExpression.
*
* @throws BadQueryException if compiling the expression failed.
*/
public IBasicExpression compile(Element expressionElement) throws BadQueryException {
if (isMergeExpression(expressionElement)) {
List expressionsToMerge = new ArrayList();
Iterator iterator = expressionElement.getChildren().iterator();
while (iterator.hasNext()) {
expressionsToMerge.add(compile((Element)iterator.next()));
}
return createMergeExpression(expressionElement.getName(),
expressionElement.getNamespaceURI(),
expressionsToMerge);
}
else {
return createExpression(expressionElement);
}
}
/**
* Creates a MergeExpression for the given element (AND, OR). The given children
* are the expressions to merge.
*
* @param name the name of the Element describing the merge expression.
* @param namespace the namespace of the Element describing the merge expression.
* @param expressionsToMerge the expressions to merge.
*
* @return an IBasicExpression
*
* @throws BadQueryException
*/
IBasicExpression createMergeExpression (String name, String namespace, List expressionsToMerge) throws BadQueryException {
IBasicExpression mergeExpression = null;
if (getStoreSpecificExpressionFactory() != null) {
mergeExpression =
getStoreSpecificExpressionFactory().createMergeExpression(name,
namespace,
expressionsToMerge);
}
if (mergeExpression == null) {
mergeExpression =
getDefaultExpressionFactory().createMergeExpression(name,
namespace,
expressionsToMerge);
}
return mergeExpression;
}
/**
* Creates a (non-merge) expression (compare...) for the given Element.
*
* @param expressionElement an Element describing the expression.
*
* @return an IBasicExpression
*
* @throws BadQueryException
*/
IBasicExpression createExpression (Element expressionElement) throws BadQueryException {
IBasicExpression expression = null;
if (getStoreSpecificExpressionFactory() != null) {
expression = getStoreSpecificExpressionFactory().createExpression(expressionElement);
}
if (expression == null) {
expression = getDefaultExpressionFactory().createExpression(expressionElement);
}
return expression;
}
/**
* Returns the default expression factory to use. If it does not exist yet,
* a {@link org.apache.slide.search.basic.BasicExpressionFactory
* BasicExpressionFactory} will be created and initialized.
*
* @return the default expression factory to use.
*
* @throws BadQueryException
*/
public IBasicExpressionFactory getDefaultExpressionFactory() throws BadQueryException {
if (defaultExpressionFactory == null) {
defaultExpressionFactory = new BasicExpressionFactory();
defaultExpressionFactory.init(query, propertyProvider);
}
return defaultExpressionFactory;
}
/**
* Returns the store specific expression factory to use.
*
* @return the store specific expression factory to use.
*/
public IBasicExpressionFactory getStoreSpecificExpressionFactory() throws BadQueryException {
if ( !alreadyTriedToInstantiate && (storeSpecificExpressionFactory == null) ) {
AbstractStore store = query.getStore();
String className = (String)store.getParameter(IBasicExpressionFactory.BASIC_EXPRESSION_FACTORY_CLASS);
if (className != null) {
try {
Class factoryClass = Class.forName (className);
storeSpecificExpressionFactory = (IBasicExpressionFactory)factoryClass.newInstance();
storeSpecificExpressionFactory.init(query, propertyProvider);
}
catch (Exception e) {
e.printStackTrace();
throw new SlideRuntimeException (e.getMessage());
}
}
}
return storeSpecificExpressionFactory;
}
/**
* Returns <code>true</code> if the given <code>expressionElement</code>
* describes a merge expression.
*
* @param expressionElement the Element that describes the expression.
*
* @return <code>true</code> if the given <code>expressionElement</code>
* describes a merge expression.
*/
public static boolean isMergeExpression(Element expressionElement) {
boolean isMerge = false;
if ( (expressionElement != null) &&
NamespaceCache.DEFAULT_URI.equals(expressionElement.getNamespaceURI()) ) {
isMerge = Literals.AND.equals(expressionElement.getName()) ||
Literals.OR.equals(expressionElement.getName());
}
return isMerge;
}
}