Skip to content

Commit 1ddfa3e

Browse files
committed
Refactor loading Product and LegacyUrlMapping data
1 parent 6361eb1 commit 1ddfa3e

File tree

36 files changed

+283
-242
lines changed

36 files changed

+283
-242
lines changed

src/Elastic.Documentation.Configuration/BuildContext.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using System.Reflection;
77
using Elastic.Documentation.Configuration.Assembler;
88
using Elastic.Documentation.Configuration.Builder;
9+
using Elastic.Documentation.Configuration.LegacyUrlMappings;
10+
using Elastic.Documentation.Configuration.Products;
911
using Elastic.Documentation.Configuration.Versions;
1012
using Elastic.Documentation.Diagnostics;
1113

@@ -30,6 +32,9 @@ public record BuildContext : IDocumentationSetContext, IDocumentationConfigurati
3032
public ConfigurationFileProvider ConfigurationFileProvider { get; }
3133
public DocumentationEndpoints Endpoints { get; }
3234

35+
public ProductsConfiguration ProductsConfiguration { get; }
36+
public LegacyUrlMappingConfiguration LegacyUrlMappings { get; }
37+
3338
public IFileInfo ConfigurationPath { get; }
3439

3540
public GitCheckoutInformation Git { get; }
@@ -82,6 +87,8 @@ public BuildContext(
8287
AvailableExporters = availableExporters;
8388
VersionsConfiguration = configurationContext.VersionsConfiguration;
8489
ConfigurationFileProvider = configurationContext.ConfigurationFileProvider;
90+
ProductsConfiguration = configurationContext.ProductsConfiguration;
91+
LegacyUrlMappings = configurationContext.LegacyUrlMappings;
8592
Endpoints = configurationContext.Endpoints;
8693

8794
var rootFolder = !string.IsNullOrWhiteSpace(source)
@@ -100,7 +107,7 @@ public BuildContext(
100107
DocumentationSourceDirectory = ConfigurationPath.Directory!;
101108

102109
Git = gitCheckoutInformation ?? GitCheckoutInformation.Create(DocumentationCheckoutDirectory, ReadFileSystem);
103-
Configuration = new ConfigurationFile(this, VersionsConfiguration);
110+
Configuration = new ConfigurationFile(this, VersionsConfiguration, ProductsConfiguration);
104111
GoogleTagManager = new GoogleTagManagerConfiguration
105112
{
106113
Enabled = false

src/Elastic.Documentation.Configuration/Builder/ConfigurationFile.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public record ConfigurationFile : ITableOfContentsScope
6363
Project is not null
6464
&& Project.Equals("Elastic documentation", StringComparison.OrdinalIgnoreCase);
6565

66-
public ConfigurationFile(IDocumentationSetContext context, VersionsConfiguration versionsConfig)
66+
public ConfigurationFile(IDocumentationSetContext context, VersionsConfiguration versionsConfig, ProductsConfiguration productsConfig)
6767
{
6868
_context = context;
6969
ScopeDirectory = context.ConfigurationPath.Directory!;
@@ -149,10 +149,10 @@ public ConfigurationFile(IDocumentationSetContext context, VersionsConfiguration
149149
break;
150150
}
151151

152-
if (!Product.AllById(versionsConfig).ContainsKey(productId.Value))
153-
reader.EmitError($"Product \"{productId.Value}\" not found in the product list. {new Suggestion(Product.All(versionsConfig).Select(p => p.Id).ToHashSet(), productId.Value).GetSuggestionQuestion()}", node);
152+
if (!productsConfig.Products.TryGetValue(productId.Value, out var productToAdd))
153+
reader.EmitError($"Product \"{productId.Value}\" not found in the product list. {new Suggestion(productsConfig.Products.Select(p => p.Value.Id).ToHashSet(), productId.Value).GetSuggestionQuestion()}", node);
154154
else
155-
_ = Products.Add(versionsConfig.Products[productId.Value]);
155+
_ = Products.Add(productToAdd);
156156
}
157157
break;
158158
case "features":
@@ -177,10 +177,10 @@ public ConfigurationFile(IDocumentationSetContext context, VersionsConfiguration
177177
_substitutions[key] = system.Base;
178178
}
179179

180-
foreach (var (id, product) in versionsConfig.Products)
180+
foreach (var product in productsConfig.Products.Values)
181181
{
182-
_substitutions[$"product.{id}"] = product.DisplayName;
183-
_substitutions[$".{id}"] = product.DisplayName;
182+
_substitutions[$"product.{product.Id}"] = product.DisplayName;
183+
_substitutions[$".{product.Id}"] = product.DisplayName;
184184
}
185185

186186
var toc = new TableOfContentsConfiguration(this, sourceFile, ScopeDirectory, _context, 0, "");

src/Elastic.Documentation.Configuration/Builder/ProductVersionMapper.cs

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/Elastic.Documentation.Configuration/ConfigurationFileProvider.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
using System.IO.Abstractions;
66
using System.Text.RegularExpressions;
77
using Elastic.Documentation.Configuration.Assembler;
8+
using Elastic.Documentation.Configuration.Serialization;
89
using Microsoft.Extensions.DependencyInjection;
910
using NetEscapades.EnumGenerators;
11+
using YamlDotNet.Serialization;
12+
using YamlDotNet.Serialization.NamingConventions;
1013

1114
namespace Elastic.Documentation.Configuration;
1215

@@ -23,6 +26,10 @@ public partial class ConfigurationFileProvider
2326
private readonly IFileSystem _fileSystem;
2427
private readonly string _assemblyName;
2528

29+
internal IDeserializer Deserializer { get; } = new StaticDeserializerBuilder(new YamlStaticContext())
30+
.WithNamingConvention(UnderscoredNamingConvention.Instance)
31+
.Build();
32+
2633
public ConfigurationSource ConfigurationSource { get; private set; } = ConfigurationSource.Embedded;
2734
public string? GitReference { get; }
2835

src/Elastic.Documentation.Configuration/IDocumentationConfigurationContext.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using Elastic.Documentation.Configuration.Products;
56
using Elastic.Documentation.Configuration.Versions;
7+
using Elastic.Documentation.Configuration.LegacyUrlMappings;
68

79
namespace Elastic.Documentation.Configuration;
810

@@ -11,6 +13,8 @@ public interface IConfigurationContext
1113
VersionsConfiguration VersionsConfiguration { get; }
1214
ConfigurationFileProvider ConfigurationFileProvider { get; }
1315
DocumentationEndpoints Endpoints { get; }
16+
ProductsConfiguration ProductsConfiguration { get; }
17+
LegacyUrlMappingConfiguration LegacyUrlMappings { get; }
1418
}
1519

1620
/// Used only to seed <see cref="IConfigurationContext"/> in DI, you primarily want to depend on <see cref="IDocumentationConfigurationContext"/>
@@ -24,6 +28,13 @@ public class ConfigurationContext : IConfigurationContext
2428

2529
/// <inheritdoc />
2630
public required DocumentationEndpoints Endpoints { get; init; }
31+
32+
/// <inheritdoc />
33+
public required ProductsConfiguration ProductsConfiguration { get; init; }
34+
35+
/// <inheritdoc />
36+
public required LegacyUrlMappingConfiguration LegacyUrlMappings { get; init; }
37+
2738
}
2839

2940
public interface IDocumentationConfigurationContext : IDocumentationContext, IConfigurationContext;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using Elastic.Documentation.Configuration.Products;
6+
7+
namespace Elastic.Documentation.Configuration.LegacyUrlMappings;
8+
9+
public record LegacyUrlMappingConfiguration
10+
{
11+
public required IReadOnlyCollection<LegacyUrlMapping> Mappings { get; init; }
12+
}
13+
public record LegacyUrlMapping
14+
{
15+
public required string BaseUrl { get; init; }
16+
public required Product Product { get; init; }
17+
public required IReadOnlyCollection<string> LegacyVersions { get; init; }
18+
}
19+
20+
public record LegacyPageMapping(Product Product, string RawUrl, string Version, bool Exists)
21+
{
22+
public override string ToString() => RawUrl.Replace("/current/", $"/{Version}/");
23+
}
24+
25+
public interface ILegacyUrlMapper
26+
{
27+
IReadOnlyCollection<LegacyPageMapping>? MapLegacyUrl(IReadOnlyCollection<string>? mappedPages);
28+
}
29+
30+
public record NoopLegacyUrlMapper : ILegacyUrlMapper
31+
{
32+
public IReadOnlyCollection<LegacyPageMapping> MapLegacyUrl(IReadOnlyCollection<string>? mappedPages) => [];
33+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Collections.Immutable;
6+
using Elastic.Documentation.Configuration.Products;
7+
8+
namespace Elastic.Documentation.Configuration.LegacyUrlMappings;
9+
10+
public static class LegacyUrlMappingExtensions
11+
{
12+
public static LegacyUrlMappingConfiguration CreateLegacyUrlMappings(this ConfigurationFileProvider provider, ProductsConfiguration products)
13+
{
14+
var legacyUrlMappingsFilePath = provider.LegacyUrlMappingsFile;
15+
16+
var legacyUrlMappingsDto = provider.Deserializer.Deserialize<LegacyUrlMappingConfigDto>(legacyUrlMappingsFilePath.OpenText());
17+
18+
var legacyUrlMappings = legacyUrlMappingsDto.Mappings.Select(kvp =>
19+
new LegacyUrlMapping
20+
{
21+
BaseUrl = kvp.Key,
22+
Product = products.Products[kvp.Value.Product],
23+
LegacyVersions = kvp.Value.LegacyVersions.ToImmutableList()
24+
});
25+
26+
return new LegacyUrlMappingConfiguration { Mappings = legacyUrlMappings.ToImmutableList() };
27+
}
28+
}
29+
30+
// Private DTOs for deserialization. These match the YAML structure directly.
31+
32+
internal sealed record LegacyUrlMappingConfigDto
33+
{
34+
public IEnumerable<string> Stack { get; set; } = [];
35+
public Dictionary<string, LegacyUrlMappingDto> Mappings { get; set; } = [];
36+
}
37+
38+
internal sealed record LegacyUrlMappingDto
39+
{
40+
public string Product { get; set; } = string.Empty;
41+
public IEnumerable<string> LegacyVersions { get; set; } = [];
42+
}

src/Elastic.Documentation.Configuration/Products/Product.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System.Collections.Frozen;
56
using Elastic.Documentation.Configuration.Versions;
67
using YamlDotNet.Serialization;
78

89
namespace Elastic.Documentation.Configuration.Products;
910

11+
public record ProductsConfiguration
12+
{
13+
public required FrozenDictionary<string, Product> Products { get; init; }
14+
}
15+
1016
[YamlSerializable]
1117
public record Product
1218
{
1319
public required string Id { get; init; }
1420
public required string DisplayName { get; init; }
15-
public VersioningSystemId? VersionSystem { get; init; }
16-
17-
public static IReadOnlyCollection<Product> All(VersionsConfiguration versions) => [.. versions.Products.Values];
18-
public static IReadOnlyDictionary<string, Product> AllById(VersionsConfiguration versions) => versions.Products;
21+
public VersioningSystem? VersioningSystem { get; init; }
1922
}
2023

2124
public sealed class ProductEqualityComparer : IEqualityComparer<Product>, IComparer<Product>
@@ -35,6 +38,6 @@ public int Compare(Product? x, Product? y)
3538
if (idComparison != 0)
3639
return idComparison;
3740
var displayNameComparison = string.Compare(x.DisplayName, y.DisplayName, StringComparison.OrdinalIgnoreCase);
38-
return displayNameComparison != 0 ? displayNameComparison : Nullable.Compare(x.VersionSystem, y.VersionSystem);
41+
return displayNameComparison != 0 ? displayNameComparison : x.VersioningSystem?.Current.CompareTo(y.VersioningSystem?.Current) ?? 0;
3942
}
4043
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Collections.Frozen;
6+
using Elastic.Documentation.Configuration.Versions;
7+
8+
namespace Elastic.Documentation.Configuration.Products;
9+
10+
public static class ProductExtensions
11+
{
12+
public static ProductsConfiguration CreateProducts(this ConfigurationFileProvider provider, VersionsConfiguration versionsConfiguration)
13+
{
14+
var productsFilePath = provider.ProductsFile;
15+
16+
var productsDto = provider.Deserializer.Deserialize<ProductConfigDto>(productsFilePath.OpenText());
17+
18+
var products = productsDto.Products.ToDictionary(
19+
kvp => kvp.Key,
20+
kvp => new Product
21+
{
22+
Id = kvp.Key,
23+
DisplayName = kvp.Value.Display,
24+
VersioningSystem = versionsConfiguration.GetVersioningSystem(VersionsConfigurationExtensions.ToVersioningSystemId(kvp.Value.Versioning))
25+
});
26+
27+
return new ProductsConfiguration
28+
{
29+
Products = products.ToFrozenDictionary()
30+
};
31+
}
32+
}
33+
34+
// Private DTOs for deserialization. These match the YAML structure directly.
35+
36+
internal sealed record ProductConfigDto
37+
{
38+
public Dictionary<string, ProductDto> Products { get; set; } = [];
39+
}
40+
internal sealed record ProductDto
41+
{
42+
public string Display { get; set; } = string.Empty;
43+
public string Versioning { get; set; } = string.Empty;
44+
}

src/Elastic.Documentation.Configuration/Serialization/YamlStaticContext.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// See the LICENSE file in the project root for more information
44

55
using Elastic.Documentation.Configuration.Assembler;
6+
using Elastic.Documentation.Configuration.LegacyUrlMappings;
7+
using Elastic.Documentation.Configuration.Products;
68
using Elastic.Documentation.Configuration.Versions;
79
using YamlDotNet.Serialization;
810

@@ -19,4 +21,6 @@ namespace Elastic.Documentation.Configuration.Serialization;
1921
[YamlSerializable(typeof(ProductConfigDto))]
2022
[YamlSerializable(typeof(VersioningSystemDto))]
2123
[YamlSerializable(typeof(ProductDto))]
24+
[YamlSerializable(typeof(LegacyUrlMappingDto))]
25+
[YamlSerializable(typeof(LegacyUrlMappingConfigDto))]
2226
public partial class YamlStaticContext;

0 commit comments

Comments
 (0)