Skip to content

Conversation

@joshika39
Copy link
Member

No description provided.

Copy link

Copilot AI left a 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 JsonMappingPlan class that loads mappings from JSON files with case-insensitive matching
  • Added IsValid property to IMappingPlan interface 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.

Comment on lines 5 to 6
public string Source { get; set; }
public string Target { get; set; }
Copy link

Copilot AI Dec 28, 2025

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).

Suggested change
public string Source { get; set; }
public string Target { get; set; }
public required string Source { get; set; } = null!;
public required string Target { get; set; } = null!;

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 50
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
Copy link

Copilot AI Dec 28, 2025

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.

Copilot uses AI. Check for mistakes.
File.ReadAllText(filePath)
) ?? throw new InvalidOperationException("Invalid mapping file");

_bySource = mappings.ToDictionary(m => m.Source, StringComparer.OrdinalIgnoreCase);
Copy link

Copilot AI Dec 28, 2025

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.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +17
var mappings = JsonConvert.DeserializeObject<List<JsonMapping>>(
File.ReadAllText(filePath)
) ?? throw new InvalidOperationException("Invalid mapping file");
Copy link

Copilot AI Dec 28, 2025

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.

Suggested change
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);
}

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented Dec 28, 2025

Test Results

25 tests  +16   25 ✅ +16   0s ⏱️ ±0s
 1 suites ± 0    0 💤 ± 0 
 1 files   ± 0    0 ❌ ± 0 

Results for commit 5998bd4. ± Comparison against base commit ecc0349.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

Code Coverage

Package Line Rate Branch Rate Complexity Health
idou.Core 100% 83% 56
Summary 100% (92 / 92) 83% (15 / 18) 56

@joshika39 joshika39 merged commit a0ab535 into master Dec 28, 2025
2 checks passed
@joshika39 joshika39 deleted the feature/json-mapping-plan branch December 28, 2025 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants