# SessionListener.java

    /*
    ** Module   : SessionListener.java
    ** Abstract : Interface for objects interested in session life cycle events
    **
    ** Copyright (c) 2004-2017, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
    ** 001 ECF 20060901   @30523 Created initial version. Interface for
    **                           objects interested in receiving Hibernate
    **                           session life cycle events (initially only a
    **                           session closing event is supported).
    ** 002 ECF 20070602   @33928 Added new scope constants. GLOBAL_SCOPE and
    **                           NO_SCOPE.
    ** 003 ECF 20070706   @34404 Added deregisteredSessionListener() to API.
    **                           Provides a notification to listener when it is
    **                           deregistered.
    ** 004 ECF 20090810   @43592 Refactored API to support arbitrary event types.
    **                           Replaced sessionClosing() with sessionEvent().
    **                           Added public enums for event types and scope of
    **                           registration.
    ** 005 ECF 20160409          Added SESSION_CLEANUP event type.
    */
    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, or (at your option) any later version.
    **
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.persist.event;

    import com.goldencode.p2j.persist.*;

    /**
     * Implemented by classes whose instances need to know about session life
     * cycle events as they happen.
     * <p>
     * The following events generate notifications:
     * <ul>
     *   <li>TRANSACTION_COMMITTING - the current database-level transaction is
     *       about to be committed.</li>
     *   <li>SESSION_CLOSING_NORMALLY - the current Hibernate session is about to
     *       be closed due to normal processing (no error).</li>
     *   <li>SESSION_CLOSING_WITH_ERROR - the current Hibernate session is about
     *       to be closed due to an error.</li>
     * </ul>
     * <p>
     * <code>SessionListener</code> instances are registered with the {@link
     * Persistence} class.  They are not explicitly deregistered, but rather are
     * implicitly deregistered at the end of a specific scope (or possibly
     * earlier -- see below).  A listener's scope is determined at registration
     * time using one of the following <code>Scope</code> types.
     * <ul>
     *   <li>NONE - the listener is never deregistered and survives until the end
     *       of the client context.
     *   <li>GLOBAL - deregister the listener when the context's global scope
     *       ends.  This corresponds with the end of the user session.
     *   <li>ENCLOSING_EXTERNAL - deregister the listener when the current,
     *       external scope ends.  This corresponds to the enclosing, external
     *       procedure scope in Progress.
     *   <li>CURRENT - deregister the listener when the current block scope ends.
     *   <li>NEXT_EXTERNAL - deregister the listener when the next external scope
     *       to be opened ends.  This corresponds to an external procedure in
     *       Progress, but not one we currently are in.  Care must be taken when
     *       using this scope;  it presumes that the next external scope to be
     *       opened actually corresponds with the life cycle of the listener.
     *       The idiom with which this usage typically corresponds is the
     *       construction of a business logic object, followed by the immediate
     *       invocation of its primary entry point method (usually called
     *       <code>execute</code>).  This is meant to support listener objects
     *       which are constructed as instance members of the business logic
     *       object.  We can get into trouble if some other, external scope is
     *       opened between the construction of our business logic object and the
     *       invocation of its <code>execute()</code> method.  This will not
     *       happen in converted code, but it is possible in hand-written code.
     * </ul>
     * <p>
     * There are two ways a session listener may be deregistered earlier than at
     * end of the scopes described above:
     * <ul>
     *   <li>If the listener object is no longer referenced by business logic, it
     *       may be collected at any time by the garbage collector.
     *   <li>If the listener's {@link #sessionEvent} method returns
     *       <code>true</code>, the listener is deregistered immediately after
     *       this method returns.
     * </ul>
     */
    public interface SessionListener
    {
       /** Type of session event */
       public enum Event
       {
          /** Transaction is about to be committed */
          TRANSACTION_COMMITTING,

          /** Session is not closing, but requires cleanup */
          SESSION_CLEANUP,

          /** Session is about to close normally */
          SESSION_CLOSING_NORMALLY,

          /** Session is about to close due to an error */
          SESSION_CLOSING_WITH_ERROR,
       };

       /** Scope of listener registration */
       public enum Scope
       {
          /** Never deregister the session listener */
          NONE,

          /** Scope listener registration to context's global scope */
          GLOBAL,

          /** Scope listener registration to enclosing external block scope */
          ENCLOSING_EXTERNAL,

          /** Scope listener registration to current block scope */
          CURRENT,

          /** Scope listener registration to next (lower) external block scope */
          NEXT_EXTERNAL,
       };

       /**
        * Invoked when a significant event occurs related to the current Hibernate
        * session or transaction.
        *
        * @param   event
        *          Type of event.
        *
        * @return  <code>true</code> if this listener should be removed from the
        *          current set of registered listeners;  <code>false</code> to
        *          remain registered.
        *
        * @throws  PersistenceException
        *          if any error occurs during the implementor's processing of the
        *          given event.  If this exception is thrown, the listener will be
        *          deregistered as if <code>true</code> had been returned.
        */
       public boolean sessionEvent(Event event)
       throws PersistenceException;

       /**
        * Invoked when a session listener is removed from the list of registered
        * session listeners.  This method is invoked due to deregistration at the
        * end of the associated scope and after {@link
        * #sessionEvent(com.goldencode.p2j.persist.event.SessionListener.Event)}
        * is invoked and returns <code>true</code>.  It is <i>not</i> invoked when
        * deregistration occurs due to garbage collection, since the listener is
        * not in a position to do anything useful at that point anyway, and is no
        * longer referenced by business logic.
        */
       public void deregisteredSessionListener();
    }