/********************************************************************** * 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 = "":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.