232 lines
12 KiB
C#
232 lines
12 KiB
C#
/*
|
|
* Copyright (c) 2022 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using Aurora.Api;
|
|
using Aurora.View;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace AuroraUIComponent.Util
|
|
{
|
|
public class DifferenceItem : NotifyPropertyChangedBase
|
|
{
|
|
private string _Item; public string Item { get => _Item; set => SetProperty(ref _Item, value); }
|
|
private string _Before; public string Before { get => _Before; set => SetProperty(ref _Before, value); }
|
|
private string _After; public string After { get => _After; set => SetProperty(ref _After, value); }
|
|
|
|
public DifferenceItem(string item, string before, string after)
|
|
{
|
|
Item = item;
|
|
Before = before;
|
|
After = after;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"[{Item}] {Before} -> {After}";
|
|
}
|
|
}
|
|
|
|
public abstract class IDataDifferenceCheck : NotifyPropertyChangedBase
|
|
{
|
|
public abstract bool CheckDifference(ref List<DifferenceItem> difference, string prefix, object org, object diff);
|
|
|
|
#region Difference Check : 공용 Method
|
|
|
|
/// <summary>
|
|
/// C#에서 기본 제공되는 데이터형의 difference check (각 Type별 체크)
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="difference">체크 결과를 return하기 위한 string</param>
|
|
/// <param name="prefix">차이가 있을 경우, 해당 데이터 변경점 앞에 붙일 string(예: Module #1)</param>
|
|
/// <param name="org">원본</param>
|
|
/// <param name="diff">비교 대상</param>
|
|
/// <returns></returns>
|
|
protected bool CheckPrimaryType<T>(ref List<DifferenceItem> difference, string prefix, object org, object diff)
|
|
{
|
|
if (org is IList<T> orgList && diff is IList<T> diffList) {
|
|
for (int i = 0; i < Math.Max(orgList.Count(), diffList.Count()); i++) {
|
|
if (i < orgList.Count() && i < diffList.Count()) {
|
|
CheckPrimaryType<T>(ref difference, $"{prefix} #{i + 1}", orgList[i], diffList[i]);
|
|
} else if (i < orgList.Count()) {
|
|
//difference = difference + "\n" + $"{prefix} #{i + 1} :: [{orgList[i]}] Deleted";
|
|
difference.Add(new DifferenceItem($"{prefix} #{i + 1}", orgList[i].ToString(), "Deleted"));
|
|
} else if (i < diffList.Count()) {
|
|
//difference = difference + "\n" + $"{prefix} #{i + 1} :: [{diffList[i]}] Added";
|
|
difference.Add(new DifferenceItem($"{prefix} #{i + 1}", "Added", diffList[i].ToString()));
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (org is T orgValue && diff is T diffValue) {
|
|
var diffString = GetDiffString(orgValue, diffValue);
|
|
if (!string.IsNullOrEmpty(diffString.Item1) || !string.IsNullOrEmpty(diffString.Item2)) {
|
|
//difference = difference + "\n" + $"{prefix} :: " + diffString;
|
|
difference.Add(new DifferenceItem(prefix, diffString.Item1, diffString.Item2));
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// C#에서 기본 제공되는 데이터형의 단순 "before -> after" string 반환
|
|
/// </summary>
|
|
/// <param name="org">원본</param>
|
|
/// <param name="diff">비교 대상</param>
|
|
/// <returns></returns>
|
|
protected (string, string) GetDiffString(object org, object diff)
|
|
{
|
|
if (org is double doubleOrgValue && diff is double doubleDiffValue && doubleOrgValue != doubleDiffValue) {
|
|
return (doubleOrgValue.ToString("F3"), doubleDiffValue.ToString("F3"));
|
|
} else if (org is float floatOrgValue && diff is float floatDiffValue && floatOrgValue != floatDiffValue) {
|
|
return (floatOrgValue.ToString("F3"), floatDiffValue.ToString("F3"));
|
|
} else if (org is ulong ulongOrgValue && diff is ulong ulongDiffValue && ulongOrgValue != ulongDiffValue) {
|
|
return (ulongOrgValue.ToString(), ulongDiffValue.ToString());
|
|
} else if (org is long longOrgValue && diff is long longDiffValue && longOrgValue != longDiffValue) {
|
|
return (longOrgValue.ToString(), longDiffValue.ToString());
|
|
} else if (org is uint uintOrgValue && diff is uint uintDiffValue && uintOrgValue != uintDiffValue) {
|
|
return (uintOrgValue.ToString(), uintDiffValue.ToString());
|
|
} else if (org is int intOrgValue && diff is int intDiffValue && intOrgValue != intDiffValue) {
|
|
return (intOrgValue.ToString(), intDiffValue.ToString());
|
|
} else if (org is ushort ushortOrgValue && diff is ushort ushortDiffValue && ushortOrgValue != ushortDiffValue) {
|
|
return (ushortOrgValue.ToString(), ushortDiffValue.ToString());
|
|
} else if (org is short shortOrgValue && diff is short shortDiffValue && shortOrgValue != shortDiffValue) {
|
|
return (shortOrgValue.ToString(), shortDiffValue.ToString());
|
|
} else if (org is string stringOrgValue && diff is string stringDiffValue && stringOrgValue != stringDiffValue) {
|
|
return (stringOrgValue, stringDiffValue);
|
|
} else if (org is char charOrgValue && diff is char charDiffValue && charOrgValue != charDiffValue) {
|
|
return (charOrgValue.ToString(), charDiffValue.ToString());
|
|
} else if (org is bool boolOrgValue && diff is bool boolDiffValue && boolOrgValue != boolDiffValue) {
|
|
return (boolOrgValue.ToString(), boolDiffValue.ToString());
|
|
}
|
|
|
|
return (null, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// C#에서 기본 제공되는 데이터형의 difference check (외부에서 호출하는 일괄 체크 함수)
|
|
/// </summary>
|
|
/// <param name="prefix">차이가 있을 경우, 해당 데이터 변경점 앞에 붙일 string(예: Module #1)</param>
|
|
/// <param name="difference">체크 결과를 return하기 위한 string</param>
|
|
/// <param name="org">원본</param>
|
|
/// <param name="diff">비교 대상</param>
|
|
/// <returns></returns>
|
|
public bool CheckPrimaryTypeAll(ref List<DifferenceItem> difference, string prefix, object org, object diff)
|
|
{
|
|
// JsonIgnore 설정되어 있으면 skip
|
|
var jsonIgnoreAttribute = org.GetType().GetCustomAttributes(typeof(JsonIgnoreAttribute), false).FirstOrDefault();
|
|
if (jsonIgnoreAttribute != null) {
|
|
//Logger.V($"Ignore {org.GetType().Name} has JsonIgnore attribute.");
|
|
return true;
|
|
} else {
|
|
//Logger.V($"Ignore {org.GetType().Name} does not have JsonIgnore attribute.");
|
|
}
|
|
|
|
if (org == null && diff == null) {
|
|
return true;
|
|
} else if (diff == null) {
|
|
//difference = difference + "\n" + $"{prefix} :: [{org}] Deleted";
|
|
difference.Add(new DifferenceItem(prefix, org.ToString(), "Deleted"));
|
|
return true;
|
|
} else if (org == null) {
|
|
//difference = difference + "\n" + $"{prefix} :: [{diff}] Added";
|
|
difference.Add(new DifferenceItem(prefix, "Added", diff.ToString()));
|
|
return true;
|
|
}
|
|
|
|
// Enum Check
|
|
if (org.GetType().IsEnum && diff.GetType().IsEnum) {
|
|
if (org.ToString() != diff.ToString()) {
|
|
//difference = difference + "\n" + prefix + " :: " + org.ToString() + "->" + diff.ToString();
|
|
difference.Add(new DifferenceItem(prefix, org.ToString(), diff.ToString()));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ret = CheckPrimaryType<double>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<float>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<ulong>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<long>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<uint>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<int>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<ushort>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<short>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<string>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<char>(ref difference, prefix, org, diff);
|
|
if (!ret) ret = CheckPrimaryType<bool>(ref difference, prefix, org, diff);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사용자가 추가한 Class의 difference check (각 Type별 체크) : Primary Type이 나올 때까지 상속자에서 구현한 CheckDifference를 반복
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="prefix"></param>
|
|
/// <param name="title"></param>
|
|
/// <param name="difference"></param>
|
|
/// <param name="org"></param>
|
|
/// <param name="diff"></param>
|
|
/// <returns></returns>
|
|
protected bool CheckCustomType<T>(ref List<DifferenceItem> difference, string prefix, object org, object diff)
|
|
{
|
|
// Null Check
|
|
if (org == null && diff == null) {
|
|
return true;
|
|
} else if (diff == null) {
|
|
//difference = difference + "\n" + $"{prefix} :: [{org}] Deleted";
|
|
difference.Add(new DifferenceItem(prefix, org.ToString(), "Deleted"));
|
|
return true;
|
|
} else if (org == null) {
|
|
//difference = difference + "\n" + $"{prefix} :: [{diff}] Added";
|
|
difference.Add(new DifferenceItem(prefix, "Added", diff.ToString()));
|
|
return true;
|
|
}
|
|
|
|
// Logger.V("TEST", prefix);
|
|
|
|
// List Check
|
|
if (org is ObservableCollection<T> obserOrgList && diff is ObservableCollection<T> obserDiffList) {
|
|
org = obserOrgList.ToList();
|
|
diff = obserDiffList.ToList();
|
|
}
|
|
if (org is IList<T> orgList && diff is IList<T> diffList) {
|
|
for (int i = 0; i < Math.Max(orgList.Count(), diffList.Count()); i++) {
|
|
if (orgList.Count > i && diffList.Count > i) {
|
|
CheckDifference(ref difference, $"{prefix} #{i + 1}", orgList[i], diffList[i]);
|
|
} else if (i < orgList.Count()) {
|
|
//difference = difference + "\n" + $"{prefix} #{i + 1} :: [{orgList[i]}] Deleted";
|
|
difference.Add(new DifferenceItem($"{prefix} #{i + 1}", org.ToString(), "Deleted"));
|
|
} else if (i < diffList.Count()) {
|
|
//difference = difference + "\n" + $"{prefix} #{i + 1} :: [{diffList[i]}] Added";
|
|
difference.Add(new DifferenceItem($"{prefix} #{i + 1}", "Added", diff.ToString()));
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Object Check
|
|
if (org.GetType() == typeof(T) && diff.GetType() == typeof(T)) {
|
|
PropertyInfo[] sourceProperties = typeof(T).GetProperties();
|
|
|
|
foreach (PropertyInfo sourceProperty in sourceProperties) {
|
|
CheckDifference(ref difference, $"{prefix} [{sourceProperty.Name}]", sourceProperty.GetValue(org), sourceProperty.GetValue(diff));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
}
|