diff --git a/KenticoInspector.Core/AbstractReport.cs b/KenticoInspector.Core/AbstractReport.cs index ed372a04..03d91a14 100644 --- a/KenticoInspector.Core/AbstractReport.cs +++ b/KenticoInspector.Core/AbstractReport.cs @@ -9,6 +9,8 @@ namespace KenticoInspector.Core { protected readonly IReportMetadataService reportMetadataService; + private ReportMetadata metadata; + public AbstractReport(IReportMetadataService reportMetadataService) { this.reportMetadataService = reportMetadataService; @@ -16,18 +18,24 @@ public AbstractReport(IReportMetadataService reportMetadataService) public string Codename => GetCodename(this.GetType()); - public static string GetCodename(Type reportType) - { - return GetDirectParentNamespace(reportType); - } - public abstract IList CompatibleVersions { get; } public virtual IList IncompatibleVersions => new List(); + public ReportMetadata Metadata + { + get + { + return metadata ?? (metadata = reportMetadataService.GetReportMetadata(Codename)); + } + } + public abstract IList Tags { get; } - public ReportMetadata Metadata => reportMetadataService.GetReportMetadata(Codename); + public static string GetCodename(Type reportType) + { + return GetDirectParentNamespace(reportType); + } public abstract ReportResults GetResults(); diff --git a/KenticoInspector.Core/Services/Interfaces/IReportMetadataService.cs b/KenticoInspector.Core/Services/Interfaces/IReportMetadataService.cs index 7b82039c..92787b18 100644 --- a/KenticoInspector.Core/Services/Interfaces/IReportMetadataService.cs +++ b/KenticoInspector.Core/Services/Interfaces/IReportMetadataService.cs @@ -4,6 +4,8 @@ namespace KenticoInspector.Core.Services.Interfaces { public interface IReportMetadataService : IService { + string DefaultCultureName { get; } + string CurrentCultureName { get; } ReportMetadata GetReportMetadata(string reportCodename) where T : new(); diff --git a/KenticoInspector.Infrastructure/Services/ReportMetadataService.cs b/KenticoInspector.Infrastructure/Services/ReportMetadataService.cs index 97b47aae..cc9b76d0 100644 --- a/KenticoInspector.Infrastructure/Services/ReportMetadataService.cs +++ b/KenticoInspector.Infrastructure/Services/ReportMetadataService.cs @@ -1,7 +1,10 @@ -using KenticoInspector.Core.Models; -using KenticoInspector.Core.Services.Interfaces; +using System; using System.IO; using System.Threading; + +using KenticoInspector.Core.Models; +using KenticoInspector.Core.Services.Interfaces; + using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; @@ -9,22 +12,97 @@ namespace KenticoInspector.Core.Helpers { public class ReportMetadataService : IReportMetadataService { + public string DefaultCultureName => "en-US"; + public string CurrentCultureName => Thread.CurrentThread.CurrentCulture.Name; public ReportMetadata GetReportMetadata(string reportCodename) where T : new() { - var yamlPath = $"{DirectoryHelper.GetExecutingDirectory()}\\{reportCodename}\\Metadata\\{CurrentCultureName}.yaml"; - return DeserializeYaml>(yamlPath); + var metadataDirectory = $"{DirectoryHelper.GetExecutingDirectory()}\\{reportCodename}\\Metadata\\"; + + var reportMetadata = GetReportMetadataInternal(metadataDirectory, CurrentCultureName); + + var isCurrentCultureDefaultCulture = CurrentCultureName == DefaultCultureName; + if (!isCurrentCultureDefaultCulture) + { + var defaultReportMetadata = GetReportMetadataInternal(metadataDirectory, DefaultCultureName); + reportMetadata = GetMergedMetadata(defaultReportMetadata, reportMetadata); + } + + return reportMetadata; } - public T DeserializeYaml(string path) + + private ReportMetadata GetReportMetadataInternal(string metadataDirectory, string cultureName) where T : new() { - var deserializer = new DeserializerBuilder() + var reportMetadataPath = $"{metadataDirectory}{cultureName}.yaml"; + var reportMetadataPathExists = File.Exists(reportMetadataPath); + return reportMetadataPathExists + ? DeserializeYaml>(reportMetadataPath) + : new ReportMetadata(); + } + + private T DeserializeYaml(string path) + { + var deserializerBuilder = new DeserializerBuilder() .WithNamingConvention(new CamelCaseNamingConvention()) + .IgnoreUnmatchedProperties(); + + var deserializer = deserializerBuilder .Build(); var yamlFile = File.ReadAllText(path); + return deserializer.Deserialize(yamlFile); } + + private ReportMetadata GetMergedMetadata(ReportMetadata defaultMetadata, ReportMetadata overrideMetadata) where T : new() + { + var mergedMetadata = new ReportMetadata + { + Details = new ReportDetails(), + Terms = new T() + }; + + mergedMetadata.Details.Name = overrideMetadata.Details?.Name ?? defaultMetadata.Details.Name; + mergedMetadata.Details.ShortDescription = overrideMetadata.Details?.ShortDescription ?? defaultMetadata.Details.ShortDescription; + mergedMetadata.Details.LongDescription = overrideMetadata.Details?.LongDescription ?? defaultMetadata.Details.LongDescription; + + RecursivelySetPropertyValues(typeof(T), defaultMetadata.Terms, overrideMetadata.Terms, mergedMetadata.Terms); + + return mergedMetadata; + } + + private static void RecursivelySetPropertyValues(Type objectType, object defaultObject, object overrideObject, object targetObject) + { + var objectTypeProperties = objectType.GetProperties(); + + foreach (var objectTypeProperty in objectTypeProperties) + { + var objectTypePropertyType = objectTypeProperty.PropertyType; + + var defaultObjectPropertyValue = objectTypeProperty.GetValue(defaultObject); + + object overrideObjectPropertyValue = null; + + if (overrideObject != null) + { + overrideObjectPropertyValue = objectTypeProperty.GetValue(overrideObject); + } + + if (objectTypePropertyType.Namespace == objectType.Namespace) + { + var targetObjectPropertyValue = Activator.CreateInstance(objectTypePropertyType); + + objectTypeProperty.SetValue(targetObject, targetObjectPropertyValue); + + RecursivelySetPropertyValues(objectTypePropertyType, defaultObjectPropertyValue, overrideObjectPropertyValue, targetObjectPropertyValue); + } + else + { + objectTypeProperty.SetValue(targetObject, overrideObjectPropertyValue ?? defaultObjectPropertyValue); + } + } + } } } \ No newline at end of file