/// <summary>
        /// Gets a <c>QueryExpression</c> instance with it's properties set to the values supplied
        /// </summary>
        /// <param name="entityName">The name of the <c>BusinessEntity</c> as a <c>string</c> to be queried</param>
        /// <param name="modifiedDate">The <c>string</c> value for the date to be queried from</param>
        /// <param name="adapter">An instance of a <c>CRM2011Adapter</c> used to retrieve the INTEGRATION user's <c>Guid</c></param>
        /// <param name="isDynamic">True if the object provider calling into this method is a <c>DynamicObbjectProvider</c> and false otherwise</param>
        /// <param name="columnSet">A CRM <c>ColumnSet</c> that contains the columns to be returned from the query.</param>
        /// <returns>An instance of a <c>QueryExpression</c> that can used as a parameter to a <c>RetrieveMultipleRequest</c></returns>
        /// <remarks>The method generates a query that is retrieved by the modified date supplied as well as the IntegrationReady flag and the modified by
        /// property not being equal to the INTEGRATION user's id</remarks>
        public static QueryExpression GetReaderQueryExpression(string entityName, DateTime modifiedDate, DynamicCrmAdapter adapter, bool isDynamic, ColumnSet columnSet)
        {
            if (adapter == null)
            {
                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ArgumentNullExceptionMessage), new ArgumentNullException("adapter")) { ExceptionId = AdapterException.SystemExceptionGuid };
            }

            ValidatePropertyQueryParameters(entityName, "modifiedon");
            QueryExpression queryHelper = new QueryExpression(entityName) { Distinct = false, Criteria = new FilterExpression(), ColumnSet = columnSet };
            queryHelper.ColumnSet.AllColumns = true;

            if (entityName != null)
            {
                if (entityName == "activitymimeattachment")
                {
                    LinkEntity emailLink = new LinkEntity()
                    {
                        LinkFromEntityName = "activitymimeattachment",
                        LinkFromAttributeName = "activityid",
                        LinkToEntityName = "email",
                        LinkToAttributeName = "activityid",
                        LinkCriteria =
                        {
                            Conditions =
                            {
                              new ConditionExpression(
                                "modifiedon", ConditionOperator.GreaterEqual, modifiedDate)
                            }
                        }
                    };

                    queryHelper.LinkEntities.Add(emailLink);
                }
                else
                {
                    queryHelper.Criteria.Conditions.Add(new ConditionExpression("modifiedon", ConditionOperator.GreaterEqual, modifiedDate));
                }
            }

            if (!isDynamic)
            {
                queryHelper.Criteria.Conditions.Add(new ConditionExpression(CRM2011AdapterUtilities.DynamicsIntegrationReady, ConditionOperator.Equal, true));
            }

            return queryHelper;
        }
        /// <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>
        /// 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 an instance of the <c>customeraddress</c> class.
        /// </summary>
        /// <param name="addressIntegrationKeyValue">The value of the address's dynamics_integrationkey property to query for.</param>
        /// <param name="parentKey">The parent of this address to use when querying for the existence of this address instance.</param>
        /// <param name="adapter">An instance of the <c>CRM2011Adapter</c> class to use when calling CRM.</param>
        /// <param name="addressIntegrationKeyProperty">The key attribute on the <c>customeraddress</c> that the supplied value is for.</param>
        /// <returns>A new instance with it's dynamics_integrationkey initialized to the value supplied or an existing instance.</returns>
        public static Entity GetDynamicAddressInstance(string addressIntegrationKeyValue, Guid parentKey, DynamicCrmAdapter adapter, string addressIntegrationKeyProperty)
        {
            if (parentKey == null || adapter == null)
            {
                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ArgumentNullExceptionMessage)) { ExceptionId = AdapterException.SystemExceptionGuid };
            }

            if (string.IsNullOrEmpty(addressIntegrationKeyProperty))
            {
                throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.AddressIntegrationKeyPropertyInvalidMessage)) { ExceptionId = ErrorCodes.AddressIntegrationKeyPropertyException };
            }

            RetrieveMultipleRequest retrieveRequest = new RetrieveMultipleRequest();
            KeyValuePair<string, string>[] propertyValues = new KeyValuePair<string, string>[2];
            propertyValues[0] = new KeyValuePair<string, string>(addressIntegrationKeyProperty, addressIntegrationKeyValue);
            propertyValues[1] = new KeyValuePair<string, string>("parentid", parentKey.ToString());
            retrieveRequest.Query = CRM2011AdapterUtilities.GetMultipartQueryExpression(LogicalOperator.And, "customeraddress", propertyValues);
            RetrieveMultipleResponse retrieveResponse = (RetrieveMultipleResponse)adapter.OrganizationService.Execute(retrieveRequest);
            Entity returnedEntity = null;

            if (retrieveResponse.EntityCollection.Entities.Count == 1)
            {
                returnedEntity = retrieveResponse.EntityCollection.Entities[0] as Entity;
                returnedEntity[CRM2011AdapterUtilities.IsNew] = false;
                return returnedEntity;
            }
            else if (retrieveResponse.EntityCollection.Entities.Count < 1)
            {
                // this is a new entity instance and we need to map the provided data onto the DynamicsEntity
                returnedEntity = new Entity() { LogicalName = "customeraddress" };
                if (addressIntegrationKeyProperty.Equals("customeraddressid", StringComparison.OrdinalIgnoreCase))
                {
                    returnedEntity[addressIntegrationKeyProperty] = new Guid(addressIntegrationKeyValue);
                }
                else
                {
                    returnedEntity[addressIntegrationKeyProperty] = addressIntegrationKeyValue;
                }

                returnedEntity[CRM2011AdapterUtilities.IsNew] = true;
                return returnedEntity;
            }
            else
            {
                throw new AdapterException(
                    string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.MultipleDynamicEntitiesReturnedExceptionMessage,
                    "customeraddress",
                    addressIntegrationKeyProperty,
                    addressIntegrationKeyValue))
                {
                    ExceptionId = ErrorCodes.MultipleCustomerAddressResult
                };
            }
        }
        /// <summary>
        /// Populates the activity party list for a given CRM <c>Entity</c>.
        /// </summary>
        /// <param name="dynamicEntity">The CRM <c>Entity</c> to be populated.</param>
        /// <param name="complexTypeDictionary">The <c>Dictionary</c> that contains the <see cref="ComplexType"/> definition.</param>
        /// <param name="property">The activity properties on the entity that was supplied.</param>
        /// <param name="adapter">The <see cref="DynamicCrmAdapter"/> to use to when calling into CRM to get the parties.</param>
        /// <param name="definition">The <see cref="FieldDefinition"/> that contains the data about the activity field.</param>
        private static void PopulatePartyList(Entity dynamicEntity, Dictionary<string, object> complexTypeDictionary, KeyValuePair<string, object> property, DynamicCrmAdapter adapter, FieldDefinition definition)
        {
            PopulateDictionary(dynamicEntity, complexTypeDictionary, property);
            var tempDictionary = new Dictionary<string, object>();

            foreach (var entity in (DataCollection<Entity>)complexTypeDictionary["Entities"])
            {
                var entityDictionary = GetDictionary(entity, adapter, definition.TypeDefinition.Children.ToList());

                var name = entityDictionary["activitypartyid"].ToString();
                if (!string.IsNullOrEmpty(name))
                {
                    tempDictionary.Add(name, entityDictionary);
                }
            }

            complexTypeDictionary.Add("ActivityParties", tempDictionary);
        }
        /// <summary>
        /// Gets a <c>Dictionary</c> that represents a <c>DynamicEntity</c>.
        /// </summary>
        /// <param name="entity">The CRM <c>Entity</c> to return as a <c>Dictioanry</c>.</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>
        /// <param name="fieldDefinitions">The <C>List</C> of <see cref="FieldDefinition"/>s to use when populating the <C>Dictionary</C>.</param>
        /// <returns>A <c>Dictionary</c> that has Keys that are the property names of the <c>DynamicEntity</c> supplied and 
        /// Values that are the values of those properties on the <c>DynamicEntity</c>.</returns>
        internal static Dictionary<string, object> GetDictionary(Entity entity, DynamicCrmAdapter adapter, List<FieldDefinition> fieldDefinitions)
        {
            Dictionary<string, object> dictionary = new Dictionary<string, object>();

            // This dictionary is for holding a complexType that might be the type for the current property on the entity
            Dictionary<string, object> holdingDictionary;
            foreach (KeyValuePair<string, object> property in entity.Attributes)
            {
                // CrmMoney needs the dictionary to be converted but it also starts with the same prefix as the property types that do not,so handle it separately
                // else if the property is not one of the Built-in types and is also not of the StringProperty type, use the holding dictionary
                Type propertyType = property.Value.GetType();
                holdingDictionary = new Dictionary<string, object>();
                if (propertyType == typeof(Money))
                {
                    PopulateDictionary(entity, holdingDictionary, property);
                }
                else if (propertyType == typeof(OptionSetValue))
                {
                    PopulateOptionSetValueDictionary(entity, holdingDictionary, property, adapter);
                }
                else if (propertyType == typeof(EntityReference))
                {
                    FieldDefinition definition = fieldDefinitions.FirstOrDefault(x => x.Name == property.Key);
                    PopulateDictionary(entity, holdingDictionary, property, adapter, definition);
                }
                else if (propertyType == typeof(EntityCollection))
                {
                    FieldDefinition definition = fieldDefinitions.FirstOrDefault(x => x.Name == property.Key);
                    PopulatePartyList(entity, holdingDictionary, property, adapter, definition);
                }

                // The property is of a ComplexType and the holding dictionary was populated
                // else if the property is one of the Built-in CRM types just convert it
                // else if the property was a string property, just use its value
                if (holdingDictionary.Count > 0)
                {
                    dictionary.Add(property.Key, holdingDictionary);
                }
                else
                {
                    dictionary.Add(property.Key, property.Value);
                }
            }

            if (fieldDefinitions.Any(x => x.Name == "overriddencreatedon"))
            {
                dictionary.Add("overriddencreatedon", null);
            }

            return dictionary;
        }
        /// <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());
                }
            }
        }
        /// <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>
        /// <param name="definition">The <see cref="FieldDefinition"/> for the referenced entity.</param>
        private static void PopulateDictionary(Entity dynamicEntity, Dictionary<string, object> complexTypeDictionary, KeyValuePair<string, object> property, DynamicCrmAdapter adapter, FieldDefinition definition)
        {
            PopulateDictionary(dynamicEntity, complexTypeDictionary, property);

            if (complexTypeDictionary.ContainsKey("Id") && complexTypeDictionary.ContainsKey("LogicalName"))
            {
                if (complexTypeDictionary["LogicalName"].ToString() != "attachment" && complexTypeDictionary["LogicalName"].ToString() != "activitymimeattachment")
                {
                    ColumnSet cols = new ColumnSet(true);
                    if (!CRM2011AdapterUtilities.GetIntegratedEntities().Contains(complexTypeDictionary["LogicalName"].ToString()))
                    {
                        cols = new ColumnSet(true);
                    }

                    RetrieveRequest request = new RetrieveRequest() { ColumnSet = cols, Target = new EntityReference(complexTypeDictionary["LogicalName"].ToString(), new Guid(complexTypeDictionary["Id"].ToString())) };
                    RetrieveResponse response = adapter.OrganizationService.Execute(request) as RetrieveResponse;
                    Entity entity = response.Entity;

                    var lookupType = definition.AdditionalAttributes.FirstOrDefault(x => x.Name == "LookupType");
                    var lookupField = definition.AdditionalAttributes.FirstOrDefault(x => x.Name == "LookupField");

                    var typeSplit = lookupType.Value.Split(',');
                    var fieldSplit = lookupField.Value.Split(',');

                    var keyValueLookup = new List<KeyValuePair<string, string>>();

                    if (typeSplit.Count() > 1 && fieldSplit.Count() > 1)
                    {
                        for (int i = 0; i < typeSplit.Count(); i++)
                        {
                            keyValueLookup.Add(new KeyValuePair<string, string>(typeSplit[i], fieldSplit[i]));
                        }

                        lookupField.Value = keyValueLookup.FirstOrDefault(x => x.Key == entity.LogicalName).Value;
                    }

                    if (lookupField != null)
                    {
                        if (lookupField.Value == "domainname" || entity.LogicalName == "systemuser")
                        {
                            lookupField.Value = "fullname";
                        }
                        else if (entity.LogicalName == "activitypointer")
                        {
                            lookupField.Value = "activityid";
                        }

                        complexTypeDictionary.Add(lookupField.Value, entity[lookupField.Value]);
                    }
                }
            }
        }
 /// <summary>
 /// Checks if the state of an entity is already properly set and removes it if it is, otherwise it is set.
 /// </summary>
 /// <param name="dictionary">The <c>Dictionary</c> that contains the state to be set on the entity.</param>
 /// <param name="entity">The CRM <c>Entity</c> to set the state on.</param>
 /// <param name="propertyName">The state code property name.</param>
 /// <param name="adapter">The <see cref="DynamicCrmAdapter"/> to be used for state name to value conversions.</param>
 private static void CheckStateAndStatus(Dictionary<string, object> dictionary, Entity entity, string propertyName, DynamicCrmAdapter adapter)
 {
     int stateToSet = (int)dictionary[propertyName];
     if (!entity.Contains(propertyName) || CRM2011AdapterUtilities.ConvertStateNameToValue(entity[propertyName].ToString(), entity.LogicalName, adapter) != stateToSet)
     {
         entity[propertyName] = new OptionSetValue(stateToSet);
     }
     else
     {
         entity.Attributes.Remove(propertyName);
         if (entity.Contains("statuscode"))
         {
             entity.Attributes.Remove("statuscode");
         }
     }
 }