Sw4   >   Tools   >   Tools (All Contents)

Tools

This section covers various object classes in StudioWorks that help are classified as tools.

Encrypt/Decrypt

The Omnis Studio blowsfish external object can be used to encrypt and decrypt strings. The oEncryptDecrypt object in swBase4 provides you with several methods that make it very easy to use the blowfish external object.

The oEncryptDecrypt object can be used to encrypt (and later decrypt) a string, row, or list.

The following pairs of public methods accomplish this.

To use the oEncryptDecrypt object.

  1. Add a local variable oEncryptDecrypt to your method.
  2. Set the data type to object, and point it to the oEncryptDecrypt object in swBase4.
  3. To encrypt a list, enter the following code:

    ; Encrypt the list.
    Do oEncryptDecrypt.$encryptList(List) Returns EncryptedBinVar

  4. To decrypt the list, enter the following code:

    ; Decrypt the list.
    Do oEncryptDecrypt.$decryptList(EncryptedBinVar) Returns List

The oEncryptDecrypt object has a default encryption key. You can get and set the key using the applicable $:EncryptionKey property methods. The exact same encryption key is needed to encrypt and decrypt the string, row, or list.

Export/Import Data

The object class oExportImportData can be used to export a list of records to a file.

The default export/import format when the object is instantiated is a tab delimited text file. You can change the format by assigning a different export format constant.

; Set the export format to be used for export and import operations.
Do oExportImportData.$:ExportFormat.$assign(kEXcommas)

Tip

The export formats are listed in the F9 > Constants

The following code shows how you might use this object to export a list of records to a file.

; Export a list of records to a tab delimited file.

; Prompt the user for a file directory and name.
Calculate Title as "Export Data File Name and Location"
Calculate FilePath as con('ExportRecords.txt')

; FileOps.$putfilename(path[,prompt,filter,initial-directory,appflags])
Do FileOps.$putfilename(FilePath,Title,,cLastFilePath) Returns FlagOK
If not(FlagOK)
   
   ; User has cancelled. Not an error.
   Calculate FlagOK as kTrue
   
Else
   
   ; Remember the last file path for the next prompt.
   Calculate cLastFilePath as FilePath
   
   ; Export the data.
   ; $exportList(pfList,pFilePath,pbInclColNames)
   Calculate bInclColNames as kTrue
   Do oExportImportData.$exportList(ExportList,FilePath,bInclColNames) Returns FlagOK
   
End If

If not(FlagOK)
   Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK

Warning

The $exportList method will automatically overwrite the specified file if it exists.

Open File

The oOpenFile object will open a specified file in the user's default application for the file type. e.g. A PDF file would be opened in Adobe Acrobat Reader or Preview.

; Prompt the user to select a file.
Do FileOps.$getfilename(FilePath,'Select a PDF or Text file to open') Returns bFileSelected
Calculate FlagOK as kTrue ;; Preset the flag to true.
If bFileSelected
   
   ; Open the file.
   Do oOpenFile.$openFile(FilePath) Returns FlagOK
End If

If not(FlagOK)
   Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK

Click the Run Demo button in the StudioTips Browser to try it out. Feel free to copy and paste the code.

The oOpenFile object also has a series of $setFileInfo... methods which can be used to set the file info on the Mac platform and extension so that the file will be opened with the correct application when the user double-clicks on the file to open it up.

Do oOpenFile.$setFileToEXCEL(FilePath) Returns FlagOK
Do oOpenFile.$setFileToHTML(FilePath) Returns FlagOK
Do oOpenFile.$setFileToJPG(FilePath) Returns FlagOK
Do oOpenFile.$setFileToPDF(FilePath) Returns FlagOK
Do oOpenFile.$setFileToWORD(FilePath) Returns FlagOK

Open URL

The oOpenURL object will open a specified URL in the user's default web browser.

Calculate URL as 'www.vencor.ca'

; Open the URL in the user's default browser.
Do oOpenURL.$openURL(URL) Returns FlagOK
If not(FlagOK)
   Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK

Click the Run Demo button in the StudioTips Browser to try it out. Feel free to copy and paste the code.

Version Objects

The object class, oVersions, contains the version information for each library.

The versions object have property methods which return information about the current version of the library.

  1. $:ReleaseDate - The latest release date as a string in the format yyyy-mm-dd[b]. (e.g. 2005-06-21b)
  2. $:ReleaseDatesList - A list which includes the release date for each release.

    The oConstants.$:AppLibsList method sends a $:Version message to each oVersions object and includes the return value in the application libraries list.

The versions objects are subclassed from swBase4.oVersions_abstract. The $:Release... property methods should be overridden in the subclass and the return values set as applicable for the containing library.

The versions object action method $retModsList returns a list of all the modifications made in the library. Parameters allow the sender to specify the date range to be included. The modifications list is compiled from the @MOD tags found the the methods of classes contained in the library.

The @MOD tags must be in the format:

; @MOD:1 Information about the 1st modification to the method. ;; yyyy-mm-dd Developer Name
; @MOD:1 Additional information about the same modification ;; yyyy-mm-dd Developer Name

; @MOD:2 Information about the 2nd modification to the method. ;; yyyy-mm-dd Developer Name

Tip

StudioWorks developers can add $update... methods to the versions objects. The $update... methods could include code that needs to be run when upgrading the application from one version to then next. The main library startup task could have a method which checks the current version and if necessary runs the applicable oVersion object update methods.

Programmer Workbench

This information on the Programmer Workbench is being documented to help me (Doug K) remember the structure and strategy for cascading updates and saving module data.

Module Data

All of the cached lists which you edit/update in the Programmers Workbench are saved to the oModuleData objects in the various libraries.

StudioWorks always to keep each module (library) portable, so that it can easily be copied from one StudioWorks app to another. The cached lists are therefore split and stored in the various oModuleData objects based on each line's home library.

The oModuleData object in each library is used to store the various cached lists applicable to that library. The $userinfo property of the oModuleData object is used to store the cached lists. A row variable, with one column for each cached list is copied to the $userinfo property.

The oModuleDataTool object class in swBase4 is the central access point for saving and getting cached lists.

Here are the cached lists used by StudioWorks:

  1. Schema classes meta-data
  2. Schema columns meta-data
  3. Query classes meta-data
  4. Query columns meta-data
  5. Window instances list
  6. Navigation Menu list, Groups list, Subgroups list
  7. Window Menu Lines list
  8. String Tables list
  9. Icons list
  10. Report Instances list

Cascading Updates

Changes made to schema meta-data can cascade to other schema meta-data, query meta-data, string tables, window instances, navigation menus, and window menus.

Changes made to window instances can cascade to navigation menus, and window menus.

Because of these cascading dependencies a structure needs to be in place to ensure that changes are properly cascaded from one cached list to another.

If a developer uses the VCS, this adds complexity to cascading updates. A schema class in one library and the oModuleData object class in that library might be checked out of the VCS, but a query class in the same or another module that contains columnns of the schema class might not be checked out of the VCS.

When a cascading update occurs the classes that are not checked out will be a problem. We won't know about the problem till we get to down to that class in the cascading updates chain. We therefore need to be able to emulate manual transactions, with commit and rollback ability for all of the cached lists.

Save/Commit/Rollback

To be able to emulate manual transactions with commit/rollback capability each cached list is set to be a smartlist immediately after it is built/loaded. The smartlist property is then used for tracking changed lines and thereby allowing us to know which module data needs to be saved. The smartlist also gives us the opportunity to rollback ($undowork) in the event of a problem, or commit ($savelistwork) if all goes well.

Each model has 3 public methods that relate to saving changes made to the model:

  1. $saveChangedData_manualtrans - This method really only tests to make sure the required oModuleData objects can be modified. It doesn't actually execute saving the modified cached list lines to the various oModuleData objects.
  2. $saveChangedData_commit - This method actually saves the modified cached list lines to the required oModuleData objects and issues a $savelistwork to the applicable smartlists.
  3. $saveChangedData_rollback - This method issues a $undowork to all of the applicable smartlists, reverting them to their previous state. Because the $saveChangedData_rollback reverses all previous changes it is vitally important to do a save and commit or rollback immediately after each modification.

None of the other method in the models can issue or call a save.

Knowing when and where to save, commit or rollback is very confusing at the model level because one model property method might call several other model property methods, which then in turn might call a few other model property methods. Any of those properties could cascade updates to other models. You can never be sure at the model level which property method was the first one to be called.

The only way to I can figure to avoid a tangled web of knowing when and where to save/commit/rollback is to control it from the source method in the Programmer Workbench cached list editors. The $event method where the value is modified triggers assigning the first cached list property... the chain of cascading updates can then go as far as it likes, eventually returning to the $event method.

If we only issue the saves from the view when the view changes a value (#MODIFIED), we can be sure that only one save/commit/rollback will be executed when a value is changed by the developer in the Programmer Workbench.

A $saveChangedDataAndCommitOrRollback method is added to each controller. The controller sends a $saveChangedData_manualtrans(bCascade=kTrue) message to the appropriate task variable, The task variable then forwards the message to its model(s). If changes to a task's models cascade to other models, then the task variable also forwards the message to the task variables which instantiate those models. To avoid looping, when one task variable forwards the message to another task variable the bCascade parameter is set to kFalse. If the manual save is successful the controller immediately issues a $saveChangedData_commit. If the manual save is not successful the controller immediately issues a $saveChangedData_rollback.

When a value is changed by a view, it sends a $saveChangedDataAndCommitOrRollback message to its controller. If all the saves are successful the flag is returned true. If the not, the changes are rolled back and flag false is returned to the sender method in the view and the view prompts the user with the appropriate error message. (The error will likely be a class that needs to be checked out of the VCS, if the VCS is being used by the developer.)