/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/search/basic/expression/ComparedProperty.java,v 1.6 2004/12/07 17:52:20 luetzkendorf Exp $
 * $Revision: 1.6 $
 * $Date: 2004/12/07 17:52:20 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 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.expression;
import org.apache.slide.search.basic.*;

import org.jdom.Element;
import org.apache.slide.search.InvalidQueryException;
import org.apache.slide.content.NodeProperty.NamespaceCache;
import org.apache.slide.common.PropertyName;

import java.util.List;
import java.util.ArrayList;

/**
 * represents a property, that is to be compared against a literal
 *
 * @version $Revision: 1.6 $
 */
public class ComparedProperty {
    
    /** a list of known properties, that have a numeric type */
    private static final List NUMERIC_PROPERTIES = new ArrayList ();
    static {
        NUMERIC_PROPERTIES.add (PropertyName.CONTENT_LENGTH);
    }
    
    /** the property's value <literal> */
    protected String literal;
    public void setLiteral (String literal) {
        this.literal = literal;
    }
    public String getLiteral() {
        return literal;
    }
    
    /** the property name <prop> */
    protected String property;
    public void setProperty (String p) {
        property = p;
    }
    public String getProperty() {
        return property;
    }
    
    /** the property's namespace */
    protected String propNamespace;
    public void setPropNamespace (String p) {
        propNamespace = p;
    }
    public String getPropNamespace() {
        return propNamespace;
    }
    
    /** indicate, if compare should be casesensitive */
    protected boolean casesensitive = true;
    public boolean getCasesensitive() {
        return casesensitive;
    }
    
    
    /**
     * allows to create a ComparedProperty without parameters.
     * property, namespace and literal msut be set with set methods
     */
    public ComparedProperty () {
    }
    
    /**
     * Creates a ComparedProperty with the given <code>propName</code>
     * and <code>propNamespace</code>.
     *
     * @param      property       the property.
     * @param      propNamespace  the property namespace.
     */
    public ComparedProperty (String property, String propNamespace) {
        setProperty(property);
        setPropNamespace(propNamespace);
    }
    
    
    /**
     * Creates a compare expression according to Element e
     *
     * @param e jdom element, that describes the expression
     *
     */
    public ComparedProperty (Element e) throws InvalidQueryException {
        this (e, true);
    }
    
    /**
     * Creates a compare expression according to Element e.
     *
     * @param e jdom element, that describes the expression
     * @param withLiteral indicates, if a literal is supplied or not (for example:
     *        iscollectionhas no literal)
     *
     */
    public ComparedProperty (Element e, boolean withLiteral) throws InvalidQueryException {
        setProperty(e);
        if (withLiteral) {
            literal  = getLiteral (e);
        }
    }
    
    /**
     * Indicates, if this property shall be treated as numeric in compare
     *
     * @return   a boolean
     *
     */
    public boolean isNumeric () {
        return NUMERIC_PROPERTIES.contains (PropertyName.getPropertyName(
                property, propNamespace));
    }
    
    /**
     * extracts the property name of this expression
     *
     * @param    e                   an Expression
     *
     * @return   the property name as string
     *
     * @throws   InvalidQueryException if no or more than one
     *           property was supplied
     *
     */
    private void setProperty (Element e) throws InvalidQueryException {
        String casesensAttr = e.getAttributeValue (Literals.CASESENSITIVE, NamespaceCache.DEFAULT_NAMESPACE);
        if (casesensAttr != null) {
            if (casesensAttr.equals ("1"))
                casesensitive = true;
            else if (casesensAttr.equals ("0"))
                casesensitive = false;
            else
                throw new InvalidQueryException ("casesensitive must be either \"0\" or \"1\"");
        }
        
        Element propListElement = e.getChild (Literals.PROP, NamespaceCache.DEFAULT_NAMESPACE);
        if (propListElement == null)
            throw new InvalidQueryException
                ("No property element supplied");
        
        List propList = propListElement.getChildren();
        
        if (propList.size() != 1)
            throw new InvalidQueryException
                ("Expected exactly 1 prop element, found " + propList.size());
        
        Element propElement = ((Element)propList.get(0));
        property = propElement.getName();
        propNamespace = propElement.getNamespace().getURI();
    }
    /**
     * extracs the value of <literal> of an expression
     *
     * @param    e                   an Expression
     *
     * @return   the literal as string
     *
     * @throws   InvalidQueryException if no <literal> found in e
     *
     */
    private String  getLiteral(Element e) throws InvalidQueryException {
        Element lit = e.getChild (Literals.LITERAL, NamespaceCache.DEFAULT_NAMESPACE);
        if (lit == null)
            throw new InvalidQueryException
                ("No literal element supplied");
        
        return lit.getText ();
    }
}

