/*
 ************************************************************************
 *
 * Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
 *
 * Copyright in this software belongs to C&C Research Laboratories,
 * Rathausallee 10, 53757 Sankt Augustin, Germany.
 *
 * This software may not be used, sold, licensed, transferred, copied
 * or reproduced in whole or in part in any manner or form or in or
 * on any media by any person other than in accordance with the terms
 * of the Licence Agreement supplied with the software, or otherwise
 * without the prior written consent of the copyright owners.
 *
 * This software is distributed WITHOUT ANY WARRANTY, without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE, except where stated in the Licence Agreement supplied with
 * the software.
 *
 *  Created By :           G.A. Kohring
 *  Created for Project :  GEMSS (IST-2001-37153)
 *
 ************************************************************************
 *
 */

package de.nece.ccrle.util;

import java.util.Set;
import java.util.Collection;
import java.util.Iterator;
import eu.gemss.components.providers.Registrable;

/**
 * A set which exploits an element's
 * <code>Registrable</code> interface whenever 
 * the element is added or removed from 
 * the register. If the element does not implement <code>Registrable</code>, 
 * then the behavior is the same as that of an ordinary <code>Set</code>.
 *
 * @author Greg Kohring
 */
public interface Register extends Set {

    /**
     * Overides the <tt>add</tt> method from <tt>Set</tt> to exploit elements
     * implementing the <tt>Registrable</tt> interface.
     * When the specified element implements <tt>Registrable</tt>,
     * then the element's <tt>onRegistration</tt> method is
     * called. If the <tt>onRegistration</tt> method
     * returns <tt>false</tt>, then the specified element is not
     * added to the register.
     *
     * @param o element to be added to this register.
     * @return <tt>true</tt> if the element is successfully added to the
     *         register and <tt>false</tt> if the register remains unchanged.
     *         (Note: The register may remain unchanged if the element already
     *          exists in the register. Use the <tt>contains</tt> method from
     *          <tt>Set</tt> to distinguish between these two cases.)
     *
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this register.
     * @throws NullPointerException if the specified element is null and this
     *         register does not support null elements.
     * @throws IllegalArgumentException if some aspect of the specified
     *         element prevents it from being added to this register.
     */
    public boolean add( Object o );

                                                                                
    /**
     * Overides the <tt>remove</tt> method from <tt>Set</tt> to exploit 
     * elements implementing the <tt>Registrable</tt> interface.
     * When the specified element implements <tt>Registrable</tt>,
     * then the element's <tt>onDeregistration</tt> method is
     * called before it is removed from the register. 
     *
     * @param o object to be removed from this register, if present.
     * @return <tt>true</tt> if the register is modified as a result 
     *      of this operation.
     * @throws ClassCastException if the type of the specified element
     *         is incompatible with this register (optional).
     * @throws NullPointerException if the specified element is null and this
     *         register does not support null elements (optional).
     */
    public boolean remove( Object o );

    /**
     * Overides the <tt>addAll</tt> method from <tt>Set</tt> to exploit 
     * elements implementing the <tt>Registrable</tt> interface.
     * When any of the elements in the specified <tt>Collection</tt> implement 
     * <tt>Registrable</tt>,
     * then that element's <tt>onRegistration</tt> method is
     * called. If the <tt>onRegistration</tt> method
     * returns <tt>false</tt>, then that element is not added to the register.
     *
     *
     * @param c collection whose elements are to be added to this register.
     * @return <tt>true</tt> if this register changed as a result of the call.
     *
     * @throws ClassCastException if the class of some element of the
     *        specified collection prevents it from being added to this
     *        register.
     * @throws NullPointerException if the specified collection contains one
     *           or more null elements and this register does not support null
     *           elements, or if the specified collection is <tt>null</tt>.
     * @throws IllegalArgumentException if some aspect of some element of the
     *        specified collection prevents it from being added to this
     *        register.
     * @see #add(Object)
     */
    public boolean addAll(Collection c);

    /**
     * Overides the <tt>removeAll</tt> method from <tt>Set</tt> to exploit 
     * elements implementing the <tt>Registrable</tt> interface.
     * When the specified element implements <tt>Registrable</tt>,
     * then the element's <tt>onDeregistration</tt> method is
     * called before it is removed from the register. 
     *
     * @param  c collection that defines which elements will be removed from
     *           this register.
     * @return true if the register is modified as a result of this operation.
     *
     * @throws ClassCastException if the types of one or more elements in this
     *            set are incompatible with the specified collection
     *            (optional).
     * @throws NullPointerException if this set contains a null element and
     *            the specified collection does not support null elements
     *            (optional).
     * @throws NullPointerException if the specified collection is
     *           <tt>null</tt>.
     * @see    #remove(Object)
     */
    public boolean removeAll(Collection c);

    /**
     * Overides the <tt>clear</tt> method from <tt>Set</tt> to exploit 
     * elements implementing the <tt>Registrable</tt> interface.
     * If any element implements <tt>Registrable</tt>,
     * then that element's <tt>onDeregistration</tt> method is
     * called before it is removed from the register.
     *
     */
    public void clear();

    /**
     * Overides the <tt>clear</tt> method from <tt>Set</tt> to exploit 
     * elements implementing the <tt>Registrable</tt> interface.
     * More concretely, the Iterator's <tt>remove</tt> method is 
     * modified to call an element's <tt>onDeregistration</tt> 
     * method prior to removal from the register.
     *
     * @return an iterator over the elements in this register.
     */
    public Iterator iterator();

    /**
     * Sets the ID of this register to the specified string. Every register
     * has its ID set when it is initialized. The string provided here can
     * used by the application to append extra, identifying information onto
     * the default ID.
     *
     * @param id a <tt>String</tt> which can be used to identify this
     *      register.
     */
    public void setRegisterID( String id );

    /**
     * Returns the ID of this register as a string. This string is not
     * necessarily unique.
     *
     * @return a <tt>String</tt> which identifies this register.
     */
    public String getRegisterID();

    /**
     * Returns the hash code for this register.
     * The hash code is defined as the sum of the hash codes for each
     * object in the register. Two registries containing the same objects
     * but different ids will have the same hash code. This ensures that
     * <code>r1.equals(r2)</code> implies
     * <code>r1.hashCode()=r2.hashCode</code>
     *
     * @return the value of the hash code for this register.
     */
    public int hashCode();

    /**
     * Tests the specified object for equality with this register.
     * Returns true if the given object is a register and they both contain
     * the same items.  Two registries which differ only by their register
     * id will test equal. 
     *
     * @return <tt>true</tt> if the specified object equals this register.
     */
    public boolean equals( Object o );



    /** @link dependency */
    /*# Registrable lnkRegistrable; */
}
