 
/*------------------------------------------------------------------------
   File        : usersHandler
   Purpose     : 
   Syntax      : 
   Description : 
   Author(s)   : walter.riechsteiner
   Created     : Fri Nov 21 11:31:01 CET 2025
   Notes       : 
 ----------------------------------------------------------------------*/


BLOCK-LEVEL ON ERROR UNDO, THROW.

USING Progress.Json.ObjectModel.JsonObject FROM PROPATH.
USING Progress.Json.ObjectModel.JsonArray FROM PROPATH.
USING utilities.utilitiesHandler FROM PROPATH.
USING Progress.Json.ObjectModel.ObjectModelParser FROM PROPATH.
USING OpenEdge.DataAdmin.IIndex FROM PROPATH.
USING OpenEdge.Web.DataObject.Writer.JsonObjectValueWriter FROM PROPATH.

CLASS admin.adminprogsHandler FINAL:
    DEFINE VARIABLE oJsonData         AS JsonObject        NO-UNDO.
    DEFINE VARIABLE oJsonArray        AS JsonArray         NO-UNDO.
    DEFINE VARIABLE oParser           AS ObjectModelParser NO-UNDO.
    
    DEFINE VARIABLE cuser_name        AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE ccompany          AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE lcJsonString      AS LONGCHAR          NO-UNDO.
    DEFINE VARIABLE iLanguage_id      AS INTEGER           NO-UNDO.

    DEFINE VARIABLE oRecords          AS JsonArray         NO-UNDO.
    DEFINE VARIABLE oJsonPosition     AS JsonObject        NO-UNDO.
        
    DEFINE VARIABLE cFileName         AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE lCompany          AS LOGICAL           NO-UNDO.
    DEFINE VARIABLE lActive           AS LOGICAL           NO-UNDO.
    DEFINE VARIABLE lWordindex        AS LOGICAL           NO-UNDO.
    DEFINE VARIABLE cActiveSelection  AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cSortField        AS CHARACTER         NO-UNDO INIT ''.
    DEFINE VARIABLE cDirection        AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cFieldReplace     AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cKeyFieldReplace  AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cFilterReplace    AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cFileReplace      AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cKeyFields        AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cKeyValues        AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cWhere            AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cString           AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE cMessage          AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE lcMessage         AS LONGCHAR          NO-UNDO.
    
    DEFINE VARIABLE iAnzahlRecords    AS INTEGER           NO-UNDO.
    DEFINE VARIABLE iActualPage       AS INTEGER           NO-UNDO.
    DEFINE VARIABLE iMaxRecords       AS INTEGER           NO-UNDO INIT 20.
    DEFINE VARIABLE iStartPage        AS INTEGER           NO-UNDO.
    DEFINE VARIABLE iStartRecord      AS INTEGER           NO-UNDO.
    DEFINE VARIABLE iPageCounter      AS INTEGER           NO-UNDO.
    DEFINE VARIABLE iCurrentPosition  AS INTEGER           NO-UNDO.

    DEFINE VARIABLE cPrimaryKey       AS CHARACTER         NO-UNDO.
    DEFINE VARIABLE iIndex            AS INTEGER           NO-UNDO.
    DEFINE VARIABLE iStartIndex       AS INTEGER           NO-UNDO.
    
    DEFINE VARIABLE httTable          AS HANDLE            NO-UNDO.
    DEFINE VARIABLE ttTable           AS HANDLE            NO-UNDO.
    
    DEFINE VARIABLE hQuery            AS HANDLE            NO-UNDO.
    DEFINE VARIABLE hBuffer           AS HANDLE            NO-UNDO.
    
    DEFINE TEMP-TABLE ttKeyFields
        FIELD iIndex        AS INTEGER 
        FIELD cLongName     AS CHARACTER 
        FIELD cFieldName    AS CHARACTER 
        FIELD cFileName     AS CHARACTER 
        FIELD cValue        AS CHARACTER 
        FIELD cDataType     AS CHARACTER
        
        INDEX ttKeyFields-k1 IS PRIMARY 
            iIndex
            cFieldName
            .
    DEFINE VARIABLE httKeyFields    AS HANDLE NO-UNDO.
    
    DEFINE TEMP-TABLE ttPrimaryIndex
        FIELD iIndex     AS INTEGER 
        FIELD cFieldName AS CHARACTER 
        FIELD cFileName  AS CHARACTER 
        FIELD cValue     AS CHARACTER 
        FIELD cDataType  AS CHARACTER
        
        INDEX ttPrimaryIndex-k1 IS PRIMARY 
        iIndex
        cFieldName
        .
    DEFINE VARIABLE httPrimaryIndex AS HANDLE NO-UNDO.

    
    DEFINE VARIABLE outilitiesHandler AS utilitiesHandler  NO-UNDO.
    
    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC VOID buildWhere(
        INPUT oJsonIdent    AS JsonObject
        ):
            
        DEFINE VARIABLE ii           AS INTEGER   NO-UNDO.
        DEFINE VARIABLE i1           AS INTEGER   NO-UNDO.
        DEFINE VARIABLE lOK          AS LOGICAL   NO-UNDO.
        DEFINE VARIABLE cValue       AS CHARACTER NO-UNDO.
        DEFINE VARIABLE cString      AS CHARACTER NO-UNDO.
        DEFINE VARIABLE iNumerisch   AS INTEGER   NO-UNDO.
        
        DEFINE VARIABLE cSearchChars AS CHARACTER NO-UNDO INIT ''.
        DEFINE VARIABLE lSearch      AS LOGICAL   NO-UNDO.
        DEFINE VARIABLE cFields      AS CHARACTER NO-UNDO EXTENT.
        DEFINE VARIABLE cField       AS CHARACTER NO-UNDO.
        DEFINE VARIABLE cFilter      AS CHARACTER NO-UNDO.
        DEFINE VARIABLE cDBField     AS CHARACTER NO-UNDO.
        DEFINE VARIABLE cType        AS CHARACTER NO-UNDO.
        
        outilitiesHandler = NEW utilitiesHandler().
        //
        //  Ermitteln des Tabellennamens, ob die Tabelle das Feld "company" und/oder das Feld "active" enthält
        //
        outilitiesHandler:evaluateFile(
            INPUT-OUTPUT oJsonIdent     ,
            OUTPUT       cFileName      ,
            OUTPUT       lCompany       ,
            OUTPUT       lActive        ,
            OUTPUT       lWordindex     ,
            INPUT-OUTPUT httKeyFields   ,
            INPUT-OUTPUT httPrimaryIndex
            ).

        cFieldReplace    = SUBSTITUTE('&1_'         , cFileName).
        cKeyFieldReplace = SUBSTITUTE('keyfield_&1_', cFileName).
        cFilterReplace   = SUBSTITUTE('filter_&1_'  , cFileName).

        lOK = outilitiesHandler:getKeyFields(
            INPUT  oJsonIdent   ,
            OUTPUT cKeyFields   ,
            OUTPUT cKeyValues
            ).
        
        CREATE BUFFER hBuffer FOR TABLE cFileName.
        
        cuser_name  = oJsonIdent:GetCharacter('user_name').
        ccompany    = oJsonIdent:GetCharacter('company').
        cSortField  = ''.
        cDirection  = ''.
        cWhere      = ''.
        iStartPage  = 1.
        iMaxRecords = 25.
        IF oJsonIdent:HAS('page')  THEN iStartPage  = INTEGER(oJsonIdent:GetCharacter('page'))  NO-ERROR.
        IF oJsonIdent:HAS('limit') THEN iMaxRecords = INTEGER(oJsonIdent:GetCharacter('limit')) NO-ERROR.

        IF oJsonIdent:HAS('search') THEN 
        DO:
            cSearchChars = oJsonIdent:GetCharacter('search').
            cSearchChars = REPLACE(cSearchChars, '+', ' ').
            lSearch      = TRUE.
            iMaxRecords  = 100.
        END.
        iStartRecord = ((iStartPage - 1) * iMaxRecords) + 1.
        
        IF lCompany THEN cWhere = SUBSTITUTE('WHERE &1.company = &2', cFileName, QUOTER(ccompany)).
        
        IF cKeyFields <> '' THEN 
        DO:
            DO ii = 1 TO NUM-ENTRIES(cKeyFields, ';'):
                cString = ENTRY(ii, cKeyFields, ';').
                cString = REPLACE(cString, cFieldReplace, '').
                IF cString = 'company' AND lCompany THEN NEXT.
                IF cString = 'active'  AND lActive  THEN NEXT.
                cValue  = ENTRY(ii, cKeyValues, CHR(01)). 
                cString = SUBSTITUTE('&1.&2 = &3 ', cFileName, cString, cValue).
                cWhere  = cWhere + (IF cWhere = '' THEN 'WHERE ' ELSE ' AND ') + cString.
            END.
        END.
        //
        //  hat es Sortierfelder ?
        //
        IF oJsonIdent:HAS('sortField') THEN 
        DO:
            cSortField = REPLACE(oJsonIdent:GetCharacter('sortField'), cFieldReplace, '').
            cDirection = oJsonIdent:GetCharacter('sortDirection').
        END.
        //
        //  Sortfeld(er) zu den User-Daten schreiben
        //      
        outilitiesHandler:writeSortfields(
            INPUT  oJsonIdent,
            INPUT  cFileName ,
            INPUT  cSortField ,
            INPUT  cDirection 
            ).
        //
        //  Suche aus dem Suchfeld -->  geht dann über Wordindex
        //
        IF lSearch THEN
        DO:
            DO ii = 1 TO NUM-ENTRIES(cSearchChars, ' '):
                cValue     = ENTRY(ii, cSearchChars, ' ').
                iNumerisch = INTEGER(cValue) NO-ERROR.
                cWhere = cWhere + (IF cWhere = '' THEN ' WHERE ' ELSE 'AND ').
                IF  NOT ERROR-STATUS:ERROR AND
                    iNumerisch > 0         THEN cValue = SUBSTITUTE('&1&2&1', CHR(01), TRIM(STRING(iNumerisch,'>>>>>>>>9-'))).
                cWhere = cWhere + 'LOOKUP(' + QUOTER(cValue) + ', ' + cFileName + '.wordindex, " ") > 0 '. 
            END.
        END.
        //
        //  wenn nicht über Suchfeld, können Filter auf den einzelnen Tabellen-Spalten gesetzt sein
        //
        IF NOT lSearch THEN  
        DO: 
            cFields = oJsonIdent:GetNames().
            DO i1 = 1 TO EXTENT(cFields):
                cField = cFields[i1].
                IF NOT cField BEGINS 'filter_' THEN NEXT. 
                cFilter = oJsonIdent:GetCharacter(cField).
                cField  = REPLACE(cField, cFilterReplace, '').
                cType   = hBuffer:BUFFER-FIELD(cField):DATA-TYPE.
                MESSAGE 'Filter-Feld =' cField 'mit Type' cType 'und wert' cFilter.
                CASE cType:
                    WHEN 'character' THEN 
                        cFilter = QUOTER(cFilter).
                    WHEN 'logical'   THEN 
                        cFilter = STRING(cFilter,'true/false').
                    WHEN 'date'      THEN 
                        cFilter = STRING(DATE(cFilter),'99.99.9999').
                END CASE.
                cDBField = SUBSTITUTE('&1.&2', cFileName, cField).
                cWhere = cWhere
                    + (IF cWhere = '' THEN 'WHERE ' ELSE 'AND ')
                    + 'INDEX(' + cDBField + ', ' + cFilter + ') > 0 '.
            END.
        END.
        //
        //  Die Tabelle hat das Feld "active" active = FALSE --> gelöscht (inaktiv)
        //
        IF lActive THEN 
        DO:
            cActiveSelection = oJsonIdent:GetCharacter('activeFilter') NO-ERROR.
            CASE cActiveSelection:
                WHEN 'activeOnly' THEN 
                    lOK = TRUE.
                WHEN 'inactiveOnly' THEN 
                    lOK = FALSE.
                OTHERWISE 
                lOK = ?.
            END CASE.
            IF lOK <> ? THEN 
                cWhere = cWhere 
                    + (IF cWhere = '' THEN ' WHERE ' ELSE ' AND ')
                    + SUBSTITUTE('&1.active = &2 ', cFileName, STRING(lOK,'true/false')).
        END.
        //
        //  Sortierung im Where-Statement
        //
        IF NOT cDirection BEGINS 'des' THEN cDirection = ''.
        IF cSortField <> '' THEN cWhere = cWhere + 'BY ' + cSortField + ' ' + cDirection.
        //
        // TEMP-Table für die selektierten Datensätze, sollte ein Sortfeld vorhanden sein, wird dort der Primary-Index gesetzt
        //
        createTempTable(
            INPUT oJsonIdent
            ).

        RETURN.

    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC LOGICAL createData(
        INPUT  oJsonIdent  AS JsonObject,
        INPUT  oJsonRecord AS jsonObject,
        OUTPUT oJsonReturn AS JsonObject  
        ):
            
        DEFINE VARIABLE oJsonMessage    AS JsonObject NO-UNDO.
        DEFINE VARIABLE oJsonMessageBox AS JsonObject NO-UNDO.

        DEFINE VARIABLE lRetVal         AS LOGICAL    NO-UNDO.
        DEFINE VARIABLE lOK             AS LOGICAL    NO-UNDO.
        DEFINE VARIABLE ii              AS INTEGER    NO-UNDO.
        DEFINE VARIABLE i1              AS INTEGER    NO-UNDO.
        DEFINE VARIABLE iIndex          AS INTEGER    NO-UNDO.
        DEFINE VARIABLE cWordIndex      AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE hField          AS HANDLE     NO-UNDO.
        DEFINE VARIABLE htField         AS HANDLE     NO-UNDO.
        DEFINE VARIABLE cField          AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE cValue          AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE cIndexFields    AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE rBuffer AS RECID NO-UNDO.

        outilitiesHandler = NEW utilitiesHandler().
        
        httKeyFields    = TEMP-TABLE ttKeyFields   :DEFAULT-BUFFER-HANDLE.
        httPrimaryIndex = TEMP-TABLE ttPrimaryIndex:DEFAULT-BUFFER-HANDLE.
        //
        //  Ermitteln des Tabellennamens, ob die Tabelle das Feld "company" und/oder das Feld "active" enthält
        //
        outilitiesHandler:evaluateFile(
            INPUT-OUTPUT oJsonIdent     ,
            OUTPUT       cFileName      ,
            OUTPUT       lCompany       ,
            OUTPUT       lActive        ,
            OUTPUT       lWordindex     ,
            INPUT-OUTPUT httKeyFields   ,
            INPUT-OUTPUT httPrimaryIndex
            ).

        cFieldReplace    = SUBSTITUTE('&1_'         , cFileName).
        cKeyFieldReplace = SUBSTITUTE('keyfield_&1_', cFileName).
        cFilterReplace   = SUBSTITUTE('filter_&1_'  , cFileName).
        
        lOK = outilitiesHandler:getKeyFields(
            INPUT  oJsonIdent   ,
            OUTPUT cKeyFields   ,
            OUTPUT cKeyValues
            ).
        
        createTempTable(
            INPUT oJsonIdent
            ).

        httTable:READ-JSON('JsonObject', oJsonRecord) NO-ERROR.
        httTable:FIND-FIRST('', NO-LOCK).
        //        
        //  Primary-Index-Fields für WHERE-Statement
        //        
        CREATE BUFFER hBuffer FOR TABLE cFileName.
        cIndexFields = outilitiesHandler:getPrimaryIndexFields(
            INPUT cFileName
            ).
        //
        //  Erzeugen von Where-Statement für UNIQUE-Find
        //
        cWhere = ''.    
        DO i1 = 1 TO NUM-ENTRIES(cIndexFields, ';'):
            cField = ENTRY(i1, cIndexFields, ';').
            hField = httTable:BUFFER-FIELD(cField):HANDLE.
            CASE hField:DATA-TYPE:
                WHEN 'character' THEN 
                    cValue = QUOTER(hField:BUFFER-VALUE).
                WHEN 'logical'   THEN 
                    cValue = STRING(hField:BUFFER-VALUE,"true/false").
                WHEN 'date'      THEN 
                    cValue = STRING(DATE(hField:BUFFER-VALUE)).
                OTHERWISE             
                cValue = hField:BUFFER-VALUE. 
            END CASE.
            cWhere = cWhere
                + (IF cWhere = '' THEN 'WHERE ' ELSE ' AND ')
                + SUBSTITUTE('&1.&2 = ', cFileName, cField)
                + cValue.
        END.
        lRetVal = FALSE.
        REPEAT TRANSACTION ON ERROR UNDO, LEAVE:
            lOK = hBuffer:FIND-UNIQUE(cWhere) NO-ERROR. 
            IF hBuffer:AVAILABLE THEN 
            DO:
                outilitiesHandler:createErrorBox(
                    INPUT  oJsonIdent       ,
                    INPUT  '2007'           ,
                    INPUT  ''               ,
                    OUTPUT oJsonMessageBox
                    ).
                oJsonReturn = NEW JsonObject().
                oJsonReturn:ADD('success'     , FALSE          ).
                oJsonReturn:ADD('showMessage' , oJsonMessageBox).
                RETURN TRUE.
            END.
            //
            //  Datensatz erstellen / active setzen / wordindex erstellen
            //
            hBuffer:BUFFER-CREATE ().
            DO ii = 1 TO httTable:NUM-FIELDS:
                hField  = hBuffer:BUFFER-FIELD(ii):HANDLE NO-ERROR.
                IF  ERROR-STATUS:ERROR       OR
                    NOT VALID-HANDLE(hField) THEN NEXT.
                    
                htField = httTable:BUFFER-FIELD(ii):HANDLE NO-ERROR.
                IF  ERROR-STATUS:ERROR       OR
                    NOT VALID-HANDLE(hField) THEN NEXT.
                    
                hField:BUFFER-VALUE = htField:BUFFER-VALUE. 
            END.
            MESSAGE '1'.
            htField = hBuffer:BUFFER-FIELD('active'):HANDLE NO-ERROR.
            IF  NOT ERROR-STATUS:ERROR AND 
                VALID-HANDLE(htField)  THEN htField:BUFFER-VALUE = TRUE.
                
            htField = hBuffer:BUFFER-FIELD('created_at'):HANDLE NO-ERROR.
            IF  NOT ERROR-STATUS:ERROR AND 
                VALID-HANDLE(htField)  THEN htField:BUFFER-VALUE = NOW.
            
            htField = hBuffer:BUFFER-FIELD('wordindex'):HANDLE NO-ERROR.
            IF  NOT ERROR-STATUS:ERROR AND 
                VALID-HANDLE(htField)  THEN 
            DO:
                cWordIndex = outilitiesHandler:createWordindex(
                    INPUT hBuffer
                    ).
                htField:BUFFER-VALUE = cWordIndex.
            END.
            rBuffer = hBuffer:RECID.
            MESSAGE '2' rBuffer.
            hBuffer:BUFFER-RELEASE ().
            
            lRetVal = TRUE.
            LEAVE.
        END.
        //
        //  Datensatz anhand der letzten Kriterien in der Tabelle finden und Pagination ermitteln
        //
        outilitiesHandler:readPosition(
            INPUT  oJsonIdent,
            INPUT  cFileName,
            OUTPUT iCurrentPosition,
            OUTPUT iStartPage,
            OUTPUT iMaxRecords
            ).
        
        DO WHILE lRetVal:
            outilitiesHandler:readLastcWhere(
                INPUT  oJsonIdent,
                INPUT  cFileName ,
                OUTPUT cWhere
                ).
            ASSIGN 
                ii               = 0
                i1               = 0
                iAnzahlRecords   = 0
                iActualPage      = 0
                iCurrentPosition = 0
                iStartRecord     = 1.
        
            CREATE QUERY hQuery.
            hQuery:SET-BUFFERS   (hBuffer) NO-ERROR.
            hQuery:QUERY-PREPARE (cWhere)  NO-ERROR.
            hQuery:QUERY-OPEN ().
            iAnzahlRecords = hQuery:NUM-RESULTS.
            
            hQuery:GET-FIRST(NO-LOCK).
            lOK = FALSE.
            DO WHILE NOT hQuery:QUERY-OFF-END:
                ii = ii + 1.
                IF ii MOD iMaxRecords = 1 THEN iActualPage = iActualPage + 1.
                IF hBuffer:RECID <> rBuffer THEN 
                DO:
                    hQuery:GET-NEXT (NO-LOCK).
                    NEXT.
                END.
                iIndex = ii MOD iMaxRecords.
                LEAVE.
            END.
            
            iStartPage       = iActualPage.
            iStartRecord     = (iStartPage - 1) * iMaxRecords + 1.
            LEAVE.
        END.
        hQuery:QUERY-CLOSE ().
        DELETE OBJECT hBuffer NO-ERROR.
        
        IF ii = 0 THEN RETURN FALSE.

        IF lRetVal THEN 
        DO:
            oJsonPosition = NEW JsonObject().
            oJsonPosition:ADD('page' , iActualPage).
            oJsonPosition:ADD('index', iIndex - 1).     /* -1 weil in Java beginnt Index bei 0  */
        
            oJsonReturn = NEW JsonObject().
            oJsonReturn:ADD('maxRecords', iAnzahlRecords).
            oJsonReturn:ADD('position'  , oJsonPosition ).
            /*            outilitiesHandler:writePosition(*/
            /*                INPUT  oJsonIdent       ,   */
            /*                INPUT  cFileName        ,   */
            /*                INPUT  iCurrentPosition ,   */
            /*                INPUT  iStartPage       ,   */
            /*                INPUT  iMaxRecords          */
            /*                ).                          */
            
            RETURN lRetVal.
        END.

        IF NOT lRetVal THEN 
        DO:
            oJsonMessage = NEW JsonObject().
            oJsonMessage:ADD('success', FALSE).
            oJsonMessage:ADD('message', lcMessage).
            oJsonMessage:WRITE(lcJsonString, FALSE).
            
            oJsonReturn = oJsonMessage.
        END.
        
        RETURN lRetVal.

        CATCH e AS Progress.Lang.Error:

        END CATCH.

        FINALLY:

        END FINALLY.

    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC VOID createTempTable(
        INPUT oJsonIdent AS JsonObject
        ):

        DEFINE VARIABLE ii             AS INTEGER   NO-UNDO.
        DEFINE VARIABLE cFunction      AS CHARACTER NO-UNDO.
        DEFINE VARIABLE cSerializeName AS CHARACTER NO-UNDO.
        DEFINE VARIABLE cttName        AS CHARACTER NO-UNDO.        
        
        CREATE TEMP-TABLE ttTable.
        ttTable:ADD-FIELDS-FROM (cFilename, 'wordindex').   /*  Alle Felder aus dem Buffer, ausser wordindex    */
        IF cSortField <> '' THEN 
        DO:
            ttTable:ADD-NEW-INDEX ('ttTable-k1', FALSE, TRUE).     /*  UNIQUE, PRIMARY */
            IF cDirection BEGINS 'des' THEN ttTable:ADD-INDEX-FIELD ('ttTable-k1', cSortField, 'desc').
            ELSE                            ttTable:ADD-INDEX-FIELD ('ttTable-k1', cSortField).
        END.
        
        cFunction = oJsonIdent:GetCharacter('function').

        CASE cFunction:
            WHEN 'delete' THEN 
                cttName = 'record'.
            WHEN 'update' THEN 
                cttName = 'record'.
            WHEN 'change' THEN 
                cttName = 'record'.
            WHEN 'create' THEN 
                cttName = 'record'.
            OTHERWISE 
            cttName = 'records'.
        END CASE.
        ttTable:TEMP-TABLE-PREPARE (cttName).
        httTable = ttTable:DEFAULT-BUFFER-HANDLE.
        //
        //  Den Feldnamen wird für das Front-End der Tabellenname vorhergestellt (Serialize-Name)
        //
        DO ii = 1 TO httTable:NUM-FIELDS:
            CASE httTable:BUFFER-FIELD(ii):NAME:
                WHEN 'active' THEN 
                    cSerializeName = 'active'.
                OTHERWISE 
                cSerializeName = cFileName + '_' + httTable:BUFFER-FIELD(ii):NAME.
            END CASE.
            httTable:BUFFER-FIELD(ii):SERIALIZE-NAME = cSerializeName NO-ERROR.
        END.

    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC LOGICAL deleteData(
        INPUT  oJsonIdent  AS JsonObject,
        INPUT  oJsonRecord AS jsonObject,
        OUTPUT oJsonReturn AS JsonObject  
        ):

        DEFINE VARIABLE oJsonMessage    AS JsonObject NO-UNDO.
        DEFINE VARIABLE oJsonMessageBox AS JsonObject NO-UNDO.

        DEFINE VARIABLE lRetVal         AS LOGICAL    NO-UNDO.
        DEFINE VARIABLE lOK             AS LOGICAL    NO-UNDO.
        DEFINE VARIABLE ii              AS INTEGER    NO-UNDO.
        DEFINE VARIABLE i1              AS INTEGER    NO-UNDO.
        DEFINE VARIABLE cString         AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE iIndex          AS INTEGER    NO-UNDO.
        DEFINE VARIABLE cWordIndex      AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE hField          AS HANDLE     NO-UNDO.
        DEFINE VARIABLE htField         AS HANDLE     NO-UNDO.
        DEFINE VARIABLE cField          AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE cValue          AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE cIndexFields    AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE rBuffer         AS RECID      NO-UNDO.
        DEFINE VARIABLE cQueryWhere     AS CHARACTER  NO-UNDO.
        
        DEFINE VARIABLE cFunction       AS CHARACTER  NO-UNDO.

        outilitiesHandler = NEW utilitiesHandler().
        //
        //  Ermitteln des Tabellennamens, ob die Tabelle das Feld "company" und/oder das Feld "active" enthält
        //
        outilitiesHandler:evaluateFile(
            INPUT-OUTPUT oJsonIdent     ,
            OUTPUT       cFileName      ,
            OUTPUT       lCompany       ,
            OUTPUT       lActive        ,
            OUTPUT       lWordindex     ,
            INPUT-OUTPUT httKeyFields   ,
            INPUT-OUTPUT httPrimaryIndex
            ).
            
        cFieldReplace    = SUBSTITUTE('&1_'         , cFileName).
        cKeyFieldReplace = SUBSTITUTE('keyfield_&1_', cFileName).
        cFilterReplace   = SUBSTITUTE('filter_&1_'  , cFileName).
        
        lOK = outilitiesHandler:getKeyFields(
            INPUT  oJsonIdent   ,
            OUTPUT cKeyFields   ,
            OUTPUT cKeyValues
            ).
        
        createTempTable(
            INPUT oJsonIdent
            ).
        httTable:READ-JSON('JsonObject', oJsonRecord) NO-ERROR.
        httTable:FIND-FIRST('', NO-LOCK).
        //        
        //  Primary-Index-Fields für WHERE-Statement
        //        
        CREATE BUFFER hBuffer FOR TABLE cFileName.
        cIndexFields = outilitiesHandler:getPrimaryIndexFields(
            INPUT cFileName
            ).
        //
        //  Erzeugen von Where-Statement für UNIQUE-Find
        //
        cWhere = ''.    
        DO i1 = 1 TO NUM-ENTRIES(cIndexFields, ';'):
            cField = ENTRY(i1, cIndexFields, ';').
            hField = httTable:BUFFER-FIELD(cField):HANDLE.
            CASE hField:DATA-TYPE:
                WHEN 'character' THEN 
                    cValue = QUOTER(hField:BUFFER-VALUE).
                WHEN 'logical'   THEN 
                    cValue = STRING(hField:BUFFER-VALUE,"true/false").
                WHEN 'date'      THEN 
                    cValue = STRING(DATE(hField:BUFFER-VALUE)).
                OTHERWISE             
                cValue = hField:BUFFER-VALUE. 
            END CASE.
            cWhere = cWhere
                + (IF cWhere = '' THEN 'WHERE ' ELSE ' AND ')
                + SUBSTITUTE('&1.&2 = ', cFileName, cField)
                + cValue.
        END.

        lRetVal = FALSE.
        REPEAT TRANSACTION ON ERROR UNDO, LEAVE:
            lOK = hBuffer:FIND-UNIQUE(cWhere, NO-LOCK) NO-ERROR.
            IF NOT hBuffer:AVAILABLE THEN 
            DO:
                outilitiesHandler:createErrorBox(
                    INPUT  oJsonIdent       ,
                    INPUT  '2000'           ,
                    INPUT  ''               ,
                    OUTPUT oJsonMessageBox
                    ).
                oJsonReturn = NEW JsonObject().
                oJsonReturn:ADD('success'     , FALSE          ).
                oJsonReturn:ADD('showMessage' , oJsonMessageBox).
                RETURN TRUE.
            END.
            rBuffer = hBuffer:RECID.
            hBuffer:BUFFER-RELEASE ().
            
            iStartPage = INTEGER(oJsonIdent:GetCharacter('page'))  NO-ERROR.
            iIndex     = INTEGER(oJsonIdent:GetCharacter('index')) NO-ERROR.
            //
            //  Index in der Tabellenanzeige ermitteln
            //
            outilitiesHandler:readLastcWhere(
                INPUT  oJsonIdent,
                INPUT  cFileName,
                OUTPUT cQueryWhere).
            cQueryWhere = REPLACE(cQueryWhere, 'FOR', 'PRESELECT').
            CREATE QUERY hQuery.
            hQuery:SET-BUFFERS(hBuffer).
            hQuery:QUERY-PREPARE (cQueryWhere).
            /*                                                                     */
            /*            outilitiesHandler:readPosition(                          */
            /*                INPUT  oJsonIdent,                                   */
            /*                INPUT  cFileName,                                    */
            /*                OUTPUT iCurrentPosition,                             */
            /*                OUTPUT iStartPage      ,                             */
            /*                OUTPUT iMaxRecords                                   */
            /*                ).                                                   */
            hQuery:QUERY-OPEN ().
            ii     = hQuery:NUM-RESULTS.
            /*            iIndex = 0.                                              */
            /*            hQuery:REPOSITION-FORWARD(iCurrentPosition - 1) NO-ERROR.*/
            /*            hQuery:GET-NEXT (NO-LOCK).                               */
            /*            DO WHILE NOT hQuery:QUERY-OFF-END:                       */
            /*                iIndex = iIndex + 1.                                 */
            /*                IF hBuffer:RECID = rBuffer THEN LEAVE.               */
            /*                IF iIndex >= iMaxRecords   THEN LEAVE.               */
            /*                hQuery:GET-NEXT (NO-LOCK).                           */
            /*            END.                                                     */
            hQuery:QUERY-CLOSE ().
            hBuffer:BUFFER-RELEASE ().

            lOK = hBuffer:FIND-UNIQUE(cWhere, EXCLUSIVE-LOCK, NO-WAIT) NO-ERROR.
            IF hBuffer:LOCKED THEN 
            DO:
                outilitiesHandler:createLockMessage(
                    INPUT  oJsonIdent,
                    INPUT  rBuffer  ,
                    OUTPUT oJsonMessageBox
                    ).
                lcMessage = oJsonMessageBox:GetLongchar('message').
                LEAVE.
            END.
                
            DO WHILE lActive :
                hField = hBuffer:BUFFER-FIELD('active'):HANDLE NO-ERROR.
                IF  ERROR-STATUS:ERROR        OR
                    NOT VALID-HANDLE(hField) THEN LEAVE.
                hField:BUFFER-VALUE = FALSE NO-ERROR.

                hField = hBuffer:BUFFER-FIELD('updated_at'):HANDLE NO-ERROR.
                IF  NOT ERROR-STATUS:ERROR AND
                    VALID-HANDLE(hField)   THEN hField:BUFFER-VALUE = NOW.

                httTable:BUFFER-COPY(hBuffer).

                lRetVal = TRUE.
                LEAVE.                
            END.
            
            DO WHILE NOT lRetVal:
                lRetVal = hBuffer:BUFFER-DELETE ().
                LEAVE.
            END.
            
            hBuffer:BUFFER-RELEASE () NO-ERROR.
            
            IF NOT lRetVal THEN LEAVE.

            LEAVE.
        END.
                
        IF lRetVal THEN 
        DO:             
            oJsonReturn = NEW JsonObject().
            oJsonReturn:ADD('success', TRUE).
            
            oJsonPosition = NEW JsonObject().
            oJsonPosition:ADD('page'        , iStartPage).
            oJsonPosition:ADD('index'       , iIndex    ).
            oJsonPosition:ADD('totalRecords', ii        ).
            
            oJsonReturn:ADD('position', oJsonPosition).
            // oJsonReturn:WriteFile('C:\TEMP\adminprog_DELETE_Respons.json', TRUE).
            
            RETURN lRetVal.
        END.

        IF NOT lRetVal THEN 
        DO:
            oJsonMessage = NEW JsonObject().
            oJsonMessage:ADD('success', FALSE).
            oJsonMessage:ADD('message', lcMessage).
            
            oJsonMessage:WRITE(lcJsonString, FALSE).
            
            oJsonReturn = oJsonMessage.
        END.
        
        RETURN lRetVal.
        
        CATCH e AS Progress.Lang.Error:
        
        END CATCH.
        
        FINALLY:
            DELETE OBJECT oJsonArray    NO-ERROR.
            DELETE OBJECT oJsonData     NO-ERROR.
        END FINALLY.

    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC LOGICAL getChanges(
        INPUT  oJsonIdent  AS JsonObject,
        OUTPUT oJsonResult AS JsonObject
        ):
    /*
              DEFINE VARIABLE lRetVal           AS LOGICAL    NO-UNDO.
                              
              DEFINE VARIABLE cFunction         AS CHARACTER  NO-UNDO.
              DEFINE VARIABLE cField            AS CHARACTER  NO-UNDO.
              DEFINE VARIABLE cAction           AS CHARACTER  NO-UNDO.
              DEFINE VARIABLE cValue            AS CHARACTER  NO-UNDO.
              DEFINE VARIABLE lcJsonString      AS LONGCHAR   NO-UNDO.
              DEFINE VARIABLE cWhere            AS CHARACTER  NO-UNDO.
                              
              DEFINE VARIABLE i1                AS INTEGER    NO-UNDO.
              DEFINE VARIABLE i2                AS INTEGER    NO-UNDO.
                              
              DEFINE VARIABLE oJsonfieldUpdates AS JsonObject NO-UNDO.
                              
              outilitiesHandler = NEW utilitiesHandler().
                              
              cField  = oJsonIdent:GetCharacter('field').
              cAction = oJsonIdent:GetCharacter('action').
              cValue  = REPLACE(oJsonIdent:GetCharacter('value'), '+', ' ').
                      
              oJsonResult       = NEW JsonObject().
              oJsonFieldUpdates = NEW JsonObject().
                      
              lRetVal = outilitiesHandler:getKeyFields(
                  INPUT  oJsonIdent   ,
                  OUTPUT cKeyFields   ,
                  OUTPUT cKeyValues
                  ).
              cWhere     = ''.
              lRetVal    = FALSE.
              DO WHILE TRUE:
                  DO i1 = 1 TO NUM-ENTRIES(cKeyFields, ';'):
                      cWhere = cWhere
                          + (IF cWhere = '' THEN 'WHERE ' ELSE 'AND ' )
                          + SUBSTITUTE('busers.&1 = &2 ',
                          REPLACE(ENTRY(i1, cKeyFields, ';'), 'users_', ''),
                          QUOTER (ENTRY(i1, cKeyValues, CHR(01)))).
                  END.
                  MESSAGE cWhere.
                  hBuffer = BUFFER busers:HANDLE.
                  lRetVal = hBuffer:FIND-UNIQUE(cWhere, NO-LOCK) NO-ERROR.
                  IF lRetVal THEN 
                  DO:
                      CASE cField:
                          WHEN 'users_firstname' THEN 
                              DO:
                                  IF hBuffer::display_Name = '' THEN 
                                  DO:
                                      cString = cValue + ' ' + hBuffer::lastname.
                                      oJsonfieldUpdates:ADD('users_display_name', cString).
                                  END.
                                  IF hBuffer::initials = '' THEN 
                                  DO:
                                      cString = TRIM(SUBSTRING(cValue,01,02)) + TRIM(SUBSTRING(hBuffer::lastname,01,02)).
                                      oJsonfieldUpdates:ADD('users_initials', cString).
                                  END.
                              END.
                      END CASE.
                      oJsonResult:ADD('fieldUpdates', oJsonfieldUpdates).
                  END.
                              
                  lRetVal = TRUE.
                  LEAVE.
              END.
                      
              IF NOT lRetVal THEN 
              DO:
                  oJsonResult = NEW JsonObject().
                  oJsonResult:ADD('success', FALSE).
                  oJsonResult:ADD('message', 'Fehler beim change').
              END.
                                      
              RETURN lRetVal.
    */
    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC LOGICAL getData(
        INPUT  oJsonIdent  AS JsonObject,
        OUTPUT oJsonReturn AS JsonObject  
        ):
        
        DEFINE VARIABLE ii        AS INTEGER   NO-UNDO.
        DEFINE VARIABLE iAnzRec   AS INTEGER   NO-UNDO.
        DEFINE VARIABLE lRetVal   AS LOGICAL   NO-UNDO.
        DEFINE VARIABLE lOK       AS LOGICAL   NO-UNDO.
        DEFINE VARIABLE cFunction AS CHARACTER NO-UNDO.
        
        DEFINE VARIABLE oRecords  AS JsonArray NO-UNDO.

        outilitiesHandler = NEW utilitiesHandler().
        
        cFunction = oJsonIdent:GetCharacter('function').
        
        httKeyFields    = TEMP-TABLE ttKeyFields   :DEFAULT-BUFFER-HANDLE.
        httPrimaryIndex = TEMP-TABLE ttPrimaryIndex:DEFAULT-BUFFER-HANDLE.
MESSAGE 'httKeyFields' VALID-HANDLE(httKeyFields) 'httPrimaryIndex' VALID-HANDLE(httPrimaryIndex). 

        IF cFunction = 'rebuild' THEN 
        DO:
            iStartPage   = 1.
            iMaxRecords  = 25.
            IF oJsonIdent:HAS('page')  THEN iStartPage  = INTEGER(oJsonIdent:GetCharacter('page'))  NO-ERROR.
            IF oJsonIdent:HAS('limit') THEN iMaxRecords = INTEGER(oJsonIdent:GetCharacter('limit')) NO-ERROR.
            iStartRecord = ((iStartPage - 1) * iMaxRecords) + 1.
            outilitiesHandler:readLastcWhere(
                INPUT  oJsonIdent,
                INPUT  cFileName ,
                OUTPUT cWhere).
                
            createTempTable(
                INPUT oJsonIdent
                ).
        END.
        ELSE 
        DO:
            iIndex = 0.        
            buildWhere(
                INPUT  oJsonIdent 
                ).
        END.

        ii      = 0.
        iAnzRec = 0.
        ttTable:EMPTY-TEMP-TABLE ().
        CREATE QUERY hQuery.
        IF cFunction = 'loaddata' THEN 
        DO:
            cWhere = SUBSTITUTE('FOR EACH &1 NO-LOCK &2 ', cFileName, cWhere) NO-ERROR.
            outilitiesHandler:writeLastcWhere(
                INPUT  oJsonIdent ,
                INPUT  cFileName  ,
                INPUT  cWhere
                ).
        END.
        //
        //  Für das Dynamische Query wird PRESELECT verwendet für die Pagination
        //
        cWhere = REPLACE(cWhere, 'FOR', 'PRESELECT').         
        hQuery:SET-BUFFERS (hBuffer) NO-ERROR.
        hQuery:QUERY-PREPARE (cWhere) NO-ERROR.
        hQuery:QUERY-OPEN ().

        ii = hQuery:NUM-RESULTS.
        hQuery:REPOSITION-FORWARD(iStartRecord - 1) NO-ERROR.
        hQuery:GET-NEXT ().
        iCurrentPosition = 0.
        DO WHILE NOT hQuery:QUERY-OFF-END:
            IF iCurrentPosition = 0 THEN iCurrentPosition = iStartRecord.
            iAnzRec = iAnzRec + 1.
            httTable:BUFFER-CREATE().
            httTable:BUFFER-COPY(hBuffer).
            IF iAnzRec >= iMaxRecords THEN LEAVE.
            hQuery:GET-NEXT ().
        END.
        hQuery:QUERY-CLOSE ().
        DELETE OBJECT hQuery  NO-ERROR.
        DELETE OBJECT hBuffer NO-ERROR.

        iPageCounter = ii / iMaxRecords.
        IF (iPageCounter * iMaxRecords) < ii THEN iPageCounter = iPageCounter + 1.  
        oRecords = NEW JsonArray().
        httTable:WRITE-JSON('JsonArray', oRecords).

        oJsonReturn = NEW JsonObject().
        oJsonReturn:ADD('records'     , oRecords     ).
        oJsonReturn:ADD('currentPage' , iStartPage   ).
        oJsonReturn:ADD('maxRecords'  , ii           ).
        oJsonReturn:ADD('pageCount'   , iPageCounter ).
        oJsonReturn:ADD('recordCount' , iAnzRec      ).
        oJsonReturn:ADD('currentIndex', iIndex       ).
        outilitiesHandler:writePosition(
            INPUT  oJsonIdent       ,
            INPUT  cFileName        ,
            INPUT  iCurrentPosition ,
            INPUT  iStartPage       ,
            INPUT  iMaxRecords
            ).
        // oJsonReturn:WriteFile('C:\TEMP\getData_messages.json', TRUE).
        
        lRetVal = TRUE.        
        RETURN lRetVal.

    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC LOGICAL rebuildData(
        INPUT  oJsonIdent  AS JsonObject,
        OUTPUT oJsonReturn AS JsonObject  
        ):
        
        DEFINE VARIABLE ii      AS INTEGER   NO-UNDO.
        DEFINE VARIABLE lRetVal AS LOGICAL   NO-UNDO.
        DEFINE VARIABLE cValue  AS CHARACTER NO-UNDO.
        DEFINE VARIABLE lOK     AS LOGICAL   NO-UNDO.
        DEFINE VARIABLE rBuffer AS RECID     NO-UNDO.
        
        outilitiesHandler = NEW utilitiesHandler().
        
        buildWhere(
            INPUT oJsonIdent
            ).
            
        CREATE BUFFER hBuffer FOR TABLE cFileName.
        //
        //  der letzte selektierte Datensatz vor dem rebuild
        //
MESSAGE 'FIND-UNIQUE WIT cWHere' cWhere.        
        lOK = hBuffer:FIND-FIRST(cWhere, NO-LOCK) NO-ERROR.
        IF lOK THEN 
        DO:
            rBuffer = hBuffer:RECID.
        END.
        //
        // Letztes Sortfeld lesen
        //
        outilitiesHandler:readSortFields(
            INPUT  oJsonIdent,
            INPUT  cFileName ,
            OUTPUT cSortField,
            OUTPUT cDirection
            ).
        DO WHILE cSortField <> '':
            IF oJsonIdent:HAS('sortField') THEN LEAVE.
            IF cDirection BEGINS 'asc' THEN cDirection = ''.
            oJsonIdent:ADD('sortField', cSortField).
            oJsonIdent:ADD('direction', cDirection).
            
            cWhere = cWhere + ' BY ' + cSortFIeld + ' ' + cDirection.
            LEAVE.
        END.
        
        outilitiesHandler:readLastcWhere(
            INPUT  oJsonIdent,
            INPUT  cFileName ,
            OUTPUT cWhere
            ).
        cWhere = REPLACE(cWHere, 'FOR', 'PRESELECT').

        CREATE QUERY hQuery.
        hQuery:SET-BUFFERS(hBuffer).
        hQuery:QUERY-PREPARE (cWhere).
        hQuery:QUERY-OPEN ().
        iAnzahlRecords = hQuery:NUM-RESULTS.

        iCurrentPosition = 0.        
        DO WHILE NOT hQuery:QUERY-OFF-END:
            hQuery:GET-NEXT() NO-ERROR.
            IF hQuery:QUERY-OFF-END THEN LEAVE.
            
            iCurrentPosition = iCurrentPosition + 1.
            IF hBuffer:RECID = rBuffer THEN LEAVE.
        END.
        hQuery:QUERY-CLOSE ().
        DELETE OBJECT hQuery NO-ERROR.
        
        IF oJsonIdent:HAS('limit') THEN iMaxRecords = INTEGER(oJsonIdent:GetCharacter('limit')) NO-ERROR.
        iIndex = (iCurrentPosition MOD iMaxRecords) - 1.
        iStartPage = ((iCurrentPosition - (iCurrentPosition MOD iMaxRecords)) / iMaxRecords) + 1. 
        iPageCounter = ii / iMaxRecords.
        IF (iPageCounter * iMaxRecords) < ii THEN iPageCounter = iPageCounter + 1.
        
        IF oJsonIdent:HAS('page')  THEN oJsonIdent:SET('page', STRING(iStartPage)).
        ELSE                            oJsonIdent:ADD('page', STRING(iStartPage)).
        IF oJsonIdent:HAS('limit') THEN iMaxRecords = INTEGER(oJsonIdent:GetCharacter('limit')) NO-ERROR.
        
        lRetVal = getData(
            INPUT  oJsonIdent ,
            OUTPUT oJsonReturn
            ).
            
        RETURN lRetVal.

    END METHOD.

    /*------------------------------------------------------------------------------
     Purpose:
     Notes:
    ------------------------------------------------------------------------------*/

    METHOD PUBLIC LOGICAL updateData(
        INPUT  oJsonIdent  AS JsonObject,
        INPUT  oJsonRecord AS jsonObject,
        OUTPUT oJsonReturn AS JsonObject  
        ):
    
        DEFINE VARIABLE oJsonMessage    AS JsonObject NO-UNDO.
        DEFINE VARIABLE oJsonMessageBox AS JsonObject NO-UNDO.

        DEFINE VARIABLE lRetVal         AS LOGICAL    NO-UNDO.
        DEFINE VARIABLE lOK             AS LOGICAL    NO-UNDO.
        DEFINE VARIABLE ii              AS INTEGER    NO-UNDO.
        DEFINE VARIABLE i1              AS INTEGER    NO-UNDO.
        DEFINE VARIABLE iIndex          AS INTEGER    NO-UNDO.
        DEFINE VARIABLE cWordIndex      AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE hField          AS HANDLE     NO-UNDO.
        DEFINE VARIABLE htField         AS HANDLE     NO-UNDO.
        DEFINE VARIABLE cField          AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE cValue          AS CHARACTER  NO-UNDO.
        DEFINE VARIABLE cIndexFields    AS CHARACTER  NO-UNDO.
        
        DEFINE VARIABLE cFunction       AS CHARACTER  NO-UNDO.

        outilitiesHandler = NEW utilitiesHandler().
        //
        //  Ermitteln des Tabellennamens, ob die Tabelle das Feld "company" und/oder das Feld "active" enthält
        //
        outilitiesHandler:evaluateFile(
            INPUT-OUTPUT oJsonIdent     ,
            OUTPUT       cFileName      ,
            OUTPUT       lCompany       ,
            OUTPUT       lActive        ,
            OUTPUT       lWordindex     ,
            INPUT-OUTPUT httKeyFields   ,
            INPUT-OUTPUT httPrimaryIndex
            ).
            
        cFieldReplace    = SUBSTITUTE('&1_'         , cFileName).
        cKeyFieldReplace = SUBSTITUTE('keyfield_&1_', cFileName).
        cFilterReplace   = SUBSTITUTE('filter_&1_'  , cFileName).

        lOK = outilitiesHandler:getKeyFields(
            INPUT  oJsonIdent   ,
            OUTPUT cKeyFields   ,
            OUTPUT cKeyValues
            ).
        
        createTempTable(
            INPUT oJsonIdent
            ).
        httTable:READ-JSON('JsonObject', oJsonRecord) NO-ERROR.
        httTable:FIND-FIRST('', NO-LOCK).
        //        
        //  Primary-Index-Fields für WHERE-Statement
        //        
        CREATE BUFFER hBuffer FOR TABLE cFileName.
        cIndexFields = outilitiesHandler:getPrimaryIndexFields(
            INPUT cFileName
            ).
        //
        //  Erzeugen von Where-Statement für UNIQUE-Find
        //
        cWhere = ''.    
        DO i1 = 1 TO NUM-ENTRIES(cIndexFields, ';'):
            cField = ENTRY(i1, cIndexFields, ';').
            hField = httTable:BUFFER-FIELD(cField):HANDLE.
            CASE hField:DATA-TYPE:
                WHEN 'character' THEN 
                    cValue = QUOTER(hField:BUFFER-VALUE).
                WHEN 'logical'   THEN 
                    cValue = STRING(hField:BUFFER-VALUE,"true/false").
                WHEN 'date'      THEN 
                    cValue = STRING(DATE(hField:BUFFER-VALUE)).
                OTHERWISE             
                cValue = hField:BUFFER-VALUE. 
            END CASE.
            cWhere = cWhere
                + (IF cWhere = '' THEN 'WHERE ' ELSE ' AND ')
                + SUBSTITUTE('&1.&2 = ', cFileName, cField)
                + cValue.
        END.

        lRetVal = FALSE.
        REPEAT TRANSACTION ON ERROR UNDO, LEAVE:
            lOK = hBuffer:FIND-UNIQUE(cWhere) NO-ERROR. 
            IF NOT hBuffer:AVAILABLE THEN 
            DO:
                outilitiesHandler:createErrorBox(
                    INPUT  oJsonIdent       ,
                    INPUT  '2000'           ,
                    INPUT  ''               ,
                    OUTPUT oJsonMessageBox
                    ).
                oJsonReturn = NEW JsonObject().
                oJsonReturn:ADD('success'     , FALSE          ).
                oJsonReturn:ADD('showMessage' , oJsonMessageBox).
                RETURN TRUE.
            END.

            DO WHILE lActive :
                hField = hBuffer:BUFFER-FIELD('active') NO-ERROR.
                IF NOT VALID-HANDLE(hField) THEN LEAVE.
                IF hField:BUFFER-VALUE = TRUE THEN LEAVE.
                
                htField = httTable:BUFFER-FIELD('active') NO-ERROR.
                IF NOT VALID-HANDLE(htField) THEN LEAVE.

                IF hField:BUFFER-VALUE = FALSE AND htField:BUFFER-VALUE = TRUE THEN LEAVE.

                outilitiesHandler:createQuestionBox(
                    INPUT  oJsonIdent       ,
                    INPUT  '2000'           ,
                    INPUT  ''               ,
                    INPUT  'active'         ,
                    INPUT  'true'           ,
                    INPUT  hBuffer          ,
                    OUTPUT oJsonMessageBox
                    ) NO-ERROR.
                
                oJsonReturn = NEW JsonObject().
                oJsonReturn:ADD('success'     , TRUE                                ).
                oJsonReturn:ADD('record'      , oJsonRecord:GetJsonObject('record') ).
                oJsonReturn:ADD('askQuestion' , oJsonMessageBox                     ).
                RETURN TRUE.
            END.

            DO ii = 1 TO httTable:NUM-FIELDS:
                hField = hBuffer:BUFFER-FIELD(ii):HANDLE NO-ERROR.
                IF  ERROR-STATUS:ERROR       OR
                    NOT VALID-HANDLE(hField) THEN NEXT.
                htField = httTable:BUFFER-FIELD(ii):HANDLE NO-ERROR.
                IF htField:BUFFER-VALUE = hField:BUFFER-VALUE THEN NEXT.
                hField:BUFFER-VALUE = htField:BUFFER-VALUE. 
            END.

            hField = hBuffer:BUFFER-FIELD('updated_at'):HANDLE NO-ERROR.
            IF  NOT ERROR-STATUS:ERROR AND
                VALID-HANDLE(hField)   THEN hField:BUFFER-VALUE = NOW.
            
            hField = hBuffer:BUFFER-FIELD('wordindex'):HANDLE NO-ERROR.
            IF  NOT ERROR-STATUS:ERROR AND
                VALID-HANDLE(hField)   THEN 
            DO:
                cWordIndex = outilitiesHandler:createWordindex(
                    INPUT hBuffer
                    ).
                hField:BUFFER-VALUE = cWordIndex.
            END.
            
            oJsonData   = NEW JsonObject().
            oJsonArray  = NEW JsonArray ().
            httTable:BUFFER-COPY(hBuffer).
            httTable:WRITE-JSON('JsonObject', oJsonData).
    
            oJsonArray = oJsonData:GetJsonArray('record').
            oJsonData  = oJsonArray:GetJsonObject(1).
            
            hBuffer:BUFFER-RELEASE ().
            
            lRetVal = TRUE.
            LEAVE.
        END.

        IF lRetVal THEN 
        DO:             
            oJsonReturn = NEW JsonObject().
            oJsonReturn:ADD('success', TRUE     ).
            oJsonReturn:ADD('record' , oJsonData).
        
            outilitiesHandler:createInfoBox(
                INPUT  oJsonIdent       ,
                INPUT  '2003'           ,
                INPUT  ''               ,
                OUTPUT oJsonMessageBox
                ) NO-ERROR.
            oJsonReturn:ADD('showMessage' , oJsonMessageBox).
        END.

        IF NOT lRetVal THEN 
        DO:
            oJsonMessage = NEW JsonObject().
            oJsonMessage:ADD('success', FALSE).
            oJsonMessage:ADD('message', lcMessage).
            oJsonMessage:WRITE(lcJsonString, FALSE).
            
            oJsonReturn = oJsonMessage.
        END.
        
        RETURN lRetVal.

        CATCH e AS Progress.Lang.Error:

        END CATCH.

        FINALLY:

        END FINALLY.

    END METHOD.

    DESTRUCTOR PUBLIC adminprogsHandler ( ):

    END DESTRUCTOR.

END CLASS.