Metadata Service

Nov 9, 2009 at 6:02 AM

Hi there,

I'm trying to use the Advanced Data Migration Map Editor, however I keep getting this error:

"Metadata could not be loaded for following reason. "Object reference not set to an instance of an object.""

We're running an on-premise installation, and I've tried running the editor both on a client machine and the actual server. We've tried both server and DM Client (With DMM running on the server) The user I use to log on is a system customiser.

The system is running on Windows Server 2008, with the client machines we've tested running either Windows XP or Windows 7. The log on to the machine is through Active Directory handled by a Server 2003 machine.

 

I can't figure out what is wrong. Please help!!!

Nov 9, 2009 at 10:36 PM

Hi everyone,

 

We solved it by installing MCRM on Windows Server 2003 and not running any of the rollups.

 

We had the problems when running MSCRM Map Editor on Windows Server 2008 with CRM updated to rollup 6. This solved our problems.

 

I don't think the rollups were causing the problem as this is an interface that is supported by Microsoft, I do think the problem was with Server 2008. However I thought I should mention both to help anyone else who is having this problem.

 

Thanks!

Nov 12, 2009 at 5:25 PM

 We ran into the same problem which we fixed with a couple of line changes to the source code. The culprit in our experience is that one of the later rollup's added an entity that did not have picklist values for True/False (they were null causing the 'Object reference not set to an instance of an object.' exception). Here is our code for DMMapEditorHelper.cs:

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Data.SqlClient;
//using Mapy.CrmService;
//using Mapy.CrmMetadataService;
using Microsoft.Crm.Sdk.Metadata;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.SdkTypeProxy.Metadata;
using Microsoft.Crm.Sdk;
using Microsoft.Crm;
using Microsoft.Crm.Sdk.Query;

namespace MapEditor
{
    class MapEditorHelper
    {

        //Constructors for MapEditorHelper and declaring CrmService and MetadataService objects
        #region Constructors and local variables

        private CrmService crmService;
        private MetadataService crmMetadataService;

        /// 
        /// Default Constructor
        /// 
        public MapEditorHelper()
        {
            crmService = new CrmService();
            crmMetadataService = new MetadataService();
        }

        /// 
        /// Parameterized constructor taking parameters needed to connect to Crm Service and Crm Metadata Service
        /// 
        /// <param name="serverDomain" />Crm Server Domain Name
        /// <param name="serverName" />Crm Server Name
        /// <param name="rootUrl" />Root Url of Crm Server
        /// <param name="userDomain" />User Domain Name
        /// <param name="userName" />Authorized User Name
        /// <param name="password" />Password for Authorized user
        /// <param name="organizationName" />Organization Name for which Crm is implemented
        /// <param name="isClientMode" />Client Mode or Server Mode
        public MapEditorHelper(string serverDomain, string serverName, string rootUrl, string userDomain, string userName, string password, string organizationName, bool isClientMode)
        {
            System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(userName, password, userDomain);
            //Creating Crm service object with required authentication information to connect to Crm WebService
            crmService = new CrmService();
            if (isClientMode)
                crmService.Url = @"http://" + serverName + ":2525/MSCRMServices/2007/CrmService.asmx";
            else
                crmService.Url = rootUrl + "/MSCRMServices/2007/CrmService.asmx";
            crmService.Credentials = credentials;
            CrmAuthenticationToken crmAuthenticationToken = new CrmAuthenticationToken();
            crmAuthenticationToken.OrganizationName = organizationName;
            crmService.CrmAuthenticationTokenValue = crmAuthenticationToken;
            crmService.UnsafeAuthenticatedConnectionSharing = true;
            crmService.Timeout = 30000000;

            //Creating Crm Metadata Service object with required authentication information to connect to Crm Metadata WebService
            crmMetadataService = new MetadataService();
            if (isClientMode)
                crmMetadataService.Url = @"http://" + serverName + ":2525/MSCRMServices/2007/MetadataService.asmx";
            else
                crmMetadataService.Url = rootUrl + "/MSCRMServices/2007/MetadataService.asmx";
            crmMetadataService.Credentials = credentials;
            CrmAuthenticationToken crmMetaAuthenticationToken = new CrmAuthenticationToken();
            crmMetaAuthenticationToken.OrganizationName = organizationName;
            crmMetadataService.CrmAuthenticationTokenValue = crmMetaAuthenticationToken;
            crmMetadataService.UnsafeAuthenticatedConnectionSharing = true;
            crmMetadataService.Timeout = 30000000;
        }

        #endregion

        //Methods where Crm Service and Metadata Service are sent some service requests
        #region CrmService and MetadataService Calls

        /// 
        /// Gets map data for existing maps in Crm and put maps as xml documents, one xml per map, in an array of xml documents
        /// Also puts some map data in Data Table to be used at Front end in Map Editor Wizard
        /// 
        /// <param name="importMapTableForManageMapDataGridView" />reference of import Map Table used to populate Data Grid in Front End
        /// Array of xml documents, one document per map
        public List GetExistingMapsData(ref DataTable importMapTableForManageMapDataGridView)
        {
            //Retrieve all import map entities from Crm
            BusinessEntityCollection importMapCollection = retrieveEntityCollection(EntityName.importmap.ToString(), null);

            //Create a list of xmls of length equal to number of map instances in Crm
            List existingMapsXml = new List();
            importmap map;

            //For each map entity instance in Crm send an export Map request to obtain map in form of xml
            for (int mapIndex = 0; mapIndex < importMapCollection.BusinessEntities.Count; mapIndex++)
            {
                map = (importmap)importMapCollection.BusinessEntities[mapIndex];
                object[] mapFieldsForDataTable = { map.name, map.statuscode.name, map.modifiedon.date + " " + map.modifiedon.time, map.importmapid.Value.ToString() };
                importMapTableForManageMapDataGridView.Rows.Add(mapFieldsForDataTable);
                ExportMappingsImportMapRequest exportMapsRequest = new ExportMappingsImportMapRequest();
                exportMapsRequest.ImportMapId = map.importmapid.Value;
                ExportMappingsImportMapResponse exportMapResponse = (ExportMappingsImportMapResponse)crmService.Execute(exportMapsRequest);
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(exportMapResponse.MappingsXml);
                //map xml exists as MappingsXml property of exportMapResponse object
                existingMapsXml.Add((XmlDocument)xmlDoc.Clone());
            }
            return existingMapsXml;
        }

        /// 
        /// Retrieve Entity collection from Crm for an entity with some filter criteria
        /// 
        /// <param name="entityName" />Entity to be retrieved
        /// <param name="filter" />Filter criteria to identify specific set of entity instances
        /// Collection of required entity instances
        private BusinessEntityCollection retrieveEntityCollection(string entityName, FilterExpression filter)
        {
            QueryExpression query = new QueryExpression();
            query.EntityName = entityName;
            query.ColumnSet = new AllColumns();
            if (filter != null)
                query.Criteria = filter;
            BusinessEntityCollection importMapCollection = crmService.RetrieveMultiple(query);
            return importMapCollection;
        }

        /// 
        /// Reads Crm Metadata using Crm Metadata Service
        /// 
        /// Crm Metadata in form of Dataset with different tables providing Entity/Attribute/Lookup/Picklist Metadata
        public DataSet ReadCrmMetadata()
        {
            DataSet crmMetadata = new DataSet("CrmMetaData");

            //Specify columns needed in different Metadata Tables
            string[] entityColumnNames = { "DisplayName", "IsImportable", "PrimaryAttribute", "MetadataId", "Name" };
            string[] attributeColumnNamesValidForCreate = { "DisplayName", "MetadataId", "EntityName", "Name", "RequiredLevel", "AttributeType" };
            string[] attributeColumnNamesValidForRead = { "DisplayName", "MetadataId", "EntityName", "Name" };
            string[] lookupColumnNames = { "ReferencedEntity", "MetadataId" };
            string[] picklistColumnNames = { "OptionValueName", "OptionValue", "MetaDataId" };

            //Create Different Metadata Tables with specified columns
            DataTable entityMetadataTable = createDataTableWithColumns("EntityMetadata", entityColumnNames);
            DataTable attributeMetadataTableValidForCreate = createDataTableWithColumns("AttributeMetadataValidForCreate", attributeColumnNamesValidForCreate);
            DataTable attributeMetadataTableValidForRead = createDataTableWithColumns("AttributeMetadataValidForRead", attributeColumnNamesValidForRead);
            DataTable lookupMetadataTable = createDataTableWithColumns("LookupMetadata", lookupColumnNames);
            DataTable picklistMetadataTable = createDataTableWithColumns("PicklistMetadata", picklistColumnNames);

            //Objects of Metadata Classes to cast each instance of Metadata to required form
            EntityMetadata entityMetadata;
            AttributeMetadata attributeMetadata;
            PicklistAttributeMetadata picklistMetadata;
            BooleanAttributeMetadata booleanMetadata;
            StateAttributeMetadata stateMetadata;
            StatusAttributeMetadata statusMetadata;
            LookupAttributeMetadata lookupMetadata;

            //Object arrays to store fields of each Metadata Table
            object[] entityMetadataFields = new Object[5];
            object[] attributeMetadataFieldsValidForCreate = new Object[6];
            object[] attributeMetadataFieldsValidForRead = new Object[4];
            object[] lookupMetadataFields = new Object[2];
            object[] picklistMetadataFields = new Object[3];

            //Request all entities Metadata from Crm
            RetrieveAllEntitiesRequest crmMetadataRequest = new RetrieveAllEntitiesRequest();
            crmMetadataRequest.MetadataItems = MetadataItems.All;
            RetrieveAllEntitiesResponse crmMetadataResponse = (RetrieveAllEntitiesResponse)crmMetadataService.Execute((MetadataServiceRequest)crmMetadataRequest);
            try
            {

                //for each entity Metadata in Crm obtain all required Metadata infromation and store in Tables
                for (int entityIndex = 0; entityIndex < crmMetadataResponse.CrmMetadata.Length; entityIndex++)
                {
                    //Get Entity Metadata and put in Entity Metadata Table
                    entityMetadata = (EntityMetadata)crmMetadataResponse.CrmMetadata[entityIndex];
                    if (entityMetadata.DisplayName.UserLocLabel == null)
                        entityMetadataFields[0] = entityMetadata.LogicalName;
                    else
                        entityMetadataFields[0] = entityMetadata.DisplayName.UserLocLabel.Label;

                    entityMetadataFields[1] = entityMetadata.IsImportable.Value;
                    entityMetadataFields[2] = entityMetadata.PrimaryField;
                    entityMetadataFields[3] = entityMetadata.MetadataId.Value;
                    entityMetadataFields[4] = entityMetadata.LogicalName;
                    entityMetadataTable.Rows.Add(entityMetadataFields);

                    //For each Entity obtain Attribute Metadata
                    for (int attributeIndex = 0; attributeIndex < entityMetadata.Attributes.Length; attributeIndex++)
                    {
                        attributeMetadata = (AttributeMetadata)entityMetadata.Attributes[attributeIndex];
                        //Get Attribute Metadata but only for 'Valid For Create' Attributes and put in Attribute Valid For Create Metadata Table
                        if (attributeMetadata.ValidForCreate.Value == true || attributeMetadata.SchemaName == "statecode")
                        {
                            if (attributeMetadata.SchemaName == "ImportSequenceNumber")
                                continue;
                            if (entityMetadata.SchemaName == "Annotation")
                            {
                                if (attributeMetadata.SchemaName == "IsDocument" || attributeMetadata.SchemaName == "ObjectTypeCode")
                                    continue;
                            }
                            if (attributeMetadata.DisplayName.UserLocLabel == null)
                                attributeMetadataFieldsValidForCreate[0] = attributeMetadata.LogicalName;
                            else
                                attributeMetadataFieldsValidForCreate[0] = attributeMetadata.DisplayName.UserLocLabel.Label;
                            attributeMetadataFieldsValidForCreate[1] = attributeMetadata.MetadataId.Value;
                            if (entityMetadata.DisplayName.UserLocLabel == null)
                                attributeMetadataFieldsValidForCreate[2] = entityMetadata.LogicalName;
                            else
                                attributeMetadataFieldsValidForCreate[2] = entityMetadata.DisplayName.UserLocLabel.Label;
                            attributeMetadataFieldsValidForCreate[3] = attributeMetadata.LogicalName;
                            attributeMetadataFieldsValidForCreate[4] = attributeMetadata.RequiredLevel.Value;
                            attributeMetadataFieldsValidForCreate[5] = attributeMetadata.AttributeType.Value.ToString();
                            attributeMetadataTableValidForCreate.Rows.Add(attributeMetadataFieldsValidForCreate);

                            //If Attribute Type is Lookup get Lookup Metadata and put in Lookup Metadata Table
                            if (attributeMetadata.AttributeType.Value == AttributeType.Lookup || attributeMetadata.AttributeType.Value == AttributeType.Customer || attributeMetadata.AttributeType.Value == AttributeType.UniqueIdentifier)
                            {
                                //Get data for each Referenced Entity for this lookup attribute
                                for (int referenceIndex = 0; referenceIndex < entityMetadata.ManyToOneRelationships.Length; referenceIndex++)
                                {
                                    if (entityMetadata.ManyToOneRelationships[referenceIndex].ReferencingAttribute.ToLower() == attributeMetadata.LogicalName.ToLower())
                                    {
                                        lookupMetadataFields[0] = entityMetadata.ManyToOneRelationships[referenceIndex].ReferencedEntity;
                                        lookupMetadataFields[1] = attributeMetadata.MetadataId.Value;
                                        lookupMetadataTable.Rows.Add(lookupMetadataFields);
                                    }
                                }
                            }
                            if (attributeMetadata.AttributeType.Value == AttributeType.PartyList)
                            {
                                lookupMetadata = attributeMetadata as LookupAttributeMetadata;
                                //Get data for each Referenced Entity for this lookup attribute
                                foreach (string entityName in lookupMetadata.Targets)
                                {
                                    lookupMetadataFields[0] = entityName;
                                    lookupMetadataFields[1] = attributeMetadata.MetadataId.Value;
                                    lookupMetadataTable.Rows.Add(lookupMetadataFields);
                                }
                            }

                            //If Attribute Type is Picklist get Picklist Metadata and put in Picklist Metadata Table
                            if (attributeMetadata.AttributeType.Value == AttributeType.Picklist || attributeMetadata.AttributeType.Value == AttributeType.Boolean || attributeMetadata.AttributeType.Value == AttributeType.State || attributeMetadata.AttributeType.Value == AttributeType.Status)
                            {
                                switch (attributeMetadata.AttributeType.Value)
                                {
                                    case AttributeType.Picklist:
                                        picklistMetadata = (PicklistAttributeMetadata)entityMetadata.Attributes[attributeIndex];
                                        for (int optionIndex = 0; optionIndex < picklistMetadata.Options.Length; optionIndex++)
                                        {
                                            picklistMetadataFields[0] = picklistMetadata.Options[optionIndex].Label.UserLocLabel.Label;
                                            picklistMetadataFields[1] = picklistMetadata.Options[optionIndex].Value.Value;
                                            picklistMetadataFields[2] = picklistMetadata.MetadataId.Value;
                                            picklistMetadataTable.Rows.Add(picklistMetadataFields);
                                        }
                                        break;
                                    case AttributeType.Boolean:
                                        booleanMetadata = (BooleanAttributeMetadata)entityMetadata.Attributes[attributeIndex];
                                        if (booleanMetadata.FalseOption == null)
                                        {
                                            picklistMetadataFields[0] = "No";
                                            picklistMetadataFields[1] = 0;
                                        }
                                        else
                                        {
                                            picklistMetadataFields[0] = booleanMetadata.FalseOption.Label.UserLocLabel.Label;
                                            picklistMetadataFields[1] = booleanMetadata.FalseOption.Value.Value;

                                        }

                                        picklistMetadataFields[2] = booleanMetadata.MetadataId.Value;
                                        picklistMetadataTable.Rows.Add(picklistMetadataFields);
                                        if (booleanMetadata.TrueOption == null)
                                        {
                                            picklistMetadataFields[0] = "Yes";
                                            picklistMetadataFields[1] = 1;
                                        }
                                        else
                                        {
                                            picklistMetadataFields[0] = booleanMetadata.TrueOption.Label.UserLocLabel.Label;
                                            picklistMetadataFields[1] = booleanMetadata.TrueOption.Value.Value;
                                        }

                                        picklistMetadataFields[2] = booleanMetadata.MetadataId.Value;
                                        picklistMetadataTable.Rows.Add(picklistMetadataFields);

                                        break;
                                    case AttributeType.State:
                                        stateMetadata = (StateAttributeMetadata)entityMetadata.Attributes[attributeIndex];
                                        foreach (Option op in stateMetadata.Options)
                                        {
                                            picklistMetadataFields[0] = op.Label.UserLocLabel.Label;
                                            picklistMetadataFields[1] = op.Value.Value;
                                            picklistMetadataFields[2] = stateMetadata.MetadataId.Value;
                                            picklistMetadataTable.Rows.Add(picklistMetadataFields);
                                        }

                                        break;
                                    case AttributeType.Status:
                                        statusMetadata = (StatusAttributeMetadata)entityMetadata.Attributes[attributeIndex];
                                        foreach (Option op in statusMetadata.Options)
                                        {
                                            picklistMetadataFields[0] = op.Label.UserLocLabel.Label;
                                            picklistMetadataFields[1] = op.Value.Value;
                                            picklistMetadataFields[2] = statusMetadata.MetadataId.Value;
                                            picklistMetadataTable.Rows.Add(picklistMetadataFields);
                                        }
                                        break;
                                }
                            }
                        }
                        //Get Attribute Metadata but only for 'Valid For Read' Attributes and put in Attribute Valid For Read Metadata Table
                        if (attributeMetadata.ValidForRead.Value == true)
                        {
                            if (attributeMetadata.DisplayName.UserLocLabel == null)
                                attributeMetadataFieldsValidForRead[0] = attributeMetadata.LogicalName;
                            else
                                attributeMetadataFieldsValidForRead[0] = attributeMetadata.DisplayName.UserLocLabel.Label;
                            attributeMetadataFieldsValidForRead[1] = attributeMetadata.MetadataId.Value;
                            if (entityMetadata.DisplayName.UserLocLabel == null)
                                attributeMetadataFieldsValidForRead[2] = entityMetadata.LogicalName;
                            else
                                attributeMetadataFieldsValidForRead[2] = entityMetadata.DisplayName.UserLocLabel.Label;
                            attributeMetadataFieldsValidForRead[3] = attributeMetadata.LogicalName;
                            attributeMetadataTableValidForRead.Rows.Add(attributeMetadataFieldsValidForRead);
                        }
                    }
                }

                //Replace Entity Schema Names by Display names in Lookup Metadata Table in Referenced Entity Column
                ReplaceReferencedEntitySchemaNamesByDisplayNames(ref lookupMetadataTable, ref entityMetadataTable);
                //Replace Attribute Schema Names by Display names in Entity Metadata Table in Primary Attribute Column
                ReplaceReferencedAttributeSchemaNamesByDisplayNames(ref entityMetadataTable, ref attributeMetadataTableValidForRead);

                //Add these Metadata Tables to Crm Metadata Dataset and return the DataSet to calling Method
                crmMetadata.Tables.Add(entityMetadataTable);
                crmMetadata.Tables.Add(attributeMetadataTableValidForCreate);
                crmMetadata.Tables.Add(attributeMetadataTableValidForRead);
                crmMetadata.Tables.Add(lookupMetadataTable);
                crmMetadata.Tables.Add(picklistMetadataTable);

            }
            catch (Exception e)
            {
                String myMessage = e.Message;
            }
            return crmMetadata;

        }

        /// 
        /// Imports map to CRM through API Call
        /// 
        /// <param name="mapXmlData" />Map xml data in form of string
        public void ImportMapToCrm(string mapXmlData)
        {
            ImportMappingsImportMapRequest importMapRequest = new ImportMappingsImportMapRequest();
            importMapRequest.MappingsXml = mapXmlData;
            importMapRequest.ReplaceIds = true;
            ImportMappingsImportMapResponse importMapResponse = (ImportMappingsImportMapResponse)crmService.Execute(importMapRequest);
        }

        /// 
        /// Deletes map in Crm through API Call
        /// 
        /// <param name="importMapId" />Guid of map to be deleted
        public void DeleteMap(Guid importMapId)
        {
            DeleteRequest deleteMapRequest = new DeleteRequest();
            TargetDeleteImportMap target = new TargetDeleteImportMap();
            target.EntityId = importMapId;
            deleteMapRequest.Target = target;
            DeleteResponse deleteMapResponse = (DeleteResponse)crmService.Execute(deleteMapRequest);
        }



        #endregion

        //Xml Helper Methods to get Map xml nodes and set their attributes/Values if required; to save map xml in form of xml file
        #region XML Helpers

        /// 
        /// Gets Map Xml Node and sets the values for its attribues if any
        /// 
        /// <param name="mapXml" />map xml document
        /// <param name="nodeName" />Name of required node
        /// <param name="attributeValues" />Set of attribute values for node if any
        /// Map xml node with values set for attributes
        public XmlNode getMapXmlNode(XmlDocument mapXml, string nodeName, string[] attributeValues)
        {
            //Get empty map xml node
            XmlNode newNode = getMapXmlNode(mapXml, nodeName);
            //Set values for its attributes if any
            if (attributeValues != null)
            {
                for (int attributeIndex = 0; attributeIndex < newNode.Attributes.Count; attributeIndex++)
                {
                    newNode.Attributes[attributeIndex].Value = attributeValues[attributeIndex];
                }
            }
            return newNode;
        }

        /// 
        /// Gets Map Xml Leaf Node and sets the its value/inner text
        /// 
        /// <param name="xmlDoc" />map xml document
        /// <param name="nodeName" />Name of required node
        /// <param name="value" />Value/Inner text for node
        /// Map xml node with value set
        public XmlNode getMapXmlNodeValue(XmlDocument xmlDoc, string nodeName, string value)
        {
            //Get empty map xml node
            XmlNode newNode = getMapXmlNode(xmlDoc, nodeName);
            //Set its value
            newNode.InnerText = value;
            return newNode;
        }

        /// 
        /// Gets Empty Map xml node with attributes created if any but no values set
        /// 
        /// <param name="mapXml" />map xml document
        /// <param name="nodeName" />Name of required node
        /// Empty Map xml node
        private XmlNode getMapXmlNode(XmlDocument mapXml, string nodeName)
        {
            XmlNode xmlNode = mapXml.CreateNode(XmlNodeType.Element, "Default", "");
            XmlAttribute attribute1, attribute2;
            switch (nodeName)
            {
                //case "Declaration":
                //    xmlNode = mapXml.CreateNode(XmlNodeType.XmlDeclaration, "xml", "");
                //    attribute1 = mapXml.CreateAttribute("version", "");
                //    attribute2 = mapXml.CreateAttribute("encoding", "");
                //    xmlNode.Attributes.Append(attribute1);
                //    xmlNode.Attributes.Append(attribute2);
                //   break;
                case "Map":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "Map", "");
                    attribute1 = mapXml.CreateAttribute("Name", "");
                    attribute2 = mapXml.CreateAttribute("Source", "");
                    xmlNode.Attributes.Append(attribute1);
                    xmlNode.Attributes.Append(attribute2);
                    break;

                case "Description":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "Description", "");
                    break;

                case "UserIdentifier":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "UserIdentifier", "");
                    break;

                case "SourceUserIdentifierForSourceDataSourceUserLink":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "SourceUserIdentifierForSourceDataSourceUserLink", "");
                    break;

                case "SourceUserIdentifierForSourceCRMUserLink":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "SourceUserIdentifierForSourceCRMUserLink", "");
                    break;

                case "TargetUserIdentifierForSourceCRMUserLink":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "TargetUserIdentifierForSourceCRMUserLink", "");
                    break;

                case "EntityMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "EntityMaps", "");
                    break;

                case "EntityMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "EntityMap", "");
                    attribute1 = mapXml.CreateAttribute("TargetEntityName", "");
                    attribute2 = mapXml.CreateAttribute("SourceEntityName", "");
                    xmlNode.Attributes.Append(attribute1);
                    xmlNode.Attributes.Append(attribute2);
                    break;

                case "AttributeMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "AttributeMaps", "");
                    break;

                case "TransformationMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "TransformationMaps", "");
                    break;

                case "AttributeMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "AttributeMap", "");
                    break;

                case "TransformationMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "TransformationMap", "");
                    break;

                case "SourceAttributeName":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "SourceAttributeName", "");
                    break;

                case "TargetAttributeName":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "TargetAttributeName", "");
                    break;

                case "ProcessCode":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "ProcessCode", "");
                    break;

                case "LookupMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "LookupMaps", "");
                    break;

                case "PicklistMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "PicklistMaps", "");
                    break;

                case "TransformationTypeName":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "TransformationTypeName", "");
                    break;

                case "InputParameterMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "InputParameterMaps", "");
                    break;

                case "OutputParameterMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "OutputParameterMaps", "");
                    break;

                case "LookupMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "LookupMap", "");
                    break;

                case "PicklistMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "PicklistMap", "");
                    break;

                case "SingletonInputParameterMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "SingletonInputParameterMaps", "");
                    break;

                case "ArrayInputParameterMaps":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "ArrayInputParameterMaps", "");
                    break;

                case "ArrayInputParameterMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "ArrayInputParameterMap", "");
                    break;

                case "OutputParameterMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "OutputParameterMap", "");
                    break;

                case "LookupEntityName":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "LookupEntityName", "");
                    break;

                case "LookupAttributeName":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "LookupAttributeName", "");
                    break;

                case "LookupType":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "LookupType", "");
                    break;

                case "SourceValue":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "SourceValue", "");
                    break;

                case "TargetValue":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "TargetValue", "");
                    break;

                case "ParameterSequence":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "ParameterSequence", "");
                    break;

                case "DataTypeCode":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "DataTypeCode", "");
                    break;

                case "Data":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "Data", "");
                    break;

                case "SingletonInputParameterMap":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "SingletonInputParameterMap", "");
                    break;

                case "Items":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "Items", "");
                    break;

                case "Item":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "Item", "");
                    break;

                case "ParameterArray":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "ParameterArray", "");
                    break;

                case "ParameterArrayIndex":
                    xmlNode = mapXml.CreateNode(XmlNodeType.Element, "ParameterArrayIndex", "");
                    break;
            }
            return xmlNode;
        }

        /// 
        /// Save Map Xml in form of Xml File
        /// 
        /// <param name="mapXml" />Map Xml Document
        /// <param name="filePath" />Path of File where it has to be stored
        /// true if successfully saved else false
        public bool saveMapXml(XmlDocument mapXml, string filePath)
        {
            try
            {
                mapXml.Save(filePath);
            }
            catch (System.Xml.XmlException xmlException)
            {
                //ToDo: Handle Xml Exception
                throw xmlException;
            }

            return true;
        }

        #endregion

        //All remaining helpers for Map Editor Helper Methods or for Front End Methods
        #region Other Helpers

        /// 
        /// Replace Entity Schema Names by Display names in Lookup Metadata Table in Referenced Entity Column
        /// 
        /// <param name="lookupMetadataTable" />Reference to Lookup MetadataTable
        /// <param name="entityMetadataTable" />Reference to Entity MetadataTable
        private void ReplaceReferencedEntitySchemaNamesByDisplayNames(ref DataTable lookupMetadataTable, ref DataTable entityMetadataTable)
        {
            object[] values = new object[2];
            for (int rowIndex = 0; rowIndex < lookupMetadataTable.Rows.Count; rowIndex++)
            {
                //Get Lookup Metadata Row to obtain entity name to be replaced
                values = lookupMetadataTable.Rows[rowIndex].ItemArray;
                //Get display name for entity from Entity Metadata Table
                values[0] = getEntityDisplayName(entityMetadataTable, values[0].ToString());
                lookupMetadataTable.Rows[rowIndex].ItemArray = values;
            }
        }

        /// 
        /// Replace Attribute Schema Names by Display names in Entity Metadata Table in Primary Attribute Column
        /// 
        /// <param name="entityMetadataTable" />Reference to Entity MetadataTable
        /// <param name="attributeMetadataTableValidForRead" />Reference to Attribute MetadataTable
        private void ReplaceReferencedAttributeSchemaNamesByDisplayNames(ref DataTable entityMetadataTable, ref DataTable attributeMetadataTableValidForRead)
        {
            object[] values = new object[5];
            for (int rowIndex = 0; rowIndex < entityMetadataTable.Rows.Count; rowIndex++)
            {
                //Get Entity Metadata Row to obtain attribute name to be replaced
                values = entityMetadataTable.Rows[rowIndex].ItemArray;
                //Get display name for attribute from Attribute Metadata Table
                values[2] = getAttributeDisplayName(attributeMetadataTableValidForRead, values[0].ToString(), values[2].ToString());
                entityMetadataTable.Rows[rowIndex].ItemArray = values;
            }
        }

        /// 
        /// Read Data File for Source Entity to obtain Column Headings/Source Attribute Names and values 
        /// and store in a File Data Table for this Source Entity
        /// 
        /// <param name="fileDataTables" />Reference List of File Data Tables, a global variable in Map Editor Wizard Class
        /// <param name="fileName" />File name with Full Path
        /// <param name="fieldSeparator" />Field separator character
        /// <param name="valueSeparator" />Data Value separator character in case fied separator is part of Data Value
        public void ReadSourceEntityFile(ref List fileDataTables, string fileName, char fieldSeparator, char valueSeparator)
        {
            //Read whole file in an input string
            string inputString = File.ReadAllText(fileName);
            DataTable dataTable = new DataTable(fileName.Trim('\\'));
            string columnHeading = "";
            string columnValue = "";
            //To separate the last value of a row with first value of next row
            string[] lastAndFirstColumnValues = new string[2];
            //First index of field separator in input string
            int indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);
            int indexOfNewLineChar = inputString.IndexOf("\r\n");
            if (indexOfFieldSeparator == -1 && inputString.Length > 0)
            {
                if (indexOfNewLineChar < 0)
                    columnHeading = inputString;
                else
                    columnHeading = inputString.Substring(0, indexOfNewLineChar);
                dataTable.Columns.Add(columnHeading);
                if (indexOfNewLineChar > -1)
                {
                    inputString = inputString.Substring(indexOfNewLineChar + 2, inputString.Length - indexOfNewLineChar - 2);
                    indexOfNewLineChar = inputString.IndexOf("\r\n");
                    while (indexOfNewLineChar > -1)
                    {
                        if (indexOfNewLineChar == 0)
                            dataTable.Rows.Add(new object[] { null });
                        else
                        {
                            columnValue = inputString.Substring(0, indexOfNewLineChar);
                            dataTable.Rows.Add(new object[] { columnValue });
                        }
                        inputString = inputString.Substring(indexOfNewLineChar + 2, inputString.Length - indexOfNewLineChar - 2);
                        indexOfNewLineChar = inputString.IndexOf("\r\n");
                    }
                    columnValue = inputString;
                    dataTable.Rows.Add(new object[] { columnValue });
                }
            }
            else if (valueSeparator != 'n')
            {
                //First index of value separator in input string
                int indexOfValueSeparator = inputString.IndexOf(valueSeparator);
                //Next index of field and value separator in input string
                int nextIndexOfValueSeparator = 0;
                int nextIndexOfFieldSeparator = 0;
                int oldLength = 0;

                //If value separator is there in input string and it appears before field separator 
                //then actual value is whole string between 2 value separators 
                //else actual value is substring from index 0 upto first appearance of field separator
                if ((indexOfValueSeparator > -1) && (indexOfValueSeparator < indexOfFieldSeparator))
                {
                    nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                    nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                    columnHeading = inputString.Substring(0, nextIndexOfFieldSeparator);
                }
                else
                    columnHeading = inputString.Substring(0, indexOfFieldSeparator);
                //while header row 
                while (!columnHeading.Contains("\r\n") && indexOfFieldSeparator > -1)
                {
                    inputString = inputString.Substring(columnHeading.Length + 1, inputString.Length - columnHeading.Length - 1);
                    dataTable.Columns.Add(columnHeading.Trim(valueSeparator));
                    indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);
                    indexOfValueSeparator = inputString.IndexOf(valueSeparator);
                    //If value separator is there in input string and it appears before field separator 
                    //then actual value is whole string between 2 value separators 
                    //else actual value is substring from index 0 upto first appearance of field separator
                    if ((indexOfValueSeparator > -1) && (indexOfValueSeparator < indexOfFieldSeparator))
                    {
                        nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                        nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                        columnHeading = inputString.Substring(0, nextIndexOfFieldSeparator + 1);
                    }
                    else
                        columnHeading = inputString.Substring(0, indexOfFieldSeparator);
                }
                //if header row ends then take string and separate last column heading with first value in next row
                if (columnHeading.Contains("\r\n"))
                {
                    //indexOfFieldSeparator = columnHeading.Substring(columnHeading.IndexOf("\r\n") + 1, columnHeading.Length - columnHeading.IndexOf("\r\n") - 1).IndexOf(fieldSeparator);
                    indexOfValueSeparator = columnHeading.Substring(columnHeading.IndexOf("\r\n") + 1, columnHeading.Length - columnHeading.IndexOf("\r\n") - 1).IndexOf(valueSeparator);
                    if (indexOfValueSeparator > -1)
                    {
                        nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                        nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                        columnHeading = inputString.Substring(0, nextIndexOfFieldSeparator);
                    }
                    lastAndFirstColumnValues = columnHeading.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                    dataTable.Columns.Add(lastAndFirstColumnValues[0].Trim(valueSeparator));
                    inputString = inputString.Substring(columnHeading.Length + 1, inputString.Length - columnHeading.Length - 1);
                }

                int columnIndex = 0;
                object[] rowValues = new object[dataTable.Columns.Count];
                while (inputString != "" && indexOfFieldSeparator > -1)
                {
                    columnIndex = 0;
                    columnValue = lastAndFirstColumnValues[1];
                    while (!columnValue.Contains("\r\n") && indexOfFieldSeparator > -1)
                    {
                        rowValues[columnIndex] = columnValue.Trim(valueSeparator);
                        indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);
                        indexOfValueSeparator = inputString.IndexOf(valueSeparator);

                        if (indexOfFieldSeparator > -1)
                        {
                            if ((indexOfValueSeparator > -1) && (indexOfValueSeparator < indexOfFieldSeparator))
                            {
                                nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                                nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                                columnValue = inputString.Substring(0, nextIndexOfFieldSeparator + 1);
                            }
                            else
                                columnValue = inputString.Substring(0, indexOfFieldSeparator);
                            inputString = inputString.Substring(columnValue.Length + 1, inputString.Length - columnValue.Length - 1);
                        }
                        else
                            columnValue = inputString;
                        columnIndex++;
                    }
                    if (columnValue.Contains("\r\n"))
                    {
                        indexOfValueSeparator = columnValue.Substring(columnValue.IndexOf("\r\n") + 1, columnValue.Length - columnValue.IndexOf("\r\n") - 1).IndexOf(valueSeparator);
                        if (indexOfValueSeparator > -1)
                        {
                            oldLength = columnValue.Length;
                            nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                            nextIndexOfFieldSeparator = inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                            columnValue += inputString.Substring(0, nextIndexOfFieldSeparator);
                            inputString = inputString.Substring(nextIndexOfFieldSeparator + 1, inputString.Length - nextIndexOfFieldSeparator - 1);
                        }

                        lastAndFirstColumnValues = columnValue.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                        rowValues[columnIndex] = lastAndFirstColumnValues[0].Trim(valueSeparator);

                        dataTable.Rows.Add(rowValues);
                    }
                }
            }
            else
            {
                if (indexOfFieldSeparator != -1)
                    columnHeading = inputString.Substring(0, indexOfFieldSeparator);
                //while header row 
                while (!columnHeading.Contains("\r\n") && indexOfFieldSeparator > -1)
                {
                    inputString = inputString.Substring(columnHeading.Length + 1, inputString.Length - columnHeading.Length - 1);
                    dataTable.Columns.Add(columnHeading);
                    indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);
                    if (indexOfFieldSeparator != -1)
                        columnHeading = inputString.Substring(0, indexOfFieldSeparator);
                }
                //if header row ends then take string and separate last column heading with first value in next row
                if (columnHeading.Contains("\r\n"))
                {
                    lastAndFirstColumnValues = columnHeading.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                    dataTable.Columns.Add(lastAndFirstColumnValues[0]);
                    inputString = inputString.Substring(columnHeading.Length + 1, inputString.Length - columnHeading.Length - 1);
                }

                int columnIndex = 0;
                object[] rowValues = new object[dataTable.Columns.Count];
                while (inputString != "" && indexOfFieldSeparator > -1)
                {
                    columnIndex = 0;
                    columnValue = lastAndFirstColumnValues[1];
                    while (!columnValue.Contains("\r\n") && indexOfFieldSeparator > -1)
                    {
                        rowValues[columnIndex] = columnValue;
                        indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);

                        if (indexOfFieldSeparator > -1)
                        {
                            columnValue = inputString.Substring(0, indexOfFieldSeparator);
                            inputString = inputString.Substring(columnValue.Length + 1, inputString.Length - columnValue.Length - 1);
                        }
                        else
                            columnValue = inputString;
                        columnIndex++;
                    }
                    if (columnValue.Contains("\r\n"))
                    {
                        lastAndFirstColumnValues = columnValue.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                        rowValues[columnIndex] = lastAndFirstColumnValues[0];

                        dataTable.Rows.Add(rowValues);
                    }
                    else
                    {
                        rowValues[columnIndex] = columnValue;
                        dataTable.Rows.Add(rowValues);
                    }
                }
            }

            fileDataTables.Add(dataTable);
        }

        /// 
        /// Read Data File for Source Entity to obtain Column Headings/Source Attribute Names and values 
        /// and store in a File Data Table for this Source Entity
        /// 
        /// <param name="fileDataTables" />Reference List of File Data Tables, a global variable in Map Editor Wizard Class
        /// <param name="fileName" />File name with Full Path
        /// <param name="fieldSeparator" />Field separator character
        /// <param name="valueSeparator" />Data Value separator character in case fied separator is part of Data Value
        public void GetSourceEntityFileColumns(ref List fileDataTables, string fileName, char fieldSeparator, char valueSeparator)
        {
            //Read whole file in an input string
            string inputString = File.ReadAllText(fileName);
            int indexOfFirstEntityNameCharacter = fileName.LastIndexOf('\\') + 1;
            int lengthOfFileName = fileName.Length;
            string sourceEntityName = fileName.Substring(indexOfFirstEntityNameCharacter, lengthOfFileName - indexOfFirstEntityNameCharacter - 4);

            DataTable dataTable = new DataTable(sourceEntityName);
            string columnHeading = "";
            //To separate the last value of a row with first value of next row
            string[] lastAndFirstColumnValues = new string[2];
            //First index of field separator in input string
            int indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);
            int indexOfNewLineChar = inputString.IndexOf("\r\n");
            if (indexOfFieldSeparator == -1 && inputString.Length > 0)
            {
                if (indexOfNewLineChar < 0)
                    columnHeading = inputString;
                else
                    columnHeading = inputString.Substring(0, indexOfNewLineChar);
                dataTable.Columns.Add(columnHeading);
            }
            else if (valueSeparator != 'n')
            {
                //First index of value separator in input string
                int indexOfValueSeparator = inputString.IndexOf(valueSeparator);
                //Next index of field and value separator in input string
                int nextIndexOfValueSeparator = 0;
                int nextIndexOfFieldSeparator = 0;

                //If value separator is there in input string and it appears before field separator 
                //then actual value is whole string between 2 value separators 
                //else actual value is substring from index 0 upto first appearance of field separator
                if ((indexOfValueSeparator > -1) && (indexOfValueSeparator < indexOfFieldSeparator))
                {
                    nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                    nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                    columnHeading = inputString.Substring(0, nextIndexOfFieldSeparator);
                }
                else
                    columnHeading = inputString.Substring(0, indexOfFieldSeparator);
                //while header row 
                while (!columnHeading.Contains("\r\n") && indexOfFieldSeparator > -1)
                {
                    inputString = inputString.Substring(columnHeading.Length + 1, inputString.Length - columnHeading.Length - 1);
                    dataTable.Columns.Add(columnHeading.Trim(valueSeparator));
                    indexOfFieldSeparator = inputString.IndexOf(fieldSeparator);
                    indexOfValueSeparator = inputString.IndexOf(valueSeparator);
                    //If value separator is there in input string and it appears before field separator 
                    //then actual value is whole string between 2 value separators 
                    //else actual value is substring from index 0 upto first appearance of field separator
                    if ((indexOfValueSeparator > -1) && (indexOfValueSeparator < indexOfFieldSeparator))
                    {
                        nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                        nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                        columnHeading = inputString.Substring(0, nextIndexOfFieldSeparator + 1);
                    }
                    else
                        columnHeading = inputString.Substring(0, indexOfFieldSeparator);
                }
                //if header row ends then take string and separate last column heading with first value in next row
                if (columnHeading.Contains("\r\n"))
                {
                    //indexOfFieldSeparator = columnHeading.Substring(columnHeading.IndexOf("\r\n") + 1, columnHeading.Length - columnHeading.IndexOf("\r\n") - 1).IndexOf(fieldSeparator);
                    indexOfValueSeparator = columnHeading.Substring(columnHeading.IndexOf("\r\n") + 1, columnHeading.Length - columnHeading.IndexOf("\r\n") - 1).IndexOf(valueSeparator);
                    if (indexOfValueSeparator > -1)
                    {
                        nextIndexOfValueSeparator = inputString.Substring(indexOfValueSeparator + 1, inputString.Length - indexOfValueSeparator - 1).IndexOf(valueSeparator);
                        nextIndexOfFieldSeparator = nextIndexOfValueSeparator + inputString.Substring(nextIndexOfValueSeparator + 1, inputString.Length - nextIndexOfValueSeparator - 1).IndexOf(fieldSeparator);
                        columnHeading = inputString.Substring(0, nextIndexOfFieldSeparator);
                    }
                    lastAndFirstColumnValues = columnHeading.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                    dataTable.Columns.Add(lastAndFirstColumnValues[0].Trim(valueSeparator));
                }
            }
            fileDataTables.Add(dataTable);
        }

        /// 
        /// Create an empty Data Table with a specific name with Column names specified in input Parameter
        /// 
        /// <param name="dataTableName" />Name of Data Table
        /// <param name="columnNames" />String Array specifying column names in table
        /// Required Data Table
        private DataTable createDataTableWithColumns(string dataTableName, string[] columnNames)
        {
            DataTable dataTable = new DataTable(dataTableName);
            foreach (string columnName in columnNames)
            {
                dataTable.Columns.Add(columnName);
            }

            return dataTable;
        }

        /// 
        /// Gets attribute metadata row from the Attribute MetaDataTable for an attribute of an entity
        /// 
        /// <param name="attributeMetadataTable" />Attribute Metadata Table
        /// <param name="entityName" />Entity Name
        /// <param name="attributeName" />Attribute Name
        /// Required Attribute Metadata Row else null to indicate error condition
        public DataRow getAttributeMetaData(DataTable attributeMetadataTable, string entityName, string attributeName)
        {
            DataRow row;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                row = attributeMetadataTable.Rows[rowIndex];
                if (row.ItemArray[0].ToString().ToLower() == attributeName.ToLower() && row.ItemArray[2].ToString().ToLower() == entityName.ToLower())
                    return row;
            }
            //Return null to indicate error condition
            return null;
        }

        /// 
        /// Gets names corresponding to Picklist values for a particular attribute from Picklist Metadata Table
        /// 
        /// <param name="picklistMetadataTable" />Picklist Metadata Table
        /// <param name="attributeId" />Id of Picklist type Attribute
        /// List of Picklist value names
        public List getPicklistOptionNames(DataTable picklistMetadataTable, Guid attributeId)
        {
            DataRow row;
            List optionNames = new List();
            for (int rowIndex = 0; rowIndex < picklistMetadataTable.Rows.Count; rowIndex++)
            {
                row = picklistMetadataTable.Rows[rowIndex];
                if (row.ItemArray[2].ToString() == attributeId.ToString())
                    optionNames.Add(row.ItemArray[0].ToString());

            }
            return optionNames;
        }

        /// 
        /// Gets Referenced Entity names for a particular attribute from Lookup Metadata Table
        /// 
        /// <param name="lookupMetadataTable" />Lookup Metadata Table
        /// <param name="attributeId" />Id of lookup type Attribute
        /// List of Referenced entity names
        public List getReferencedEntities(DataTable lookupMetadataTable, Guid attributeId)
        {
            DataRow row;
            List referencedEntities = new List();
            for (int rowIndex = 0; rowIndex < lookupMetadataTable.Rows.Count; rowIndex++)
            {
                row = lookupMetadataTable.Rows[rowIndex];
                if (row.ItemArray[1].ToString() == attributeId.ToString())
                    referencedEntities.Add(row.ItemArray[0].ToString());

            }
            return referencedEntities;
        }

        /// 
        /// Gets picklist option value for a particular option name for an attribute from Picklist Metadata Table
        /// 
        /// <param name="picklistMetadataTable" />Picklist Metadata Table
        /// <param name="attributeId" />Id of Picklist type Attribute
        /// <param name="valueName" />Option name
        /// Option value else Return -1 to indicate error condition
        public int getPicklistOptionValue(DataTable picklistMetadataTable, Guid attributeId, string valueName)
        {
            DataRow row;
            for (int rowIndex = 0; rowIndex < picklistMetadataTable.Rows.Count; rowIndex++)
            {
                row = picklistMetadataTable.Rows[rowIndex];
                if (row.ItemArray[2].ToString() == attributeId.ToString() && row.ItemArray[0].ToString() == valueName)
                    return Int32.Parse(row.ItemArray[1].ToString());
            }
            //Return -1 to indicate error condition
            return -1;
        }

        /// 
        /// Gets picklist option name for a particular option value for an attribute from Picklist Metadata Table
        /// 
        /// <param name="picklistMetadataTable" />Picklist Metadata Table
        /// <param name="attributeId" />Id of Picklist type Attribute
        /// <param name="valueName" />Option value
        /// Option name else Return empty string to indicate error condition
        public string getPicklistOptionName(DataTable picklistMetadataTable, Guid attributeId, string value)
        {
            DataRow row;
            for (int rowIndex = 0; rowIndex < picklistMetadataTable.Rows.Count; rowIndex++)
            {
                row = picklistMetadataTable.Rows[rowIndex];
                if (row.ItemArray[2].ToString() == attributeId.ToString() && row.ItemArray[1].ToString() == value)
                    return row.ItemArray[0].ToString();
            }
            //Return empty string to indicate error condition
            return string.Empty;
        }

        /// 
        /// Gets attribute type from the Attribute MetaDataTable for an attribute of an entity
        /// 
        /// <param name="attributeMetadataTable" />Attribute Metadata Table
        /// <param name="entityName" />Entity Name
        /// <param name="attributeName" />Attribute Name
        /// 
        /// string representing Attribute Type else Return 'Error' to indicate error condition as 'Error' is no attribute type currently in Crm
        /// 
        public string getAttributeType(DataTable attributeMetadataTable, string entityName, string attributeName)
        {
            DataRow attributeRow;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                attributeRow = attributeMetadataTable.Rows[rowIndex];
                if ((attributeRow.ItemArray[0].ToString().ToLower() == attributeName.ToLower()) && (attributeRow.ItemArray[2].ToString().ToLower() == entityName.ToLower()))
                    return attributeRow.ItemArray[5].ToString();
            }
            //Return 'Error' to indicate error condition as 'Error' is no attribute type currently in Crm
            return "Error";
        }

        /// 
        /// Gets Display name from Entity Metadata Table for an entity given its schema name
        /// 
        /// <param name="entityMetadataTable" />Entity Metadata Table
        /// <param name="entitySchemaName" />Schema name of entity
        /// Display name of entity else Return empty string to indicate error condition
        public string getEntityDisplayName(DataTable entityMetadataTable, string entitySchemaName)
        {
            DataRow row;
            for (int rowIndex = 0; rowIndex < entityMetadataTable.Rows.Count; rowIndex++)
            {
                row = entityMetadataTable.Rows[rowIndex];
                if (row.ItemArray[4].ToString().ToLower() == entitySchemaName.ToLower())
                    return row.ItemArray[0].ToString();
            }
            //Return empty string to indicate error condition
            return string.Empty;
        }

        /// 
        /// Gets Schema name from Entity Metadata Table for an entity given its diplay name
        /// 
        /// <param name="entityMetadataTable" />Entity Metadata Table
        /// <param name="entitySchemaName" />Display name of entity
        /// Schema name of entity else Return empty string to indicate error condition
        public string getEntitySchemaName(DataTable entityMetadataTable, string entityDisplayName)
        {
            DataRow row;
            for (int rowIndex = 0; rowIndex < entityMetadataTable.Rows.Count; rowIndex++)
            {
                row = entityMetadataTable.Rows[rowIndex];
                if (row.ItemArray[0].ToString().ToLower() == entityDisplayName.ToLower())
                    return row.ItemArray[4].ToString();
            }
            //Return empty string to indicate error condition
            return string.Empty;
        }

        /// 
        /// Gets count of Attributes which are valid for create for given Entity
        /// 
        /// <param name="attributeMetadataTable" />Valid for create Attribute Metadata Table
        /// <param name="entityName" />Entity Name
        /// Count of Valid for create attributes
        public int getCountOfValidForCreateAttributes(DataTable attributeMetadataTable, string entityName)
        {
            int count = 0;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                if (attributeMetadataTable.Rows[rowIndex].ItemArray[2].ToString().ToLower() == entityName.ToLower())
                    count++;
            }
            //Return null to indicate error condition
            return count;
        }

        /// 
        /// Gets Display name from Attribute Metadata Table for an attribute of an entity given its schema name
        /// 
        /// <param name="attributeMetadataTable" />Attribute Metadata Table
        /// <param name="entityName" />Entity name
        /// <param name="attributeSchemaName" />Schema name of attribute
        /// Display name of attribute else Return empty string to indicate error condition
        public string getAttributeDisplayName(DataTable attributeMetadataTable, string entityName, string attributeSchemaName)
        {
            DataRow attributeRow;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                attributeRow = attributeMetadataTable.Rows[rowIndex];
                if ((attributeRow.ItemArray[3].ToString().ToLower() == attributeSchemaName.ToLower()) && (attributeRow.ItemArray[2].ToString().ToLower() == entityName.ToLower()))
                    return attributeRow.ItemArray[0].ToString();
            }
            //Return empty string to indicate error condition
            return string.Empty;
        }

        /// 
        /// Gets Schema name from Attribute Metadata Table for an attribute of an entity given its attribute name
        /// 
        /// <param name="attributeMetadataTable" />Attribute Metadata Table
        /// <param name="entityName" />Entity name
        /// <param name="attributeSchemaName" />Display name of attribute
        /// Schema name of attribute else Return empty string to indicate error condition
        public string getAttributeSchemaName(DataTable attributeMetadataTable, string entityName, string attributeDisplayName)
        {
            DataRow attributeRow;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                attributeRow = attributeMetadataTable.Rows[rowIndex];
                if ((attributeRow.ItemArray[0].ToString().ToLower() == attributeDisplayName.ToLower()) && (attributeRow.ItemArray[2].ToString().ToLower() == entityName.ToLower()))
                    return attributeRow.ItemArray[3].ToString();
            }
            //Return empty string to indicate error condition
            return string.Empty;
        }

        /// 
        /// Gets Primary Attribute name for an entity from entity metadata table
        /// 
        /// <param name="entityMetadataTable" />entity metadata table
        /// <param name="entityName" />Entity Name
        /// Primary Attribute name else Return empty string to indicate error condition
        public string getPrimaryAttribute(DataTable entityMetadataTable, string entityName)
        {
            DataRow row;
            for (int rowIndex = 0; rowIndex < entityMetadataTable.Rows.Count; rowIndex++)
            {
                row = entityMetadataTable.Rows[rowIndex];
                if (row.ItemArray[0].ToString().ToLower() == entityName.ToLower())
                    return row.ItemArray[2].ToString();
            }
            //Return empty string to indicate error condition
            return string.Empty;
        }

        /// 
        /// Checks if given attribute name is of a system required attribute
        /// 
        /// <param name="attributeName" />Attribute Name
        /// true if system required else false
        public bool isSystemRequired(string attributeName)
        {
            //if name ends with '*' then buesiness required
            if (attributeName.LastIndexOf('*') == (attributeName.Length - 1))
                return true;
            return false;
        }

        /// 
        /// Checks if given attribute of an entity name is System Required from 'Attribute Required Level' property in Attribute Metadata Table
        /// 
        /// <param name="attributeMetadataTable" />Attribute Metadata Table
        /// <param name="entityName" />Entity Name
        /// <param name="attributeName" />Attribute Name
        /// true if system required else false
        public bool isSystemRequired(DataTable attributeMetadataTable, string entityName, string attributeName)
        {
            DataRow attributeRow;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                attributeRow = attributeMetadataTable.Rows[rowIndex];
                if ((attributeRow.ItemArray[0].ToString().ToLower() == attributeName.ToLower()) && (attributeRow.ItemArray[2].ToString().ToLower() == entityName.ToLower()))
                {
                    if (attributeRow.ItemArray[4].ToString() == AttributeRequiredLevel.SystemRequired.ToString())
                        return true;
                    else
                        return false;
                }

            }
            return false;
        }

        /// 
        /// Gets count of System Required Attributes for an entity from Attribute Metadata Table
        /// 
        /// <param name="attributeMetadataTable" />Attribute Metadata Table
        /// <param name="entityName" />Entity Name
        /// Count of System Required Attribute
        public int getCountofSystemRequiredAttributes(DataTable attributeMetadataTable, string entityName)
        {
            int count = 0;
            DataRow row;
            for (int rowIndex = 0; rowIndex < attributeMetadataTable.Rows.Count; rowIndex++)
            {
                row = attributeMetadataTable.Rows[rowIndex];
                //If attribute name and entity names for current attribute metadata row matches those in input 
                //and if attribute required level is system required then increment count
                if (row.ItemArray[2].ToString().ToLower() == entityName.ToLower() && row.ItemArray[4].ToString() == AttributeRequiredLevel.SystemRequired.ToString())
                    count++;
            }
            return count;
        }

        #endregion

    }

}