/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/search/XBasicExpressionFactory.java,v 1.3 2004/07/30 06:51:57 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:51:57 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 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.store.tamino.datastore.search;

import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.store.ISlideAccessor;
import java.util.Collection;
import org.apache.slide.content.NodeProperty.NamespaceCache;
import org.apache.slide.search.BadQueryException;
import org.apache.slide.search.InvalidQueryException;
import org.apache.slide.search.PropertyProvider;
import org.apache.slide.search.basic.IBasicExpression;
import org.apache.slide.search.basic.IBasicExpressionFactory;
import org.apache.slide.search.basic.IBasicQuery;
import org.jdom.Element;


/**
 * Creates all expressions of one query.
 *
 * @author <a href="mailto:martin.wallmer@softwareag.com">Martin Wallmer</a>
 * @version $Revision: 1.3 $
 */
public class XBasicExpressionFactory implements IBasicExpressionFactory {
    
    /** = operator */
    static final String OP_EQ   = "=";
    
    /** != operator */
    static final String OP_N_EQ = "!=";
    
    /** > operator */
    static final String OP_GT   = ">";
    
    /** >= operator */
    static final String OP_GTE  = ">=";
    
    /** < operator */
    static final String OP_LT   = "<";
    
    /** <= operator */
    static final String OP_LTE  = "<=";
    
    /** ~= operator */
    static final String OP_LIKE = "~=";
    
    
    private ISlideAccessor slideAccessor;
    
    /** the query for this expression */
    protected XBasicQuery query;
    
    /** the property provider for this expression */
    protected PropertyProvider propertyProvider;
    
    /**
     * Factory method to create the concrete expression.
     *
     * @param    e the jdom element representing the expression
     *
     * @return   an IBasicExpression
     *
     * @throws   InvalidQueryException
     */
    public IBasicExpression createExpression (Element e)
        throws BadQueryException
    {
        XBasicExpression result = null;
        
        if (e == null) {
            result = new XEmptyExpression ();
        }
        else {
            String namespace = e.getNamespace().getURI();
            if (namespace.equals (NamespaceCache.DEFAULT_URI))
                result = createDAVExpression (e);
            else
                result = createNonDAVExpression (e, namespace);
        }
        
        if (result != null) {
            result.init (slideAccessor, query);
        }
        
        result.setFactory(this);
        return result;
    }
    
    /**
     * Tries to create an XMergeEpression for all IBasicExpressions in the
     * collection of children. If not all children can be merged together,
     * null is returned.
     *
     * @param    name                a  String
     * @param    namespace           a  String
     * @param    children            a  Collection
     *
     * @return   an IBasicExpression
     *
     * @throws   BadQueryException
     *
     */
    public IBasicExpression createMergeExpression (String name, String namespace,
                                                   Collection children)
        throws BadQueryException
    {
        XBasicExpression result = null;
        
        if (XBasicExpression.isMergeable (children)) {
            
            if (namespace.equals (NamespaceCache.DEFAULT_URI)) {
                if (name.equals (XLiterals.AND))
                    result = new XMergeExpression (children, XLiterals.AND);
                else if (name.equals (XLiterals.OR))
                    result = new XMergeExpression (children, XLiterals.OR);
                    
                else
                    throw new InvalidQueryException
                        ("operator " + namespace + ":" + name + " is an unprocessable entity");
            }
            else {
                throw new InvalidQueryException
                    ("operator " + namespace + ":" + name + " is an unprocessable entity");
            }
            result.init (slideAccessor, query);
        }
        result.setFactory (this);
        return result;
    }
    
    /**
     * Method createDAVExpression
     *
     * @param    e                   an Element
     *
     * @return   a XBasicExpression
     *
     * @throws   InvalidQueryException
     *
     */
    private XBasicExpression createDAVExpression
        (Element e) throws InvalidQueryException
    {
        String name = e.getName();
        XBasicExpression result = null;
        
        if (name.equals (XLiterals.EQ))
            result = new XCompareExpression (e, OP_EQ);
            
        else if (name.equals (XLiterals.NOT_EQ))
            result = new XNotEqualExpression (e);
            
        else if (name.equals (XLiterals.GT))
            result = new XCompareExpression (e, OP_GT);
            
        else if (name.equals (XLiterals.NOT_GT))
            result = new XCompareExpression (e, OP_LTE);
            
        else if (name.equals (XLiterals.GTE))
            result = new XCompareExpression (e, OP_GTE);
            
        else if (name.equals (XLiterals.NOT_GTE))
            result = new XCompareExpression (e, OP_LT);
            
        else if (name.equals (XLiterals.LT))
            result = new XCompareExpression (e, OP_LT);
            
        else if (name.equals (XLiterals.NOT_LT))
            result = new XCompareExpression (e, OP_GTE);
            
        else if (name.equals (XLiterals.LTE))
            result = new XCompareExpression (e, OP_LTE);
            
        else if (name.equals (XLiterals.NOT_LTE))
            result = new XCompareExpression (e, OP_GT);
            
        else if (name.equals (XLiterals.LIKE))
            result = new XLikeExpression (e);
            
        else if (name.equals (XLiterals.NOT_LIKE))
            result = new XLikeExpression (e, true);
            
        else if (name.equals (XLiterals.ISCOLLECTION))
            result =  new XIsPropertyTypeExpression (e, "collection");
            
        else if (name.equals (XLiterals.NOT_ISCOLLECTION))
            result = new XIsPropertyTypeExpression (e, "collection", true);
            
        else if (name.equals (XLiterals.ISDEFINED))
            result = new XIsDefinedExpression (e);
            
        else if (name.equals (XLiterals.NOT_ISDEFINED))
            result = new XIsDefinedExpression (e, true);
        
        
        //      else
        //          throw new InvalidQueryException
        //              ("operator " + NamespaceCache.DEFAULT_URI + name + " is an unprocessable entity");
        
        return result;
    }
    
    /**
     * Create expressions that are extensions to the DAV standard.
     *
     * @param    e                   an Element
     * @param    namespace           a  String
     *
     * @return   an XBasicExpression
     *
     * @throws   InvalidQueryException
     *
     */
    private XBasicExpression createNonDAVExpression
        (Element e, String namespace) throws BadQueryException
    {
        
        String name = e.getName();
        XBasicExpression result = null;
        
        if (namespace.equals (NamespaceCache.SLIDE_URI)
            && name.equals (XLiterals.ISPRINCIPAL))
        {
            result = new XIsPropertyTypeExpression (e, "principal");
        }
            
        else if (namespace.equals (NamespaceCache.SLIDE_URI)
                 && name.equals (XLiterals.NOT_ISPRINCIPAL))
        {
            result = new XIsPropertyTypeExpression (e, "principal", true);
        }
            
        else if (namespace.equals (NamespaceCache.SLIDE_URI)
                 && name.equals (XLiterals.PROPCONTAINS))
        {
            result = new XPropertyContainsExpression (e);
        }
            
        else if (namespace.equals (NamespaceCache.SLIDE_URI)
                 && name.equals (XLiterals.NOT_PROPCONTAINS))
        {
            result = new XPropertyContainsExpression (e, true);
        }
            
        else if (namespace.equals (XGlobals.TAMINO_NAMESPACE_URI)
                 && name.equals (XLiterals.XPATH))
        {
            result = new XPathExpression (e, query);
        }
            
        else if (namespace.equals (XGlobals.TAMINO_NAMESPACE_URI)
                 && name.equals (XLiterals.NOT_XPATH))
        {
            result = new XPathExpression (e, query, true);
        }
            
        else
            throw new InvalidQueryException
                ("operator " + namespace + name + " is an unprocessable entity");
        
        return result;
    }
    
    
    /**
     * Method init
     *
     * @param    query               an IBasicQuery
     * @param    propertyProvider    a  PropertyProvider
     *
     * @throws   BadQueryException
     *
     */
    public void init (IBasicQuery query,
                      PropertyProvider propertyProvider)
        throws BadQueryException
    {
        this.query = (XBasicQuery) query;
        this.propertyProvider = propertyProvider;
        slideAccessor = (ISlideAccessor)query.getStore();
    }
    
    /**
     * Method getPropertyProvider
     *
     * @return   a PropertyProvider
     *
     */
    public PropertyProvider getPropertyProvider() {
        return propertyProvider;
    }
    
    /**
     * Method getQuery
     *
     * @return   an IBasicQuery
     *
     */
    public IBasicQuery getQuery() {
        return query;
    }
}

