-
Notifications
You must be signed in to change notification settings - Fork 0
Added JSON mapping plan implementation #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a JSON-based mapping plan implementation that allows entity types to be mapped from source to target names using configuration loaded from a JSON file. The implementation extends the existing mapping infrastructure by adding a new JsonMappingPlan class and introducing an IsValid property to the IMappingPlan interface.
Key changes:
- New
JsonMappingPlanclass that loads mappings from JSON files with case-insensitive matching - Added
IsValidproperty toIMappingPlaninterface to indicate mapping plan validity - Added Newtonsoft.Json dependency for JSON deserialization
Reviewed changes
Copilot reviewed 11 out of 15 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| idou.Core/idou.Core.csproj | Added Newtonsoft.Json 13.0.4 package reference |
| idou.Core/Mapping/JsonMappingPlan.cs | Implements IMappingPlan to load and apply entity type mappings from JSON files |
| idou.Core/Mapping/JsonMapping.cs | Data model representing a single source-to-target mapping entry |
| idou.Core/Mapping/IMappingPlan.cs | Added IsValid property to the interface |
| idou.Core/Mapping/DefaultMappingPlan.cs | Implemented IsValid property (always returns true) |
| idou.Core.Tests/idou.Core.Tests.csproj | Configured test asset JSON files to be copied to output directory |
| idou.Core.Tests/Mapping/assets/valid.json | Test fixture with a sample mapping configuration |
| idou.Core.Tests/Mapping/assets/empty.json | Test fixture with empty mappings array |
| idou.Core.Tests/Mapping/JsonMappingPlanTests.cs | Unit tests for JsonMappingPlan functionality |
| idou.Core.Tests/Engine/ChangePipelineTests.cs | Updated RecordingMappingPlan to implement new IsValid property |
| docs/flow.puml | Added PlantUML diagram documenting sync job execution flow |
| .gitignore | Replaced minimal ignore rules with comprehensive .NET/IDE gitignore patterns |
| .idea/.idea.idou/.idea/vcs.xml | JetBrains Rider VCS configuration |
| .idea/.idea.idou/.idea/indexLayout.xml | JetBrains Rider index layout configuration |
| .idea/.idea.idou/.idea/.gitignore | JetBrains Rider ignore patterns |
Files not reviewed (3)
- .idea/.idea.idou/.idea/.gitignore: Language not supported
- .idea/.idea.idou/.idea/indexLayout.xml: Language not supported
- .idea/.idea.idou/.idea/vcs.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
idou.Core/Mapping/JsonMapping.cs
Outdated
| public string Source { get; set; } | ||
| public string Target { get; set; } |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Source and Target properties are nullable reference types but should not be null for valid mappings. Consider adding null-forgiving operators, making them required properties, or adding validation to ensure they're not null during deserialization. Currently, if the JSON contains null values for these properties, a NullReferenceException will occur when JsonMappingPlan tries to use them in line 19 (ToDictionary) or line 27 (new EntityType).
| public string Source { get; set; } | |
| public string Target { get; set; } | |
| public required string Source { get; set; } = null!; | |
| public required string Target { get; set; } = null!; |
| using idou.Core.Domain; | ||
| using idou.Core.Mapping; | ||
|
|
||
| namespace idou.Core.Tests.Mapping; | ||
|
|
||
| public class JsonMappingPlanTests | ||
| { | ||
| [Fact] | ||
| public void MappingPlanIsValid_WhenTheFileExistsAndHasMappings() | ||
| { | ||
| var plan = new JsonMappingPlan("Mapping/assets/valid.json"); | ||
| Assert.True(plan.IsValid); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Throws_WhenTheFileDoesNotExist() | ||
| { | ||
| Assert.Throws<FileNotFoundException>(() => new JsonMappingPlan("Mapping/assets/does-not-exist.json")); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void MappingPlanIsInvalid_WhenTheMappingsAreEmpty() | ||
| { | ||
| var plan = new JsonMappingPlan("Mapping/assets/empty.json"); | ||
| Assert.False(plan.IsValid); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void MapsTheEntityType_WhenTheMappingExists() | ||
| { | ||
| var plan = new JsonMappingPlan("Mapping/assets/valid.json"); | ||
|
|
||
| var sourceType = new EntityType("users"); | ||
| var mapped = plan.MapEntityType(sourceType); | ||
|
|
||
| Assert.True(plan.IsValid); | ||
| Assert.Equal("accounts", mapped.Name); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void DoesNotMapTheEntityType_WhenNoMappingExists() | ||
| { | ||
| var plan = new JsonMappingPlan("Mapping/assets/valid.json"); | ||
|
|
||
| var sourceType = new EntityType("unknown"); | ||
| var mapped = plan.MapEntityType(sourceType); | ||
|
|
||
| Assert.Equal(sourceType.Name, mapped.Name); | ||
| } | ||
| } No newline at end of file |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MapRecord method lacks test coverage. While MapEntityType is tested, there are no tests verifying that MapRecord correctly creates a new EntityRecord with mapped type and key, or that it properly copies the Attributes dictionary. Consider adding a test that verifies MapRecord behavior, similar to the existing tests for MapEntityType.
| File.ReadAllText(filePath) | ||
| ) ?? throw new InvalidOperationException("Invalid mapping file"); | ||
|
|
||
| _bySource = mappings.ToDictionary(m => m.Source, StringComparer.OrdinalIgnoreCase); |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the JSON file contains duplicate source values (considering case-insensitive comparison due to StringComparer.OrdinalIgnoreCase), the ToDictionary call will throw an ArgumentException. Consider either validating for duplicates and providing a clearer error message, or handling this case explicitly. There's also no test coverage for this scenario.
| var mappings = JsonConvert.DeserializeObject<List<JsonMapping>>( | ||
| File.ReadAllText(filePath) | ||
| ) ?? throw new InvalidOperationException("Invalid mapping file"); |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the JSON file contains malformed JSON, JsonConvert.DeserializeObject will throw a JsonException that isn't caught or handled. Consider adding try-catch to provide a more user-friendly error message, or document that callers should expect JsonException in addition to FileNotFoundException and InvalidOperationException.
| var mappings = JsonConvert.DeserializeObject<List<JsonMapping>>( | |
| File.ReadAllText(filePath) | |
| ) ?? throw new InvalidOperationException("Invalid mapping file"); | |
| List<JsonMapping> mappings; | |
| try | |
| { | |
| mappings = JsonConvert.DeserializeObject<List<JsonMapping>>( | |
| File.ReadAllText(filePath) | |
| ) ?? throw new InvalidOperationException("Invalid mapping file"); | |
| } | |
| catch (JsonException ex) | |
| { | |
| throw new InvalidOperationException("Invalid mapping file", ex); | |
| } |
No description provided.