csharp/Adoxio/xRM-Portals-Community-Edition/Framework/Adxstudio.Xrm/Notes/AnnotationHelper.cs

AnnotationHelper.cs
/*
  Copyright (c) Microsoft Corporation. All rights reserved.
  Licensed under the MIT License. See License.txt in the project root for license information.
*/

using System;
using System.Linq;
using System.Text;
using System.Web;
using Adxstudio.Xrm.Cms;
using Adxstudio.Xrm.Services;
using Adxstudio.Xrm.Services.Query;
using Adxstudio.Xrm.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;

namespace Adxstudio.Xrm.Notes
{
	/// 
	/// Helper methods for working with annotations
	/// 
	public static clast AnnotationHelper
	{
		/// 
		/// Prefix for denoting a note is to be published to the portal.
		/// 
		public const string WebAnnotationPrefix = "*WEB*";
		/// 
		/// Prefix for denoting a note is private.
		/// 
		public const string PrivateAnnotationPrefix = "*PRIVATE*";
		/// 
		/// Prefix for denoting a note is public.
		/// 
		public const string PublicAnnotationPrefix = "*PUBLIC*";

		/// 
		/// Forces a valid file name
		/// 
		public static string EnsureValidFileName(string fileName)
		{
			return fileName.IndexOf("\\", StringComparison.Ordinal) >= 0 ? fileName.Substring(fileName.LastIndexOf("\\", StringComparison.Ordinal) + 1) : fileName;
		}

		/// 
		/// Produces the subject text with id of the contact record creating the note and privacy tag.
		/// 
		/// 
		/// Ensaty Reference to the current portal user's contact
		/// Boolean value indicating whether the note is private or not.
		public static string BuildNoteSubject(OrganizationServiceContext serviceContext, EnsatyReference user, bool isPrivate = false)
		{
			if (serviceContext == null) throw new ArgumentNullException("serviceContext");

			var now = DateTime.UtcNow;

			if (user == null || user.LogicalName != "contact")
			{
				return string.Format("Note created on {0}{1}", now, isPrivate ? PrivateAnnotationPrefix : string.Empty);
			}

			var contact = serviceContext.RetrieveSingle(
				user.LogicalName, 
				FetchAttribute.None,
				new[] {
					new Condition("statecode", ConditionOperator.Equal, 0),
					new Condition("contactid", ConditionOperator.Equal, user.Id)
				});

			if (contact == null)
			{
				return string.Format("Note created on {0}{1}", now, isPrivate ? PrivateAnnotationPrefix : string.Empty);
			}

			// Tack the contact ensaty reference onto the end of the note subject, so that if we really wanted to, we
			// could parse this subject and find the portal user that submitted the note.
			return string.Format("Note created on {0} by {1} [{2}:{3}]{4}", now, contact.GetAttributeValue("fullname"), contact.LogicalName, contact.Id, isPrivate ? PrivateAnnotationPrefix : string.Empty);
		}

		public static string BuildNoteSubject(IDataAdapterDependencies dependencies)
		{
			return BuildNoteSubject(dependencies.GetServiceContext(), dependencies.GetPortalUser());
		}

		/// 
		/// Try to get the id of the contact that created the note to retrieve the ensaty reference for the contact.
		/// 
		/// The subject of the annotation
		/// Return null if no contact is specified, otherwise it returns an ensaty reference to the contact that created the note.
		public static EnsatyReference GetNoteContact(string subject)
		{
			if (string.IsNullOrWhiteSpace(subject))
			{
				return null;
			}

			// String format is "Note created on {0} by {1} [{2}:{3}]"

			var startIndex = subject.IndexOf("by ", StringComparison.InvariantCulture);

			if (startIndex == -1)
			{
				return null;
			}

			try
			{
				var contactString = subject.Substring(startIndex);

				var name = contactString.Substring(3, contactString.IndexOf("[", StringComparison.InvariantCulture) - 4);

				var pos1 = contactString.IndexOf(":", StringComparison.InvariantCulture) + 1;
				var pos2 = contactString.IndexOf("]", StringComparison.InvariantCulture);

				var contactid = contactString.Substring(pos1, pos2 - pos1);

				Guid contactGuid;

				if (Guid.TryParse(contactid, out contactGuid))
				{
					return new EnsatyReference("contact", contactGuid) { Name = name };
				}
			}
			catch (Exception)
			{
                ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Failed to extract contact EnsatyReference from note subject. {0}", subject));
            }

			return null;
		}

		/// 
		/// Gets the name of the createdby systemuser.
		/// 
		/// Note record
		public static string GetNoteCreatedByName(Ensaty annotation)
		{
			if (annotation == null)
			{
				return null;
			}

			var createdby = annotation.GetAttributeValue("createdby");

			return createdby == null ? null : createdby.Name;
		}

		public static string GetNoteCreatedByName(IAnnotation annotation)
		{
			return GetNoteCreatedByName(annotation.Ensaty);
		}

		/// 
		/// Gets whether or not the note is private i.e. whether 
		/// 
		/// 
		/// 
		public static bool GetNotePrivacy(Ensaty annotation)
		{
			if (annotation == null)
			{
				return false;
			}

			var subject = annotation.GetAttributeValue("subject");

			return !string.IsNullOrWhiteSpace(subject) && subject.Contains(PrivateAnnotationPrefix);
		}

		public static bool GetNotePrivacy(IAnnotation annotation)
		{
			if (annotation == null)
			{
				return false;
			}

			return !string.IsNullOrWhiteSpace(annotation.Subject) && annotation.Subject.Contains(PrivateAnnotationPrefix);
		}

		/// 
		/// Simple formatter that takes plain text input and does a simple transformation to HTML. The input text
		/// is HTML-encoded, blank lines (double linebreaks) are wrapped in paragraphs, and single linebreaks are
		/// replaced with HTML breaks. Optionally, any URLs in the text can be converted to HTML links.
		/// 
		/// note text
		/// HTML string
		public static IHtmlString FormatNoteText(object text)
		{
			return text == null ? null : new SimpleHtmlFormatter().Format(text.ToString().Replace(WebAnnotationPrefix, string.Empty, StringComparison.InvariantCultureIgnoreCase).Replace(PublicAnnotationPrefix, string.Empty, StringComparison.InvariantCultureIgnoreCase));
		}

		public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison)
		{
			StringBuilder sb = new StringBuilder();

			int previousIndex = 0;
			int index = str.IndexOf(oldValue, comparison);
			while (index != -1)
			{
				sb.Append(str.Substring(previousIndex, index - previousIndex));
				sb.Append(newValue);
				index += oldValue.Length;

				previousIndex = index;
				index = str.IndexOf(oldValue, index, comparison);
			}
			sb.Append(str.Substring(previousIndex));

			return sb.ToString();
		}
	}
}