diff --git a/src/dajet-metadata-tests/ConfigDiff.cs b/src/dajet-metadata-tests/ConfigDiff.cs
new file mode 100644
index 0000000..7d1edba
--- /dev/null
+++ b/src/dajet-metadata-tests/ConfigDiff.cs
@@ -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);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dajet-metadata/enrichers/InfoBaseEnricher.cs b/src/dajet-metadata/enrichers/InfoBaseEnricher.cs
index 699770c..bbe6870 100644
--- a/src/dajet-metadata/enrichers/InfoBaseEnricher.cs
+++ b/src/dajet-metadata/enrichers/InfoBaseEnricher.cs
@@ -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)
diff --git a/src/dajet-metadata/model/DataTypeInfo.cs b/src/dajet-metadata/model/DataTypeInfo.cs
index 2af8da3..1a58d34 100644
--- a/src/dajet-metadata/model/DataTypeInfo.cs
+++ b/src/dajet-metadata/model/DataTypeInfo.cs
@@ -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";
+ }
}
}
\ No newline at end of file
diff --git a/src/dajet-metadata/model/MetaDiff.cs b/src/dajet-metadata/model/MetaDiff.cs
new file mode 100644
index 0000000..7c57529
--- /dev/null
+++ b/src/dajet-metadata/model/MetaDiff.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+
+namespace DaJet.Metadata.Model
+{
+ public enum DiffType
+ {
+ ///No difference (used just as a root of child differences)
+ None,
+ ///New item to add
+ Insert,
+ ///Some properties has been changed
+ Update,
+ ///Target item to be deleted
+ 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 Children { get; } = new List();
+ public Dictionary NewValues { get; } = new Dictionary();
+ }
+}
\ No newline at end of file
diff --git a/src/dajet-metadata/model/MetadataObject.cs b/src/dajet-metadata/model/MetadataObject.cs
index 4ab42ef..b52b3a1 100644
--- a/src/dajet-metadata/model/MetadataObject.cs
+++ b/src/dajet-metadata/model/MetadataObject.cs
@@ -2,15 +2,28 @@
namespace DaJet.Metadata.Model
{
- public abstract class MetadataObject
+ public abstract class MetadataObject : IComparable
{
- ///Идентификатор объекта метаданных из файла объекта метаданных
+ ///Внутренний идентификатор объекта метаданных
public Guid Uuid { get; set; } = Guid.Empty;
///Идентификатор файла объекта метаданных в таблице Config и DBNames
public Guid FileName { get; set; } = Guid.Empty;
+ ///Имя объекта метаданных
public string Name { get; set; } = string.Empty;
+ ///Синоним объекта метаданных
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); }
}
}
\ No newline at end of file
diff --git a/src/dajet-metadata/model/MetadataProperty.cs b/src/dajet-metadata/model/MetadataProperty.cs
index 6c8245f..814b960 100644
--- a/src/dajet-metadata/model/MetadataProperty.cs
+++ b/src/dajet-metadata/model/MetadataProperty.cs
@@ -5,17 +5,8 @@
namespace DaJet.Metadata.Model
{
///Класс для описания свойств объекта метаданных (реквизитов, измерений и ресурсов)
- public class MetadataProperty
+ public class MetadataProperty : MetadataObject
{
- ///
- /// Идентификатор свойства объекта метаданных из файла DBNames таблицы Params.
- /// Используется для того, чтобы ссылаться на свойство в файле объекта метаданных из таблицы Config.
- ///
- public Guid FileName { get; set; } = Guid.Empty;
- ///Имя свойства объекта метаданных
- public string Name { get; set; } = string.Empty;
- ///Синоним свойства объекта метаданных
- public string Alias { get; set; } = string.Empty;
///Основа имени поля в таблице СУБД (может быть дополнено постфиксами в зависимости от типа данных свойства)
public string DbName { get; set; } = string.Empty;
///Коллекция для описания полей таблицы СУБД свойства объекта метаданных
diff --git a/src/dajet-metadata/services/Configurator.cs b/src/dajet-metadata/services/Configurator.cs
index d88c149..8613170 100644
--- a/src/dajet-metadata/services/Configurator.cs
+++ b/src/dajet-metadata/services/Configurator.cs
@@ -223,6 +223,7 @@ public MetadataProperty CreateProperty(Guid uuid, string token, int code)
{
return new MetadataProperty()
{
+ Uuid = uuid,
FileName = uuid,
DbName = CreateDbName(token, code)
};
diff --git a/src/dajet-metadata/services/MetaDiffService.cs b/src/dajet-metadata/services/MetaDiffService.cs
new file mode 100644
index 0000000..322b903
--- /dev/null
+++ b/src/dajet-metadata/services/MetaDiffService.cs
@@ -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(MetaDiff parent, List target_list, List 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);
+ }
+ }
+ }
+}
\ No newline at end of file