/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/RequestedPropertiesImpl.java,v 1.17 2004/07/28 09:38:17 ib Exp $
 * $Revision: 1.17 $
 * $Date: 2004/07/28 09:38:17 $
 *
 * ====================================================================
 *
 * 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.common;

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

import org.apache.slide.content.NodeProperty;
import org.jdom.Element;


/**
 * Holds one property as part of the SELECT element.
 *
 * @version $Revision: 1.17 $
 */
public class RequestedPropertiesImpl implements RequestedProperties {
    
    protected boolean isAllProp = false;
    protected List propertyList = new ArrayList ();
    
    /**
     * Default constructor
     */
    public RequestedPropertiesImpl() {}

    /**
     * Constructs 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 RequestedPropertiesImpl (Element propElement) throws PropertyParseException {
        add(propElement);
    }
    
    
    /**
     * 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 prefix  = propElement.getNamespace().getPrefix();
        String name = propElement.getName ();
        
        if (name.equals ("allprop") && uri.equals ("DAV:")) {
            isAllProp = true;
        }
        else {
            Iterator it = propElement.getChildren().iterator();
            
            while (it.hasNext()) {
                Element prop = (Element)it.next();
                uri  = prop.getNamespace().getURI();
                prefix = prop.getNamespace().getPrefix();
                name = prop.getName ();
                if (uri.equals ("DAV:") && name.equals ("property")) {
                    name = prop.getAttributeValue ("name");
                    if( prop.getAttributeValue ("namespace") != null ) {
                        uri = prop.getAttributeValue ("namespace");
                        prefix = ""; // will be ignored anyway
                    }
                }

                addProperty (createRequestedProperty(name,
                                                     prefix,
                                                     uri,
                                                     prop.getContent()));
            }
        }
    }
    
    /**
     * Creates a RequestedProperty from the given parameters. This method
     * may be overwritten by subclasses in order to create appropriate
     * implementations of RequestedProperty.
     *
     * @param      name       the name of the propery.
     * @param      namespacePrefix  the namespace prefix of the propery.
     * @param      namespaceUri     the namespace URI of the propery.
     * @param      text       the text of the propery element.
     * @param      children   the children of the propery element.
     *
     * @return     the created RequestedProperty.
     *
     * @throws      PropertyParseException  if parsing the property fails for any reason.
     */
    protected RequestedProperty createRequestedProperty(String name, String namespacePrefix, String namespaceUri, List content) throws PropertyParseException {
        return new RequestedPropertyImpl(name, namespaceUri);
    }
    
    /**
     * Returns an iterator for all selected properties
     *
     * @return   an Iterator
     */
    public Iterator iterator () {
        if (isAllProp == true)
            throw new IllegalStateException ();
        
        return propertyList.iterator();
    }
    
    
    // interface methods
    
    /**
     * Method getRequestedProperties
     *
     * @return   an Iterator to retrieve all RequestedProperty items
     * @throws   IllegalStateException when isAllProp == true
     */
    public Iterator getRequestedProperties() {
        if (isAllProp)
            throw new IllegalStateException ();
        
        return propertyList.iterator();
    }
    
    /**
     * Method isAllProp
     *
     * @return   true, if all properties are requested
     *
     */
    public boolean isAllProp()  {
        return isAllProp;
    }

    /**
     * Set the isAllProp member.
     */
    public void setIsAllProp(boolean isAllProp) {
        this.isAllProp = isAllProp;
    }
    
    /**
     * Checks, if the property identified by name and namespace, is requested
     *
     * @param    name          name of the property to be checked
     * @param    namespace     namespace of the property to be checked
     *
     * @return   true, if property is requested
     */
    public boolean contains (String name, String namespace) {
        if (isAllProp)
            return true;
        
        RequestedProperty prop = new RequestedPropertyImpl (name, namespace);
        return propertyList.contains (prop);
    }
    
    /**
     * Checks, if the NodeProperty is a RequestedProperty
     *
     * @param    property    NodeProperty to be checked
     *
     * @return   true, if property is requested
     *
     */
    public boolean contains (NodeProperty property) {
        if (isAllProp)
            return true;
        
        RequestedProperty prop =
            new RequestedPropertyImpl (property.getName(),
                                       property.getNamespace());
        return propertyList.contains (prop);
    }
    
    
//    /**
//   * Method equals
//   *
//   * @param    o                   an Object
//   *
//   * @return   true if equal
//   */
//    public boolean equals (Object o) {
//      if (! (o instanceof RequestedProperties))
//          return false;
//
//      RequestedProperties p = (RequestedProperties) o;
//
//      RequestedProperties sThis, sOther;
//
//      Iterator it = p.iterator();
//      int size = propertyList.size();
//
//      for (int i = 0; i < size; i++) {
//          if (!it.hasNext())
//              return false;
//
//          sThis = (SelectedProperty) propertyList.get (i);
//          sOther = (SelectedProperty) it.next();
//
//          if (!sThis.equals(sOther))
//              return false;
//      }
//      if (it.hasNext())
//          return false;
//
//      return true;
//    }
//
    
    /**
     * Method toString
     *
     * @return   string representation
     */
    public String toString () {
        Iterator it = iterator();
        StringBuffer sb = new StringBuffer();
        
        while (it.hasNext()) {
            sb.append (((RequestedProperty)it.next()).toString());
            if (it.hasNext())
                sb.append (", ");
        }
        return sb.toString();
    }
    
    
    /**
     * Method addSelectedProperty
     *
     * @param    prop                a  SelectedProperty
     */
    public void addProperty (RequestedProperty prop) {
        if (isAllProp == true)
            throw new IllegalStateException ();
        
        propertyList.add (prop);
    }
}

