View RSS Feed

Development Team Blog

Inside the Studio: DD Classes and Create New Wizards (part 3)

Rate this Entry
In the previous article I explained how to access the workspace paths in a Create New wizard. The information is retrieved via the Studio Workspace file (.sws) that is passed to the wizard via a temporary config file. Accessing the wizard's temporary config file is explained in part one of this series.

In this article I will talk about the DDClassList temporary file that is also created before the wizard is launched. The DDClassList file contains information about each data dictionary class that is used in the current workspace. The name and location of this file is also located in the temporary config file which is passed to the wizard.

Disclaimer: The information presented here describes implementation details that are undocumented and are internal to the Studio. Feel free to use this information as you require but at your own risk. Data Access does not pretend to support these techniques and reserves the right to change the way this works at their discretion.

The DDClassList File

The name and location of the file containing the list of data dictionary classes can is stored in the [DDClassList] section of the temp Config file that is passed to your Create New wizard. An explanation this temp Config file and how to read its contents can be found in Part One of this series.

Code:
[DDClassList]
File=C:\Users\John-h\AppData\Local\Temp\DF5085.tmp
The DDClassList file is an XML document with the following node structure....

Code:
<WizardDataDictionaryList>
    <DDClasses>
        <DDClass>
            <tableNumber>
            <tableName>
            <className>
            <classFile>
where...

<WizardDataDictionaryList> is the xml document's root node.
<DDClasses> this node contains a collection of DDClass nodes.
<DDClass> contains information about one data dictionary class.
<tableNumber> stores the table number from filelist.cfg of the table that the data dictionary class is bound to.
<tableName> stores the table name of the table that the data dictionary class is bound to.
<className> stores the name of the data dictionary class.
<classFile> stores the filename where the class is declared.

This information can be used by your wizards to create data dictionary objects of the correct class for selected tables. Below is a subset of the DClassList xml file generated from the Order Entry sample workspace.

Code:
<WizardDataDictionaryList xmlns="http://www.dataaccess.com/VisualDataFlex/2008/WizardDataDictionaryList/">
    <DDClasses>
        <DDClass>
            <tableNumber>22</tableNumber>
            <tableName>Invt</tableName>
            <className>Invt_DataDictionary</className>
            <classFile>Invt.DD</classFile>
        </DDClass>
        <DDClass>
            <tableNumber>25</tableNumber>
            <tableName>Customer</tableName>
            <className>Customer_DataDictionary</className>
            <classFile>Customer.DD</classFile>
        </DDClass>
        <DDClass>
            <tableNumber>30</tableNumber>
            <tableName>OrderHea</tableName>
            <className>OrderHea_DataDictionary</className>
            <classFile>OrderHea.DD</classFile>
        </DDClass>
        <DDClass>
            <tableNumber>31</tableNumber>
            <tableName>OrderDtl</tableName>
            <className>OrderDtl_DataDictionary</className>
            <classFile>OrderDtl.DD</classFile>
        </DDClass>
    </DDClasses>
</WizardDataDictionaryList>
Reading the DDClassList xml File

The example below demonstrates how you can extract a data dictionary class list data from the xml file.

Code:
Use FlexML.pkg

Struct tDDClass
    Integer tableNumber
    String tableName
    String className
    String classFile
End_Struct

Function GetDDClassList String sXMLFile Returns tDDClass[]
    Handle hoXML hoRoot hoDDClassList hoDDClass
    Handle hoAttributeCollection hoAttribute
    Integer i iAttribute icAttribute
    Boolean bOK
    String sNameSpace sAttribute
    tDDClass[] DDClassList
    
    // Create an XML document object and parse the DDClassList xml file....
    Get Create (RefClass(cXMLDOMDocument)) to hoXML
    // Get Create U_cXMLDOMDocument to hoXML  // prior to VDF 15.1 you must write it this way
    Set psDocumentName of hoXML to sXMLFile
    Set pbAsync of hoXML to False
    Set pbValidateOnParse of hoXML to True
    Get LoadXMLDocument of hoXML to bOK
    Move 0 to i
    
    If (bOK) Begin
        // Get the root node <WizardDataDictionaryList>....
        Get DocumentElement of hoXML to hoRoot
        
        If (hoRoot <> 0) Begin
            // Get the namespace string....
            Get AttributeNodes of hoRoot to hoAttributeCollection
            Move "" to sNameSpace
            
            If (hoAttributeCollection <> 0) Begin
                Get NodeListLength of hoAttributeCollection to icAttribute
               
                For iAttribute from 0 to (icAttribute - 1)
                    // we are searching for the "xmlns" attribute....
                    Get CollectionNode of hoAttributeCollection iAttribute to hoAttribute
                    Get psNodeName of hoAttribute to sAttribute
                    
                    If (Uppercase(sAttribute) = "XMLNS") Begin
                        Get psText of hoAttribute to sNameSpace
                    End
                    
                    Send Destroy to hoAttribute
                Loop
                
                Send Destroy to hoAttributeCollection
            End

            // Get the <DDClasses> node....
            Get ChildElementNS of hoRoot sNameSpace "DDClasses" to hoDDClassList
            
            If (hoDDClassList <> 0) Begin
                // Iterate each <DDClass> node in <DDClassList>....
                Get ChildElementNS of hoDDClassList sNameSpace "DDClass" to hoDDClass
                
                While (hoDDClass <> 0)
                    // retrieve the actual DDClass data....
                    Get ChildElementValueNS of hoDDClass sNamespace "tableNumber" to DDClassList[i].tableNumber
                    Get ChildElementValueNS of hoDDClass sNamespace "tableName"   to DDClassList[i].tableName
                    Get ChildElementValueNS of hoDDClass sNamespace "className"   to DDClassList[i].className
                    Get ChildElementValueNS of hoDDClass sNamespace "classFile"   to DDClassList[i].classFile
                    Increment i
                    
                    // Get the next sibling <DDClass>. This function destroys the
                    // passed object handle and returns a handle to it's sibling
                    Get NextElementNS of hoDDClass sNameSpace "DDClass" to hoDDClass
                Loop
                
                Send Destroy to hoDDClassList
            End
            
            Send Destroy to hoRoot
        End
    End

    Send Destroy to hoXML
    
    Function_Return DDClassList
End_Function  // GetDDClassList
Because the XML document uses a namespace (xmlns=xxx) we must use the dedicated namespace handling cXMLDOMDocument functions to parse the XML. To do this we must pass the namespace string to each function call.

We could hard-code the string since we know what it is ("http://www.dataaccess.com/VisualDataFlex/2008/WizardDataDictionaryList/"), but I decided to make the function a little bit more flexible. It reads the attribute list of the root node to get the namespace string.

The function returns an array of type tDDClass containing all the DD class information from the XML document.

In the next and final part in this series I will describe how your Create New wizard can write data back into the temporary config file to instruct the Studio to perform different operations with the files you have created.

Comments

  1. Hans van de Laar's Avatar
    Hi John,

    The example code above is supposed to work only for the xmlns="http://www.dataaccess.com/VisualDataFlex/2006/DataDictionaryList/
    and not for the
    xmlns="http://www.dataaccess.com/VisualDataFlex/2008/DataDictionaryList/

    Could you confirm this?