private void ToggleItem(ListViewItem item) { if (item.Checked) // expanded { using (new LockRedraw(comparisonListView.Handle)) { while (comparisonListView.Items.Count > item.Index + 1 && comparisonListView.Items[item.Index + 1].IndentCount > item.IndentCount) { comparisonListView.Items.RemoveAt(item.Index + 1); } item.Checked = false; item.StateImageIndex = StateImageIndexDashPlus; } } else { MetadataComparison comparison = (MetadataComparison)item.Tag; if (comparison.Children.Count > 0) { using (new LockRedraw(comparisonListView.Handle)) { foreach (MetadataComparison childComparison in comparison.Children.AsEnumerable().Reverse()) { AddItem(childComparison, item); } item.StateImageIndex = StateImageIndexDashMinus; item.Checked = true; } } } }
private void AddItem(MetadataComparison customizationRoot, ListViewItem parentItem) { if (_configuration.ListHideEqualItems && (customizationRoot.Name != "Entities" || customizationRoot.Name != "Forms" || customizationRoot.Name != "Views") && customizationRoot.IsDifferent == false) { return; } ListViewItem item = new ListViewItem { Text = customizationRoot.Name, Checked = false, StateImageIndex = customizationRoot.Children.Count > 0 ? StateImageIndexDashPlus : -1, Tag = customizationRoot, ImageIndex = GetImageIndex(customizationRoot), IndentCount = parentItem?.IndentCount + 1 ?? 0 }; item.SubItems.Add(customizationRoot.ValueTypeName); object obj = customizationRoot.SourceValue ?? customizationRoot.TargetValue; if (obj != null && customizationRoot.Children.Count > 0) { item.SubItems.Add(customizationRoot.GetUnchangedCount().ToString()); item.SubItems.Add(customizationRoot.GetChangedCount().ToString()); item.SubItems.Add(customizationRoot.GetMissingInSourceCount().ToString()); item.SubItems.Add(customizationRoot.GetMissingInTargetCount().ToString()); } comparisonListView.Items.Insert(parentItem?.Index + 1 ?? 0, item); }
private bool BuildArrayComparisonTypes(MetadataComparison 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?.Length ?? 0; int targetLength = targetArray?.Length ?? 0; 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); }
public MetadataComparison Compare(string name, List <CustomizationEntity> source, List <CustomizationEntity> target) { MetadataComparison entities = new MetadataComparison(name, source, target, null); BuildComparisons(entities, null, source, target); return(entities); }
private void comparisonListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { if (e.IsSelected) { MetadataComparison comparison = (MetadataComparison)e.Item.Tag; webBrowserSource.Document.Body.InnerHtml = ""; webBrowserTarget.Document.Body.InnerHtml = ""; string sourceString = JsonConvert.SerializeObject(comparison.SourceValue, Formatting.Indented, new JsonSerializerSettings { MaxDepth = 1 }); string targetString = JsonConvert.SerializeObject(comparison.TargetValue, Formatting.Indented, new JsonSerializerSettings { MaxDepth = 1 }); /*List<string> sourceLines = new List<string>(); * * JsonTextReader reader = new JsonTextReader(new StringReader(sourceString)); * while (reader.Read()) * { * if (reader.Value != null) * { * sourceLines.Add($"Token: {reader.TokenType}, Value: {reader.Value}"); * } * else * { * sourceLines.Add($"Token: {reader.TokenType}"); * } * } * * StringBuilder sourceBuilder = new StringBuilder(); * HtmlTextWriter sourceWriter = new HtmlTextWriter(new StringWriter(sourceBuilder)); * * for (int i = 0; i < sourceLines.Count; i++) * { * sourceWriter.RenderBeginTag(HtmlTextWriterTag.P); * sourceWriter.RenderBeginTag(HtmlTextWriterTag.Span); * sourceLines[i] = HttpUtility.HtmlEncode(sourceLines[i]); * sourceWriter.Write(sourceLines[i].Replace(" ", " ").Replace("\t", " ")); * sourceWriter.RenderEndTag(); * sourceWriter.RenderEndTag(); * }*/ webBrowserSource.Document.Body.InnerHtml = sourceString /*sourceBuilder.ToString()*/; webBrowserTarget.Document.Body.InnerHtml = targetString; } }
private int GetImageIndex(MetadataComparison metadataComparison) { if (metadataComparison.IsDifferent) { if (metadataComparison.SourceValue == null) { return(DifferenceImageIndexNotInSource); } if (metadataComparison.TargetValue == null) { return(DifferenceImageIndexNotInTarget); } return(DifferenceImageIndexChanged); } return(DifferenceImageIndexUnchanged); }
private void CreateListFromResults(Logic.SystemComparer emds) { SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(0, $"Generating List")); comparisonListView.Items.Clear(); /*OrganizationComparer orgComparer = new OrganizationComparer(); * MetadataComparison orgComparison = null; * orgComparison = orgComparer.Compare("Organization", emds._sourceCustomizationRoot.Organizations, * emds._targetCustomizationRoot.Organizations);*/ if (_configuration.IncludeViews) { SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(0, "Processing Views...")); EntityComparer viewComparer = new EntityComparer(); MetadataComparison viewComparison = viewComparer.Compare("Views", emds.SourceCustomizationRoot.Views, emds.TargetCustomizationRoot.Views); AddItem(viewComparison, null); } if (_configuration.IncludeForms) { SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(33, "Processing Forms...")); EntityComparer formComparer = new EntityComparer(); MetadataComparison formComparison = formComparer.Compare("Forms", emds.SourceCustomizationRoot.Forms, emds.TargetCustomizationRoot.Forms); AddItem(formComparison, null); } SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(66, "Processing Forms...")); MetadataComparer comparer = new MetadataComparer(_configuration); MetadataComparison comparison = comparer.Compare("Entities", emds.SourceCustomizationRoot.EntitiesRaw, emds.TargetCustomizationRoot.EntitiesRaw); AddItem(comparison, null); SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs("List generated!")); }
private void BuildComparisons(MetadataComparison parent, PropertyInfo prop, object source, object target) { //OnLogMessageRaised(new EventArgs()); // 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 { MetadataComparison originalParent = parent; // Determine if a new CustomizationComparison node should be created if (type != typeof(List <CustomizationEntity>) && type != typeof(List <CustomizationType>) && type != typeof(List <Entity>)) { string name; switch (type.Name) { case "CustomizationEntity": case "CustomizationType": { //name = ((KeyValuePair<string, Dictionary<string, List<Entity>>>)(source ?? target)).Key; name = ((dynamic)(source ?? target)).Name; break; } case "Entity": { name = ((Entity)(source ?? target)).LogicalName; break; } case "BooleanManagedProperty": { name = ((BooleanManagedProperty)(source ?? target)).ManagedPropertyLogicalName; break; } ///ToDo: This is still wrong here case "KeyValuePair`2": { name = ((KeyValuePair <string, dynamic>)(source ?? target)).Key; source = ((KeyValuePair <string, object>?)source)?.Value; target = ((KeyValuePair <string, object>?)target)?.Value; type = GetCommonType(source, target); break; } default: name = prop.Name; break; } parent = new MetadataComparison(name, source, target, type) { ParentProperty = prop }; if (_ignoreList.Any(s => parent.Name.Contains(s))) { return; } originalParent.Children.Add(parent); } ///ToDo: There should never be a null Type !!! if (type == null) { return; } if (IsSimpleType(type) /*&& !ignoreList.Any(s => parent.Name.Contains(s))*/ && !type.Name.StartsWith("KeyValuePair")) { // for simple types just compare values if (!Equals(source, target)) { 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) { if (p.GetIndexParameters().Length > 0) { continue; } 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; } } } } } }
private void BuildComparisons(MetadataComparison 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 { MetadataComparison originalParent = parent; // Determine if a new CustomizationComparison node should be created if (type != typeof(List <Entity>)) //&& ComparisonTypeMap.IsTypeComparisonType(type)) { string name; switch (type.Name) { case "Entity": { name = ((Entity)(source ?? target)).LogicalName; break; } case "AttributeMetadata": case "StringAttributeMetadata": case "MemoAttributeMetadata": case "DoubleAttributeMetadata": case "IntegrationAttributeMetadata": case "MoneyAttributeMetadata": case "DateTimeAttributeMetadata": case "LookupAttributeMetadata": case "DecimalAttributeMetadata": case "PicklistAttributeMetadata": case "IntegerAttributeMetadata": case "BooleanAttributeMetadata": case "ImageAttributeMetadata": case "BigIntAttributeMetadata": case "EntityNameAttributeMetadata": case "StateAttributeMetadata": case "StatusAttributeMetadata": { name = ((AttributeMetadata)(source ?? target)).LogicalName; break; } default: name = prop.Name; break; } parent = new MetadataComparison(name, source, target, type) { ParentProperty = prop }; originalParent.Children.Add(parent); } if (IsSimpleType(type)) { // for simple types just compare values if (!Equals(source, target)) { 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; } } } } } }
private void BuildComparisons(MetadataComparison parent, PropertyInfo prop, object source, object target) { //OnLogMessageRaised(new EventArgs()); // 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 { MetadataComparison originalParent = parent; // Determine if a new CustomizationComparison node should be created if (type != typeof(List <EntityMetadata>)) //&& ComparisonTypeMap.IsTypeComparisonType(type)) { string name; switch (type.Name) { case "EntityMetadata": { name = ((EntityMetadata)(source ?? target)).LogicalName; break; } case "AttributeMetadata": case "StringAttributeMetadata": case "MemoAttributeMetadata": case "DoubleAttributeMetadata": case "IntegrationAttributeMetadata": case "MoneyAttributeMetadata": case "DateTimeAttributeMetadata": case "LookupAttributeMetadata": case "DecimalAttributeMetadata": case "PicklistAttributeMetadata": case "IntegerAttributeMetadata": case "BooleanAttributeMetadata": case "ImageAttributeMetadata": case "BigIntAttributeMetadata": case "EntityNameAttributeMetadata": case "StateAttributeMetadata": case "MultiSelectPicklistAttributeMetadata": case "StatusAttributeMetadata": { name = ((AttributeMetadata)(source ?? target)).LogicalName; break; } default: name = prop.Name; break; } parent = new MetadataComparison(name, source, target, type) { ParentProperty = prop }; originalParent.Children.Add(parent); } if (IsSimpleType(type) && !_ignoreList.Any(s => parent.Name.Contains(s))) { // for simple types just compare values if (parent.Name == "AutoNumberFormat" && (source == null || string.IsNullOrEmpty(source.ToString())) && (target == null || string.IsNullOrEmpty(target.ToString())) ) { // Ignore AutonumberFormat when null or Empty String } else if (_configuration.IgnoreManagedState && _ignoreManagedList.Any(s => parent.Name.Contains(s))) { // ignore IsManaged } else if (!Equals(source, target)) { 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).OrderBy(property => property.Name)) { 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; } } } } } }
private void LoadEntities() { _systemComparer = new Logic.SystemComparer(_sourceConnection, _targetConnection); WorkAsync(new WorkAsyncInfo { Message = "Getting Metadata", Work = (worker, args) => { LogInfo("Start retrieving metadata on Source"); _systemComparer.RetrieveMetadata(ConnectionType.Source, _configuration.IncludeAttributeMetadata, worker.ReportProgress); //_systemComparer.RetrieveOrganization(ConnectionType.Source, worker.ReportProgress); _systemComparer.RetrieveForms(ConnectionType.Source, _configuration.IncludeForms, worker.ReportProgress); _systemComparer.RetrieveViews(ConnectionType.Source, _configuration.IncludeViews, worker.ReportProgress); LogInfo("Start retrieving metadata on Target"); _systemComparer.RetrieveMetadata(ConnectionType.Target, _configuration.IncludeAttributeMetadata, worker.ReportProgress); //_systemComparer.RetrieveOrganization(ConnectionType.Target, worker.ReportProgress); _systemComparer.RetrieveForms(ConnectionType.Target, _configuration.IncludeForms, worker.ReportProgress); _systemComparer.RetrieveViews(ConnectionType.Target, _configuration.IncludeViews, worker.ReportProgress); args.Result = _systemComparer; }, PostWorkCallBack = (args) => { LogInfo("Postprocessing Metadata"); if (args.Error != null) { LogError(args.Error.ToString(), args); MessageBox.Show(args.Error.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } var emds = (Logic.SystemComparer)args.Result; comparisonListView.Items.Clear(); /*OrganizationComparer orgComparer = new OrganizationComparer(); * MetadataComparison orgComparison = null; * orgComparison = orgComparer.Compare("Organization", emds._sourceCustomizationRoot.Organizations, * emds._targetCustomizationRoot.Organizations);*/ if (_configuration.IncludeViews) { EntityComparer viewComparer = new EntityComparer(); MetadataComparison viewComparison = viewComparer.Compare("Views", emds._sourceCustomizationRoot.Views, emds._targetCustomizationRoot.Views); AddItem(viewComparison, null); } if (_configuration.IncludeForms) { EntityComparer formComparer = new EntityComparer(); MetadataComparison formComparison = formComparer.Compare("Forms", emds._sourceCustomizationRoot.Forms, emds._targetCustomizationRoot.Forms); AddItem(formComparison, null); } MetadataComparer comparer = new MetadataComparer(); MetadataComparison comparison = comparer.Compare("Entities", emds._sourceCustomizationRoot.EntitiesRaw, emds._targetCustomizationRoot.EntitiesRaw); AddItem(comparison, null); }, ProgressChanged = e => { SetWorkingMessage(e.UserState.ToString()); } }); }