/* OdmJniPend.java 0.01              UTF-8                   dh:2007-01-25
 *
 * The OdmJniPend class implements the the OdmPendingDocument interface for
 * any document-in-creation instance.  The ODMA DMS has already accepted the
 * request and the IodmPending100 interface is provided to the constructor.
 *
 * The purpose of this implementation is to exist just long enough to allow
 * the program to save the content for the new DMS document at the
 * docSubmissionLocation and perform commitContent.  After that, all useful
 * operation is with the OdmWorkingDocument interface that is returned.
 *
 * The OdmJniPend document switches into null behavior once the commit-
 * Content is performed.
 */


package info.odma.odmjni100;

class OdmJniPend
          extends info.odma.practical100.OdmNullPendingDocument
          implements info.odma.practical100.OdmPendingDocument

{   /* Instance Variables and Constructor
     * ----------------------------------
       */

    final info.odma.practical100.OdmNull nullDocument;
        /* A reference to the OdmNullCache provided by OdmApp
           for use by methods of this implementation.
           */

    long rNativePending;
        /* The disguised reference to a Native document interface that
           is passed as a handle back to native method so they can
           operate with the correct instance.
           */

    boolean isAvailable;
        /* Automatically true until the interface is released */

    private boolean isDmsAvailable;
        /* Automatically true until the interface is released */

    private boolean isOperationSucceeded;
        /* Automatically true until the interface is released */

    private boolean knowDocLocation;
    private java.lang.String ourDocLocation;
        /* Cache for docLocation() */

    OdmJniPend(long rIodmPending,
                    info.odma.practical100.OdmNull nullDoc)
    {   /* Use the supplied interface reference and the nullDoc cache
           to implement OdmPendingDocument functions for the new document.
           */

        /* Preconditions:
                This constructor is never used unless rIodmPending
                is a disguised interface pointer for a successfully-
                created Native document interface to an already-
                opened pending document for which the document submission
                location is established.
                */

        super(0);
            /* Our parent is the failed version of OdmPendingDocument
               implementation.  We take advantage of that for our
               operations.
               */

        nullDocument = nullDoc;

        rNativePending
          = info.odma.odmjni100.OdmJniBind.holdNativeInterface
                (rIodmPending);

        isAvailable = true;
        isDmsAvailable = true;
        isOperationSucceeded = true;
            /* Used to over-ride the failed null case. */

        } /* OdmJniPend */



    /* OdmInterface Interface Method Implementations
     * ---------------------------------------------
     */

    public java.lang.String interfaceImplementation()
    {   /* Return a text string describing this implementation */

        return "ODMJNI 1.0 OdmJniPend 0.01 OdmPendingDocument";
            /* Over-ride with our identification. */

        } /* interfaceImplementation */


    public boolean available()
    {   /* When this object is constructed, it must be because
           there is an available ODMA Connection Manager.
           */

        return isAvailable;

        /* When this object is released, isAvailable is set to
           false.
           */

        } /* available */


    public void release()
    {   /* Release all of our resources, setting ourselves for null
           responses.  Then release resources of the object we extend.
           */

        isAvailable = false;
        isDmsAvailable = false;
        isOperationSucceeded = false;


        info.odma.odmjni100.OdmJniBind.freeNativeInterface(rNativePending);
        rNativePending = 0;
            /* Ensures that methods fail properly if used after
               a release.  This is the trigger for other methods to
               determine that null behavior is required. */

        super.release();

        } /* release */


    public void finalize()
                   throws Throwable
    {   /* We must do this, in case this object becomes inaccessible
           without release() having been performed.  This is how
           we intend to clean up after ourselves no matter what.

           The throw clause is required by finalize() inheritance from
           java.lang.Object.  No checked exceptions arise from the
           implementation here.

           XXX: There is some indication that the finalize method
                does not complete under shutdown conditions.  It is
                important that applications give explicit release
                whenever possible.  Otherwise, ODMA operations may not
                be completed properly.  [This could also be a problem
                with the ODMA32 log not being flushed.  We have to
                check this out.]
           */

        release();

        super.finalize();

        } /* finalize */


    /* OdmDocument Interface Method Implementations
     * --------------------------------------------
     *
     * These methods indicate that operationSucceeded() or else we
     * wouldn't be here.  After release, the default failed behavior
     * condition will apply.  operationCancelled() and localOperation-
     * Requested are always false and supplied by our parent class.
     */

    public boolean dmsAvailable()
    {   /* True for instances of this class until set false on release.
           The variable is only set in the constructor (true) and in
           the release method (false). */

        return isDmsAvailable;

        } /* dmsAvailable */


    public boolean operationSucceeded()
    {
        return isOperationSucceeded;

        } /* operationSucceeded */




    /* OdmPendingDocument Interface Method Implementations
     * ---------------------------------------------------
     */


    public java.lang.String docSubmissionLocation()
    {
        /* Cache the string if necessary, then return the same value
           until the cache is obsoleted for any reason.
           */

        if (!knowDocLocation)
             {  /* We will know it one way or the other now. */
                knowDocLocation = true;
                if (rNativePending == 0)
                     ourDocLocation = null;
                else ourDocLocation = jniPendLoc(rNativePending);
                }

        return ourDocLocation;

        } /* docLocation */


    private static native java.lang.String jniPendLoc(long rIface);
        /* The only place where we fish out the document submission
           location from the native Pending Document object */



    public info.odma.practical100.OdmWorkingDocument commitContent()
                throws info.odma.practical100.OdmError
    {   /* There is no document and an application should never reach
           this point in a returned null-document implementation.
           */

        if (rNativePending == 0)
             throw new info.odma.practical100.OdmError
                            (   "Invalid commitContent: "
                                + interfaceImplementation() );
             /* Make the throw ourselves, so that this class is
                identified as reporting the invalid condition.
                */

        /* Use essentially the same approach as chooseDocument because
           we are in the same situation but with a newly-created one.
           However, if we are this far, we either succeed or fail.  There
           are no other cases.
           */

        long rIworking = jniCommitContent(rNativePending);

        int iStatus =
                info.odma.odmjni100.OdmJniBind.getInterfaceStatus(rIworking);

        if (rIworking == 0 || iStatus > 0)
             return nullDocument.workingFailed();

        /* We have a successful result.  Deliver an OdmJniWork to
           continue with.
           */

        release();
            /* Because we have nothing more to offer */

        info.odma.practical100.OdmWorkingDocument odmWorking = null;

        try
        {   odmWorking = new info.odma.odmjni100.OdmJniWork
                                   ( rIworking, nullDocument);
            }
        catch (java.lang.Throwable e) { }

        info.odma.odmjni100.OdmJniBind.freeNativeInterface(rIworking);
            /* Our copy is no longer useful and we must release it. */

        if (odmWorking == null)
             return nullDocument.workingFailed();

        return odmWorking;

        } /* commitContent */


    private static native long jniCommitContent(long rIface);
        /* The function used to carry out the native Commit Content
           and return a reference to the next object or an indicator
           of the next thing to do.
           */



    static

        {   /* Static initialization of this class specifies the
               loading of the only DLL used with odmjni100. */

            System.loadLibrary("odmjni100");

            } /* static initialization */

    } /* OdmJniPend */


/* 0.01 2007-01-25-14:53 Correct failure to release Iworking on successful
        commitContent.
   0.00 2007-01-20-15:01 Customized from OdmNullPendingDocument 0.06 which
        it extends.  Many elements of OdmJniView 0.09 are also incorporated
        into this version.

   $Header: /ODMdev/info/odma/odmjni100/OdmJniPend.java 3     07-01-25 15:56 Orcmid $
   */

/*                       *** end of OdmJniPend.java ***              */