/// <summary>
        /// Returns a 'sharepointdocumentlocation' that represents the path from an existing 'sharepointsite' to an existing entity.
        /// If the document location path does not exist, a relative path of locations is created between the two entities.
        /// The folder path structure defined by the site is respected when retrieving or creating the document location path.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sharePointSite"></param>
        /// <param name="entity"></param>
        /// <param name="relativeUrl"></param>
        /// <returns>
        /// The 'sharepointdocumentlocation' referencing the folder of the entity.
        /// </returns>
        public static T AddOrGetExistingDocumentLocation <T>(this OrganizationServiceContext context, Entity sharePointSite, Entity entity, string relativeUrl)
            where T : Entity, new()
        {
            if (sharePointSite == null)
            {
                throw new ArgumentNullException("sharePointSite");
            }
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            sharePointSite.AssertEntityName(_sharepointsite);

            // Replace the following invalid characters ~ " # % & * : < > ? / \ { | } . with hyphens (Same as what CRM does).
            var spSafeRelativeUrl = Regex.Replace(relativeUrl, @"[\~\""\#\%\&\*\:\<\>\?\/\\\{\|\}\.]", "-");

            var siteName     = sharePointSite.GetAttributeValue <string>("name");
            var locationName = "Documents on {0}".FormatWith(siteName);

            var folderStructureEntity = sharePointSite.GetAttributeValue <string>("folderstructureentity");

            if (folderStructureEntity == "contact" && entity.LogicalName != "contact")
            {
                // <site>/contact/<contact name>/<entity name>/<record name>

                var related = context.GetRelatedForEntityCentricFolderStructure(entity, folderStructureEntity);

                if (related != null)
                {
                    return(context.AddOrGetEntityCentricDocumentLocation <T>(locationName, spSafeRelativeUrl, entity, related, sharePointSite));
                }
            }

            if (folderStructureEntity == "account" && entity.LogicalName != "account")
            {
                // <site>/account/<account name>/<entity name>/<record name>

                var related = context.GetRelatedForEntityCentricFolderStructure(entity, folderStructureEntity);

                if (related != null)
                {
                    return(context.AddOrGetEntityCentricDocumentLocation <T>(locationName, spSafeRelativeUrl, entity, related, sharePointSite));
                }
            }

            // <site>/<entity name>/<record name>

            var entitySetLocation = sharePointSite
                                    .GetRelatedEntities(context, _sharepointdoclocationsiterelationship)
                                    .FirstOrDefault(loc => loc.GetAttributeValue <string>("relativeurl") == entity.LogicalName);

            if (entitySetLocation == null)
            {
                entitySetLocation = context.CreateDocumentLocation <T>(locationName, entity.LogicalName, sharePointSite, _sharepointdoclocationsiterelationship);
                return(context.CreateDocumentLocation <T>(locationName, spSafeRelativeUrl, entitySetLocation, _sharepointdoclocationparentrelationship, entity.ToEntityReference()));
            }

            return(context.CreateOrUpdateRecordDocumentLocation <T>(locationName, spSafeRelativeUrl, entitySetLocation, entity));
        }
        private static T AddOrGetEntityCentricDocumentLocation <T>(this OrganizationServiceContext context, string locationName, string relativeUrl, Entity record, EntityReference related, Entity sharePointSite) where T : Entity, new()
        {
            var entityCentricSetLocation = sharePointSite
                                           .GetRelatedEntities(context, _sharepointdoclocationsiterelationship)
                                           .FirstOrDefault(loc => loc.GetAttributeValue <string>("relativeurl") == related.LogicalName);

            T entityCentricNameLocation;
            T entityNameLocation;

            if (entityCentricSetLocation == null)
            {
                entityCentricSetLocation  = context.CreateDocumentLocation <T>(locationName, related.LogicalName, sharePointSite, _sharepointdoclocationsiterelationship);
                entityCentricNameLocation = context.CreateDocumentLocation <T>(locationName, related.Name, entityCentricSetLocation, _sharepointdoclocationparentrelationship, related);
                entityNameLocation        = context.CreateDocumentLocation <T>(locationName, record.LogicalName, entityCentricNameLocation, _sharepointdoclocationparentrelationship);
                return(context.CreateDocumentLocation <T>(locationName, relativeUrl, entityNameLocation, _sharepointdoclocationparentrelationship, record.ToEntityReference()));
            }

            entityCentricNameLocation = entityCentricSetLocation
                                        .GetRelatedEntities(context, _sharepointdoclocationparentrelationship, EntityRole.Referenced)
                                        .FirstOrDefault(loc => loc.GetAttributeValue <string>("relativeurl") == related.Name) as T;

            if (entityCentricNameLocation == null)
            {
                entityCentricNameLocation = context.CreateDocumentLocation <T>(locationName, related.Name, entityCentricSetLocation, _sharepointdoclocationparentrelationship, related);
                entityNameLocation        = context.CreateDocumentLocation <T>(locationName, record.LogicalName, entityCentricNameLocation, _sharepointdoclocationparentrelationship);
                return(context.CreateDocumentLocation <T>(locationName, relativeUrl, entityNameLocation, _sharepointdoclocationparentrelationship, record.ToEntityReference()));
            }

            entityNameLocation = entityCentricNameLocation
                                 .GetRelatedEntities(context, _sharepointdoclocationparentrelationship, EntityRole.Referenced)
                                 .FirstOrDefault(loc => loc.GetAttributeValue <string>("relativeurl") == record.LogicalName) as T;

            if (entityNameLocation == null)
            {
                entityNameLocation = context.CreateDocumentLocation <T>(locationName, record.LogicalName, entityCentricNameLocation, _sharepointdoclocationparentrelationship);
                return(context.CreateDocumentLocation <T>(locationName, relativeUrl, entityNameLocation, _sharepointdoclocationparentrelationship, record.ToEntityReference()));
            }

            return(context.CreateOrUpdateRecordDocumentLocation <T>(locationName, relativeUrl, entityNameLocation, record));
        }
        private static T CreateOrUpdateRecordDocumentLocation <T>(this OrganizationServiceContext context, string name, string relativeUrl, Entity parentLocation, Entity record) where T : Entity, new()
        {
            var recordLocation = parentLocation
                                 .GetRelatedEntities(context, _sharepointdoclocationparentrelationship, EntityRole.Referenced)
                                 .FirstOrDefault(loc => loc.GetAttributeValue <string>("relativeurl") == relativeUrl) as T;

            if (recordLocation == null)
            {
                return(context.CreateDocumentLocation <T>(name, relativeUrl, parentLocation, _sharepointdoclocationparentrelationship, record.ToEntityReference()));
            }

            if (recordLocation.GetAttributeValue <EntityReference>("regardingobjectid") == null)
            {
                recordLocation.SetAttributeValue("regardingobjectid", record.ToEntityReference());

                context.UpdateObject(recordLocation);
            }

            return(recordLocation);
        }