Skip to content

Commit

Permalink
Ajout parsing property params sur mapper from
Browse files Browse the repository at this point in the history
  • Loading branch information
JabX committed Oct 25, 2023
1 parent af144de commit 0f9b746
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 106 deletions.
4 changes: 2 additions & 2 deletions TopModel.Core/FileModel/ModelFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ public class ModelFile
.Concat(Classes.SelectMany(c => new[] { c.DefaultPropertyReference, c.OrderPropertyReference, c.FlagPropertyReference }.Select(r => (r, (object)c.ExtendedProperties.FirstOrDefault(p => p.Name == r?.ReferenceName)))))
.Concat(Classes.SelectMany(c => c.UniqueKeyReferences.SelectMany(uk => uk).Select(propRef => (propRef, (object)c.Properties.FirstOrDefault(p => p.Name == propRef.ReferenceName)))))
.Concat(Classes.SelectMany(c => c.ValueReferences.SelectMany(rv => rv.Value).Select(prop => (prop.Key, (object)c.ExtendedProperties.FirstOrDefault(p => p.Name == prop.Key.ReferenceName)))))
.Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.Params).Concat(c.ToMappers)).Select(p => (p.ClassReference as Reference, (object)p.Class)))
.Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.Params).Concat(c.ToMappers).SelectMany(m => m.MappingReferences.SelectMany(mr => new[] { (mr.Key, (object)c.ExtendedProperties.FirstOrDefault(k => k.Name == mr.Key.ReferenceName)), (mr.Value, mr.Value.ReferenceName == "this" || mr.Value.ReferenceName == "false" ? new Keyword { ModelFile = c.ModelFile } : m.Mappings.Values.FirstOrDefault(k => k.Name == mr.Value.ReferenceName)) }))))
.Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.ClassParams).Concat(c.ToMappers)).Select(p => (p.ClassReference as Reference, (object)p.Class)))
.Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.ClassParams).Concat(c.ToMappers).SelectMany(m => m.MappingReferences.SelectMany(mr => new[] { (mr.Key, (object)c.ExtendedProperties.FirstOrDefault(k => k.Name == mr.Key.ReferenceName)), (mr.Value, mr.Value.ReferenceName == "this" || mr.Value.ReferenceName == "false" ? new Keyword { ModelFile = c.ModelFile } : m.Mappings.Values.FirstOrDefault(k => k.Name == mr.Value.ReferenceName)) }))))
.Concat(Converters.SelectMany(c => c.DomainsFromReferences.Select(d => (d as Reference, c.From.FirstOrDefault(dom => dom.Name == d.ReferenceName) as object))))
.Concat(Converters.SelectMany(c => c.DomainsToReferences.Select(d => (d as Reference, c.To.FirstOrDefault(dom => dom.Name == d.ReferenceName) as object))))
.Concat(DataFlows.Select(d => (d.ClassReference as Reference, d.Class as object)))
Expand Down
89 changes: 63 additions & 26 deletions TopModel.Core/Loaders/ClassLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,37 +152,74 @@ public Class Load(Parser parser)
mapper.Reference = new LocatedString(prop);
parser.ConsumeSequence(() =>
{
var param = new ClassMappings();
mapper.Params.Add(param);
parser.Consume<MappingStart>();
if (parser.Current is Scalar { Value: "class" })
{
var param = new ClassMappings();
mapper.Params.Add(param);

Scalar classScalar = null!;
while (parser.Current is not MappingEnd)
{
var prop = parser.Consume<Scalar>();
switch (prop.Value)
{
case "class":
classScalar = parser.Consume<Scalar>();
param.ClassReference = new ClassReference(classScalar);
break;
case "required":
param.Required = parser.Consume<Scalar>().Value == "true";
break;
case "comment":
param.Comment = parser.Consume<Scalar>().Value;
break;
case "name":
param.Name = new LocatedString(parser.Consume<Scalar>());
break;
case "mappings":
parser.ConsumeMapping(prop =>
{
param.MappingReferences.Add(new Reference(prop), new Reference(parser.Consume<Scalar>()));
});
break;
}
}

Scalar classScalar = null!;
parser.ConsumeMapping(prop =>
param.Name ??= new LocatedString(classScalar) { Value = param.ClassReference.ReferenceName.ToCamelCase(strictIfUppercase: true) };
}
else if (parser.Current is Scalar { Value: "property" })
{
switch (prop.Value)
while (parser.Current is not MappingEnd)
{
case "class":
classScalar = parser.Consume<Scalar>();
param.ClassReference = new ClassReference(classScalar);
break;
case "required":
param.Required = parser.Consume<Scalar>().Value == "true";
break;
case "comment":
param.Comment = parser.Consume<Scalar>().Value;
break;
case "name":
param.Name = new LocatedString(parser.Consume<Scalar>());
break;
case "mappings":
parser.ConsumeMapping(prop =>
{
param.MappingReferences.Add(new Reference(prop), new Reference(parser.Consume<Scalar>()));
});
break;
var prop = parser.Consume<Scalar>();
switch (prop.Value)
{
case "property":
foreach (var p in _propertyLoader.Load(parser))
{
var param = new PropertyMapping { Property = p };
mapper.Params.Add(param);
}

break;
case "target":
var targetReference = new Reference(parser.Consume<Scalar>());
foreach (var cp in mapper.PropertyParams)
{
cp.TargetPropertyReference = targetReference;
}

break;
}
}
});
}
else
{
throw new ModelException(classe, $"Erreur dans la construction des paramètres du mapper 'from'.");
}

param.Name ??= new LocatedString(classScalar) { Value = param.ClassReference.ReferenceName.ToCamelCase(strictIfUppercase: true) };
parser.Consume<MappingEnd>();
});
break;
}
Expand Down
2 changes: 1 addition & 1 deletion TopModel.Core/Loaders/PropertyLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public IEnumerable<IProperty> Load(Parser parser)
parser.Consume<MappingStart>();
switch (parser.Current)
{
case Scalar { Value: "name" } s:
case Scalar { Value: "name" }:
var rp = new RegularProperty { UseLegacyRoleName = _modelConfig.UseLegacyRoleNames };

while (parser.Current is not MappingEnd)
Expand Down
2 changes: 1 addition & 1 deletion TopModel.Core/Model/DataFlowSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class DataFlowSource
#nullable enable
public FromMapper? TargetFromMapper
{
get => DataFlow.Class.FromMappers.FirstOrDefault(fm => fm.Params.Count == 1 && fm.Params.First().Class == Class);
get => DataFlow.Class.FromMappers.FirstOrDefault(fm => fm.Params.Count == 1 && fm.ClassParams.First().Class == Class);
}

public ClassMappings? FirstSourceToMapper
Expand Down
10 changes: 8 additions & 2 deletions TopModel.Core/Model/FromMapper.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
namespace TopModel.Core;
using OneOf;

namespace TopModel.Core;

public class FromMapper
{
#nullable enable
public string? Comment { get; set; }

public List<ClassMappings> Params { get; } = new();
public List<OneOf<ClassMappings, PropertyMapping>> Params { get; } = new();

public IEnumerable<ClassMappings> ClassParams => Params.Where(p => p.IsT0).Select(p => p.AsT0);

public IEnumerable<PropertyMapping> PropertyParams => Params.Where(p => p.IsT1).Select(p => p.AsT1);

#nullable disable
internal LocatedString Reference { get; set; }
Expand Down
13 changes: 13 additions & 0 deletions TopModel.Core/Model/PropertyMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#nullable disable
using TopModel.Core.FileModel;

namespace TopModel.Core;

public class PropertyMapping
{
public IProperty Property { get; set; }

public IProperty TargetProperty { get; set; }

public Reference TargetPropertyReference { get; set; }
}
4 changes: 2 additions & 2 deletions TopModel.Core/ModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static class ModelExtensions
.Select(c => (Reference: c.ExtendsReference!, File: c.GetFile())))
.Concat(modelStore.DataFlows.Where(d => d.Class == classe).Select(d => (Reference: d.ClassReference, File: d.GetFile())))
.Concat(modelStore.DataFlows.SelectMany(d => d.Sources.Where(s => s.Class == classe).Select(s => (Reference: s.ClassReference, File: d.GetFile()))))
.Concat(modelStore.Classes.SelectMany(c => c.FromMappers.SelectMany(c => c.Params).Concat(c.ToMappers).Where(m => m.Class == classe).Select(m => (Reference: m.ClassReference, File: c.GetFile()))))
.Concat(modelStore.Classes.SelectMany(c => c.FromMappers.SelectMany(c => c.ClassParams).Concat(c.ToMappers).Where(m => m.Class == classe).Select(m => (Reference: m.ClassReference, File: c.GetFile()))))
.Where(r => r.Reference is not null)
.DistinctBy(l => l.File.Name + l.Reference.Start.Line);
}
Expand Down Expand Up @@ -198,7 +198,7 @@ public static ModelFile GetFile(this object? objet)

foreach (var classe in modelStore.Classes)
{
foreach (var mappings in classe.FromMappers.SelectMany(m => m.Params).Concat(classe.ToMappers))
foreach (var mappings in classe.FromMappers.SelectMany(m => m.ClassParams).Concat(classe.ToMappers))
{
if (mappings.Mappings.ContainsKey(fp))
{
Expand Down
20 changes: 10 additions & 10 deletions TopModel.Core/ModelStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ IEnumerable<ModelError> ResolveAliases(IEnumerable<AliasProperty> alps)
// Résolutions des mappers
foreach (var classe in modelFile.Classes)
{
foreach (var mappings in classe.FromMappers.SelectMany(m => m.Params).Concat(classe.ToMappers))
foreach (var mappings in classe.FromMappers.SelectMany(m => m.ClassParams).Concat(classe.ToMappers))
{
if (!referencedClasses.TryGetValue(mappings.ClassReference.ReferenceName, out var mappedClass))
{
Expand Down Expand Up @@ -1174,12 +1174,12 @@ IEnumerable<ModelError> ResolveAliases(IEnumerable<AliasProperty> alps)

foreach (var mapper in classe.FromMappers)
{
foreach (var param in mapper.Params.Where((e, i) => mapper.Params.Where((p, j) => p.Name == e.Name && j < i).Any()))
foreach (var param in mapper.ClassParams.Where((e, i) => mapper.ClassParams.Where((p, j) => p.Name == e.Name && j < i).Any()))
{
yield return new ModelError(classe, $"Le nom '{param.Name}' est déjà utilisé.", param.GetLocation()) { ModelErrorType = ModelErrorType.TMD0003 };
}

var mappings = mapper.Params.SelectMany(p => p.MappingReferences);
var mappings = mapper.ClassParams.SelectMany(p => p.MappingReferences);

var hasDoublon = false;
foreach (var mapping in mappings.Where((e, i) => e.Value.ReferenceName != "false" && mappings.Where((p, j) => p.Value.ReferenceName != "false" && p.Key.ReferenceName == e.Key.ReferenceName && j < i).Any()))
Expand All @@ -1190,9 +1190,9 @@ IEnumerable<ModelError> ResolveAliases(IEnumerable<AliasProperty> alps)

if (!hasDoublon)
{
var explicitMappings = mapper.Params.SelectMany(p => p.Mappings).ToList();
var explicitMappings = mapper.ClassParams.SelectMany(p => p.Mappings).ToList();

foreach (var param in mapper.Params.Where(p => p.Class != null))
foreach (var param in mapper.ClassParams.Where(p => p.Class != null))
{
foreach (var property in classe.ExtendedProperties.OfType<AliasProperty>().Where(property => !property.Readonly && !explicitMappings.Any(m => m.Key == property) && !param.MappingReferences.Any(m => m.Key.ReferenceName == property.Name && m.Value.ReferenceName == "false")))
{
Expand All @@ -1208,9 +1208,9 @@ IEnumerable<ModelError> ResolveAliases(IEnumerable<AliasProperty> alps)
}
}

var explicitAndAliasMappings = mapper.Params.SelectMany(p => p.Mappings).ToList();
var explicitAndAliasMappings = mapper.ClassParams.SelectMany(p => p.Mappings).ToList();

foreach (var param in mapper.Params.Where(p => p.Class != null))
foreach (var param in mapper.ClassParams.Where(p => p.Class != null))
{
foreach (var property in classe.ExtendedProperties.OfType<IFieldProperty>().Where(property => !property.Readonly && !explicitAndAliasMappings.Any(m => m.Key == property) && !param.MappingReferences.Any(m => m.Key.ReferenceName == property.Name && m.Value.ReferenceName == "false")))
{
Expand All @@ -1224,11 +1224,11 @@ IEnumerable<ModelError> ResolveAliases(IEnumerable<AliasProperty> alps)
}
}

var finalMappings = mapper.Params.SelectMany(p => p.Mappings).ToList();
var finalMappings = mapper.ClassParams.SelectMany(p => p.Mappings).ToList();

foreach (var mapping in finalMappings.Where((e, i) => finalMappings.Where((p, j) => p.Key == e.Key && j < i).Any()))
{
yield return new ModelError(classe, $"Plusieurs propriétés de la classe peuvent être mappées sur '{mapping.Key.Name}' : {string.Join(", ", mapper.Params.SelectMany(p => p.Mappings.Where(m => m.Key == mapping.Key).Select(m => $"'{p.Name}.{m.Value}'")))}.", mapper.GetLocation()) { ModelErrorType = ModelErrorType.TMD1016 };
yield return new ModelError(classe, $"Plusieurs propriétés de la classe peuvent être mappées sur '{mapping.Key.Name}' : {string.Join(", ", mapper.ClassParams.SelectMany(p => p.Mappings.Where(m => m.Key == mapping.Key).Select(m => $"'{p.Name}.{m.Value}'")))}.", mapper.GetLocation()) { ModelErrorType = ModelErrorType.TMD1016 };
}
}
}
Expand Down Expand Up @@ -1287,7 +1287,7 @@ IEnumerable<ModelError> ResolveAliases(IEnumerable<AliasProperty> alps)
{
foreach (var mapper in classe.FromMappers)
{
if (!mapper.Params.SelectMany(p => p.Mappings).Any())
if (!mapper.ClassParams.SelectMany(p => p.Mappings).Any())
{
yield return new ModelError(classe, "Aucun mapping n'a été trouvé sur ce mapper.", mapper.GetLocation()) { ModelErrorType = ModelErrorType.TMD1025 };
}
Expand Down
1 change: 1 addition & 0 deletions TopModel.Core/TopModel.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="NJsonSchema" Version="10.8.0" />
<PackageReference Include="OneOf" Version="3.0.263" />
<PackageReference Include="YamlDotNet" Version="13.1.0" />
</ItemGroup>

Expand Down
Loading

0 comments on commit 0f9b746

Please sign in to comment.