/**********************************************************************************
 * $URL: https://source.sakaiproject.org/svn/calendar/tags/sakai_2-3-1/calendar-impl/impl/src/java/org/sakaiproject/calendar/impl/ExclusionRecurrenceRule.java $
 * $Id: ExclusionRecurrenceRule.java 8050 2006-04-20 17:39:55Z ggolden@umich.edu $
 ***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
 * 
 * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
 * 
 * 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.sakaiproject.calendar.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.TimeZone;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.calendar.api.RecurrenceRule;
import org.sakaiproject.time.api.Time;
import org.sakaiproject.time.api.TimeRange;
import org.sakaiproject.time.cover.TimeService;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* <p>ExclusionRecurrenceRule is a rule which excludes specific time ranges from a list of instances.</p>
*/
public class ExclusionRecurrenceRule
	implements RecurrenceRule
{
	/** Our logger. */
	private static Log M_log = LogFactory.getLog(ExclusionRecurrenceRule.class);

	/** The list of TimeRange values to exclude. */
	protected List m_ranges = null;

	/**
	* Construct.
	*/
	public ExclusionRecurrenceRule()
	{
		m_ranges = new Vector();

	}	// ExclusionRecurrenceRule

	/**
	* Construct with these limits.
	* @param ranges The list of ranges to exclude
	*/
	public ExclusionRecurrenceRule(List ranges)
	{
		m_ranges = new Vector(ranges);

	}	// ExclusionRecurrenceRule

	/**
	* Access the List of TimeRange values excluded.
	* @return the List of TimeRange values excluded.
	*/
	public List getRanges() { return m_ranges; }

	/**
	* Take values from this xml element
	* @param el The xml element.
	*/
	public void set(Element el)
	{
		// the children (time ranges)
		NodeList children = el.getChildNodes();
		final int length = children.getLength();
		for(int i = 0; i < length; i++)
		{
			Node child = children.item(i);
			if (child.getNodeType() != Node.ELEMENT_NODE) continue;
			Element element = (Element)child;

			// look for a time range
			if (element.getTagName().equals("range"))
			{
				try
				{
					m_ranges.add(TimeService.newTimeRange(element.getAttribute("range")));
				}
				catch (Exception e) { M_log.warn("set: while reading time range: " + e); }
			}
		}

	}	// set

	/**
	* Serialize the resource into XML, adding an element to the doc under the top of the stack element.
	* @param doc The DOM doc to contain the XML (or null for a string return).
	* @param stack The DOM elements, the top of which is the containing element of the new "resource" element.
	* @return The newly added element.
	*/
	public Element toXml(Document doc, Stack stack)
	{
		// add the "rule" element to the stack'ed element
		Element rule = doc.createElement("ex-rule");
		((Element)stack.peek()).appendChild(rule);

		// set the class name - old style for CHEF 1.2.10 compatibility
		rule.setAttribute("class", "org.chefproject.osid.calendar.ExclusionRecurrenceRule");

		// set the rule class name w/o package, for modern usage
		rule.setAttribute("name", "ExclusionRecurrenceRule");

		// set the ranges
		for (Iterator iRanges = m_ranges.iterator(); iRanges.hasNext();)
		{
			TimeRange range = (TimeRange) iRanges.next();

			Element rangeElement = doc.createElement("range");
			rule.appendChild(rangeElement);
			rangeElement.setAttribute("range", range.toString());
		}

		return rule;

	}	// toXml

	/**
	* Return a List of all RecurrenceInstance objects generated by this rule within the given time range, based on the
	* prototype first range, in time order.
	* @param prototype The prototype first TimeRange.
	* @param range A time range to limit the generated ranges.
	* @return a List of RecurrenceInstance generated by this rule in this range.
	*/
	public List generateInstances(TimeRange prototype, TimeRange range, TimeZone timeZone)
	{
		return new Vector();

	}	// generateInstances

	/**
	* Remove from the ranges list any RecurrenceInstance excluded by this rule.
	* @param ranges The list (RecurrenceInstance) of ranges.
	*/
	public void excludeInstances(List ranges)
	{
		Vector rv = new Vector();
		
		for (Iterator iInstances = ranges.iterator(); iInstances.hasNext();)
		{
			RecurrenceInstance ri = (RecurrenceInstance) iInstances.next();

			if (!m_ranges.contains(ri.getRange()))
			{
				rv.add(ri);
			}
		}

		ranges.clear();
		ranges.addAll(rv);

	}

	/**
	 * {@inheritDoc}
	 */
	public String getFrequencyDescription()
	{
		return "x";
	}

	/**
	 * {@inheritDoc}
	 */
	public Time getUntil()
	{
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	public int getCount()
	{
		return 0;
	}

	/**
	 * {@inheritDoc}
	 */
	public int getInterval()
	{
		return 0;
	}

}	// ExclusionRecurrenceRule



