//*************************************************************************** //* //* Class: cWSDataDictionary //* Package Name: cWSDataDictionary.pkg //* //* Garret Mott garret@automatesoftware.com 20140201 //* //*************************************************************************** Use DFAllEnt.pkg Use Datadict.pkg Declare_Datafile AudFiles Declare_Datafile AudDet Declare_Datafile AudInfo Register_Object oApplication Class cWSDataDictionary is a DataDictionary Procedure Construct_object Forward Send Construct_Object // Define new Properties: Property {Type} {pxName} {initial_value} Property Boolean pbReadOnlyState //Audit Properties Property String pbLogChanges False // If True - Log User changes Property String[] psaOldValues // Stores Old Values (see Backout) End_Procedure Procedure End_Construct_Object Integer iFile String sFileName Forward Send End_Construct_Object //Enable Auditing Get Main_File to iFile Get_Attribute DF_FILE_LOGICAL_NAME of iFile to sFileName Clear AudFiles Move sFileName to AudFiles.Table Find EQ AudFiles.Table If ((Found) and (AudFiles.Audit="Y")) Begin Set pbLogChanges to True Send Add_System_File AudInfo.File_Number DD_LOCK_ON_ALL Send Add_System_File AudDet.File_Number DD_LOCK_ON_ALL Send Add_System_File AudFiles.File_Number DD_LOCK_ON_ALL End Else Set pbLogChanges to False End_Procedure //Gets the View/Dialog Name Function ObjectNameOfContainer Returns String String sObjectName sDiscard Integer iPOS Get Name of (Parent(Self)) to sObjectName Repeat POS "." in sObjectName to iPOS If (not(iPOS)) Break Left sObjectName to sDiscard iPOS Replace sDiscard in sObjectName with "" Loop Function_Return sObjectName End_Function Procedure Backout Integer iNumOfFields iField String sDescription sFileName sValue Handle hDDO hFile String[] saOldValues String[] saEmpty //Auditing: Set up Array to hold old values - but only if this table is being logged If (pbLogChanges(Self)) Begin Move saEmpty to saOldValues //Clear Array Move (Self) to hDDO Get Main_File of hDDO to hFile Get_Attribute Df_File_Number_Fields of hFile to iNumOfFields For iField from 1 to iNumOfFields Get_Field_Value hFile iField to sValue Move (Trim(sValue)) to saOldValues[iField] Loop Set psaOldValues to saOldValues End Forward Send Backout End_Procedure Procedure Request_Save Integer iRightsLevel iRecNum Handle hFile Boolean bChanged bChangedRecBuff RowID riTemp // Log Changes - check if record has changed Get Main_File to hFile Get CurrentRowId to riTemp Get Should_Save of Self to bChanged If (IsNullRowId(riTemp)) Move False to bChanged //Don't log new records Forward Send Request_Save //Log Changes If (bChanged) Begin // if record is changed at all - checked BEFORE the Forward Send (bChanged, above)! If ((pbLogChanges(Self))=True) Begin // Only check if this table is being logged. Called after the Forward Send to get the new values as well as old Send DoLog False // False means NOT Deleting End End End_Procedure Procedure Request_Delete Forward Send Request_Delete // Audit: only do it if this table is being logged If ((pbLogChanges(Self))=True) Begin // Called after the forward send, as Backout gets called during Request_Delete Send DoLog True // True means Deleting End End_Procedure //This sets up a string with the Time variables as supplied: 00:00:00 Function TimeSaved Integer iHr Integer iMin Integer iSec Returns String String sHr sMin sSec sReturn Move (String(ihr)) to sHr Move (String(iMin)) to sMin Move (String(iSec)) to sSec If (Length(sHr)=1) Move ("0"+sHr) to sHr If (Length(sMin)=1) Move ("0"+sMin) to sMin If (Length(sSec)=1) Move ("0"+sSec) to sSec Move (sHr + ":" + sMin + ":" + sSec) to sReturn Function_Return sReturn End_Function //Gets the workstation Name from Windows Define MAX_COMPUTERNAME_LENGTH for 15 External_Function GetComputerNameEf "GetComputerNameA" Kernel32.Dll Pointer lpComputerName DWord nNameSize Returns Integer Function GetComputerName Global Returns String String sComputerName DWord dwNameSize Integer iRetval ZeroString MAX_COMPUTERNAME_LENGTH to sComputerName Move MAX_COMPUTERNAME_LENGTH to dwNameSize Move (GetComputerNameEf(AddressOf(sComputerName), AddressOf(dwNameSize))) to iRetval Function_Return (CString(sComputerName)) End_Function // GetComputerName //Procedure to save changes to AudInfo & AudDetl Procedure DoLog Boolean bDeleting Integer iNumOfFields iField iHr iMin iSec iAudInfoID iLogCount iRecNum String sDescription sFileName sValue sTime sLoginID Handle hDDO hFile String[] saOldValues Boolean bChanged bHeaderCreated Date dToday RowID riRecord Lock //DoLog is called from Request_Save & Request_Delete, so a lock is needed Move (Self) to hDDO Get Main_File of hDDO to hFile Get_Attribute DF_FILE_LOGICAL_NAME of hFile to sFileName Get gpsLoginID of (oApplication(Self)) to sLoginID Sysdate dToday iHr iMin iSec Get TimeSaved iHr iMin iSec to sTime //Function above Get psaOldValues to saOldValues Move 0 to iLogCount If (not(bDeleting)) Begin Move False to bHeaderCreated Get_Attribute Df_File_Number_Fields of hFile to iNumOfFields // Get_Field_Value hFile 0 to iRecNum //Get the RecNum - ignore if a Standard Table - put in if not Move (GetRowID(hFile)) to riRecord //Get the RowID - for use in DBExplorer (Ctrl+F on any record, paste value) //Header record (AudInfo) Move 1 to iAudInfoID //Find last record & increment it. If set up as an SQL Identity field, this can be removed. Clear AudInfo Move 99999999 to AudInfo.Id Find LE AudInfo.Id If (Found) Move (AudInfo.Id + 1) to iAudInfoID //End of ID Fill Clear AudInfo Move iAudInfoID to AudInfo.Id Move (Trim(sFileName)) to AudInfo.TableName Move dToday to AudInfo.CDate Move sTime to AudInfo.CTime Move sLoginID to AudInfo.User Get GetComputerName to AudInfo.WorkStation Get ObjectNameOfContainer to AudInfo.ViewName Move "N" to AudInfo.Deleted Move iRecNum to AudInfo.RecordNumber Move (SerializeRowID(riRecord)) to AudInfo.RecordRowID SaveRecord AudInfo //Detail records (AudDet) Move 0 to iLogCount For iField from 1 to iNumOfFields Get_Field_Value hFile iField to sValue If (Trim(sValue) <> saOldValues[iField]) Begin Get_Attribute DF_FIELD_NAME of hFile iField to sDescription Increment iLogCount Clear AudDet Move iAudInfoID to AudDet.AudInfoID Move sDescription to AudDet.FieldName Move saOldValues[iField] to AudDet.OldValue Move sValue to AudDet.NewValue Move iLogCount to AudDet.Num SaveRecord AudDet End Loop End Else Begin //If Deleting Move False to bHeaderCreated Move (SizeOfArray(saOldValues)) to iNumOfFields //Here we just want the old data - as there's no record, but show all Fields, even if blank //Header record (AudInfo) Move 1 to iAudInfoID Clear AudInfo Move 99999999 to AudInfo.Id Find LE AudInfo.Id If (Found) Move (AudInfo.Id + 1) to iAudInfoID Clear AudInfo Move iAudInfoID to AudInfo.Id Move (Trim(sFileName)) to AudInfo.TableName Move dToday to AudInfo.CDate Move sTime to AudInfo.CTime Move sLoginID to AudInfo.User Get GetComputerName to AudInfo.WorkStation Get ObjectNameOfContainer to AudInfo.ViewName Move "Y" to AudInfo.Deleted SaveRecord AudInfo //Detail record (AudDet) Move 0 to iLogCount For iField from 1 to (iNumOfFields-1) Increment iLogCount Get_Attribute DF_FIELD_NAME of hFile iField to sDescription Clear AudDet Move iAudInfoID to AudDet.AudInfoID Move sDescription to AudDet.FieldName Move saOldValues[iField] to AudDet.OldValue Move "" to AudDet.NewValue Move iLogCount to AudDet.Num SaveRecord AudDet Loop End Unlock End_Procedure //DoLog End_Class // cWSDataDictionary