Module cReportDS.pkg

     1//****************************************************************************//
     2//                                                                            //
     3// $File name  : cReportDS.PKG                                                //
     4// $File title : cReportDS class                                              //
     5// $Author     : John Tuohy                                                   //
     6//                                                                            //
     7// Confidential Trade Secret.                                                 //
     8// Copyright 1991-1999 Data Access Corporation, Miami FL, USA                 //
     9// All Rights reserved                                                        //
    10// DataFlex is a registered trademark of Data Access Corporation.             //
    11//                                                                            //
    12//                                                                            //
    13//****************************************************************************//
    14
    15//************************************************************************
    16// ReportDS.Pkg
    17// Version: 1.1
    18//  Wed  11-25-1992  Created
    19//
    20// Author: John J. Tuohy
    21//
    22//************************************************************************
    23// 10/19/97 JJT - changed find_init to send clear to srvr when DD used.
    24//                Otherwise parent is not cleared and it is attached in for
    25//                a find first.
    26// 06/09/97 JJT - made mods for DD support. Request_Save in RO now sends
    27
    28//************************************************************************
    29
    30//
    31// Report_Ds - Report class that can optionally use data_sets.
    32//
    33// If Data_sets are used the report can support batch updates where files
    34// are saved and deleted (via request_save and request_delete).
    35//
    36// IMPORTANT: All constraints including "relates to" constraints MUST be
    37// handled by the data_set and not the report object (when in Rome do as the
    38// Romans). Also, the report's relate_main_file, No_Constrained_Find_State and
    39// No_relate_state are ignored - these same properties in the data_set are used
    40// instead.
    41//
    42// This class can be used as a non-data_set class (just don't set the server).
    43//
    44// New Syntax:
    45//
    46// To hook into a Data_set, three syntaxes
    47//       Object Order_Rpt is a Report_ds Using DATA_SET_NAME
    48//
    49// <or>  Object Order_Rpt is a Report_ds
    50//          Report_Data_Set DATA_SET_NAME
    51//
    52// <or>  Object Order_Rpt is a Report_ds
    53//         Set Server to DATA_SET_NAME
    54//
    55// New Public Interface:
    56//
    57//   PROPERTY: Server
    58//      This is the object ID of the data_set. If 0, the report will behave
    59//      exactly like a non_ds report. This is usually only set once and
    60//      usually when the object is created. This can be done with the USING
    61//      object command line parameter, the SET SERVER TO command, or the
    62//      RPT_DATA_SET command.
    63//
    64//   PROPERTY: Deferred_State (Default=TRUE)
    65//      This determines if accesses to the data_set causes refresh messages
    66//      to get sent to other objects using this data_set. Setting this TRUE
    67//      reduces traffic a bit. This can be set FALSE but you should know what
    68//      you are doing.
    69//
    70//   PROCEDURE: Request_Save
    71//      If sent, will save the current record. Usually sent in OnBody section.
    72//      Use Entry_Update message to make the changes during the save process.
    73//      All parent files are properly modified. This is M/U solid.
    74//
    75//   PROCEDURE: Request_Delete
    76//      If sent (usually in the body) this will delete the current record thru
    77//      the data_set. After delete the record remains unchanged in the buffer
    78//      (including the recnum). All parent files are properly updated and
    79//      all multi-user requirements are met.
    80//
    81//   PROCEDURE Entry_Update
    82//      Does nothing. This is the user hook that you fill out to make changes
    83//      the record you are saving. If this were a DEO this would get called
    84//      when you need to update from the forms to the database. This is a
    85//      manual version of this.
    86//
    87//   PROCEDURE Refresh
    88//      This is normally a stub that does nothing. A clever data_set expert
    89//      might be able to make use of this.
    90//
    91
    92use cReport.pkg
    93use DataDict.pkg
    94
    95
    96{ ClassLibrary=WebApp ClassType=Abstract }
    97{ HelpTopic=cReportDS }
    98Class cReportDS is a cReport
    99
   100  Procedure Construct_Object // Integer Img#
   101    Forward Send Construct_Object // Img#
   102
   103
   104    { DesignTime=False }
   105    Property Integer Server                    0      // data_set
   106    // When used with DDs, deferred_state will really not work properly and
   107    // should therefore be avoided.
   108    { Visibility=Private }
   109    { PropertyType=Boolean }
   110    Property Integer Deferred_State            False  // makes less traffic
   111    { Visibility=Private }
   112    { PropertyType=Boolean }
   113    Property Integer Auto_Fill_State           False  // Required not used
   114  End_Procedure  // Construct_Object
   115
   116  { MethodType=Event Visibility=Private }
   117  Procedure Refresh          // Display - required
   118  End_Procedure
   119
   120  { Visibility=Private }
   121  Procedure Entry_Update     // Update from report to datafile.
   122  End_Procedure              // User hook routine.
   123
   124  { Visibility=Private }
   125  Function Validate_items integer fg returns integer // called during request_validate to DDO
   126  End_Function
   127
   128  Procedure Request_Delete   // Supports deletes. Should be called in body
   129    Integer Srvr# iRec //                   procedure.
   130    integer iFile iStat
   131    Boolean bSupportRecnum
   132    Get Server to Srvr#
   133    If Srvr# Begin
   134       if (Deferred_State(self)) ;
   135           send Request_Assign to srvr# 0  //0 means main_file of Server
   136      // when deleted the record number is lost. Remember this number
   137      // and restore it so that findings will work properly.
   138      Get main_file of srvr# to iFile
   139      Move (IsRecnumTable(self,iFile)) to bSupportRecnum
   140      If bSupportRecnum Begin
   141          Get_Field_value iFile 0 to iRec        // compatibility w/ recnum
   142      end
   143      Send Request_Delete to Srvr#
   144      If bSupportRecnum Begin
   145        // now move rec back into file if a delete really occured
   146        Get_Attribute DF_FILE_STATUS of iFile to iStat
   147        If (iStat=DF_FILE_INACTIVE) Begin
   148            Set_Field_value iFile 0 to iRec   // compatibility w/ recnum
   149        end
   150      end
   151    End
   152  End_Procedure
   153
   154  Procedure Request_Save   // supports saves
   155    Integer Srvr#    // entry_update should handle updating.
   156    Integer NotOK
   157    Get Server to Srvr#
   158    If Srvr# Begin
   159       if (Deferred_State(self)) ;
   160           send Request_Assign to srvr# 0  //0 means main_file of Server
   161       Set Changed_state of Srvr# to TRUE
   162       Get Request_Validate of Srvr# to NotOK
   163       If NotOk Procedure_return
   164       Send Request_Save to Srvr# // note: returns ERR if error occurred
   165    End
   166  End_Procedure
   167
   168    // See notes in DoRunReport. Added in 11.1 Attaches all reports to all DDs just once in outer report
   169    { Visibility=Private }
   170    Procedure AddReportsToServer
   171        Handle hoDD
   172        Boolean bHasChildren
   173        Get pbHasChildReports to bHasChildren
   174        get Server to hoDD
   175        If hoDD Begin
   176            Send Add_User_Interface of hoDD self
   177        end
   178        if bHasChildren Begin
   179           Broadcast Send AddReportsToServer
   180        end
   181    end_Procedure
   182
   183    // See notes in DoRunReport. Added in 11.1 detaches all reports from all DDs just once in outer report
   184    { Visibility=Private }
   185    Procedure RemoveReportsFromServer
   186        Handle hoDD
   187        Boolean bHasChildren
   188        Get pbHasChildReports to bHasChildren
   189        get Server to hoDD
   190        // remove in childmost order. This is what the old behavior did, so just keep using it
   191        if bHasChildren begin
   192           Broadcast Send RemoveReportsFromServer
   193        end
   194        If hoDD Begin
   195            Send Remove_User_Interface of hoDD self
   196        end
   197    end_Procedure
   198  //
   199  //  Augmented to add this object from the Data_set's user interface
   200  //
   201  { NoDoc=True }
   202  Function DoRunReport returns integer
   203    Integer Retval
   204    // 11.1 change. The outer report will attach all child reports to their DDs at the start of the
   205    // report and not every time a child starts (this slowed down reports). This connection is only needed
   206    // if you are sending request_save from your report and you are counting on using entry_update to update
   207    // your fields. This is an old technique and is not recommended. It would be better to interact directly
   208    // with the DD using the DD interface. All of this extra work of attaching and detaching is only provided
   209    // for backwards compatibility. Also, this might make more sense in Starting_main_report, but we are keeping
   210    // it here for compatibility reasons. Otherwise, we'd just remove all of the attaching/detaching completely.
   211    // All of the above appliues to End_report.
   212    If (not(pbChildReport(self))) begin
   213        Send AddReportsToServer
   214    end
   215    forward get DoRunReport to retval
   216    Function_Return retval
   217  End_Function // DoRunReport
   218
   219  //
   220  //  Augmented to remove this object from the Data_set's user interface
   221  //
   222  { NoDoc=True }
   223  // See notes in DoRunReport about 11.1 change
   224  Function End_Report integer rpt_Status returns integer
   225    Integer Retval
   226    forward get end_report rpt_status to retval
   227    If (not(pbChildReport(self))) begin
   228        Send RemoveReportsFromServer
   229    end
   230    Function_Return retval
   231  End_Function
   232
   233  //
   234  // Procedure: Find_Init
   235  // set up this file for finding... This clears the needed buffers
   236  //
   237  { Visibility=Private }
   238  Procedure Find_Init
   239    Integer Srvr# Mode file# ndx#
   240    Get Server to Srvr#
   241    If Srvr# eq 0 Forward send Find_init
   242    Else begin
   243      Move (if(pbFindDown(self),1,3)) to Mode // LE or GE
   244      Get main_file of srvr# to File#
   245      Get piOrdering to Ndx#
   246      // 9/7/98 JJT - we do not need to set the DDO
   247      //              ordering
   248      //Set Ordering of Srvr# to Ndx#
   249      Send Rebuild_Constraints to Srvr#
   250      // we only want to clear parents of the outer report. This was changed in 11.1. The Clear
   251      // message is not needed with child reports and it can really slows things down because it
   252      // adds a lot of DD messages (even when deferred). This clear is only needed at the top report
   253      // level where a buffer may contain unknown parent data. With child reports this is controlled.
   254      If Not (pbChildReport(self)) begin
   255          Send Clear to Srvr# // this will clear needed parents as well
   256      End
   257      Constrained_Clear Mode File# BY Ndx#
   258      Send establish_find_direction to srvr# mode file# Ndx#
   259    end
   260  End_Procedure
   261
   262  //
   263  // Augment to find record in Data_set if Server exists
   264  //
   265  { Visibility=Private }
   266  Function Find_Rec Returns Integer
   267    Integer srvr# rval
   268    Integer File# Ndx# Dfrd
   269    integer iRec
   270    Get server to srvr#
   271    if srvr# eq 0 begin                 // if no server do
   272       forward get find_rec to rval     // standard finding
   273       function_return rval             // behavior
   274    end
   275    //
   276    // Server exists. Channel the Find through the data_set
   277    //
   278    Get main_file to File#
   279    Get piOrdering to Ndx#
   280    Get Deferred_State to Dfrd
   281    // if not deferred find next record and notify all other DEOs
   282    // if deferred just find the record
   283    If Dfrd eq 0 Send Request_Find to Srvr# Next_record file# Ndx#
   284    Else Send Locate_Next to Srvr#
   285    If (Found) Begin                   // set priFoundRec
   286      Set priFoundRec to (GetRowId(File#))
   287      // for compatibility sake.
   288      If (IsRecnumTable(self,File#)) begin
   289          Get_field_value File# 0 to iRec  // compatibility w/ recnum
   290          Set Found_Rec to  iRec
   291      end
   292      Function_Return RPT_OK
   293    End
   294    Function_return RPT_END
   295  End_Function
   296
   297    { Visibility=Private NoDoc=True }
   298    Procedure ReadByRowId RowId riRec
   299        Handle hoDD
   300        integer iFile eStat
   301        rowId riCrnt riDDO
   302        Boolean bSameRec
   303
   304        // optimized for 11.1: If no find is needed, don't find. If DD is up to date, leave it alone
   305        // We will not find if rec if active and is the same RowId. If DDOs and not-deferred, CurrentRowId must also match
   306
   307        Get Server to hoDD
   308        Get Main_File of (if(hoDD,hoDD,self)) to iFile // main-file from Object or DDO (if ddo)
   309
   310        // if no main file we cannot find
   311        If (iFile=0) Begin
   312            indicate Found False
   313            Procedure_Return    
   314        End
   315
   316        Get_Attribute DF_FILE_STATUS of iFile to eStat
   317        Move (eStat<>DF_FILE_INACTIVE) to bSameRec
   318        If bSameRec begin
   319            Move (GetRowID(iFile)) to riCrnt
   320            Move (IsSameRowId(riRec,riCrnt)) to bSameRec
   321            Indicate Found True // you should not rely on this - but just in case.
   322        End
   323
   324        If not hoDD begin
   325            If not bSameRec Begin
   326                Forward send ReadByRowId riRec
   327            end
   328        end
   329        Else Begin
   330            If (Deferred_state(self)) begin
   331                If not bSameRec begin
   332                    Send ReadbyRowId of hoDD iFile riRec // if deferred
   333                End
   334            end
   335            Else Begin
   336                Get CurrentRowId of hoDD to riDDO
   337                If ( Not(bSameRec) or Not(IsSameRowId(riRec,riDDO)) ) begin
   338                    Send FindByRowId of hoDD iFile riRec // if not deferred
   339                End
   340            end
   341        End
   342    End_procedure
   343//    Procedure ReadByRowId RowId riRec
   344//        Handle hoDD
   345//        integer iFile
   346//        Get Server to hoDD
   347//        If not hoDD begin
   348//            Forward send ReadByRowId riRec
   349//        end
   350//        Else Begin
   351//            Get Main_File of hoDD to iFile
   352//            If (Deferred_state(self)) begin
   353//                Send ReadbyRowId of hoDD iFile riRec // if deferred
   354//            end
   355//            Else Begin
   356//                Send FindByRowId of hoDD iFile riRec // if not deferred
   357//            end
   358//        End
   359//    End_procedure
   360
   361
   362//  //
   363//  //  Procedure : Read_By_RecNum
   364//  //              Augmented to direct read to server
   365//  //
   366//  //Doc/ Visibility=Private
   367//  Procedure Read_by_RecNum Integer Rec#
   368//    Integer srvr# File#
   369//    Get Server to Srvr#
   370//    If Srvr# eq 0 Forward send Read_by_Recnum Rec#
   371//    Else Begin
   372//      Get Main_File of Srvr# to File#
   373//      If (Deferred_state(self)) ;
   374//           Send Read_by_Recnum to srvr# File# rec# // if deferred
   375//      Else Send Find_by_Recnum to srvr# File# rec# // if not deferred
   376//    End
   377//  End_procedure
   378
   379  //**Procedure rebuild_constraints
   380  //**  Integer srvr#
   381  //**  Get server to srvr#
   382  //**  if srvr# eq 0 forward send rebuild_constraints
   383  //**  Else Begin
   384  //**    send rebuild_constraints to srvr#
   385  //**    if (Constrain_by_Report_State(self)) Send constrain
   386  //**  End
   387  //**End_procedure
   388  //**
   389  //**Procedure constrain
   390  //**  integer srvr# file# Prnt_srvr#
   391  //**  Get server to srvr#
   392  //**  If Srvr# eq 0 Forward send constrain // this'll set object relates to constraint
   393  //**  else begin
   394  //**    if (pbChildReport(self)) begin
   395  //**       delegate get Server to Prnt_srvr#
   396  //**       CONSTRAIN (Main_File(srvr#)) RELATES TO ;
   397  //**          (if(prnt_srvr#=0,;
   398  //**               Main_File(Parent(self)), Main_file(Prnt_Srvr#)))
   399  //**    end
   400  //**  end
   401  //**End_Procedure
   402
   403  //
   404  // Augment to set Report Object's main_file if server exists
   405  //
   406  Procedure End_Construct_Object
   407    Integer Srvr# File#
   408    Get Server to Srvr#
   409    If Srvr# Begin
   410       Get Main_file of Srvr# to File#
   411       Set Main_File to File#
   412    End
   413    Forward Send End_Construct_Object
   414  End_Procedure
   415
   416
   417End_Class
   418
   419
   420//
   421//  Set a report's dataset
   422//
   423#COMMAND Report_Data_Set R .
   424   #IFDEF !1
   425     set Server to !1
   426   #ELSE
   427     set Server to !1.obj
   428   #ENDIF
   429#ENDCOMMAND
   430