/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   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.bodington.servlet;

import org.bodington.server.NavigationSession;

/**
 * Interface for objects that handle the initialization of sessions. Objects
 * that implement this interface are used by instances of {@link Request} to
 * handle the initialization of sessions associated with incoming requests. The
 * primary motivation for this interface is that the administrator of an
 * installation can specify the (possibly multiple) supported authentication
 * mechanisms by specifying them as ordered links in a session initializer chain
 * (see {@link org.bodington.servlet.SessionInitializerChain}).
 * <p>
 * This interface follows the <em>chain of responsibility</em> pattern from
 * the classic <a href="http://hillside.net/patterns/DPBook/DPBook.html">Gang of
 * Four</a> design patterns book. A given instance attempts to handle the
 * request when its {@link #handleRequest(Request)} method is called. If it can
 * handle the request itself, it does so and then returns. If it can not, then
 * it calls the {@link #handleRequest(Request)} of the next link in the chain
 * (specified to it via its
 * {@link #setNextSessionInitializer(SessionInitializer)} method) or if this is
 * <code>null</code> just returns.
 * <p>
 * Whilst this appears to be a simple interface, actual implementations are
 * tightly-bound to the application as they need to understand the associations
 * between instances of {@link Request}, {@link HttpSession},
 * {@link NavigationSession} and {@link SessionInitializer}. In practice, users
 * would be expected to use the
 * {@link SessionInitializerChain#getSessionInitializer(String)} to obtain an
 * instance configured using the default session initializers. However, it is
 * still possible to supply custom instances, if that is what is required. A key
 * distinction between concrete implementations is that some will call the code
 * that perform the actual authentication themselves. Other implementations will
 * receive requests where the authentication has already happened (prehaps
 * externally) and it is their responsibility to initialize sessions based on
 * the presence of specific tokens in the request.
 * @see Request
 * @see HttpSession
 * @see NavigationSession
 * @see SessionInitializerChain#getSessionInitializer(String)
 * @see SessionInitializerChain
 * @author Alexis O'Connor
 */
public interface SessionInitializer
{
    /**
     * Handle the request. If the object implementing this method can handle the
     * request it should do so and then return an instance of
     * {@link NavigationSession}. If it can not handle the request itself, then
     * it is expected to call the {@link #handleRequest(Request)} of the next
     * link in the chain (that link having been specified to this object via its
     * {@link #setNextSessionInitializer(SessionInitializer)} method). If the
     * current object has been unable to handle the request, but it is the last
     * link in the chain, then this method should ideally return a non-null
     * {@link NavigationSession} instance, albeit one who's
     * {@link NavigationSession#isAuthenticated()} returns <code>false</code>.
     * @param request the request object to be handled.
     * @return a corresponding navigation session instance, or <code>null</code>
     *         if one could not be found.
     * @see #setNextSessionInitializer(SessionInitializer)
     * @see NavigationSession#isAuthenticated()
     */
    NavigationSession handleRequest(Request request);
    
    /**
     * Set the next session initializer. This method is used to specify to the
     * implementing object what is the next link in the chain after this one.
     * @param initializer the next link in the chain after this one.
     */
    void setNextSessionInitializer(SessionInitializer initializer);
}
