#region License

/*
 * Copyright (C) 2002-2008 the original author or authors.
 *
 * 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.
 */

#endregion

#region Imports

using System;
using System.Collections;
using System.Collections.Generic;
using Spring.Collections;

#endregion

namespace Spring.Collections
{
    /// <summary>
    /// A collection designed for holding elements prior to processing.
    /// </summary>
    /// <remarks>
    /// <p>
    /// Besides basic <see cref="ICollection"/> operations,
    /// queues provide additional insertion, extraction, and inspection
    /// operations.
    /// </p>
    /// <p>
    /// Each of these methods exists in two forms: one throws
    /// an exception if the operation fails, the other returns a special
    /// value (either <see lang="null"/> or <see lang="false"/>, depending on the
    /// operation). The latter form of the insert operation is designed
    /// specifically for use with capacity-restricted <see cref="IQueue"/>
    /// implementations; in most implementations, insert operations cannot
    /// fail.
    /// </p>
    /// <p>
    /// Queues typically, but do not necessarily, order elements in a
    /// FIFO (first-in-first-out) manner. Among the exceptions are
    /// priority queues, which order elements according to a supplied
    /// comparator, or the elements' natural ordering, and LIFO queues (or
    /// stacks) which order the elements LIFO (last-in-first-out).
    /// Whatever the ordering used, the head of the queue is that
    /// element which would be removed by a call to
    /// <see cref="Spring.Collections.IQueue.Remove"/> or
    /// <see cref="Spring.Collections.IQueue.Poll"/>. In a FIFO queue, all new
    /// elements are inserted at the tail of the queue. Other kinds of queues may
    /// use different placement rules. Every <see cref="IQueue"/> implementation
    /// must specify its ordering properties.
    /// </p>
    /// <p>
    /// The <see cref="Spring.Collections.IQueue.Offer(object)"/> method inserts an
    /// element if possible, otherwise returning <see lang="false"/>. This differs from the 
    /// <see cref="Spring.Collections.IQueue.Add(object)"/> method, which can fail to
    /// add an element only by throwing an exception. The
    /// <see cref="Spring.Collections.IQueue.Offer(object)"/> method is designed for
    /// use when failure is a normal, rather than exceptional occurrence, for example,
    /// in fixed-capacity (or "bounded" queues.
    /// </p>
    /// <p>
    /// The <see cref="Spring.Collections.IQueue.Remove()"/>
    /// <see cref="Spring.Collections.IQueue.Poll()"/> methods remove and
    /// return the head of the queue. Exactly which element is removed from the
    /// queue is a function of the queue's ordering policy, which differs from
    /// implementation to implementation. The
    /// <see cref="Spring.Collections.IQueue.Remove()"/> and
    /// <see cref="Spring.Collections.IQueue.Poll()"/> methods differ only in their
    /// behavior when the queue is empty: the
    /// <see cref="Spring.Collections.IQueue.Remove()"/> method throws an exception,
    /// while the <see cref="Spring.Collections.IQueue.Poll()"/> method returns
    /// <see lang="null"/>.
    /// </p>
    /// <p>
    /// The <see cref="Spring.Collections.IQueue.Element()"/> and
    /// <see cref="Spring.Collections.IQueue.Peek()"/> methods return, but do
    /// not remove, the head of the queue.
    /// </p>
    /// <p>
    /// The <see cref="IQueue"/> interface does not define the blocking queue
    /// methods, which are common in concurrent programming.
    /// </p>
    /// <p>
    /// <see cref="IQueue"/> implementations generally do not allow insertion
    /// of <see lang="null"/> elements, although some implementations, such as
    /// a linked list, do not prohibit the insertion of <see lang="null"/>.
    /// Even in the implementations that permit it, <see lang="null"/> should
    /// not be inserted into a <see cref="IQueue"/>, as <see lang="null"/> is also
    /// used as a special return value by the
    /// <see cref="Spring.Collections.IQueue.Poll()"/> method to
    /// indicate that the queue contains no elements.
    /// </p>
    /// <p>
    /// <see cref="IQueue"/> implementations generally do not define
    /// element-based versions of methods <see cref="System.Object.Equals(object)"/> 
    /// and <see cref="System.Object.GetHashCode()"/>, but instead inherit the
    /// identity based versions from the class object, because element-based equality
    /// is not always well-defined for queues with the same elements but different
    /// ordering properties.
    /// </p>
    /// <p>
    /// Based on the back port of JCP JSR-166.
    /// </p>
    /// </remarks>
    /// <author>Doug Lea</author>
    /// <author>Griffin Caprio (.NET)</author>
    public interface IQueue : ICollection
    {
        /// <summary> 
        /// Inserts the specified element into this queue if it is possible to do so
        /// immediately without violating capacity restrictions, returning
        /// <see lang="true"/> upon success and throwing an
        /// <see cref="System.InvalidOperationException"/> if no space is
        /// currently available.
        /// </summary>
        /// <param name="objectToAdd">
        /// The element to add.
        /// </param>
        /// <returns> 
        /// <see lang="true"/> if successful.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// If the element cannot be added at this time due to capacity restrictions.
        /// </exception>
        /// <exception cref="InvalidCastException">
        /// If the class of the supplied <paramref name="objectToAdd"/> prevents it
        /// from being added to this queue.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the specified element is <see lang="null"/> and this queue does not
        /// permit <see lang="null"/> elements.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// If some property of the supplied <paramref name="objectToAdd"/> prevents
        /// it from being added to this queue.
        /// </exception>
        bool Add(object objectToAdd);

        /// <summary> 
        /// Inserts the specified element into this queue if it is possible to do
        /// so immediately without violating capacity restrictions.
        /// </summary>
        /// <remarks>
        /// <p>
        /// When using a capacity-restricted queue, this method is generally
        /// preferable to <see cref="Spring.Collections.IQueue.Add(object)"/>,
        /// which can fail to insert an element only by throwing an exception.
        /// </p>
        /// </remarks>
        /// <param name="objectToAdd">
        /// The element to add.
        /// </param>
        /// <returns>
        /// <see lang="true"/> if the element was added to this queue.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// If the element cannot be added at this time due to capacity restrictions.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="objectToAdd"/> is
        /// <see lang="null"/>.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// If some property of the supplied <paramref name="objectToAdd"/> prevents
        /// it from being added to this queue.
        /// </exception>
        bool Offer(object objectToAdd);

        /// <summary> 
        /// Retrieves and removes the head of this queue.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This method differs from <see cref="Spring.Collections.IQueue.Poll()"/>
        /// only in that it throws an exception if this queue is empty.
        /// </p>
        /// </remarks>
        /// <returns> 
        /// The head of this queue
        /// </returns>
        /// <exception cref="Spring.Collections.NoElementsException">if this queue is empty</exception>
        object Remove();

        /// <summary> 
        /// Retrieves and removes the head of this queue,
        /// or returns <see lang="null"/> if this queue is empty.
        /// </summary>
        /// <returns> 
        /// The head of this queue, or <see lang="null"/> if this queue is empty.
        /// </returns>
        object Poll();

        /// <summary> 
        /// Retrieves, but does not remove, the head of this queue.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This method differs from <see cref="Spring.Collections.IQueue.Peek()"/>
        /// only in that it throws an exception if this queue is empty.
        /// </p>
        /// </remarks>
        /// <returns> 
        /// The head of this queue.
        /// </returns>
        /// <exception cref="Spring.Collections.NoElementsException">If this queue is empty.</exception>
        object Element();

        /// <summary> 
        /// Retrieves, but does not remove, the head of this queue,
        /// or returns <see lang="null"/> if this queue is empty.
        /// </summary>
        /// <returns> 
        /// The head of this queue, or <see lang="null"/> if this queue is empty.
        /// </returns>
        object Peek();

        /// <summary>
        /// Returns <see lang="true"/> if there are no elements in the <see cref="IQueue"/>, <see lang="false"/> otherwise.
        /// </summary>
        bool IsEmpty { get; }
    }
}
namespace Spring.Collections.Generic
{
    /// <summary>
    /// A collection designed for holding elements prior to processing.
    /// </summary>
    /// <remarks>
    /// <para>
    /// Besides basic <see cref="ICollection{T}"/> operations, queues provide 
    /// additional insertion, extraction, and inspection operations. 
    /// </para>
    /// <para>
    /// Each of these methods exists in two forms: one throws an exception if 
    /// the operation fails, the other returns a special value. The latter 
    /// form of the insert operation is designed specifically for use with 
    /// capacity-restricted <see cref="IQueue{T}"/> implementations; in most 
    /// implementations, insert operations cannot fail. 
    /// </para>
    /// <para>
    /// Queues typically, but do not necessarily, order elements in a FIFO 
    /// (first-in-first-out) manner. Among the exceptions are priority queues, 
    /// which order elements according to a supplied comparator, or the 
    /// elements' natural ordering, and LIFO queues (or stacks) which order 
    /// the elements LIFO (last-in-first-out). Whatever the ordering used,
    ///  the head of the queue is that element which would be removed by a call 
    /// to <see cref="Remove"/> or <see cref="Poll"/>. In a FIFO queue, all new 
    /// elements are inserted at the tail of the queue. Other kinds of queues 
    /// may use different placement rules. Every <see cref="IQueue{T}"/> 
    /// implementation must specify its ordering properties. 
    /// </para>
    /// <para>
    /// The <see cref="Offer"/> method inserts an element if possible, 
    /// otherwise returning <c>false</c>. This differs from the 
    /// <see cref="ICollection{T}.Add"/> method, which can fail to add an 
    /// element only by throwing an exception. The <see cref="Offer"/> method 
    /// is designed for use when failure is a normal, rather than exceptional 
    /// occurrence, for example, in fixed-capacity (or "bounded") queues. 
    /// </para>
    /// <para>
    /// The <see cref="Remove"/> and <see cref="Poll"/> methods remove and 
    /// return the head of the queue. Exactly which element is removed from 
    /// the queue is a function of the queue's ordering policy, which differs 
    /// from implementation to implementation. The <see cref="Remove"/> and Poll
    /// <see cref="Poll"/> methods differ only in their behavior when the queue 
    /// is empty: the <see cref="Remove"/> method throws an exception, while 
    /// the <see cref="Poll"/> method returns <c>false</c>. 
    /// </para>
    /// <para>
    /// The <see cref="Element"/> and <see cref="Peek"/> methods return, but do 
    /// not remove, the head of the queue. 
    /// </para>
    /// <para>
    /// The <see cref="IQueue{T}"/> interface does not define the blocking queue 
    /// methods, which are common in concurrent programming. 
    /// </para>
    /// <para>
    /// <see cref="IQueue{T}"/> implementations generally do not define 
    /// element-based versions of methods <see cref="object.Equals(object)"/> 
    /// and  <see cref="object.GetHashCode"/>, but instead inherit the identity 
    /// based versions from the class object, because element-based equality is 
    /// not always well-defined for queues with the same elements but different 
    /// ordering properties. 
    /// </para>
    /// <para>
    /// Based on the back port of JCP JSR-166.
    /// </para>
    /// </remarks>
    /// <typeparam name="T">The type of the elements in the queue.</typeparam>
    /// <author>Doug Lea</author>
    /// <author>Griffin Caprio (.NET)</author>
    /// <author>Kenneth Xu</author>
    public interface IQueue<T> : ICollection<T>
    {
        /// <summary>
        /// Gets the remaining capacity of a bounded queue or
        /// <see cref="int.MaxValue"/> if the queue is un-bounded.
        /// </summary>
        int RemainingCapacity { get; }

        /// <summary>
        /// Retrieves, but does not remove, the head of this queue. 
        /// </summary>
        /// <remarks>
        /// This method differs from <see cref="Peek(out T)"/> in that it throws an 
        /// exception if this queue is empty. 
        /// </remarks>
        /// <returns>The head of this queue.</returns>
        /// <exception cref="NoElementsException">
        /// If this queue is empty.
        /// </exception>
        T Element();

        /// <summary>
        /// Inserts the specified element into this queue if it is possible to 
        /// do so immediately without violating capacity restrictions. 
        /// </summary>
        /// <remarks>
        /// When using a capacity-restricted queue, this method is generally 
        /// preferable to <see cref="ICollection{T}.Add"/>, which can fail to 
        /// insert an element only by throwing an exception. 
        /// </remarks>
        /// <param name="element">The element to add.</param>
        /// <returns>
        /// <c>true</c> if the element was added to this queue. Otherwise 
        /// <c>false</c>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// If the <paramref name="element"/> is <c>null</c> and the queue 
        /// implementation doesn't allow <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If some property of the supplied <paramref name="element"/> 
        /// prevents it from being added to this queue. 
        /// </exception>
        bool Offer(T element);

        /// <summary>
        /// Retrieves, but does not remove, the head of this queue into out
        /// parameter <paramref name="element"/>.
        /// </summary>
        /// <param name="element">
        /// The head of this queue. <c>default(T)</c> if queue is empty.
        /// </param>
        /// <returns>
        /// <c>false</c> is the queue is empty. Otherwise <c>true</c>.
        /// </returns>
        bool Peek(out T element);

        /// <summary>
        /// Retrieves and removes the head of this queue into out parameter
        /// <paramref name="element"/>. 
        /// </summary>
        /// <param name="element">
        /// Set to the head of this queue. <c>default(T)</c> if queue is empty.
        /// </param>
        /// <returns>
        /// <c>false</c> if the queue is empty. Otherwise <c>true</c>.
        /// </returns>
        bool Poll(out T element);

        /// <summary>
        /// Retrieves and removes the head of this queue. 
        /// </summary>
        /// <returns>The head of this queue</returns>
        /// <exception cref="NoElementsException">
        /// If this queue is empty.
        /// </exception>
        T Remove();
    }
}