# TempLock.java

    /*
    ** Module   : TempLock.java
    ** Abstract : An object which encapsulates a resettable lock on a specific DMO
    **
    ** Copyright (c) 2004-2024, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- -----------------------------------Description-----------------------------------
    ** 001 ECF 20061112   @31143 Created initial version. An object which encapsulates a resettable
    **                           lock on a specific DMO.
    ** 002 ECF 20070412   @32991 Retrofit to use RecordLockContext for record locking. Minor
    **                           implementation change.
    ** 003 ECF 20131029          Import change. Removed unused instance variable.
    ** 004 ECF 20200906          New ORM implementation.
    ** 005 OM  20241128          Multi-tenant runtime support: selected the proper persistence context, eventually
    **                           based on [sharedDb] parameter.
    */

    /*
    ** 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;

    import com.goldencode.p2j.persist.lock.*;

    /**
     * Object which encapsulates a resettable lock on a specific DMO.  Successful
     * construction of an instance of this class indicates that the requested
     * lock type was obtained from the appropriate lock manager or was already
     * available to this session.  The old lock type is restored by invoking
     * {@link #reset}.
     */
    public final class TempLock
    {
       /** Unique record identifier */
       private final RecordIdentifier<String> ident;

       /** Previous lock type of DMO */
       private final LockType originalLockType;

       /** Object which services lock requests */
       private final Persistence persistence;

       /** In case of multi-tenant environment: is the buffer shared or private? */
       private final boolean sharedDb;

       /**
        * Constructor which acquires a record lock of the specified type.  This
        * constructor may block indefinitely if the lock is unavailable and the
        * requested lock type is not a NO_WAIT variant.
        *
        * @param   persistence
        *          Object which services lock requests.
        * @param   lockType
        *          Type of lock to be acquired.
        * @param   table
        *          Table containing target DMO.
        * @param   recordID
        *          Primary key ID of DMO being locked.
        * @param   sharedDb
        *          In case of multi-tenant environment: is the buffer shared or private?
        */
       TempLock(Persistence persistence, LockType lockType, String table, Long recordID, boolean sharedDb)
       throws LockUnavailableException
       {
          this.persistence = persistence;
          this.sharedDb = sharedDb;
          this.ident = new RecordIdentifier<>(table, recordID);

          LockType currentType = persistence.queryLock(ident, sharedDb);

          if (lockType.compareTo(currentType) > 0)
          {
             originalLockType = currentType;
             RecordLockContext lockCtx = persistence.getRecordLockContext(sharedDb);
             lockCtx.lock(ident, lockType);
          }
          else
          {
             originalLockType = null;
          }
       }

       /**
        * Reset the record lock back to its original type.  This is a no-op if
        * the old and new types are the same or if the lock type was never
        * changed by this object.
        */
       void reset()
       {
          if (originalLockType == null)
          {
             // Lock type was never changed;  nothing to do.
             return;
          }

          LockType currentType = persistence.queryLock(ident, sharedDb);

          if (currentType.compareTo(originalLockType) > 0)
          {
             try
             {
                RecordLockContext lockCtx = persistence.getRecordLockContext(sharedDb);
                lockCtx.lock(ident, originalLockType);
             }
             catch (LockUnavailableException exc)
             {
                // Not thrown when requesting non-NO_WAIT lock type variants.
             }
          }
       }
    }