/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/search/XRequestedPropertiesImpl.java,v 1.3 2004/07/30 06:51:58 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:51:58 $
 *
 * ====================================================================
 *
 * 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 java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.slide.common.PropertyName;
import org.apache.slide.common.PropertyParseException;
import org.apache.slide.common.RequestedPropertiesImpl;
import org.apache.slide.common.RequestedProperty;
import org.apache.slide.common.RequestedPropertyImpl;
import org.apache.slide.search.BadQueryException;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.datastore.search.XLiterals;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Element;

/**
 * A RequestedProperties container, that may also hold Tamino specific
 * properties (xpath for example)
 *
 * @author <a href="mailto:martin.wallmer@softwareag.com">Martin Wallmer</a>
 * @version $Revision: 1.3 $
 */
public class XRequestedPropertiesImpl extends RequestedPropertiesImpl {
    
    private XBasicQueryImpl query;
    
    /** all xpath properties of this query */
    private List xpathProperties = new ArrayList();
    
    /**
     * constructor
     *
     * @param propElement the <prop> element describing this requested resource
     * @param query the query this property belongs to
     */
    public XRequestedPropertiesImpl (Element propElement, XBasicQueryImpl query)
        throws PropertyParseException {
        this.query = query;
        add (propElement);
    }
    
    
    /**
     * Creates a RequestedProperty from the given parameters. This method
     * may be overwritten by subclasses in order to create appropriate
     * implementations of RequestedProperty.
     *
     * @param      propElement  the Element describing this property
     *
     * @return     the created RequestedProperty.
     */
    protected RequestedProperty createRequestedProperty (Element propElement)
        throws PropertyParseException {
        RequestedProperty result = null;
        String uri  = propElement.getNamespace().getURI();
        String name = propElement.getName ();
                
        if (uri.equals ("DAV:") && name.equals ("property")) {
            name = propElement.getAttributeValue ("name");
        }
        
        String namespaceUri = propElement.getNamespace().getURI();
        String text = propElement.getText();
        List attributes = propElement.getAttributes();
        
        try {
            if (namespaceUri.equals (XGlobals.TAMINO_NAMESPACE_URI)
                && name.equals (XLiterals.XPATH))
            {
                
                Attribute isUnwrapAttr = propElement.getAttribute (XLiterals.XPATH_UNWRAP);
                boolean isUnwrap =
                    isUnwrapAttr == null ?
                    false : isUnwrapAttr.getBooleanValue();
                
                result = createXPathProperty(propElement, attributes, text, result, isUnwrap);
                xpathProperties.add (result);
            }
                
            else
            {
                PropertyName propName = new PropertyName (name, namespaceUri);
                
                String xPath = query.getXPathPropertyMapper().getMapping (propName);
                if (xPath != null)
                {
                    Attribute nameAttr = new Attribute ("name", propName.getName());
                    attributes.add (nameAttr);
                    result = createXPathProperty (propElement, attributes,
                                                  xPath, result,
                                                  true);
                    
                    xpathProperties.add (result);
                }
                    
                else
                {
                    result = new RequestedPropertyImpl(name, namespaceUri);
                }
            }
        }
        catch (BadQueryException e) {
            throw new PropertyParseException (e.getMessage(), e);
        }
        catch (DataConversionException e) {
            throw new PropertyParseException (e.getMessage(), e);
        }
        
        return result;
    }
    
    private RequestedProperty createXPathProperty (Element propElement,
                                                   List attributes,
                                                   String text,
                                                   RequestedProperty result,
                                                   boolean isUnwrap)
        throws BadQueryException
    {
        Attribute nsAttr = propElement.getAttribute (XLiterals.XPATH_NAMESPACE);
        XPathContentQuery contentQuery = query.getContentQuery (attributes, text);
        result = new XPathProperty (contentQuery);
        
        if (nsAttr != null) {
            ((XPathProperty)result).setNamespace(nsAttr.getValue());
        }
        
        ((XPathProperty)result).setUnwrap (isUnwrap);
        return result;
    }
    
    /**
     * Adds a List of RequestedProperty from a <code>&lt;DAV:prop&gt;</code>
     * or <code>&lt;DAV:allprop&gt;</code>.
     *
     * @param      propElement  <code>&lt;DAV:prop&gt;</code> or
     *                          <code>&lt;DAV:allprop&gt;</code>.
     *
     * @throws      PropertyParseException  if parsing the property fails for any reason.
     */
    public void add (Element propElement) throws PropertyParseException {
        
        String uri  = propElement.getNamespace().getURI();
        String name = propElement.getName ();
        
        if (name.equals ("allprop") && uri.equals ("DAV:")) {
            isAllProp = true;
            
            
            // WAM it would be nice to add nixe-meta to allProp in case of
            // nixeEnabled, however this must be implemented in the WebDAV layer.
            // It would be no good idea to have xdav specific stuff in the
            // webdavlayer.
//            boolean isNixeEnabled = true;
//            if (isNixeEnabled) {
//                Element nixeMetaElement = new Element
//                  (XGlobals.NIXE_META, XGlobals.TAMINO_NAMESPACE_URI);
//
//
//            }
            
        }
            
        else {
            Iterator it = propElement.getChildren().iterator();
            
            while (it.hasNext()) {
                Element prop = (Element)it.next();
                addProperty (createRequestedProperty(prop));
            }
        }
    }
    
    
    /**
     * Method hasXPathProperties
     *
     * @return   true, if any xPath result is requested
     *
     */
    public boolean hasXPathProperties () {
        return xpathProperties.size()  > 0;
    }
    
    /**
     * Method xPathIterator
     *
     * @return   an Iterator for all xPath properties
     *
     */
    public Iterator xPathIterator () {
        return xpathProperties.iterator();
    }
}


