
//<script>
/*****************************************************************************************************************************
 * @DOC     ClientSideDictionary
 * @CLASS   Dictionary | 
 *          JavaScript implementation of a .Net Dictionary (or name value pair collection)
 * @LOC     Client-Side
 * @LANG    JavaScript
 *
 * @SUBINDEX Dictionary Members
 */

/* Interfaces:
 ******************************************************************************************************************************
 * @MFUNC   | Dictionary | Dictionary | <c Dictionary> constructor.
 * @XREF    <c Dictionary> Class Definition
 ******************************************************************************************************************************
 * @MDATA   Array | Dictionary | keys | Array of the keys conatained in the Dictionary.
 * @XREF    <c Dictionary> Class Definition
 ******************************************************************************************************************************
 * @MDATA   Array | Dictionary | indexes | Array of the indexes conatained in the Dictionary (indexed by key).
 * @XREF    <c Dictionary> Class Definition
 ******************************************************************************************************************************
 * @MDATA   Array | Dictionary | items | Array of the items conatained in the Dictionary.
 * @XREF    <c Dictionary> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   object | Dictionary | add | Public function to add a new item to the Dictionary.
 * @PARM    string | key | Unique key for the item.  If the key already exists in the Dictionary the item will be replaced.
 * @PARM    object | item | the item to be added to the dictionary.
 * @RDESC   returns the item added to the dictionary
 * @XREF    <c Dictionary> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | Dictionary | remove | Public function to remove an item from the Dictionary.
 * @PARM    string | key | Unique key of the item to be removed.  If the key already exists in the Dictionary the item will be 
 *              replaced.
 * @XREF    <c Dictionary> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | Dictionary | clear | Public function to remove all items from the Dictionary.
 * @XREF    <c Dictionary> Class Definition
 ****************************************************************************************************************************/
function Dictionary() {
    this.keys = new Array();
    this.indexes = new Object();
    this.items = new Array();
    
    // add - add a new item to the dictionary
    this.add = function(key, item) {
        var index = this.indexes[key];
        // add the key to the collection (if we have not already done so)
	    if(index == null){
	        index = this.keys.length;
	        this.keys[index] = key;
	        this.indexes[key] = index;
		    // update the length property
		    this.length = this.keys.length;
	    }
	    
	    // if there is already an item for this key, dispose of it properly where possible
	    if(this.items[index] && typeof(this.items[index].dispose) == 'function')
	       this.items[index].dispose();
	    
	    // add the item to the cache
	    this.items[index] = item;
	    
	    // return the item we have just added
        return this.items[index];
    }
    
    // remove - remove an item based on it's key
    this.remove = function(key) {
        var index = this.indexes[key];
        if (index != null) {
            // remove the item and key from the arrays
	        var newKeyArray = new Array();
	        var newItemArray = new Array();
	        var newIndexList = new Object();
		    for(var i = 0; i < this.keys.length; i++)
		    {
		        if (i != index) {
		            newIndexList[this.keys[i]] = newKeyArray.length;
		            newKeyArray[newKeyArray.length] = this.keys[i];
		            newItemArray[newItemArray.length] = this.items[i];
		        }
		    }
		    this.keys = newKeyArray;
		    this.items = newItemArray;
		    this.indexes = newIndexList;
    		
		    // update the length property
		    this.length = this.keys.length;
		    return true;
		}
		return false;
    }
    
    // clear - empty the dictionary of all items
    this.clear = function() {
        this.keys = null;
        this.keys = new Array();
        this.indexes = null;
        this.indexes = new Object();
        for(var index = 0; index < this.items.length; index++) {
            if(typeof(this.items[index].dispose) == 'function')
                this.items[index].dispose();
        }
        this.items = null;
        this.items = new Array();
        this.length = null;
        this.length = 0;
    }
    
    // length - the number of items currently in the dictionary
    this.length = 0;
}

/*****************************************************************************************************************************
 * @DOC     ClientSideDataSet
 * @CLASS   DataSet | 
 *          JavaScript implementation of a .Net DataSet
 * @LOC     Client-Side
 * @LANG    JavaScript
 *
 * @XREF    <c Dictionary> Class Definition
 * @XREF    <c DataTable> Class Definition
 * @SUBINDEX DataSet Members
 */

/* Interfaces:
 ******************************************************************************************************************************
 * @MFUNC   | DataSet | DataSet | <c DataSet> constructor.
 * @PARM    string | name | Optional name for the data set, this will override the value set by an xml serialised DataSet.  If 
 *              not set the value 'NewDataSet' will be used.
 * @PARM    string | xml | Optional xml serialised DataSet to be expanded as the initial data for the DataSet.  If not set an 
 *              exmpty DataSet will be created.
 * @XREF    <c DataSet>
 ******************************************************************************************************************************
 * @MDATA    Dictionary  | DataSet | tables | The collection of DataTables that make up this DataSet
 * @XREF    <c Dictionary> Class Definition
 * @XREF    <c DataTable> Class Definition
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MDATA    Date  | DataSet | timeStamp | The date / time that the item was retrived from the server (i.e. valid at this time).
 *              This will be used to determine if the copy that is on the server has changed since we last retrieved it.  The 
 *              initial value of the timeStamp is null until it is either manually set or the DataSet is populated from an xml
 *              serialised DataSet containing the timestamp.
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MDATA    Date  | DataSet | TTL | the time to live of the data on the client (i.e. how long the data should be synchronised 
             with the server between uses. If the data is not used for this amount of time (i.e. not requested from the ACE 
             mananger, it will stop synchronising with the server top save resources.
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   XmlDocument | DataSet | getXml | Public function to generate the xml for this DataSet based on the current values.
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | DataSet | setXml | Public function to set the contents of the DataSet.
 * @PARM    XmlDocument | xmlDoc | An xml document of a serialised DataSet to be deserialised into the object.
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MDATA    string | DataSet | name | The name of the data set.  This can be set in one of the following ways: Setting the 
 *              value of this property; Setting the name parrameter to a non-null value when calling the contructor or by 
 *              loading the passing in an xml serialised named DataSet into the setXml method.
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | DataSet | clone | Public function to make a clone of the DataSet Object.  The entire DataSet will be 
 *              duplicated into a new object.
 * @XREF    <c DataSet> Class Definition
 ****************************************************************************************************************************/
function DataSet(name, xml) {
    // collection of tables in this data set
    this.tables = new Dictionary();
    
    /* timeStamp - the date / time that the item was retrived from the server (i.e. valid at this time).  This will be used 
                   to determine if the copy that is on the server has changed since we last retrieved it. */
    this.timeStamp = null;
    
    /* TTL - the time to live of the data on the client (i.e. how long the data should be synchronised with the server between 
             uses. If the data is not used for this amount of time (i.e. not requested from the ACE mananger, it will stop 
             synchronising with the server top save resources. */
    this.TTL = -1;
    
    // getXml - generate the xml for this DataSet based on the current values
    this.getXml = function() {
        var ret = null;
        if (document.implementation && document.implementation.createDocument) {
            ret = document.implementation.createDocument('', '', null);
        }
        else {
            ret = new ActiveXObject('Microsoft.XMLDOM');
        }
        if(ret == null) {
            /*25955*/ Log('Unable to build xml response.  Could not create xml document.', logVerbosity.Warning);
            return null;
        }
        // create the data set node
        var dataSetNode = ret.createElement('DataSet');
        var attributeNode = null;
        attributeNode = ret.createAttribute('Name')
        attributeNode.nodeValue = this.name;
        dataSetNode.attributes.setNamedItem(attributeNode);
        attributeNode = ret.createAttribute('TimeStamp')
        attributeNode.nodeValue = this.TimeStamp;
        dataSetNode.attributes.setNamedItem(attributeNode);
        ret.appendChild(dataSetNode);
        attributeNode = ret.createAttribute('ClientSideTTL')
        attributeNode.nodeValue = this.TTL;
        dataSetNode.attributes.setNamedItem(attributeNode);
        ret.appendChild(dataSetNode);

        var tableNode = null;
        var rowNode = null;
        var fieldNode = null;
        var currentTable = null;
        var currentRow = null;
        // add the tables
        for(var tableIndex = 0; tableIndex < this.tables.length; tableIndex++){
            currentTable = this.tables.items[tableIndex]
            // create the new table node
            tableNode = ret.createElement('Table');
            // add the attributes
            attributeNode = ret.createAttribute('Name');
            attributeNode.nodeValue = currentTable.name;
            tableNode.attributes.setNamedItem(attributeNode);
            attributeNode = ret.createAttribute('UniqueId');
            attributeNode.nodeValue = currentTable.uniqueId;
            tableNode.attributes.setNamedItem(attributeNode);
            // add the rows
            for (var rowIndex = 0; rowIndex < currentTable.rows.length; rowIndex++) {
                currentRow = currentTable.rows.items[rowIndex];
                // Create the new row node
                rowNode = ret.createElement('Row');
                // add the fields
                for (var fieldIndex = 0; fieldIndex < currentRow.fields.length; fieldIndex++) {
                    currentField = currentRow.fields.items[fieldIndex];
                    // create the new field node
                    fieldNode = ret.createElement('Field');
                    attributeNode = ret.createAttribute('Name');
                    attributeNode.nodeValue = currentField.name;
                    fieldNode.attributes.setNamedItem(attributeNode);
                    attributeNode = ret.createAttribute('Value');
                    attributeNode.nodeValue = currentField.value;
                    fieldNode.attributes.setNamedItem(attributeNode);
                    attributeNode = ret.createAttribute('DataType');
                    attributeNode.nodeValue = currentField.dataType;
                    fieldNode.attributes.setNamedItem(attributeNode);
                    // add the new field node to the row
                    rowNode.appendChild(fieldNode);
                }
                // add the new row node to the table
                tableNode.appendChild(rowNode);
            }
            // add the new table node to the data set
            dataSetNode.appendChild(tableNode);
        }
        
        // clear temp vars
        dataSetNode = null;
        attributeNode = null;
        tableNode = null;
        rowNode = null;
        fieldNode = null;
        currentTable = null;
        currentRow = null;

        return ret;
    }
    
    // setXml - populate the DataSet from the xml provided
    this.setXml = function(xmlDoc) {
        this.tables.clear();
        
        if (xmlDoc != null && xmlDoc.documentElement != null) {
            // set the properties from the data set attributes
            var attributes = xmlDoc.documentElement.attributes;
            for(var attributeIndex = 0; attributeIndex < attributes.length; attributeIndex++) {
                switch(attributes[attributeIndex].nodeName) {
                    case 'Name':
                        this.name = attributes[attributeIndex].nodeValue;
                        break;
                    case 'TimeStamp':
                        this.timeStamp = attributes[attributeIndex].nodeValue;
                        break;
                    case 'ClientSideTTL':
                        this.TTL = attributes[attributeIndex].nodeValue * 1;
                        break;
                }
            }
            attribtues = null;
        
            var newTable = null;
            var newRow = null;
            var newField = null;
            
            var tableNode = xmlDoc.documentElement.firstChild;
            var rowNode = null;
            var fieldNode = null;
            
            // itterate the tables
            while (tableNode != null) {
                if (tableNode.nodeName == 'Table') {
                    // create the new table
                    newTable = createNewTable(tableNode, this);

                    // itterate the rows
                    rowNode = tableNode.firstChild;
                    while (rowNode != null) {
                        if (rowNode.nodeName == 'Row') {
                            //create the new row
                            newRow = new DataRow(newTable);
                            
                            // itterate the fields
                            fieldNode = rowNode.firstChild;
                            while (fieldNode != null) {
                                if (fieldNode.nodeName == 'Field') {
                                    // create and add the new field
                                    newField = createNewField(fieldNode, newRow);
                                    newRow.fields.add(newField.name, newField);
                                }
                                fieldNode = fieldNode.nextSibling;
                            }
                            
                            // add the new row
                            newTable.rows.add(newRow.fields.items[newRow.fields.indexes[newTable.uniqueId]].value, newRow);
                        }
                        rowNode = rowNode.nextSibling;
                    }
                    // add the new table
                    this.tables.add(newTable.name, newTable);
                }
                tableNode = tableNode.nextSibling;
            }
            
            // clear temp vars
            newTable = null;
            newRow = null;
            newField = null;
            tableNode = null;
            rowNode = null;
            fieldNode = null;
        }
    }
    
    // if we have been provided with xml to initialise the object - load it
    if(xml != null) {
        this.setXml(xml);
        xml = null;
    }
    
    this.clone = function() {
        var newDataSet = new DataSet(this.name, null);
        newDataSet.timeStamp = this.timeStamp;
        for(var i = 0; i < this.tables.length; i++){
            newDataSet.tables.add(this.tables.keys[i], this.tables.items[i].clone());
            newDataSet.tables.items[i].dataSet = newDataSet;
        }
            
        return newDataSet;
    }

    // the name of the data set
    this.name = (name == null ? (this.name == null ? 'NewDataSet' : this.name) : name);
    
    this.dispose = function() {
        for(var i = 0; i < this.tables.length; i++)
            if(this.tables.items[i].dispose)
                this.tables.items[i].dispose();
        this.tables = null;
        this.timeStamp = null;
        this.name = null;
    }
    
    function createNewTable(tableNode, dataSet) {
        var tableName = '';
        var tableUniqueId = '';
        var availableRows = -1;

        for (var attributeIndex = 0; attributeIndex < tableNode.attributes.length; attributeIndex++) {
            switch(tableNode.attributes[attributeIndex].nodeName)
            {
                case "Name" :
                    tableName = tableNode.attributes[attributeIndex].nodeValue;
                    break;
                case "UniqueId" :
                    tableUniqueId = tableNode.attributes[attributeIndex].nodeValue;
                    break;
                case "AvailableRows" :
                    availableRows = tableNode.attributes[attributeIndex].nodeValue;
                    break;
            }
        }
        
        return new DataTable(tableName, tableUniqueId, dataSet, availableRows);
    }
    
    function createNewField(fieldNode, row) {
        var fieldName = '';
        var fieldValue = '';
        var fieldDataType = '';

        for (var attributeIndex = 0; attributeIndex < fieldNode.attributes.length; attributeIndex++) {
            switch(fieldNode.attributes[attributeIndex].nodeName)
            {
                case "Name" :
                    fieldName = fieldNode.attributes[attributeIndex].nodeValue;
                    break;
                case "Value" :
                    fieldValue = fieldNode.attributes[attributeIndex].nodeValue;
                    break;
                case "DataType" :
                    fieldDataType = fieldNode.attributes[attributeIndex].nodeValue.toLowerCase();
                    break;
            }
        }
        
        return new DataField(fieldName, fieldValue, fieldDataType, row);
    }
}

/*****************************************************************************************************************************
 * @DOC     ClientSideDataTable
 * @CLASS   DataTable | 
 *          JavaScript implementation of a .Net DataTable
 * @LOC     Client-Side
 * @LANG    JavaScript
 *
 * @XREF    <c Dictionary> Class Definition
 * @XREF    <c DataSet> Class Definition
 * @XREF    <c DataRow> Class Definition
 * @SUBINDEX DataTable Members
 */

/* Interfaces:
 ******************************************************************************************************************************
 * @MFUNC   | DataTable | DataTable | <c DataTable> constructor.
 * @PARM    string | name | Optional name for the data table, this will override the value set by an xml serialised DataSet. 
 *              If not set the value 'NewDataSet' will be used.
 * @PARM    string | uniqueId | The key field column name.  This will be used by custom controls to determine the value that 
 *              needs to be passed back to the server in order to uniuely identify a row from the table.
 * @PARM    pointer | dataSet | Pointer to the DataSet that contains this DataTable (this is included to ease navigation, when 
 *              passing DataTables into methods it is possible to determine the DataSet it is part of).
 * @PARM    int | availableRows | The total number of available rows that this DataTable could contain.  This is used to 
 *              determine if there is more data available on the server (i.e. more than the MaxRows specified when the data 
 *              was requested) or if this is the complete data set.  Special cases: -ve - DataTable contins all available rows.
 * @XREF    <c DataTable> Class Definition
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MDATA    Dictionary  | DataTable | rows | The collection of DataRows that make up this DataTable
 * @XREF    <c DataTable> Class Definition
 * @XREF    <c Dictionary> Class Definition
 * @XREF    <c DataRow> Class Definition
 ******************************************************************************************************************************
 * @MDATA    string  | DataTable | name | The name for this DataTable.
 * @XREF    <c DataTable> Class Definition
 ******************************************************************************************************************************
 * @MDATA    string  | DataTable | uniqueId | The key field column name.  This will be used by custom controls to determine 
 *              the value that needs to be passed back to the server in order to uniuely identify a row from the table.
 * @XREF    <c DataTable> Class Definition
 ******************************************************************************************************************************
 * @MDATA    pointer  | DataTable | dataSet | Pointer to the DataSet that contains this DataTable (this is included to ease 
 *              navigation, when passing DataTables into methods it is possible to determine the DataSet it is part of).
 * @XREF    <c DataTable> Class Definition
 * @XREF    <c DataSet> Class Definition
 ******************************************************************************************************************************
 * @MDATA    int  | DataTable | availableRows | The total number of available rows that this DataTable could contain.  
 *              This is used to determine if there is more data available on the server (i.e. more than the MaxRows specified 
 *              when the data was requested) or if this is the complete data set.  Special cases: -ve - DataTable contins all 
 *              available rows.
 * @XREF    <c DataTable> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | DataTable | clone | Public function to make a clone of the DataTable Object.  The entire DataTable will be 
 *              duplicated into a new object.  As a result the reference to the parent DataSet will be lost.
 * @XREF    <c DataTable> Class Definition
 ****************************************************************************************************************************/
function DataTable(name, uniqueId, dataSet, availableRows) {
    if(Dictionary == null) {
        /*25955*/ Log('Unable to create new DataTable, underlying Dictionary class could not be found.', logVerbosity.Warning);
        return null;
    }
    
    this.rows = new Dictionary();
    
    this.name = name;
    
    this.uniqueId = uniqueId;
    
    this.dataSet = dataSet;
    
    this.availableRows = availableRows;
    
    this.clone = function() {
        var newDataTable = new DataTable(this.name, this.uniqueId, null, this.availableRows);
        for(var i = 0; i < this.rows.length; i++) {
            newDataTable.rows.add(this.rows.keys[i], this.rows.items[i].clone());
            newDataTable.rows.items[i].dataTable = newDataTable;
        }
            
        return newDataTable;
    }
    
    this.dispose = function() {
        for(var i = 0; i < this.rows.length; i++)
            if(this.rows.items[i].dispose)
                this.rows.items[i].dispose();
        this.rows = null;
        this.name = null;
        this.uniqueId = null;
        this.dataSet = null;
        this.availableRows = null;
    }
}

/*****************************************************************************************************************************
 * @DOC     ClientSideDataRow
 * @CLASS   DataRow | 
 *          JavaScript implementation of a .Net DataRow
 * @LOC     Client-Side
 * @LANG    JavaScript
 *
 * @XREF    <c Dictionary> Class Definition
 * @XREF    <c DataTable> Class Definition
 * @XREF    <c DataField> Class Definition
 * @SUBINDEX DataRow Members
 */

/* Interfaces:
 ******************************************************************************************************************************
 * @MFUNC   | DataRow | DataRow | <c DataRow> constructor.
 * @PARM    pointer | table | Pointer to the DataTable that contains this DataRow (this is included to ease navigation, when 
 *              passing a DataRow into a method it is possible to determine the DataTable it is part of).
 * @XREF    <c DataRow> Class Definition
 * @XREF    <c DataTable> Class Definition
 ******************************************************************************************************************************
 * @MDATA    Dictionary  | DataRow | fields | The collection of DataFields that make up this DataRow.
 * @XREF    <c DataRow> Class Definition
 * @XREF    <c Dictionary> Class Definition
 * @XREF    <c DataField> Class Definition
 ******************************************************************************************************************************
 * @MDATA    pointer | DataRow | table | Pointer to the DataTable that contains this DataRow (this is included to ease 
 *              navigation, when passing a DataRow into a method it is possible to determine the DataTable it is part of).
 * @XREF    <c DataRow> Class Definition
 * @XREF    <c DataTable> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | DataRow | clone | Public function to make a clone of the DataRow Object.  The entire DataRow will be 
 *              duplicated into a new object.  As a result the reference to the parent DataTable will be lost.
 * @XREF    <c DataRow> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | DataRow | getFieldValue | Public function to retrieve the value of a field in this DataRow.  If the field
 *              does not exist null will be returned.
 * @XREF    <c DataRow> Class Definition
 ****************************************************************************************************************************/
function DataRow(table) {
    if(Dictionary == null) {
        /*25955*/ Log('Unable to create new DataRow, underlying Dictionary class could not be found.', logVerbosity.Warning);
        return null;
    }
    
    this.fields = new Dictionary();
    
    this.table = table;
    
    this.getFieldValue = function(fieldName) {
        try { 
            var fieldIndex = this.fields.indexes[fieldName]; 
        
            return this.fields.items[fieldIndex].value;
        }
        catch (ex) { 
            // BD: Commented out logging, because it usually throws up LOTS of error messages
            //Log(ex, 'could not get field value (' + fieldName + ') in EMRDataObjects', logVerbosity.SuperVerbose); return false; 
            // instead return null
            return null;
        }
    }
    
    this.setFieldValue = function(fieldName, value) {
        try
        {
            var fieldIndex = this.fields.indexes[fieldName]; 
            if(fieldIndex)
            {
                this.fields.items[fieldIndex].value = value;
                return true;
            }
            
            var object = function()
            {
                var me = this;
                this.value = value;
                this.clone = function()
                {
                    return me;
                }
            };
            
            this.fields.add(fieldName, new object());
            return true;    
        }
        catch(ex) {Log(ex, 'could not set field value (' + fieldName + ') in EMRDataObjects', logVerbosity.SuperVerbose); return null; }
    }
    
    this.clone = function() {
        var newDataRow = new DataRow(null);
        for(var i = 0; i < this.fields.length; i++) {
            newDataRow.fields.add(this.fields.keys[i], this.fields.items[i].clone());
            newDataRow.fields.items[i].dataRow = newDataRow;
        }
            
        return newDataRow;
    }
    
    this.matchesFilter = function() {
        var filterField = this.getFieldValue('blnMatchesFilter');
        // if the filter field is not pressent, we can assume we are dealing with a server-side filtered data type where filtered rows are not returned.  In which case those that are all match the filter.
        if(filterField == null)
            return true;
            
        // blnMatchesFilter is a boolean column (i.e. values True or False) indicating whether it matched the current filter options
        return (filterField == 'True');
    }
    
    this.dispose = function() {
        for(var i = 0; i < this.fields.length; i++)
            if(this.fields.items[i].dispose)
                this.fields.items[i].dispose();
        this.fields = null;
        this.table = null;
    }
}

/*****************************************************************************************************************************
 * @DOC     ClientSideDataField
 * @CLASS   DataField | 
 *          JavaScript implementation of a .Net DataField
 * @LOC     Client-Side
 * @LANG    JavaScript
 *
 * @XREF    <c DataRow> Class Definition
 * @SUBINDEX DataField Members
 */

/* Interfaces:
 ******************************************************************************************************************************
 * @MFUNC   | DataField | DataField | <c DataField> constructor.
 * @PARM    string | name | The name of the column.
 * @PARM    string | value | The value of the column on this row.  This is stored as a string for simplicity when serialising 
 *              to xml.
 * @PARM    string | dataType | The data type of the field so it can be cast / converted from the string value as appropriate.
 * @PARM    pointer | row | Pointer to the DataRow that contains this DataField (this is included to ease navigation, 
 *              when passing a DataField into a method it is possible to determine the DataRow it is part of).
 * @XREF    <c DataField> Class Definition
 * @XREF    <c DataRow> Class Definition
 ******************************************************************************************************************************
 * @MDATA    string  | DataField | name | The name of the column.
 * @XREF    <c DataField> Class Definition
 ******************************************************************************************************************************
 * @MDATA    string  | DataField | value | The value of the column on this row.  This is stored as a string for simplicity when 
 *              serialising to xml.
 * @XREF    <c DataField> Class Definition
 ******************************************************************************************************************************
 * @MDATA    string  | DataField | dataType | The data type of the field so it can be cast / converted from the string value as 
 *              appropriate.
 * @XREF    <c DataField> Class Definition
 ******************************************************************************************************************************
 * @MDATA    pointer | DataField | row | Pointer to the DataRow that contains this DataField (this is included to ease 
 *              navigation, when passing a DataField into a method it is possible to determine the DataRow it is part of).
 * @XREF    <c DataField> Class Definition
 * @XREF    <c DataRow> Class Definition
 ******************************************************************************************************************************
 * @MFUNC   void | DataField | clone | Public function to make a clone of the DataField Object.  The entire DataField will be 
 *              duplicated into a new object.  As a result the reference to the parent DataRow will be lost.
 * @XREF    <c DataField> Class Definition
 ****************************************************************************************************************************/
function DataField(name, value, dataType, row) {
    if(Dictionary == null) {
        /*25955*/ Log('Unable to create new DataField, underlying Dictionary class could not be found.', logVerbosity.Warning);
        return null;
    }
    
    this.name = name;
    
    this.value = value;
    
    this.dataType = dataType;
    
    this.row = row;
    
    this.clone = function() {
        var newDataField = new DataField(this.name, this.value, this.dataType, null);
            
        return newDataField;
    }
    
    this.dispose = function() {
        this.name = null;
        this.value = null;
        this.row = null;
    }
}
