/// <summary> /// Builds the comparison types for arrays. /// </summary> /// <param name="parent">The parent CustomizationComparison.</param> /// <param name="prop">The property that source and target are values of.</param> /// <param name="source">The source value.</param> /// <param name="target">The target value.</param> /// <returns>true if the arrays are different; false if equal</returns> private bool BuildArrayComparisonTypes(CustomizationComparison parent, PropertyInfo prop, IEnumerable source, IEnumerable target) { bool isDifferent = false; Array sourceArray = ToArray(source); Array targetArray = ToArray(target); // If the arrays need special sorting, this will sort them and // insert nulls for the missing entries from either the source // or target. SynchronizeArraysByIdentity(ref sourceArray, ref targetArray); int sourceLength = sourceArray == null ? 0 : sourceArray.Length; int targetLength = targetArray == null ? 0 : targetArray.Length; for (int i = 0; i < Math.Max(sourceLength, targetLength); i++) { object sourceItem = i < sourceLength?sourceArray.GetValue(i) : null; object targetItem = i < targetLength?targetArray.GetValue(i) : null; BuildComparisons(parent, prop, sourceItem, targetItem); isDifferent |= parent.IsDifferent; } return(isDifferent); }
/// <summary> /// Compares the specified customization files. /// </summary> /// <param name="sourcePath">The source customization path.</param> /// <param name="targetPath">The target customization path.</param> /// <returns></returns> public CustomizationComparison Compare(string sourcePath, string targetPath) { ImportExportXml sourceImportExport = LoadImportExportObject(sourcePath); ImportExportXml targetImportExport = LoadImportExportObject(targetPath); CustomizationComparison ret = new CustomizationComparison("Import Export Xml", sourceImportExport, targetImportExport); BuildComparisons(ret, null, sourceImportExport, targetImportExport); return(ret); }
private string GetTypeName(CustomizationComparison self, string typeString) { object selfValue = self.SourceValue ?? self.TargetValue; if (selfValue is IIdentifiable[]) { typeString = ComparisonTypeMap.GetComparisonTypeName(selfValue); } return(typeString); }
private string GetChangeStatus(CustomizationComparison self) { if (!self.IsDifferent) { return("Unchanged"); } else { if (self.SourceValue != null && self.TargetValue != null) { return("Changed"); } else if (self.SourceValue == null) { return("Not in Source"); } else { return("Not in Target"); } } }
public IEnumerable <String> SerializeObjectToLines(CustomizationComparison comparison, object item) { if (item != null) { using (MemoryStream stream = new MemoryStream()) { XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; settings.Indent = true; XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlAttributeOverrides overrides = ComparisonTypeMap.GetComparisonTypeXmlOverrides(item.GetType()); XmlSerializer serializer = new XmlSerializer(item.GetType(), overrides); XmlFilter filter = new XmlFilter(); BuildXmlFilter(filter, item, comparison.ParentProperty); using (FilteringXmlWriter writer = new FilteringXmlWriter(XmlWriter.Create(stream, settings))) { writer.Filter = filter; serializer.Serialize(writer, item, ns); } stream.Seek(0, SeekOrigin.Begin); using (StreamReader sourceReader = new StreamReader(stream)) { string line; while ((line = sourceReader.ReadLine()) != null) { yield return(line); } } } } }
public void CreateChangleLogForSolution(string solutionUniqueName) { var result = ExportSolution(solutionUniqueName); if (result.Length > 1 && result[0] != null) { CustomizationComparer comparer = new CustomizationComparer(); CustomizationComparison comparison = null; comparison = comparer.Compare(result[0], result[1]); if (comparison.IsDifferent) { Entity changeLog = new Entity("ita_changelog"); changeLog["ita_name"] = solutionUniqueName; changeLog.Id = crmSvc.Create(changeLog); AddChangeLogComponent(changeLog, comparison, null); CleanupOldFiles(solutionUniqueName); } else { System.IO.File.Delete(result[1]); } } }
public CustomizationComparison(CustomizationComparison parentComparison) { Children = new List <CustomizationComparison>(); ParentComparison = parentComparison; IsDifferentBase = false; }
public ExportToExcel(string fileName, CustomizationComparison comparison) { _fileName = fileName; _comparison = comparison; }
/// <summary> /// Recursively loops through the customization object hierarchy and creates a CustomizationComparison hierarchy. /// </summary> /// <param name="parent">The parent CustomizationComparison.</param> /// <param name="prop">The property that source and target are values of.</param> /// <param name="source">The source value.</param> /// <param name="target">The target value.</param> private void BuildComparisons(CustomizationComparison parent, PropertyInfo prop, object source, object target) { // Make sure at least one value is not null if (source != null || target != null) { // Extract the value types Type type = GetCommonType(source, target); // Don't continue if the types differ if (type == null) { parent.IsDifferent = true; } else { CustomizationComparison originalParent = parent; // Determine if a new CustomizationComparison node should be created if (type != typeof(ImportExportXml) && ComparisonTypeMap.IsTypeComparisonType(type)) { string name = ComparisonTypeMap.GetComparisonTypeName(source, target); parent = new CustomizationComparison(name, source, target, originalParent); parent.ParentProperty = prop; originalParent.Children.Add(parent); } if (IsSimpleType(type)) { // for simple types just compare values if (!Object.Equals(source, target)) { originalParent.IsDifferentBase = true; originalParent.IsDifferent = true; parent.IsDifferent = true; } } else if (typeof(IEnumerable).IsAssignableFrom(type)) { // Several arrays need to be sorted by a specific property (for example: Entity name) originalParent.IsDifferent |= BuildArrayComparisonTypes(parent, prop, (IEnumerable)source, (IEnumerable)target); } else { // for classes, just compare each property foreach (PropertyInfo p in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (p.CanRead) { object sourceValue = source != null?p.GetValue(source, null) : null; object targetValue = target != null?p.GetValue(target, null) : null; BuildComparisons(parent, p, sourceValue, targetValue); originalParent.IsDifferent |= parent.IsDifferent; } } } } } }
public void AddChangeLogComponent(Entity changeLog, CustomizationComparison comparison, CustomizationComparison parentComparison) { if (comparison.IsDifferent) { COMPONENT_ACTION action = COMPONENT_ACTION.UPDATED; if (comparison.SourceValue == null) { action = COMPONENT_ACTION.CREATED; } else if (comparison.TargetValue == null) { action = COMPONENT_ACTION.REMOVED; } if (comparison.IsDifferentBase || action != COMPONENT_ACTION.UPDATED) { Entity changeLogComponent = new Entity("ita_changelogcomponent"); changeLogComponent["ita_name"] = comparison.GetFullPath(); changeLogComponent["ita_changelog"] = changeLog.ToEntityReference(); changeLogComponent["ita_action"] = new OptionSetValue((int)action); if (extractXml) { CustomizationSerializer serializer = new CustomizationSerializer(); IEnumerable <String> sourceLines = serializer.SerializeObjectToLines(comparison, comparison.SourceValue); IEnumerable <String> targetLines = serializer.SerializeObjectToLines(comparison, comparison.TargetValue); string beforeXml = ""; if (sourceLines != null) { foreach (var s in sourceLines) { beforeXml = beforeXml + s + System.Environment.NewLine; } } string afterXml = ""; if (targetLines != null) { foreach (var s in targetLines) { afterXml = afterXml + s + System.Environment.NewLine; } } changeLogComponent["ita_xmlbefore"] = beforeXml; changeLogComponent["ita_xmlafter"] = afterXml; } changeLogComponent.Id = crmSvc.Create(changeLogComponent); } if (action == COMPONENT_ACTION.UPDATED) { foreach (var c in comparison.Children) { AddChangeLogComponent(changeLog, c, comparison); } } } }