private static AttributeMetadata LoadAttributeMetadata(string entityLogicalName, string attributeLogicalName)
        {
            string cacheKey = entityLogicalName +"|" + attributeLogicalName;
            AttributeMetadata metaData = (AttributeMetadata)_attributeMetaData[cacheKey];

            if (metaData==null)
            {
                RetrieveAttributeRequest request = new RetrieveAttributeRequest();
                request.EntityLogicalName = entityLogicalName;
                request.LogicalName = attributeLogicalName;
                request.RetrieveAsIfPublished = true;

                RetrieveAttributeResponse response = (RetrieveAttributeResponse)OrganizationServiceProxy.Execute(request);
                metaData = response.AttributeMetadata;
                _attributeMetaData[cacheKey] = metaData;
            }
            return metaData;
        }
        /// <summary>
        /// Processes the non-global option sets
        /// </summary>
        /// <param name="dictionary">The <C>Dictionary</C> that contains the name value pairs for the option set.</param>
        /// <param name="entityName">The name of the <C>Entity</C> that the option set belongs to.</param>
        private void ProcessPickLists(Dictionary<string, object> dictionary, string entityName)
        {
            if (dictionary == null)
            {
                return;
            }

            OrganizationResponse langRes = null;
            foreach (string attributeName in dictionary.Keys)
            {
                string[] values = dictionary[attributeName] as string[];
                if (values.Length < 1)
                {
                    continue;
                }

                RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest();
                attribReq.EntityLogicalName = entityName;
                attribReq.LogicalName = attributeName;
                attribReq.RetrieveAsIfPublished = true;
                OrganizationRequest langReq = new OrganizationRequest("RetrieveAvailableLanguages");

                // Get the attribute metadata for the state attribute.
                RetrieveAttributeResponse metadataRespone = null;
                try
                {
                    metadataRespone = (RetrieveAttributeResponse)this.CrmAdapter.OrganizationService.Execute(attribReq);
                    if (langRes == null)
                    {
                        langRes = this.CrmAdapter.OrganizationService.Execute(langReq);
                    }
                }
                catch (Exception e)
                {
                    throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.MetadataClientPicklistExceptionMessage, entityName, e.Message), e) { ExceptionId = ErrorCodes.PicklistMetadataRetrieval };
                }

                if (metadataRespone != null)
                {
                    PicklistAttributeMetadata picklistAttrib = metadataRespone.AttributeMetadata as PicklistAttributeMetadata;
                    int optionNumber = 200000;
                    InsertOptionValueRequest insertRequest = new InsertOptionValueRequest();
                    insertRequest.AttributeLogicalName = picklistAttrib.LogicalName;
                    insertRequest.EntityLogicalName = entityName;
                    insertRequest.Label = new Label();
                    insertRequest.Value = new int?();
                    foreach (string picklistName in values)
                    {
                        try
                        {
                            var option = picklistAttrib.OptionSet.Options.FirstOrDefault(opt => opt.Label.UserLocalizedLabel.Label.Replace(NotInErp, string.Empty).Trim().ToUpperInvariant() == picklistName.ToUpperInvariant() || opt.Label.UserLocalizedLabel.Label.Replace("*", string.Empty).Trim().ToUpperInvariant() == picklistName.ToUpperInvariant());
                            optionNumber += picklistAttrib.OptionSet.Options.Count();

                            // Add new values
                            if (option == null)
                            {
                                insertRequest.Value = optionNumber++;
                                insertRequest.Label = CreateSingleLabel(picklistName, metadataRespone.AttributeMetadata.DisplayName.UserLocalizedLabel.LanguageCode);
                                this.CrmAdapter.OrganizationService.Execute(insertRequest);
                            }
                            else if (option.Label.UserLocalizedLabel.Label != picklistName)
                            {
                                // Update existing values if they are different
                                this.CrmAdapter.OrganizationService.Execute(new UpdateOptionValueRequest() { AttributeLogicalName = picklistAttrib.LogicalName, EntityLogicalName = entityName, Label = CreateSingleLabel(picklistName, option.Label.UserLocalizedLabel.LanguageCode), MergeLabels = false, Value = option.Value.Value });
                            }
                        }
                        catch (FaultException e)
                        {
                            if (e.Message.Contains("because another picklist or status option for this attribute already exists"))
                            {
                                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ValueExistsMessage, entityName, e.Message), e) { ExceptionId = ErrorCodes.PicklistMetadataCreation };
                            }
                            else
                            {
                                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.AddingValueExceptionMessage, picklistName, e.Message), e) { ExceptionId = ErrorCodes.PicklistMetadataCreation };
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Converts all representations of the state property to an integer.
        /// </summary>
        /// <param name="stateName">The state to get the integer value of as a <c>string</c>.</param>
        /// <param name="entityName">The name of the entity type to get the state code for.</param>
        /// <param name="adapter">The <see cref="DynamicCrmAdapter"/> to use for calling into a CRM for resolving that state.</param>
        /// <returns>An <c>int</c> the represents the state.</returns>
        public static int ConvertStateNameToValue(string stateName, string entityName, DynamicCrmAdapter adapter)
        {
            if (adapter == null)
            {
                throw new ArgumentNullException("adapter");
            }

            RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest() { EntityLogicalName = entityName, LogicalName = "statecode", RetrieveAsIfPublished = true };

            // Get the attribute metadata for the state attribute.
            RetrieveAttributeResponse metadataResponse = (RetrieveAttributeResponse)adapter.OrganizationService.Execute(attribReq);
            StateAttributeMetadata picklistAttrib = (StateAttributeMetadata)metadataResponse.AttributeMetadata;

            var picklistValue = from option in picklistAttrib.OptionSet.Options
                                where option.Label.UserLocalizedLabel.Label.ToUpperInvariant() == stateName.ToUpperInvariant()
                                select option.Value;

            // Ensure that both the returned list and the first item in the returned list are not null or empty.
            if ((picklistValue.Count() > 0) && (picklistValue.First() != null))
            {
                return picklistValue.First().Value;
            }

            return CRM2011AdapterUtilities.GetDefaultStateCodeValue(stateName);
        }
        /// <summary>
        /// Gets a <c>Picklist</c> instance who's values are set based on the parameters provided.
        /// </summary>
        /// <param name="entity">The current <c>Entity</c>.</param>
        /// <param name="field">The current <c>DefinitionField</c> for the property being mapped to this <c>Picklist</c>.</param>
        /// <param name="mappedLookupObject">The <c>Dictionary</c> containing the lookup information for the <c>Picklist</c>.</param>
        /// <param name="crm2011Adapter">The <c>CRM2011Adapter</c> to use when calling the CRM web service.</param>
        /// <param name="providedEntityName">The name of the <c>Entity</c> that the current object provider is for.</param>
        /// <returns>A <c>Picklist</c> with it's value property set to the one requested in the <c>Dictionary</c>, if one is found and <c>null</c> otherwise.</returns>
        /// <exception cref="ArgumentException">Thrown if the requested value is not currently in the <c>Picklist</c> within the CRM system.</exception>
        public static OptionSetValue MapPicklist(Entity entity, FieldDefinition field, Dictionary<string, object> mappedLookupObject, DynamicCrmAdapter crm2011Adapter, string providedEntityName)
        {
            if (entity == null || field == null || crm2011Adapter == null)
            {
                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ArgumentNullExceptionMessage)) { ExceptionId = AdapterException.SystemExceptionGuid };
            }

            ValidateDictionary(mappedLookupObject);

            if (!mappedLookupObject.Keys.Contains("Value"))
            {
                if (!mappedLookupObject.Keys.Contains("name") || string.IsNullOrEmpty(mappedLookupObject["name"] as string))
                {
                    return null;
                }

                RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest() { EntityLogicalName = entity.LogicalName, LogicalName = field.Name, RetrieveAsIfPublished = true };
                if (IsSpecialAddressPicklist(entity, field))
                {
                    attribReq.EntityLogicalName = providedEntityName;
                    attribReq.LogicalName = string.Format(CultureInfo.CurrentCulture, "address{0}_{1}", ((int?)entity["addressnumber"]).Value.ToString(CultureInfo.CurrentCulture), field.Name);
                }

                // Get the attribute metadata for the state attribute.
                RetrieveAttributeResponse metadataResponse = (RetrieveAttributeResponse)crm2011Adapter.OrganizationService.Execute(attribReq);
                PicklistAttributeMetadata picklistAttrib = (PicklistAttributeMetadata)metadataResponse.AttributeMetadata;

                var picklistValue = from option in picklistAttrib.OptionSet.Options
                                    where option.Label.UserLocalizedLabel.Label.ToUpperInvariant() == mappedLookupObject["name"].ToString().ToUpperInvariant()
                                    select option.Value;

                // ensure that both the returned list and the first item in the returned list are not null or empty.
                if ((picklistValue.Count() > 0) && (picklistValue.First() != null))
                {
                    return new OptionSetValue(picklistValue.First().Value);
                }

                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.PicklistValueNotFound, mappedLookupObject["name"].ToString(), field.DisplayName, entity.LogicalName)) { ExceptionId = ErrorCodes.PicklistMappingNotFound };
            }

            OptionSetValue mapping = new OptionSetValue();
            SetRelationshipValuesFromDictionary(mappedLookupObject, mapping);
            return mapping;
        }
        /// <summary>
        /// Populates a <c>Dictionary</c> with the values contained in a <c>DynamicEntity</c>.
        /// </summary>
        /// <param name="dynamicEntity">The <c>DynamicEntity</c> to get the properties and data from.</param>
        /// <param name="complexTypeDictionary">The <c>Dictionary</c> to be populated.</param>
        /// <param name="property">The property on the <c>DynamicEntity</c> to populate the supplied <c>Dictionary</c> for.</param>
        /// <param name="adapter">An instance of a <c>CRMAdapter</c> to use when getting dynamics_integrationkey data for a <c>Lookup</c> type.</param>
        private static void PopulateOptionSetValueDictionary(Entity dynamicEntity, Dictionary<string, object> complexTypeDictionary, KeyValuePair<string, object> property, DynamicCrmAdapter adapter)
        {
            PopulateDictionary(dynamicEntity, complexTypeDictionary, property);

            if (!complexTypeDictionary.ContainsKey("name"))
            {
                RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest() { EntityLogicalName = dynamicEntity.LogicalName, LogicalName = property.Key, RetrieveAsIfPublished = true };

                // Get the attribute metadata for the state attribute.
                RetrieveAttributeResponse metadataResponse = (RetrieveAttributeResponse)adapter.OrganizationService.Execute(attribReq);

                PicklistAttributeMetadata picklistAttrib = metadataResponse.AttributeMetadata as PicklistAttributeMetadata;
                StateAttributeMetadata stateAttrib = metadataResponse.AttributeMetadata as StateAttributeMetadata;
                IEnumerable<string> picklistValue = null;
                if (picklistAttrib != null)
                {
                    picklistValue = from option in picklistAttrib.OptionSet.Options
                                    where option.Value == ((OptionSetValue)property.Value).Value
                                    select option.Label.UserLocalizedLabel.Label;
                }
                else if (stateAttrib != null)
                {
                    picklistValue = from option in stateAttrib.OptionSet.Options
                                    where option.Value == ((OptionSetValue)property.Value).Value
                                    select option.Label.UserLocalizedLabel.Label;
                }

                // ensure that both the returned list and the first item in the returned list are not null or empty.
                if (picklistValue != null && picklistValue.Count() > 0 && picklistValue.First() != null)
                {
                    complexTypeDictionary.Add("name", picklistValue.First());
                }
            }
        }