/*
 * 
 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * The contents of this file are subject to the Sun Community Source
 * License v3.0/Jini Technology Specific Attachment v 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://wwws.sun.com/software/jini/licensing/SCSL3_JiniTSA1.html.
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Reference Code is Jini Technology Core Platform code, v2.0. The
 * Developer of the Reference Code is Sun Microsystems, Inc.
 * 
 * Contributor(s): Sun Microsystems, Inc.
 * 
 * The contents of this file comply with the Jini Technology Core
 * Platform Compatibility Kit, v2.0A.
 * 
 * Tester(s): Sun Microsystems, Inc.
 * 
 * Test Platform(s):
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Solaris(TM)SPARC/x86
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Linux (Intel x86)
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Windows (Intel Platform)
 * 
 */

package net.jini.lookup;

import net.jini.core.lookup.ServiceItem;
/**
 * The <code>ServiceDiscoveryListener</code> interface defines the
 * methods used by objects such as a {@link net.jini.lookup.LookupCache 
 * LookupCache} to notify an entity that events of interest related to
 * the elements of the cache have occurred. It is the responsibility of
 * the entity wishing to be notified of the occurrence of such events to
 * construct an object that implements the 
 * <code>ServiceDiscoveryListener</code> interface and then register
 * that object with the cache's event mechanism. Any implementation of
 * this interface must define the actions to take upon receipt of an
 * event notification. The action taken is dependent on both the
 * application and the particular event that has occurred.
 * <p>
 * When the cache receives from one of the managed lookup services, an event
 * signaling the <i>registration</i> of a service of interest for the 
 * <i>first time</i> (or for the first time since the service has been
 * discarded), the cache applies any requested filtering and, if the service of
 * interest passes the filter (or if no filtering was requested), the cache
 * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded
 * serviceAdded} method on all instances of
 * <code>ServiceDiscoveryListener</code> that are registered with the cache.
 * Invoking the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded
 * serviceAdded} method notifies the entity that a service of interest that
 * matches any additional selection criteria has been discovered, and is
 * <i>safe</i> to use (if {@link net.jini.security.ProxyPreparer
 * proxy preparation} was requested).
 * <p>
 * When the cache receives, from a managed lookup service, an event signaling
 * the <i>removal</i> of a service of interest from the <i>last</i> such lookup
 * service with which it was registered, the cache invokes the 
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method on all instances of
 * <code>ServiceDiscoveryListener</code> that are registered with the cache;
 * doing so notifies the entity that a service of interest has been discarded.
 * <p>
 * In addition to the scenarios just described, the cache may also receive,
 * from a managed lookup service, a notification indicating that one of the
 * following events has occurred:
 * <ul><li> The service has changed in some fundamental way (for example,
 *          the service is replaced with a new version), as determined by
 *          {@link net.jini.io.MarshalledInstance#fullyEquals
 *          MarshalledInstance.fullyEquals}
 *     <li> The attributes of interest (across the attribute sets of all
 *          references to the service) have been uniquely modified
 * </ul>
 * <p>
 * Note that that when determining whether the proxy referenced in the event
 * is fundamentally different from the corresponding proxy held by the cache
 * (the proxy that references the same service as the proxy from the event),
 * the cache applies {@link net.jini.io.MarshalledInstance#fullyEquals
 * MarshalledInstance.fullyEquals} to the <b><i>unprepared</i></b> forms
 * of both proxies.
 * <p>
 * When the cache receives, from a managed lookup service, a notification
 * indicating that one of the above events has occurred, the cache will first
 * apply any requested filtering to the service referenced by the event;
 * after which the cache will invoke either the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
 * serviceChanged} method or
 * the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method, possibly followed by the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}
 * method. Which of those methods the cache ultimately invokes is dependent
 * on the nature of the notification from the lookup service as well as the
 * results of any filtering that is performed.
 * <p>
 * If the event from the lookup service indicates that attributes of the
 * service have been modified, and if either no filtering is requested or
 * the service referenced by the event passes the filter, then the cache
 * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
 * serviceChanged} method on all instances of 
 * <code>ServiceDiscoveryListener</code> that are registered with the cache.
 * Invoking the {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
 * serviceChanged} method notifies the entity that the attributes of the
 * previously discovered service have been changed in some way that is still
 * of interest to the entity.
 * <p>
 * If the event from the lookup service indicates that the previously
 * discovered service itself has changed, then if either filtering is not
 * requested or the service passes the requested filter, the cache invokes
 * the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method and then the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}
 * method on all instances of <code>ServiceDiscoveryListener</code> that are
 * registered with the cache. Invoking the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method followed by the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}
 * method notifies the entity that the previously discovered service has been
 * replaced with a new reference.
 * <p>
 * If, on the other hand, filtering is requested but the service fails the
 * filter, then the cache invokes only the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method on all instances of
 * <code>ServiceDiscoveryListener</code> that are registered with the
 * cache. In this case, the
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method is invoked because the cache has concluded that
 * the previously discovered service has been replaced with a new reference
 * that is either no longer of interest to the entity, or is not safe
 * to use.
 * <p>
 * Finally, if filtering is requested but the filtering process results in
 * an <i>indefinite</i> state, then the cache first invokes the 
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method (to indicate to the entity that the service
 * is currently unusable), and then periodically retries the filter for
 * an implementation-dependent amount of time that is likely to exceed
 * the typical service lease duration, until either a failure occurs
 * or a pass occurs. If a pass occurs within the retry time period, the cache
 * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded
 * serviceAdded} method because the cache has concluded that the previously
 * discovered service has been replaced with a new reference that is still
 * of interest to the entity, and is now safe to use.
 * <p>
 * The methods just described -- 
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded},
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved}, and
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
 * serviceChanged} -- each take a single parameter of type
 * {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent}, which
 * contains references to the service item corresponding to the event,
 * including representations of the service's state both before and after
 * the event.
 * <p>
 * Except for possible modifications that result from filtering, each method
 * defined by this interface must not modify the contents of the
 * {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent}
 * parameter; doing so can result in unpredictable and undesirable effects
 * on future processing by the {@link net.jini.lookup.ServiceDiscoveryManager
 * ServiceDiscoveryManager}. Therefore, the effects of such modifications
 * are undefined.
 * <p>
 * The <code>ServiceDiscoveryListener</code> interface makes the following
 * concurrency guarantee: for any given listener object that implements this
 * interface or any sub-interface, no two methods defined by the interface
 * or sub-interface will be invoked at the same time by the same cache.
 * This applies to different invocations of the same or different methods,
 * on the same or different listeners registered with a single cache. For
 * example, the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method of one listener will not be invoked while the
 * invocation of another listener's
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded},
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved}, or
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
 * serviceChanged} method is in progress. Similarly, the one listener's
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
 * serviceRemoved} method will not be invoked while that same listener's
 * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded},
 * or {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
 * serviceChanged} method is in progress.
 * <p>
 * Note that the intent of the methods of this interface is to allow the
 * recipient of the {@link net.jini.lookup.ServiceDiscoveryEvent
 * ServiceDiscoveryEvent} to be informed that a service has been added to,
 * removed from, or modified in the cache. Calls to these methods are
 * synchronous to allow the entity that makes the call (for example, a
 * thread that interacts with the various lookup services of interest)
 * to determine whether or not the call succeeded. However, it is not
 * part of the semantics of the call that the notification return can be
 * delayed while the recipient of the call reacts to the occurrence of the
 * event. Thus, it is highly recommended that implementations of this
 * interface avoid time consuming operations, and return from the method
 * as quickly as possible. For example, one strategy might be to simply
 * note the occurrence of the {@link net.jini.lookup.ServiceDiscoveryEvent
 * ServiceDiscoveryEvent}, and perform any time consuming event handling
 * asynchronously. 
 * 
 * @author Sun Microsystems, Inc.
 *
 * @see LookupCache
 * @see ServiceDiscoveryEvent
 */
public interface ServiceDiscoveryListener {
    /** 
     * When the cache receives from one of the managed lookup services,
     * an event signaling the <i>registration</i> of a service of
     * interest for the <i>first time</i> (or for the first time since
     * the service has been discarded), the cache invokes the
     * <code>serviceAdded</code> method on all instances of
     * <code>ServiceDiscoveryListener</code> that are registered with the
     * cache; doing so notifies the entity that a service of interest has
     * been discovered.
     *
     * @param event an instance of <code>ServiceDiscoveryEvent</code> 
     * 			containing references to the service item 
     *			corresponding to the event, including 
     * 			representations of the service's state both 
     *			before and after the event.
     */
    void serviceAdded(ServiceDiscoveryEvent event);

    /** 
     * When the cache receives, from a managed lookup service, an event
     * signaling the removal of a service of interest from the last such
     * lookup service with which it was registered, the cache invokes
     * the <code>serviceRemoved</code> method on all instances of
     * <code>ServiceDiscoveryListener</code> that are registered with
     * the cache; doing so notifies the entity that a service of interest 
     * has been discarded.
     * 
     * @param event a <code>ServiceDiscoveryEvent</code> object 
     * 			containing references to the service item 
     *			corresponding to the event, including 
     *			representations of the service's state both 
     *			before and after the event.
     */
    void serviceRemoved(ServiceDiscoveryEvent event);

    /** 
     * When the cache receives, from a managed lookup service, an event
     * signaling the unique modification of the attributes of a service
     * of interest (across the attribute sets of all references to the
     * service), the cache invokes the <code>serviceChanged</code>
     * method on all instances of <code>ServiceDiscoveryListener</code>
     * that are registered with the cache; doing so notifies the entity
     * that the state of a service of interest has changed.
     * 
     * @param event a <code>ServiceDiscoveryEvent</code> object
     * 			containing references to the service item 
     * 			corresponding to the event, including 
     * 			representations of the service's state both
     * 			before and after the event.
     */
    void serviceChanged(ServiceDiscoveryEvent event);
}
