Function HTTP_Resource_Manager_Services(@Service, @Params)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from SRP Computer Solutions, Inc.

    Name        :   HTTP_Resource_Manager_Services

    Description :   Handler program for all module related services.

    Notes       :   The generic parameters should contain all the necessary information to process the services. Often
                    this will be information like the data Record and Key ID.

    Parameters  :
        Service         [in] -- Name of the service being requested
        Param1-10   [in/out] -- Additional request parameter holders
        Response       [out] -- Response to be sent back to the Controller (MCP) or requesting procedure

    Metadata    :

    History     :   (Date, Initials, Notes)
        07/12/19    dmb     [SRPFW-277] Original programmer.
        07/13/19    dmb     [SRPFW-277] Added various services so that the NDW_HTTP_FRAMEWORKS_SERVICES commuter as well
                            as additional tools can get or set various resource meta data.
        07/15/19    dmb     [SRPFW-277] Added the GetEndpointResourceKeyID service.
        07/16/19    dmb     [SRPFW-277] Added the GetResourceSignature service.
        07/16/19    dmb     [SRPFW-277] Update GetResourceProperty service to support the RESOURCE property.
        07/16/19    dmb     [SRPFW-277] Replaced harcoded cache duration with the CacheTTL$ equate.
        07/16/19    dmb     [SRPFW-277] Rename the IsResource service to IsValidEndpoint.
        07/17/19    dmb     [SRPFW-277] Update the SetResource service to refresh the GetResource cache better.
        07/24/19    dmb     [SRPFW-278] Fix bug in the GetEndpointResourceKeyID service so that matching the URLEndpoint
                            works better.
        09/25/19    dmb     [SRPFW-278] Fix bug in the GetResource service that prevented endpoints with a resource ID
                            from being matched correctly to the currently stored resources endpoints.
        12/09/19    dmb     [SRPFW-296] Update all calls to Memory_Services to use a specific cache name.
        01/23/20    dmb     [SRPFW-296] Update the SetResourceProperty and GetResourceSignature services to support the
                            HEAD method.

***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler

$insert LOGICAL
$insert HTTP_INSERTS
$insert SERVICE_SETUP
$insert INET_EQUATES
$insert INET_HEADERS
$insert HTTP_FRAMEWORK_SETUP_EQUATES

Equ CRLF$           to \0D0A\
Equ CacheTTL$       to 300   ; // Allow cached data to only be fresh for 5 seconds.
Equ CacheName$      to 'SRPHTTPFramework'
Equ ValidMethods$   to 'GET,POST,PUT,PATCH,DELETE,HEAD'

Declare function    HTTP_Resource_Manager_Services, HTTP_Resource_Services, Database_Services, Memory_Services, SRP_Array
Declare subroutine  HTTP_Resource_Manager_Services, HTTP_Resource_Services, Database_Services, Memory_Services

GoToService else
    HTTP_Services('SetResponseError', '', '', 404, Service : ' is not a valid service request within the HTTP Resource Manager services module.')
end

Return Response OR ''


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN     = True$, False$
Options CLASSES     = 'APIROOT', 'RESOURCE', 'RESOURCE_ID', 'PROPERTY'
Options PROPERTIES  = 'CLASS', 'DESCRIPTION', 'EXCLUDE_LOGGING', 'METHODS', 'NAME', 'RESOURCE', 'TITLE', 'QUERY_PARAMS'
Options CHILDREN    = 'ALL', 'RESOURCE', 'RESOURCE_ID', 'PROPERTY'
Options METHODS     = 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//----------------------------------------------------------------------------------------------------------------------
// GetResourceProperty
//
// URLEndpoint  - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// PropertyName - Name of the property whose value is being queried. - [Required]
//
// Returns the value of the indicated resource property for the indicated URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceProperty(URLEndpoint, PropertyName=PROPERTIES)

    PropertyValue   = ''

    If PropertyName NE '' then
        Resource        = HTTP_Resource_Manager_Services('GetResource', URLEndpoint)
        If Error_Services('NoError') then
            PropertyNames   = Resource<1>
            Locate PropertyName in PropertyNames using @VM setting PropertyPos then
                PropertyValue   = Resource<2, PropertyPos>
            end
            Begin Case
                Case PropertyName EQ 'EXCLUDE_LOGGING'
                    // This property defaults to false unless true.
                    If PropertyValue NE True$ then PropertyValue = False$
                Case PropertyName EQ 'RESOURCE' AND PropertyValue = ''
                    // Unless the system has forced this property to store a value, it should be derived from the
                    // resource signature.
                    Signature       = HTTP_Resource_Manager_Services('GetResourceSignature', URLEndpoint)
                    PropertyValue   = Signature[1, '.']
            End Case
        end
    end else
        Error_Services('Add', 'PropertyName argument was missing in the ' : Service : ' service.')
    end

    Response        = PropertyValue

end service


//----------------------------------------------------------------------------------------------------------------------
// SetResourceProperty
//
// URLEndpoint      - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// PropertyName     - Name of the property whose value is being set. - [Required]
// PropertyValue    - Value of the property being updated. Depending upon the property, this might clear the value or
//                    set a default value. - [Optional]
//
// Sets (or updates) the value of the indicated resource property for the indicated URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service SetResourceProperty(URLEndpoint, PropertyName=PROPERTIES, PropertyValue)

    If PropertyName NE '' then
        Resource        = HTTP_Resource_Manager_Services('GetResource', URLEndpoint)
        If Error_Services('NoError') then
            PropertyNames   = Resource<1>
            Begin Case
                Case PropertyName EQ 'METHODS'
                    // Make sure only valid HTTP methods are set.
                    Transfer PropertyValue to Methods
                    For Each Method in Methods using ',' setting cPos
                        Locate Method in ValidMethods$ using ',' setting MethodPos then
                            PropertyValue  := Method : ','
                        end
                    Next Method
                    PropertyValue[-1, 1]    = ''
                Case PropertyName EQ 'EXCLUDE_LOGGING'
                    // This property defaults to false unless true.
                    If PropertyValue NE True$ then PropertyValue = False$
                Case PropertyName EQ 'CLASS'
                    // Make sure only a valid resource class is set.
                    Locate PropertyValue in 'RESOURCE,RESOURCE_ID,PROPERTY' using ',' setting ClassPos else
                        PropertyValue   = 'RESOURCE'
                    end
            End Case
            Locate PropertyName in PropertyNames using @VM setting PropertyPos else
                Resource<1, PropertyPos>    = PropertyName
            end
            Resource<2, PropertyPos>    = PropertyValue
            HTTP_Resource_Manager_Services('SetResource', URLEndpoint, Resource)
        end
    end else
        Error_Services('Add', 'PropertyName argument was missing in the ' : Service : ' service.')
    end

end service


//----------------------------------------------------------------------------------------------------------------------
// GetResourceChildren
//
// URLEndpoint  - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// ChildType    - Type of child resource being queried. If empty or ALL then all children are returned. - [Optional]
//
// Returns an @FM delimited list of URL endpoints matching the indicated child type that are children to the indicated
// URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceChildren(URLEndpoint, ChildType=CHILDREN)

    Children    = ''

    ResourceList    = HTTP_Resource_Manager_Services('GetResourceList')
    If Error_Services('NoError') then
        // Loop through the resource list to find resource children.
        If ResourceList NE '' then
            Locate ChildType in 'ALL,RESOURCE,RESOURCE_ID,PROPERTY' using ',' setting ChildPos else
                ChildType   = 'ALL'
            end
            ThisEndpointKeyID   = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
            ThisLevel           = DCount(ThisEndpoint, '/')
            For Each ResourceItem in ResourceList using @FM
                Endpoint        = ResourceItem<0, 2>
                EndpointLevel   = DCount(Endpoint, '/')
                If EndpointLevel EQ 2 then
                    EndpointParent  = 'APIROOT'
                end else
                    EndpointParent  = Field(Endpoint, '/', 1, EndpointLevel - 1)
                end
                If EndpointParent _EQC ThisEndpointKeyID then
                    EndpointType        = ResourceItem<0, 5>
                    If (EndpointType EQ ChildType) OR (ChildType EQ 'ALL') then
                        Children    := Endpoint : @FM
                    end
                end
            Next ResourceItem
        end
    end
    Children[-1, 1]  = ''

    Response    = Children

end service


//----------------------------------------------------------------------------------------------------------------------
// GetResourceSignature
//
// URLEndpoint  - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// Method       - HTTP method for the signature. This must be a valid method but it can also be empty. If empty,
//                the signature returned will simply omit the method. - [Optional]
//
// Returns the API calling signature for the indicated URL endpoint. This is used by the RunWebAPI service (a member of
// HTTP_Services) when calling the Web API module.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceSignature(URLEndpoint, Method=METHODS)

    Signature           = ''

    URLEndpointKeyID    = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)

    // Validate the HTTP method.
    Locate Method in ValidMethods$ using ',' setting MethodPos else
        Method  = ''
    end

    If URLEndpointKeyID EQ 'APIROOT' then
        Signature   = 'APIROOT.'
    end else
        ThisLevel   = DCount(URLEndpointKeyID, '/')
        For LevelCnt = 2 to ThisLevel
            Class   = HTTP_Resource_Manager_Services('GetResourceProperty', Field(URLEndpointKeyID, '/', 1, LevelCnt), 'CLASS')
            Begin Case
                Case Class EQ 'RESOURCE'
                    // A resource starts a new signature.
                    Signature   = Field(URLEndpointKeyID, '/', LevelCnt, 1) : '.'
                Case Class EQ 'RESOURCE_ID'
                    Signature  := 'ID.'
                Case Otherwise$
                    Signature  := Field(URLEndpointKeyID, '/', LevelCnt, 1) : '.'
            End Case
        Next LevelCnt
    end

    If Method NE '' then
        Signature          := Method
    end else
        Signature[-1, 1]    = ''
    end

    Response    = Signature

end service


//----------------------------------------------------------------------------------------------------------------------
// GetEndpointResourceKeyID
//
// URLEndpoint  - URL endpoint to be validated. If empty, the APIROOT resource will be returned. - [Optional]
// AllowNew     - Boolean flag indicating if a URL endpoint can be returned if new. Default is false. - [Optional]
//
// Returns the resource Key ID for the indicated URL endpoint. If AllowNew is true, a URL endpoint will be returned that
// best matches the available endpoints but it will not be cached.
//----------------------------------------------------------------------------------------------------------------------
Service GetEndpointResourceKeyID(URLEndpoint, AllowNew)

    ServiceKeyID       := '*' : URLEndpoint
    ResourceKeyID       = Memory_Services('GetValue', ServiceKeyID, True$, CacheTTL$, CacheName$)
    ResourceKeyIDFound  = True$ ; // Assume true for now.

    If AllowNew NE True$ then AllowNew = False$
    IsNew   = False$    ; // Assume false for now.

    If ResourceKeyID EQ '' then
        If (URLEndpoint EQ '') OR (URLEndpoint _EQC 'APIROOT') then
            ResourceKeyID   = 'APIROOT'
        end else
            // Make sure the URL endpoint is well formed. The intent is for the incoming URL endpoint to be forgiving but
            // internally it needs to match with the exact format of the endpoints used to uniquely identify each resource.
            Swap 'https' with '' in URLEndpoint
            Swap 'http' with '' in URLEndpoint
            HomeURL = HTTP_Services('GetHomeURL')
            Swap 'https' with '' in HomeURL
            Swap 'http' with '' in HomeURL
            APIURL  = HTTP_Services('GetAPIRootURL', False$)
            If URLEndpoint[-1, 1] EQ '/' then URLEndpoint[-1, 1] = ''
            // Remove references to the Home or API URLs since these are not used when creating the resource endpoint
            // identifiers.
            Swap HomeURL with '' in URLEndpoint
            Swap APIURL with '' in URLEndpoint
            If URLEndpoint EQ '' then
                // An empty URL endpoint implies APIROOT.
                ResourceKeyID   = 'APIROOT'
            end else
                // The URL endpoint needs to be walked one segment at a time to confirm that it matches the pattern of
                // an existing resource endpoint. Since the true URL endpoint might contains a resource ID, there needs
                // to be a check to see if the value of a given segment matches a defined resource or resource property
                // first. If not, then confirm there is a resource ID defined for this segment.
                ResourceList        = HTTP_Resource_Manager_Services('GetResourceList')
                ResourceArray       = SRP_Array('Rotate', ResourceList, @FM , @VM)
                ResourceEndpoints   = ResourceArray<2>
                ResourceNames       = ResourceArray<3>
                ResourceClasses     = ResourceArray<5>
                // Since the stored resource endpoints contain user defined resource IDs, each of these need to be
                // converted to a generic '{ResourceID}' so simple comparison logic can work.
                For Each Class in ResourceClasses using @VM setting ClassPos
                    If Class EQ 'RESOURCE_ID' then
                        OrigResourceEndpoint            = ResourceEndpoints<0, ClassPos>
                        ResourceEndpoint                = OrigResourceEndpoint
                        ResourceName                    = ResourceNames<0, ClassPos>
                        Swap ResourceName with '{ResourceID}' in ResourceEndpoint
                        Swap OrigResourceEndpoint with ResourceEndpoint in ResourceEndpoints
                    end
                Next Class
                Convert @Upper_Case to @Lower_Case in ResourceEndpoints
                Convert @Upper_Case to @Lower_Case in URLEndpoint
                // Remove any preceding "/" characters so the For Each will work
                // better.
                If URLEndpoint[1, 1] EQ '/' then URLEndpoint = URLEndpoint[2, 9999]
                MatchResourceKeyID  = ''
                // Walk the URL endpoint provided and check for matches. Build the resource Key ID along the way. If a
                // given segment is unable to be matched to a defined resource endpoint, end the loop and clear the
                // resource Key ID.
                FinalSegment    = False$
                For Each Segment in URLEndpoint using '/' setting SegmentPos
                    MatchResourceKeyID := '/' : Segment
                    Locate MatchResourceKeyID in ResourceEndpoints using @VM setting URLPos then
                        If Segment[1, 1] EQ '{' then
                            ResourceKeyID  := '/{resourceid}'
                        end else
                            ResourceKeyID  := '/' : Segment
                        end
                    end else
                        MatchResourceKeyID  = Field(MatchResourceKeyID, '/', 1, SegmentPos) : '/{resourceid}'
                        Locate MatchResourceKeyID in ResourceEndpoints using @VM setting URLPos then
                            ResourceKeyID      := '/{resourceid}'
                        end else
                            If AllowNew EQ True$ then
                                ResourceKeyID      := '/' : Segment
                                IsNew               = True$
                            end else
                                FinalSegment        = True$
                            end
                        end
                    end
                While (ResourceKeyIDFound EQ True$) AND (FinalSegment EQ False$)
                Next Segment
            end
        end

        If ResourceKeyIDFound EQ True$ then
            If IsNew NE True$ then
                Memory_Services('SetValue', ServiceKeyID, ResourceKeyID, CacheName$)
            end
        end else
            ResourceKeyID = ''
        end
    end

    Response        = ResourceKeyID

end service


//----------------------------------------------------------------------------------------------------------------------
// GetResource
//
// URLEndpoint  - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
//
// Returns an array of resource property names and values for the indicated URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service GetResource(URLEndpoint)

    URLEndpointKeyID    = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
    ServiceKeyID       := '*' : URLEndpointKeyID
    Resource            = Memory_Services('GetValue', ServiceKeyID, True$, CacheTTL$, CacheName$)

    If Resource EQ '' then
        ResourceList    = HTTP_Resource_Manager_Services('GetResourceList')
        If Error_Services('NoError') then
            // The URL endpoint needs to be walked one segment at a time to confirm that it matches the pattern of
            // an existing resource endpoint. Since the true URL endpoint might contains a resource ID, there needs
            // to be a check to see if the value of a given segment matches a defined resource or resource property
            // first. If not, then confirm there is a resource ID defined for this segment.
            ResourceArray       = SRP_Array('Rotate', ResourceList, @FM , @VM)
            ResourceEndpoints   = ResourceArray<2>
            ResourceNames       = ResourceArray<3>
            ResourceClasses     = ResourceArray<5>
            // Since the stored resource endpoints contain user defined resource IDs, each of these need to be
            // converted to a generic '{ResourceID}' so simple comparison logic can work.
            For Each Class in ResourceClasses using @VM setting ClassPos
                If Class EQ 'RESOURCE_ID' then
                    OrigResourceEndpoint            = ResourceEndpoints<0, ClassPos>
                    ResourceEndpoint                = OrigResourceEndpoint
                    ResourceName                    = ResourceNames<0, ClassPos>
                    Swap ResourceName with '{ResourceID}' in ResourceEndpoint
                    Swap OrigResourceEndpoint with ResourceEndpoint in ResourceEndpoints
                end
            Next Class
            Convert @Upper_Case to @Lower_Case in ResourceEndpoints
            MatchURLEndpointKeyID   = URLEndpointKeyID
            Convert @Upper_Case to @Lower_Case in MatchURLEndpointKeyID

            Locate MatchURLEndpointKeyID in ResourceEndpoints using @VM setting ResourcePos then
                ResourceArray   = ResourceList<ResourcePos>
                Convert @VM to @FM in ResourceArray
                NameProperty    = ResourceArray<3>
                ClassProperty   = ResourceArray<5>
                OtherProperties = ResourceArray<19>
                Convert @SVM to @FM in OtherProperties
                Convert @TM to @VM in OtherProperties
                ResourceList    = 'NAME' : @VM : NameProperty : @FM : 'CLASS' : @VM : ClassProperty : @FM : OtherProperties
                Resource        = SRP_Array('Rotate', ResourceList, @FM, @VM)
                Memory_Services('SetValue', ServiceKeyID, Resource, CacheName$)
            end
        end
    end

    Response        = Resource

end service


//----------------------------------------------------------------------------------------------------------------------
// SetResource
//
// URLEndpoint      - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// PropertyArray    - An @FM/@VM delimited array of resource property names and values for the resource. - [Required]
//
// Updates the array of resource property names and values for the indicated URL endpoint. Note, this replaces the
// existing property names and values. Other services should be used to update an existing array and then call this
// service when the array is updated. The PropertyArray must have at least one property name and value.
//----------------------------------------------------------------------------------------------------------------------
Service SetResource(URLEndpoint, PropertyArray)

    If PropertyArray NE '' then
        URLEndpointKeyID    = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint, True$)
        ResourceList        = HTTP_Resource_Manager_Services('GetResourceList')
        If Error_Services('NoError') then
            ResourceArray           = SRP_Array('Rotate', ResourceList, @FM , @VM)
            MatchURLEndpointKeyID   = URLEndpointKeyID
            Convert @Upper_Case to @Lower_Case in MatchURLEndpointKeyID
            ResourceEndpoints       = ResourceArray<2>
            Convert @Upper_Case to @Lower_Case in ResourceEndpoints
            Locate MatchURLEndpointKeyID in ResourceEndpoints By 'AL' using @VM setting ResourcePos then
                // This is an existing resource so update it.
                Resource    = ResourceList<ResourcePos>
                Convert @VM to @FM in Resource
            end else
                // This is a new resource.
                ResourceList    = Insert(ResourceList, ResourcePos, 0, 0, '')
                GoSub GetResourceTemplate
            end
            // Update the resource array with the property array data.
            PropertyNames   = PropertyArray<1>
            PropertyValues  = PropertyArray<2>
            Locate 'NAME' in PropertyNames using @VM setting PropertyPos then
                Name            = PropertyValues<0, PropertyPos>
                PropertyNames   = Delete(PropertyNames, 0, PropertyPos, 0)
                PropertyValues  = Delete(PropertyValues, 0, PropertyPos, 0)
            end else
                // If no Name is provided, use the final segment of the URL endpoint.
                Name            = URLEndpointKeyID[-1, 'B/']
                PropertyArray   = Insert(PropertyArray, 1, 1, 0, 'NAME')
                PropertyArray   = Insert(PropertyArray, 2, 1, 0, Name)
            end
            Locate 'CLASS' in PropertyNames using @VM setting PropertyPos then
                Class           = PropertyValues<0, PropertyPos>
                Locate Class in 'RESOURCE,RESOURCE_ID,PROPERTY' using ',' setting ClassPos else
                    Class                           = 'RESOURCE'
                    PropertyArray<2, PropertyPos>   = Class
                end
                PropertyNames   = Delete(PropertyNames, 0, PropertyPos, 0)
                PropertyValues  = Delete(PropertyValues, 0, PropertyPos, 0)
            end else
                // All resources are required to have a class. If none is specified then set it to 'RESOURCE'.
                Class           = 'RESOURCE'
                PropertyArray   = Insert(PropertyArray, 1, 1, 0, 'CLASS')
                PropertyArray   = Insert(PropertyArray, 2, 1, 0, Class)
            end
            Memory_Services('SetValue', ServiceModule : '*GetResource*' : URLEndpointKeyID, PropertyArray, CacheName$)
            Resource<03>                = Name
            Resource<05>                = Class
            OtherProperties             = PropertyNames : @FM : PropertyValues
            OtherPropertiesList         = SRP_Array('Rotate', OtherProperties, @FM, @VM)
            Convert @VM to @TM in OtherPropertiesList
            Convert @FM to @SVM in OtherPropertiesList
            Resource<19>                = OtherPropertiesList
            Convert @FM to @VM in Resource
            ResourceList<ResourcePos>   = Resource
            ResourcesKeyID              = HTTP_Services('GetLocalAppKeyID', ResourcesKeyID$)
            Database_Services('WriteDataRow', SetupTable$, ResourcesKeyID, ResourceList, True$, False$, True$)
        end
    end else
        Error_Services('Add', 'PropertyArray was missing from the ' : Service : ' service.')
    end

end service


//----------------------------------------------------------------------------------------------------------------------
// IsValidEndpoint
//
// URLEndpoint  - URL endpoint for the resource. If empty, a False value will be returned. - [Required]
//
// Returns a Boolean flag indicating if the indicated URL endpoint exists.
//----------------------------------------------------------------------------------------------------------------------
Service IsValidEndpoint(URLEndpoint)

    IsValidEndpoint = False$    ; // Assume False for now.

    If URLEndpoint NE '' then
        URLEndpointKeyID    = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
        If URLEndpointKeyID NE '' then IsValidEndpoint = True$
    end else
        Error_Services('Add', 'URLEndpoint argument was missing in the ' : Service : ' service.')
    end

    Response        = IsValidEndpoint

end service


//----------------------------------------------------------------------------------------------------------------------
// GetResourceList
//
// Returns the resource list for the current application.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceList()

    ResourceList    = ''

    ResourcesKeyID  = HTTP_Services('GetLocalAppKeyID', ResourcesKeyID$)
    If Error_Services('NoError') then
        ResourceList    = Database_Services('ReadDataRow', SetupTable$, ResourcesKeyID, True$, CacheTTL$, False$)
    end

    Response        = ResourceList

end service


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//----------------------------------------------------------------------------------------------------------------------
// GetResourceTemplate
//
// Returns a template for a new resource. Most of this information is needed for the NDW_HTTP_FRAMEWORK_SETUP form's
// Tree control.
//----------------------------------------------------------------------------------------------------------------------
GetResourceTemplate:

    Resource            = ''
    Resource<01>        = DCount(URLEndpointKeyID, '/')
    Resource<02>        = URLEndpointKeyID
    Resource<03>        = URLEndpointKeyID[-1, 'B/']
    Resource<04>        = 'Text' : @SVM
    Resource<05>        = ''
    Resource<06>        = ''
    Resource<07>        = 'RGB{68, 68, 68}' : @SVM : 'White'
    Resource<08>        = 'Segoe UI' : @SVM : '-12' : @SVM : '400' : @SVM : '0' : @SVM : '0' : @SVM : '0' : @SVM : '1' : @SVM : '0' : @SVM : '0' : @SVM : '0' : @SVM : '0' : @SVM : '0'
    Resource<09>        = 'Left' : @SVM : 'Center'
    Resource<10>        = 'N'
    Resource<11>        = 'None'
    Resource<12>        = 1
    Resource<13>        = 24
    Resource<14>        = 0
    Resource<15>        = 1
    Resource<16>        = 'None'
    Resource<17>        = 'Left'
    Resource<18>        = 13 : @SVM : 13

return
