Skip to content

Commit

Permalink
config diff service added
Browse files Browse the repository at this point in the history
  • Loading branch information
zhichkin committed May 12, 2021
1 parent 7ec26cc commit 450922d
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 13 deletions.
59 changes: 59 additions & 0 deletions src/dajet-metadata-tests/ConfigDiff.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using DaJet.Metadata.Model;
using DaJet.Metadata.Services;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Text;

namespace DaJet.Metadata.ConfigDiff
{
[TestClass] public sealed class ConfigDiff
{
[TestMethod] public void TestDiff()
{
IMetadataService metadata = new MetadataService();
IMetaDiffService metadiff = new MetaDiffService();

metadata
.UseDatabaseProvider(DatabaseProvider.SQLServer)
.UseConnectionString("Data Source=ZHICHKIN;Initial Catalog=cerberus;Integrated Security=True");
InfoBase ibOld = metadata.LoadInfoBase();

metadata
.UseDatabaseProvider(DatabaseProvider.SQLServer)
.UseConnectionString("Data Source=ZHICHKIN;Initial Catalog=cerberus_new;Integrated Security=True");
InfoBase ibNew = metadata.LoadInfoBase();

MetaDiff diff = metadiff.Compare(ibOld, ibNew);

WriteDiffToFile(diff);
}

private void WriteDiffToFile(MetaDiff diff)
{
using (StreamWriter stream = new StreamWriter(@"C:\temp\diff.txt", false, Encoding.UTF8))
{
WriteToFile(stream, diff, 0, string.Empty);
}
}
private void WriteToFile(StreamWriter stream, MetaDiff diff, int level, string path)
{
string indent = level == 0 ? string.Empty : "-".PadLeft(level * 4, '-');
//string thisPath = path + (string.IsNullOrEmpty(path) ? string.Empty : ".") + i.ToString();
stream.WriteLine(indent + "[" + level.ToString() + "] (" + diff.Difference.ToString() + ") "
+ diff.Target.ToString()
+ (diff.Target is MetadataProperty property ? " (" + property.PropertyType.ToString() + ")" : string.Empty));

foreach (var entry in diff.NewValues)
{
indent = "-".PadLeft((level + 1) * 4, '-');
stream.WriteLine(indent + "[*] " + entry.Key + " = " + entry.Value.ToString());
}

for (int i = 0; i < diff.Children.Count; i++)
{
//thisPath = path + (string.IsNullOrEmpty(path) ? string.Empty : ".") + i.ToString();
WriteToFile(stream, diff.Children[i], level + 1, path);
}
}
}
}
5 changes: 5 additions & 0 deletions src/dajet-metadata/enrichers/InfoBaseEnricher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public void Enrich(MetadataObject metadataObject)

ConfigureConfigInfo(infoBase, config);
ConfigureCommonObjects(infoBase, config);

if (string.IsNullOrWhiteSpace(infoBase.Name) && infoBase.ConfigInfo != null)
{
infoBase.Name = infoBase.ConfigInfo.Name;
}
}

private void ConfigureConfigInfo(InfoBase infoBase, ConfigObject config)
Expand Down
13 changes: 13 additions & 0 deletions src/dajet-metadata/model/DataTypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,18 @@ public bool IsMultipleType
return false;
}
}
public override string ToString()
{
if (IsMultipleType) return "Multiple";
else if (IsUuid) return "Uuid";
else if (IsBinary) return "Binary";
else if (IsValueStorage) return "ValueStorage";
else if (CanBeString) return "String";
else if (CanBeBoolean) return "Boolean";
else if (CanBeNumeric) return "Numeric";
else if (CanBeDateTime) return "DateTime";
else if (CanBeReference) return "Reference";
else return "Unknown";
}
}
}
31 changes: 31 additions & 0 deletions src/dajet-metadata/model/MetaDiff.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections.Generic;

namespace DaJet.Metadata.Model
{
public enum DiffType
{
///<summary>No difference (used just as a root of child differences)</summary>
None,
///<summary>New item to add</summary>
Insert,
///<summary>Some properties has been changed</summary>
Update,
///<summary>Target item to be deleted</summary>
Delete
}
public sealed class MetaDiff
{
public MetaDiff() { }
public MetaDiff(MetaDiff parent, MetadataObject target, DiffType difference)
{
Parent = parent;
Target = target;
Difference = difference;
}
public MetaDiff Parent { set; get; }
public DiffType Difference { set; get; }
public MetadataObject Target { set; get; }
public List<MetaDiff> Children { get; } = new List<MetaDiff>();
public Dictionary<string, object> NewValues { get; } = new Dictionary<string, object>();
}
}
19 changes: 16 additions & 3 deletions src/dajet-metadata/model/MetadataObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,28 @@

namespace DaJet.Metadata.Model
{
public abstract class MetadataObject
public abstract class MetadataObject : IComparable
{
///<summary>Идентификатор объекта метаданных из файла объекта метаданных</summary>
///<summary>Внутренний идентификатор объекта метаданных</summary>
public Guid Uuid { get; set; } = Guid.Empty;
///<summary>Идентификатор файла объекта метаданных в таблице Config и DBNames</summary>
public Guid FileName { get; set; } = Guid.Empty;
///<summary>Имя объекта метаданных</summary>
public string Name { get; set; } = string.Empty;
///<summary>Синоним объекта метаданных</summary>
public string Alias { get; set; } = string.Empty;

// TODO: add Comment property ?
public override string ToString() { return string.Format("{0}.{1}", GetType().Name, Name); }

public int CompareTo(object other)
{
return this.CompareTo((MetadataObject)other);
}
public int CompareTo(MetadataObject other)
{
if (other == null) return 1; // this instance is bigger than other
return this.Name.CompareTo(other.Name);
}
public override string ToString() { return string.Format("{0}.{1}", this.GetType().Name, this.Name); }
}
}
11 changes: 1 addition & 10 deletions src/dajet-metadata/model/MetadataProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@
namespace DaJet.Metadata.Model
{
///<summary>Класс для описания свойств объекта метаданных <see cref="ApplicationObject"> (реквизитов, измерений и ресурсов)</summary>
public class MetadataProperty
public class MetadataProperty : MetadataObject
{
///<summary>
/// Идентификатор свойства объекта метаданных из файла DBNames таблицы Params.
/// Используется для того, чтобы ссылаться на свойство в файле объекта метаданных из таблицы Config.
///</summary>
public Guid FileName { get; set; } = Guid.Empty;
///<summary>Имя свойства объекта метаданных</summary>
public string Name { get; set; } = string.Empty;
///<summary>Синоним свойства объекта метаданных</summary>
public string Alias { get; set; } = string.Empty;
///<summary>Основа имени поля в таблице СУБД (может быть дополнено постфиксами в зависимости от типа данных свойства)</summary>
public string DbName { get; set; } = string.Empty;
///<summary>Коллекция для описания полей таблицы СУБД свойства объекта метаданных</summary>
Expand Down
1 change: 1 addition & 0 deletions src/dajet-metadata/services/Configurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ public MetadataProperty CreateProperty(Guid uuid, string token, int code)
{
return new MetadataProperty()
{
Uuid = uuid,
FileName = uuid,
DbName = CreateDbName(token, code)
};
Expand Down
166 changes: 166 additions & 0 deletions src/dajet-metadata/services/MetaDiffService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
using DaJet.Metadata.Model;
using System;
using System.Collections.Generic;
using System.Linq;

namespace DaJet.Metadata.Services
{
public interface IMetaDiffService
{
MetaDiff Compare(InfoBase target, InfoBase source);
}
public sealed class MetaDiffService : IMetaDiffService
{
public MetaDiff Compare(InfoBase target, InfoBase source)
{
MetaDiff root = new MetaDiff(null, target, DiffType.None);
CompareLists(root, target.Catalogs.Values.ToList(), source.Catalogs.Values.ToList());
CompareLists(root, target.Documents.Values.ToList(), source.Documents.Values.ToList());
CompareLists(root, target.Characteristics.Values.ToList(), source.Characteristics.Values.ToList());
CompareLists(root, target.InformationRegisters.Values.ToList(), source.InformationRegisters.Values.ToList());
CompareLists(root, target.AccumulationRegisters.Values.ToList(), source.AccumulationRegisters.Values.ToList());
return root;
}
private void CompareLists<T>(MetaDiff parent, List<T> target_list, List<T> source_list) where T : MetadataObject, IComparable
{
int target_count = target_list.Count;
int source_count = source_list.Count;
int target_index = 0;
int source_index = 0;
int compareResult;

if (target_count == 0 && source_count == 0) return;

target_list.Sort();
source_list.Sort();

while (target_index < target_count)
{
if (source_index < source_count)
{
compareResult = target_list[target_index].CompareTo(source_list[source_index]);
if (compareResult < 0)
{
MetaDiff difference = new MetaDiff(parent, target_list[target_index], DiffType.Delete);
parent.Children.Add(difference);
SetUpdateDiffType(parent);
AddChildren(difference);
target_index++;
}
else if (compareResult == 0)
{
MetaDiff difference = new MetaDiff(parent, target_list[target_index], DiffType.None);
CompareListItems(difference, target_list[target_index], source_list[source_index]);
if (difference.Difference == DiffType.Update) parent.Children.Add(difference);
target_index++;
source_index++;
}
else
{
MetaDiff difference = new MetaDiff(parent, source_list[source_index], DiffType.Insert);
parent.Children.Add(difference);
SetUpdateDiffType(parent);
AddChildren(difference);
source_index++;
}
}
else
{
MetaDiff difference = new MetaDiff(parent, target_list[target_index], DiffType.Delete);
parent.Children.Add(difference);
SetUpdateDiffType(parent);
AddChildren(difference);
target_index++;
}
}
while (source_index < source_count)
{
MetaDiff difference = new MetaDiff(parent, source_list[source_index], DiffType.Insert);
parent.Children.Add(difference);
SetUpdateDiffType(parent);
AddChildren(difference);
source_index++;
}
}
// Compare methods is used by Update difference
private void CompareListItems(MetaDiff difference, MetadataObject target, MetadataObject source)
{
if (target is ApplicationObject)
{
CompareObjects(difference, (ApplicationObject)target, (ApplicationObject)source);
}
else if (typeof(MetadataProperty) == target.GetType())
{
CompareProperties(difference, (MetadataProperty)target, (MetadataProperty)source);
}
}
private void CompareObjects(MetaDiff difference, ApplicationObject target, ApplicationObject source)
{
//difference.NewValues.Clear();
//if (target.TypeCode != source.TypeCode)
//{
// difference.NewValues.Add("TypeCode", source.TypeCode);
//}
//if (difference.NewValues.Count > 0) SetUpdateDiffType(difference);

//if (target.Uuid == source.Uuid || target.FileName == source.FileName)
//{

//}

CompareLists(difference, target.Properties, source.Properties);
CompareLists(difference, target.TableParts, source.TableParts);
}
private void CompareProperties(MetaDiff difference, MetadataProperty target, MetadataProperty source)
{
difference.NewValues.Clear();
if (target.PropertyType.CanBeBoolean != source.PropertyType.CanBeBoolean
|| target.PropertyType.CanBeString != source.PropertyType.CanBeString
|| target.PropertyType.CanBeNumeric != source.PropertyType.CanBeNumeric
|| target.PropertyType.CanBeDateTime != source.PropertyType.CanBeDateTime
|| target.PropertyType.CanBeReference != source.PropertyType.CanBeReference
|| target.PropertyType.IsUuid != source.PropertyType.IsUuid
|| target.PropertyType.IsValueStorage != source.PropertyType.IsValueStorage
|| target.PropertyType.IsMultipleType != source.PropertyType.IsMultipleType)
{
difference.NewValues.Add("PropertyType", source.PropertyType);
}
if (difference.NewValues.Count > 0) SetUpdateDiffType(difference);
}
private void SetUpdateDiffType(MetaDiff difference)
{
if (difference.Difference != DiffType.None) return;
difference.Difference = DiffType.Update;
MetaDiff parent = difference.Parent;
while (parent != null)
{
parent.Difference = DiffType.Update;
parent = parent.Parent;
}
}
// Add children is used by Insert and Delete differences
private void AddChildren(MetaDiff difference)
{
if (difference.Target is ApplicationObject)
{
AddObjectChildren(difference);
}
}
private void AddObjectChildren(MetaDiff difference)
{
ApplicationObject target = (ApplicationObject)difference.Target;

foreach (MetadataProperty child in target.Properties)
{
MetaDiff diff = new MetaDiff(difference, child, difference.Difference);
difference.Children.Add(diff);
}
foreach (TablePart child in target.TableParts)
{
MetaDiff diff = new MetaDiff(difference, child, difference.Difference);
difference.Children.Add(diff);
AddObjectChildren(diff);
}
}
}
}

0 comments on commit 450922d

Please sign in to comment.