# OerequestInfo.java

    /*
    ** Module   : OerequestInfo.java
    ** Abstract : Implementation of the builtin class.
    **
    ** Copyright (c) 2019-2025, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- -------------------------------Description--------------------------------
    ** 001 CA  20190526 First version, stubs taken by converting the skeleton using FWD.
    ** 002 CA  20190812 Added LegacyResource annotation.
    ** 003 CA  20191024 Added method support levels and updated the class support level.
    ** 004 CA  20200427 Completed runtime.
    ** 005 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
    **                  signature.
    ** 006 HC  20230116 Replaced some handle usages with the actual wrapped resources for
    **                  performance.
    ** 007 CA  20231113 The 'execute' method must be annotated with LegacySignature Type.Execute, and also can be
    **                  dropped if is a no-op.
    ** 008 GBB 20240112 Support adapterType enum.
    ** 009 GBB 20250403 Javadoc fixes.
    */

    /*
    ** 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.oo.lang;

    import com.goldencode.p2j.util.*;
    import com.goldencode.p2j.oo.applicationserver.*;

    import static com.goldencode.p2j.util.BlockManager.*;
    import static com.goldencode.p2j.report.ReportConstants.*;
    import static com.goldencode.p2j.util.InternalEntry.Type;

    /**
     * Business logic (converted to Java from the 4GL source code
     * in Progress/Lang/OERequestInfo.cls).
     *
     * Can be accessed in ABL with:
     * <ul>
     *    <li>server-handle:REQUEST-INFO</li>
     *    <li>server-handle:RESPONSE-INFO</li>
     *    <li>async-request-handle:REQUEST-INFO<</li>
     *    <li>async-request-handle:RESPONSE-INFO<</li>
     * </ul>
     *
     * Can be accessed in appserver with:
     * <ul>
     *    <li>SESSION:CURRENT-REQUEST-INFO</li>
     *    <li>SESSION:CURRENT-RESPONSE-INFO</li>
     * </ul>
     */
    @LegacyResource(resource = "Progress.Lang.OERequestInfo")
    @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_STUB)
    public final class OerequestInfo
    extends BaseObject
    {
       /** The adapter type. */
       private object<? extends AdapterTypes> adapterType = TypeFactory.object(AdapterTypes.class);

       /** The agent ID. Only in multi-session agent appservers. */
       private integer agentId = TypeFactory.integer();

       /** The session ID. Only in multi-session agent appservers. */
       private integer sessionId = TypeFactory.integer();

       /** The thread ID. Only in multi-session agent appservers. */
       private integer threadId = TypeFactory.integer();

       /** The client context ID. */
       private character clientContextId = TypeFactory.character();

       /** The procedure name. */
       private character procedureName = TypeFactory.character();

       /** The request ID. */
       private character requestId = TypeFactory.character();

       /** The version info. */
       private object<? extends OeversionInfo> versionInfo = TypeFactory.object(OeversionInfo.class);

       /** The client principal. */
       private handle clientPrincipal = TypeFactory.handle();

       /**
        * Default constructor.  Sets only the {@link #versionInfo}.
        */
       @LegacySignature(type = Type.CONSTRUCTOR)
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public void __lang_OerequestInfo_constructor__()
       {
          internalProcedure(this, "__lang_OerequestInfo_constructor__", new Block((Body) () ->
          {
             __lang_BaseObject_constructor__();

             // AdapterType property: only SESSION:request

             // ClientContextId property:
             // - get/set, generated on the SERVER:request when SERVER is built
             // - transported to the SESSION:request via CONNECT/RUN and read via SESSION:request.
             // - SESSION:response will send it back

             // RequestId property:
             // - get, SESSION/SERVER:request/response, generated by the client and sent with each RUN

             // ProcedureName property
             // - only SESSION:request
             // - the original (rel/full) path of the external program invoked by the client

             // AgentId, SessionId, ThreadId:
             // - set by appserver, SESSION:request/response, SERVER:response

             // VersionInfo property:
             // - r/o, REQUEST: ver of the client, RESPONSE: ver of the appserver
             this.versionInfo.assign(SessionUtils.localVersionInfo());

             // GetClientPrincipal and SetClientPrincipal
             // - both are transported via each CONNECT/RUN
          }));
       }

       /**
        * Get the {@link #adapterType} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "OBJECT", qualified = "Progress.ApplicationServer.AdapterTypes", type = Type.GETTER, name = "AdapterType")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public object<? extends com.goldencode.p2j.oo.applicationserver.AdapterTypes> getAdapterType()
       {
          return function(this, "AdapterType", object.class, new Block((Body) () ->
          {
             returnNormal(adapterType);
          }));
       }

       /**
        * Get the {@link #agentId} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "INTEGER", type = Type.GETTER, name = "AgentId")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public integer getAgentId()
       {
          return function(this, "AgentId", integer.class, new Block((Body) () ->
          {
             returnNormal(agentId);
          }));
       }

       /**
        * Get the {@link #clientContextId} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "CHARACTER", type = Type.GETTER, name = "ClientContextId")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public character getClientContextId()
       {
          return function(this, "ClientContextId", character.class, new Block((Body) () ->
          {
             returnNormal(clientContextId);
          }));
       }

       /**
        * Set the {@link #clientContextId} field.
        *
        * @param    _var
        *           The client context ID.
        */
       @LegacySignature(type = Type.SETTER, name = "ClientContextId", parameters =
       {
          @LegacyParameter(name = "var", type = "CHARACTER", mode = "INPUT")
       })
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public void setClientContextId(final character _var)
       {
          character var = TypeFactory.initInput(_var);

          internalProcedure(this, "ClientContextId", new Block((Body) () ->
          {
             clientContextId.assign(var);
          }));
       }

       /**
        * Get the {@link #procedureName} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "CHARACTER", type = Type.GETTER, name = "ProcedureName")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public character getProcedureName()
       {
          return function(this, "ProcedureName", character.class, new Block((Body) () ->
          {
             returnNormal(procedureName);
          }));
       }

       /**
        * Get the {@link #requestId} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "CHARACTER", type = Type.GETTER, name = "RequestId")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public character getRequestId()
       {
          return function(this, "RequestId", character.class, new Block((Body) () ->
          {
             returnNormal(requestId);
          }));
       }

       /**
        * Get the {@link #sessionId} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "INTEGER", type = Type.GETTER, name = "SessionId")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public integer getSessionId()
       {
          return function(this, "SessionId", integer.class, new Block((Body) () ->
          {
             returnNormal(sessionId);
          }));
       }

       /**
        * Get the {@link #threadId} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "INTEGER", type = Type.GETTER, name = "ThreadId")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public integer getThreadId()
       {
          return function(this, "ThreadId", integer.class, new Block((Body) () ->
          {
             returnNormal(threadId);
          }));
       }

       /**
        * Get the {@link #versionInfo} field.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "OBJECT", qualified = "Progress.Lang.OEVersionInfo", type = Type.GETTER, name = "VersionInfo")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public object<? extends com.goldencode.p2j.oo.lang.OeversionInfo> getVersionInfo()
       {
          return function(this, "VersionInfo", object.class, new Block((Body) () ->
          {
             returnNormal(versionInfo);
          }));
       }

       /**
        * Get the {@link #clientPrincipal}.
        *
        * @return   See above.
        */
       @LegacySignature(returns = "HANDLE", type = Type.METHOD, name = "GetClientPrincipal")
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public handle getClientPrincipal()
       {
          return function(this, "GetClientPrincipal", handle.class, new Block((Body) () ->
          {
             returnNormal(this.clientPrincipal);
          }));
       }

       /**
        * Get the {@link #clientPrincipal}.
        *
        * @return   See above.
        */
       public ClientPrincipal getClientPrincipalNative()
       {
          return (ClientPrincipal) this.clientPrincipal.getResource();
       }

       /**
        * Set the {@link #clientPrincipal}.  This deletes any other instance it may reference via the
        * {@link #clientPrincipal}.
        *
        * @param    _h
        *           The client principal handle.
        *
        * @return   <code>true</code> if the assign was possible.
        */
       @LegacySignature(returns = "LOGICAL", type = Type.METHOD, name = "SetClientPrincipal", parameters =
       {
          @LegacyParameter(name = "h", type = "HANDLE", mode = "INPUT")
       })
       @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
       public logical setClientPrincipal(final handle _h)
       {
          handle h = TypeFactory.initInput(_h);

          return function(this, "SetClientPrincipal", logical.class, new Block((Body) () ->
          {
             if (h.isUnknown())
             {
                if (this.clientPrincipal._isValid())
                {
                   HandleOps.delete(this.clientPrincipal);
                   this.clientPrincipal.setUnknown();
                }

                returnNormal(true);
             }
             else if (!(h.getResource() instanceof ClientPrincipal) || !h._isValid())
             {
                returnNormal(false);
             }

             this.clientPrincipal.assign(h);

             returnNormal(true);
          }));
       }

       /**
        * Set the {@link #requestId}.  This is not a legacy setter!
        *
        * @param    requestId
        *           The request ID.
        */
       public void setRequestId(String requestId)
       {
          this.requestId.assign(requestId);
       }

       /**
        * Initialize this instance with the specified values for each field.
        *
        * @param    procedureName
        *           The procedure name.
        * @param    clientContextId
        *           The client context ID.
        * @param    requestId
        *           The request ID.
        * @param    versionInfo
        *           The version info, in the [major, minor, maint] format.
        * @param    clientType
        *           The client type.
        * @param    agentId
        *           The agent ID.
        * @param    sessionId
        *           The session ID.
        * @param    threadId
        *           The thread ID.
        * @param    clientPrincipal
        *           The serialized client principal.
        */
       public void initialize(String   procedureName,
                              String   clientContextId,
                              String   requestId,
                              String[] versionInfo,
                              String   clientType,
                              Integer  agentId,
                              Integer  sessionId,
                              Integer  threadId,
                              byte[]   clientPrincipal)
       {
          this.procedureName.assign(procedureName);
          this.clientContextId.assign(clientContextId);
          this.requestId.assign(requestId);
          this.versionInfo.assign(OeversionInfo.newInstance(versionInfo == null ? null : versionInfo[0],
                                                            versionInfo == null ? null : versionInfo[1],
                                                            versionInfo == null ? null : versionInfo[2],
                                                            clientType));
          this.agentId.assign(agentId);
          this.sessionId.assign(sessionId);
          this.threadId.assign(threadId);

          if (this.clientPrincipal._isValid())
          {
             HandleOps.delete(this.clientPrincipal);
          }

          if (clientPrincipal == null)
          {
             this.clientPrincipal.setUnknown();
          }
          else
          {
             ClientPrincipal.create(this.clientPrincipal);
             this.clientPrincipal.unwrapClientPrincipal().importPrincipal(new raw(clientPrincipal));
          }
       }

       /**
        * Initialize this instance from the specified reference, by copying the state.
        *
        * @param    req
        *           The request instance to initialize from.
        * @param    request
        *           Flag indicating if the current instance is for a request - if so, set the
        *           {@link #procedureName}.
        */
       public void initialize(OerequestInfo req, boolean request)
       {
          if (request)
          {
             // do not set it in response
             this.procedureName.assign(req.procedureName);
          }
          else
          {
             this.procedureName.setUnknown();
          }

          this.clientContextId.assign(req.clientContextId);
          this.requestId.assign(req.requestId);

          this.agentId.assign(req.agentId);
          this.sessionId.assign(req.sessionId);
          this.threadId.assign(req.threadId);

          this.versionInfo.assign(SessionUtils.localVersionInfo());

          if (req.clientPrincipal._isValid())
          {
             this.clientPrincipal.set(((ClientPrincipal) req.clientPrincipal.getResource()).clone());
          }
       }

       /**
        * Obtain an array representation of this instance, for serialization purposes.
        *
        * @return   The instance fields, in the [adapterType, procedureName, clientContextId, requestId,
        *           agentId, sessionId, threadId, [major, minor, maint, clientType], clientPrincipal]
        *           order.
        */
       public Object[] toArray()
       {
          OeversionInfo ver = versionInfo.ref();

          Object[] res = new Object[9];
          res[0] = adapterType._isValid() ? adapterType.ref().toLegacyString() : null;
          res[1] = procedureName.getValue();
          res[2] = clientContextId.getValue();
          res[3] = requestId.getValue();
          res[4] = agentId.toJavaIntegerType();
          res[5] = sessionId.toJavaIntegerType();
          res[6] = threadId.toJavaIntegerType();
          res[7] = new String[]
          {
             ver.getOemajorVersion().getValue(),
             ver.getOeminorVersion().getValue(),
             ver.getOemaintVersion().getValue(),
             ver.getOeclientType().getValue()
          };
          res[8] = null;
          if (clientPrincipal._isValid())
          {
             raw r = ((ClientPrincipal) clientPrincipal.getResource()).exportPrincipal();
             res[8] = r.getByteArray();
          }

          return res;
       }

       /**
        * Initialize this instance from the given array representation (from a previous
        * {@link #toArray()} call).
        *
        * @param    arr
        *           The serialized instance, as was returned by {@link #toArray()}.
        */
       public void fromArray(Object[] arr)
       {
          adapterType.assign(arr[0]);
          procedureName.assign(arr[1]);
          clientContextId.assign(arr[2]);
          requestId.assign(arr[3]);
          agentId.assign(arr[4]);
          sessionId.assign(arr[5]);
          threadId.assign(arr[6]);
          String[] ver = (String[]) arr[7];
          versionInfo.assign(OeversionInfo.newInstance(ver[0], ver[1], ver[2], ver[3]));

          if (clientPrincipal._isValid())
          {
             HandleOps.delete(clientPrincipal);
          }

          byte[] cp = (byte[]) arr[8];
          if (cp == null)
          {
             this.clientPrincipal.setUnknown();
          }
          else
          {
             ClientPrincipal.create(clientPrincipal);
             ((ClientPrincipal) clientPrincipal.getResource()).importPrincipal(new raw(cp));
          }
       }
    }