/**********************************************************************
 * Copyright (C) 2006-2014 by Consultingwerk Ltd. ("CW") -            *
 * www.consultingwerk.de and other contributors as listed             *
 * below.  All Rights Reserved.                                       *
 *                                                                    *
 *  Software is distributed on an "AS IS", WITHOUT WARRANTY OF ANY    *
 *   KIND, either express or implied.                                 *
 *                                                                    *
 *  Contributors:                                                     *
 *                                                                    *
 **********************************************************************/ 
/*------------------------------------------------------------------------
    File        : OrderDataAccess
    Purpose     : 
    Syntax      : 
    Description : 
    Author(s)   : Mike Fechner / Consultingwerk Ltd.
    Created     : 10.02.2015 12:30:02 
    Notes       : 
  ----------------------------------------------------------------------*/

ROUTINE-LEVEL ON ERROR UNDO, THROW.

USING Consultingwerk.* FROM PROPATH.
USING Consultingwerk.* FROM PROPATH.
USING Consultingwerk.* FROM PROPATH.
USING Consultingwerk.OERA.* FROM PROPATH.
USING Consultingwerk.Util.* FROM PROPATH.
USING Consultingwerk.Util.* FROM PROPATH.

@BusinessEntityGenerator (entityname="Test.Automate.Order.OrderBusinessEntity", type="DataAccess") .

CLASS Test.Order.OrderDataAccess 
    INHERITS DataAccess
    USE-WIDGET-POOL: 

    { Test/Automate/Order/dsOrder.i &ACCESS="PRIVATE" &REFERENCE-ONLY="REFERENCE-ONLY"}

    @DefineDataSourcesStart.
    DEFINE PRIVATE DATA-SOURCE src_Order FOR Order .
    @DefineDataSourcesEnd.

    /* Alternative data-source by Order and OrderLine */
    DEFINE VARIABLE cFilterCase AS CHARACTER NO-UNDO INIT "":U.

    DEFINE VARIABLE hDynDataSourceQuery  AS HANDLE NO-UNDO .
    DEFINE VARIABLE hDynDataSource       AS HANDLE NO-UNDO .
    DEFINE VARIABLE hDynDataSourceBuffer AS HANDLE NO-UNDO EXTENT .

    /*------------------------------------------------------------------------------
        Purpose: Constructor for the OrderDataAccess class                                                                      
        Notes:   Used by the BusinessEntity, will receive the handle of the dataset
                 instance form the BusinessEntity as a parameter. Permanently BIND's
                 to that dataset using the PRIVATE BindDataset Method.                                                                        
        @param phDataset The handle of the Business Entity dataset 
    ------------------------------------------------------------------------------*/
    CONSTRUCTOR PUBLIC OrderDataAccess (phDataset AS HANDLE):
        SUPER (INPUT phDataset).
        
        BindDataset (DATASET-HANDLE phDataset BIND) .
        
        /* Fields that are not assigned to the database record when a new record is created. */
        /* THIS-OBJECT:AssignSkipList = "<key fields>":U. */

        /* Mike Fechner, Consultingwerk Ltd. 01.07.2014
           SCL-334: By default, prepare queries of joined data source 
                    queries. This behavior is the new default, and should
                    only be set to FALSE, when customers are already manipulating
                    the data-source query in code (e.g. QUERY-PREPARE in a BEFORE-FILL
                    call back) */
        THIS-OBJECT:PrepareJoinedChildTableQueries = TRUE . 
        
    END CONSTRUCTOR.

    /*------------------------------------------------------------------------------
        Purpose: Attaches the DATA-SOURCE objects to the ProDataset Buffers                                                                      
        Notes:   Overrides ABSTRACT method in Consultingwerk.OERA.DataAccess,
                 Invoked in FetchData and SaveChanges
    ------------------------------------------------------------------------------*/
    METHOD OVERRIDE PROTECTED VOID AttachDataSources ():
        
        Consultingwerk.Util.DatasetHelper:SetTrackingChanges (DATASET dsOrder:HANDLE, FALSE) .
        
        CASE cFilterCase:
            WHEN "OrderLine" THEN DO:
            
                EXTENT (hDynDataSourceBuffer) = ? . 
                EXTENT (hDynDataSourceBuffer) = 2 .
        
                CREATE BUFFER hDynDataSourceBuffer[1] FOR TABLE "Order" . 
                CREATE BUFFER hDynDataSourceBuffer[2] FOR TABLE "OrderLine" . 
        
                CREATE QUERY hDynDataSourceQuery . 
                hDynDataSourceQuery:ADD-BUFFER (hDynDataSourceBuffer[1]) . 
                hDynDataSourceQuery:ADD-BUFFER (hDynDataSourceBuffer[2]) . 
        
                CREATE DATA-SOURCE hDynDataSource . 
                hDynDataSource:QUERY = hDynDataSourceQuery . 

                THIS-OBJECT:AttachDataSource (BUFFER eOrder:HANDLE,
                                              hDynDataSource, "Ordernum,Order.Ordernum,CustNum,Order.CustNum,OrderDate,Order.OrderDate,ShipDate,Order.ShipDate,PromiseDate,Order.PromiseDate,
                                              Carrier,Order.Carrier,Instructions,Order.Instructions,PO,Order.PO,Terms,Order.Terms,SalesRep,Order.SalesRep,BillToID,Order.BillToID,ShipToID,Order.ShipToID,
                                              OrderStatus,Order.OrderStatus,WarehouseNum,Order.WarehouseNum,Creditcard,Order.Creditcard":U) .

            END.
            
            OTHERWISE DO:
        
        @AttachDataSourcesStart.
        THIS-OBJECT:AttachDataSource (BUFFER eOrder:HANDLE,
                                      DATA-SOURCE src_Order:HANDLE, "Ordernum,Order.Ordernum,CustNum,Order.CustNum,OrderDate,Order.OrderDate,ShipDate,Order.ShipDate,PromiseDate,Order.PromiseDate,
                                              Carrier,Order.Carrier,Instructions,Order.Instructions,PO,Order.PO,Terms,Order.Terms,SalesRep,Order.SalesRep,BillToID,Order.BillToID,ShipToID,Order.ShipToID,
                                              OrderStatus,Order.OrderStatus,WarehouseNum,Order.WarehouseNum,Creditcard,Order.Creditcard":U) .

        @AttachDataSourcesEnd.

            END.
        END CASE . 
        
    END METHOD.

    /*------------------------------------------------------------------------------
        Purpose: Do nothing, just receive the parameter and bind to the received 
                 Dataset reference                                                                    
        Notes:   Invoked from the class constructor   
        @param dsOrder DATASET to bind to                                                                     
    ------------------------------------------------------------------------------*/
    METHOD PRIVATE VOID BindDataset (DATASET dsOrder BIND):
        /* NOOP */
    END METHOD.

    /*------------------------------------------------------------------------------
        Purpose: TO-DO: Subscribe to ProDataset Event Handlers using SET-CALLBACK
                 as needed                                                                      
        Notes:   Overrides ABSTRACT method in Consultingwerk.OERA.DataAccess,
                 Invoked in FetchData, note that the callback methods need to be 
                 PUBLIC and need to have the Dataset defined as an INPUT Parameter.
                 Errors thrown from or raised in the FILL call-back methods of the 
                 DataAccess class (SET-CALLBACK) will stop the Dataset from getting 
                 filled / filled further. However errors thrown from the call-back 
                 methods are not thrown from the FILL() method further up into a 
                 catch block or to the client.  
                 See http://knowledgebase.progress.com/articles/Article/P188375
        Sample:  BUFFER eCustomer:SET-CALLBACK (Consultingwerk.DatasetBufferCallbackEnum:AfterFill,
                                                "eCustomerAfterRowFill":U) .                 
    ------------------------------------------------------------------------------*/
    METHOD OVERRIDE PROTECTED VOID DefineReadEvents ():
        
    END METHOD.

    /*------------------------------------------------------------------------------
        Purpose: Detaches the DATA-SOURCE objects to the ProDataset Buffers                                                                      
        Notes:   Overrides ABSTRACT method in Consultingwerk.OERA.DataAccess,
                 Invoked in FetchData and SaveChanges
    ------------------------------------------------------------------------------*/
    METHOD OVERRIDE PROTECTED VOID DetachDataSources ():

        DEFINE VARIABLE i AS INTEGER NO-UNDO.

        Consultingwerk.Util.DatasetHelper:SetTrackingChanges (DATASET dsOrder:HANDLE, FALSE) .
    
        @DetachDataSourcesStart.
        BUFFER eOrder:DETACH-DATA-SOURCE () .        
        @DetachDataSourcesEnd.
        
        FINALLY:
             /* Delete dynamic DATA-SOURCE and supporting object handles */
            IF cFilterCase > "":U THEN DO:

                GarbageCollectorHelper:DeleteObject(hDynDataSource) .
                GarbageCollectorHelper:DeleteObject(hDynDataSourceQuery) .

                DO i = 1 TO EXTENT (hDynDataSourceBuffer):
                    GarbageCollectorHelper:DeleteObject(hDynDataSourceBuffer[i]) .
                END.

                EXTENT (hDynDataSourceBuffer) = ? . 
            END.
        END FINALLY.
        
    END METHOD.

	/*------------------------------------------------------------------------------
	    Purpose:
	    Notes:
	------------------------------------------------------------------------------*/
	METHOD OVERRIDE PUBLIC VOID FetchData (poFetchDataRequest AS Consultingwerk.OERA.IFetchDataRequest):

        DEFINE VARIABLE oQueryParser     AS QueryParser      NO-UNDO . 
        DEFINE VARIABLE oQueryExpression AS IQueryExpression NO-UNDO . 
        DEFINE VARIABLE cQueryString     AS CHARACTER        NO-UNDO .
    
        /* Only try to filter by OrderLine.Item, when eOrder is the first requested table */    
        IF ENTRY (1, THIS-OBJECT:ExpandTables (poFetchDataRequest:Tables)) = "eOrder":U THEN DO:
        
            cQueryString = ENTRY (1, poFetchDataRequest:Queries, CHR(1)) . 

            /* Parse QueryString of the request into a list of query predicates */
            oQueryParser = NEW QueryParser () .
            oQueryExpression = oQueryParser:ParseQueryString (cQueryString) .

            /* Filter by eOrder.ItemNum? */
            IF VALID-OBJECT (QueryExpression:FindQueryExpressionForBufferField (BufferHelper:ParseFieldName ("eOrder.ItemNum":U),
                                                                                oQueryExpression)) THEN 
                                                                                
                ASSIGN cFilterCase = "OrderLine":U .                                                                                 

        END.
		
		SUPER:FetchData(INPUT poFetchDataRequest).

        FINALLY:
            ASSIGN cFilterCase = "":U . 		
        END FINALLY.

	END METHOD.

    /*------------------------------------------------------------------------------
        Purpose: Returns the database field name matching a temp-table field name
                 contained in a consumers query string (query string vs. temp-table
                 definition) 
        Notes:   Call-back used by Consultingwerk.OERA.Query.DSQueryString (part of 
                 DataAccess:FetchData () query preparation                        
                 TO-DO: Provide code for alternative mapping                                             
        @param pcTable The temp table name to return the source (database table) field name for
        @param pcColumn The temp table column name to return the source (database table) field name for             
        @return The database field name mapped to the passed in temp-table field
    ------------------------------------------------------------------------------*/
    METHOD OVERRIDE PUBLIC CHARACTER SourceColumn (pcTable AS CHARACTER, pcColumn AS CHARACTER):

        DEFINE VARIABLE cMap  AS CHARACTER NO-UNDO.
        DEFINE VARIABLE iPos  AS INTEGER   NO-UNDO .
            
        IF pcTable = "eOrder" AND pcColumn = "eOrder.ItemNum" THEN 
            RETURN "OrderLine.ItemNum" . 
            
        @SourceColumnCaseBlock.
        CASE pcTable:
            WHEN "eOrder":U THEN
                cMap = BUFFER eOrder:DATA-SOURCE-COMPLETE-MAP . 

        END.
     
        ASSIGN iPos = LOOKUP(pcColumn, cMap) .
        
        IF iPos MODULO 2 = 1 THEN  
            RETURN ENTRY(LOOKUP(pcColumn,cMap) + 1,cMap).    
        ELSE 
            RETURN "":U . 

    END METHOD.

    /*------------------------------------------------------------------------------
        Purpose: Returns the base query string used to retrieve data for the temp
                 tables. This query string will be appended by the query provided by
                 the consumer (FetchDataRequest object).                                                                      
        Notes:   Call-back used by Consultingwerk.OERA.Query.DSQueryString (part of 
                 DataAccess:FetchData () query preparation                        
                 TO-DO: Provide code to return the DATA-SOURCE root query string                                             
        @param pcTable The temp table name to return the source default (database) query string for
        @return The base query string used to retrieve data for the given temp-table
    ------------------------------------------------------------------------------*/
    METHOD OVERRIDE PUBLIC CHARACTER SourceDefaultQuery (pcTable AS CHARACTER):
    
        IF cFilterCase = "OrderLine" THEN 
            RETURN "FOR EACH Order, FIRST OrderLine WHERE OrderLine.OrderNum = Order.OrderNum use-index OrderLine INDEXED-REPOSITION":U . 
    
        @SourceDefaultQueryCaseBlock.
        CASE pcTable:
            WHEN "eOrder":U THEN
                RETURN "FOR EACH Order INDEXED-REPOSITION":U. 

        END. 
        
    END METHOD.

END CLASS.
