Notes
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();
}
}
}