Skip to content
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

Mapping preview #729

Merged
merged 34 commits into from Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d4167eb
investigation added
RichardIrons-neo4j Aug 22, 2023
f9c1732
mapping with paths working
RichardIrons-neo4j Aug 29, 2023
d2e4189
WIP
RichardIrons-neo4j Aug 31, 2023
bed3370
Merge branch '5.0' into hydration-investigation
RichardIrons-neo4j Aug 31, 2023
b8c20a4
WIP
RichardIrons-neo4j Sep 1, 2023
477bc1c
Unit tests added
RichardIrons-neo4j Sep 7, 2023
fbb9378
minor deletion
RichardIrons-neo4j Sep 7, 2023
1e88b01
Adding more test coverage
RichardIrons-neo4j Sep 7, 2023
611e5f2
Test coverage for DictAsRecord
RichardIrons-neo4j Sep 8, 2023
c461d33
Update DictAsRecordTests
RichardIrons-neo4j Sep 11, 2023
332c9b0
DoNotMap attribute added
RichardIrons-neo4j Sep 11, 2023
f554731
Added some xml docs
RichardIrons-neo4j Sep 12, 2023
fb5e633
minor updates
RichardIrons-neo4j Sep 13, 2023
835c16a
Punctuation
RichardIrons-neo4j Sep 14, 2023
040c1f2
remove investigation doc
RichardIrons-neo4j Sep 14, 2023
f3aa98d
correct extensions method
RichardIrons-neo4j Sep 14, 2023
44080c0
Correct extension method
RichardIrons-neo4j Sep 15, 2023
2511e9b
Undo weird change
RichardIrons-neo4j Sep 15, 2023
4104bfa
Rename extension method
RichardIrons-neo4j Sep 18, 2023
14dc062
Fix test
RichardIrons-neo4j Sep 18, 2023
a0005ed
Undo unintentional changes
RichardIrons-neo4j Sep 19, 2023
637ab9b
Added convenience methods
RichardIrons-neo4j Sep 19, 2023
b038afb
Node changed to entity where possible
RichardIrons-neo4j Sep 19, 2023
d491929
changed node to entity throughout
RichardIrons-neo4j Sep 19, 2023
579ac7c
Test for nested lists of nodes
RichardIrons-neo4j Sep 19, 2023
30b5297
Add labels and relationship types
RichardIrons-neo4j Sep 21, 2023
488585a
Rename InternalMappingSource
RichardIrons-neo4j Sep 21, 2023
279e26b
Renaming
RichardIrons-neo4j Sep 21, 2023
80238db
more renaming
RichardIrons-neo4j Sep 21, 2023
78950f2
More renaming
RichardIrons-neo4j Sep 21, 2023
6e43be3
wip
RichardIrons-neo4j Sep 26, 2023
18ea7f4
Remove non-generic IRecordMapper interface
RichardIrons-neo4j Sep 26, 2023
24a718b
Renaming
RichardIrons-neo4j Sep 26, 2023
3aecb67
Update Neo4j.Driver/Neo4j.Driver/Preview/Mapping/AsyncEnumerableExten…
RichardIrons-neo4j Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions Neo4j.Driver/.editorconfig
Expand Up @@ -369,11 +369,11 @@ dotnet_naming_symbols.types_and_namespaces_symbols.applicable_kinds = namespace,
dotnet_naming_symbols.type_parameters_symbols.applicable_accessibilities = *
dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_accessibilities = *
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_applicable_kinds = unity_serialised_field
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_required_modifiers = instance
dotnet_separate_import_directive_groups = false
Expand Down Expand Up @@ -663,8 +663,8 @@ resharper_line_break_before_requires_clause = do_not_change
resharper_linkage_specification_braces = end_of_line
resharper_linkage_specification_indentation = none
resharper_local_function_body = block_body
resharper_macro_block_begin =
resharper_macro_block_end =
resharper_macro_block_begin =
resharper_macro_block_end =
resharper_max_array_initializer_elements_on_line = 10000
resharper_max_attribute_length_for_same_line = 38
resharper_max_enum_members_on_line = 1
Expand Down Expand Up @@ -698,7 +698,7 @@ resharper_parentheses_non_obvious_operations = none, shift, bitwise_and, bitwise
resharper_parentheses_redundancy_style = remove_if_not_clarifies_precedence
resharper_parentheses_same_type_operations = false
resharper_pi_attributes_indent = align_by_first_attribute
resharper_place_accessorholder_attribute_on_same_line = if_owner_is_single_line
resharper_place_accessorholder_attribute_on_same_line = false
resharper_place_accessor_attribute_on_same_line = if_owner_is_single_line
resharper_place_comments_at_first_column = false
resharper_place_constructor_initializer_on_same_line = true
Expand Down Expand Up @@ -734,7 +734,7 @@ resharper_resx_attribute_indent = single_indent
resharper_resx_blank_line_after_pi = true
resharper_resx_indent_text = OneIndent
resharper_resx_keep_user_linebreaks = true
resharper_resx_linebreak_before_elements =
resharper_resx_linebreak_before_elements =
resharper_resx_max_blank_lines_between_tags = 0
resharper_resx_pi_attribute_style = do_not_touch
resharper_resx_space_before_self_closing = false
Expand Down Expand Up @@ -963,7 +963,7 @@ resharper_xml_attribute_indent = align_by_first_attribute
resharper_xml_blank_line_after_pi = true
resharper_xml_indent_text = OneIndent
resharper_xml_keep_user_linebreaks = true
resharper_xml_linebreak_before_elements =
resharper_xml_linebreak_before_elements =
resharper_xml_max_blank_lines_between_tags = 2
resharper_xml_pi_attribute_style = do_not_touch
resharper_xml_space_before_self_closing = true
Expand Down
16 changes: 8 additions & 8 deletions Neo4j.Driver/Neo4j.Driver.Tests/.editorconfig
@@ -1,4 +1,4 @@
[*]
[*]
charset = utf-8-bom
end_of_line = crlf
indent_size = 4
Expand Down Expand Up @@ -369,11 +369,11 @@ dotnet_naming_symbols.types_and_namespaces_symbols.applicable_kinds = namespace,
dotnet_naming_symbols.type_parameters_symbols.applicable_accessibilities = *
dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_accessibilities = *
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_applicable_kinds = unity_serialised_field
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_required_modifiers = instance
dotnet_separate_import_directive_groups = false
Expand Down Expand Up @@ -663,8 +663,8 @@ resharper_line_break_before_requires_clause = do_not_change
resharper_linkage_specification_braces = end_of_line
resharper_linkage_specification_indentation = none
resharper_local_function_body = block_body
resharper_macro_block_begin =
resharper_macro_block_end =
resharper_macro_block_begin =
resharper_macro_block_end =
resharper_max_array_initializer_elements_on_line = 10000
resharper_max_attribute_length_for_same_line = 38
resharper_max_enum_members_on_line = 1
Expand Down Expand Up @@ -698,7 +698,7 @@ resharper_parentheses_non_obvious_operations = none, shift, bitwise_and, bitwise
resharper_parentheses_redundancy_style = remove_if_not_clarifies_precedence
resharper_parentheses_same_type_operations = false
resharper_pi_attributes_indent = align_by_first_attribute
resharper_place_accessorholder_attribute_on_same_line = if_owner_is_single_line
resharper_place_accessorholder_attribute_on_same_line = false
resharper_place_accessor_attribute_on_same_line = if_owner_is_single_line
resharper_place_comments_at_first_column = false
resharper_place_constructor_initializer_on_same_line = true
Expand Down Expand Up @@ -734,7 +734,7 @@ resharper_resx_attribute_indent = single_indent
resharper_resx_blank_line_after_pi = true
resharper_resx_indent_text = OneIndent
resharper_resx_keep_user_linebreaks = true
resharper_resx_linebreak_before_elements =
resharper_resx_linebreak_before_elements =
resharper_resx_max_blank_lines_between_tags = 0
resharper_resx_pi_attribute_style = do_not_touch
resharper_resx_space_before_self_closing = false
Expand Down Expand Up @@ -963,7 +963,7 @@ resharper_xml_attribute_indent = align_by_first_attribute
resharper_xml_blank_line_after_pi = true
resharper_xml_indent_text = OneIndent
resharper_xml_keep_user_linebreaks = true
resharper_xml_linebreak_before_elements =
resharper_xml_linebreak_before_elements =
resharper_xml_max_blank_lines_between_tags = 2
resharper_xml_pi_attribute_style = do_not_touch
resharper_xml_space_before_self_closing = true
Expand Down
49 changes: 49 additions & 0 deletions Neo4j.Driver/Neo4j.Driver.Tests/Mapping/DictAsRecordTests.cs
@@ -0,0 +1,49 @@
// Copyright (c) "Neo4j"
// Neo4j Sweden AB [http://neo4j.com]
//
// This file is part of Neo4j.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Collections.Generic;
using FluentAssertions;
using Neo4j.Driver.Preview.Mapping;
using Xunit;
using Record = Neo4j.Driver.Internal.Result.Record;

namespace Neo4j.Driver.Tests.Mapping
{
public class DictAsRecordTests
{
[Fact]
public void ShouldReturnCorrectValues()
{
var originalRecord = new Record(new[] {"name", "age"}, new object[] {"Bob", 42});
var dict = new Dictionary<string, object>
{
{"key1", "value1"},
{"key2", "value2"}
};

var subject = new DictAsRecord(dict, originalRecord);

subject.Record.Should().BeSameAs(originalRecord);
subject.Keys.Should().BeEquivalentTo(dict.Keys);
subject.Values.Should().BeEquivalentTo(dict);
subject[0].Should().Be("value1");
subject[1].Should().Be("value2");
subject["key1"].Should().Be("value1");
subject["key2"].Should().Be("value2");
}
}
}
130 changes: 130 additions & 0 deletions Neo4j.Driver/Neo4j.Driver.Tests/Mapping/LabelCaptureTests.cs
@@ -0,0 +1,130 @@
// Copyright (c) "Neo4j"
// Neo4j Sweden AB [http://neo4j.com]
//
// This file is part of Neo4j.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Neo4j.Driver.Internal.Types;
using Neo4j.Driver.Preview.Mapping;
using Xunit;
using Record = Neo4j.Driver.Internal.Result.Record;

namespace Neo4j.Driver.Tests.Mapping
{
public class LabelCaptureTests
{
public class TestMappedClass
{
[MappingSource("Person", EntityMappingSource.NodeLabel)]
public string Label { get; set; }

[MappingSource("Person", EntityMappingSource.NodeLabel)]
public List<string> Labels { get; set; }

[MappingSource("Relationship", EntityMappingSource.RelationshipType)]
public string RelationshipType { get; set; }
}

public LabelCaptureTests()
{
RecordObjectMapping.Reset();
}

[Fact]
public void ShouldCaptureSingleNodeLabel()
{
var node = new Node(1, new[] { "Test" }, new Dictionary<string, object>());
var record = new Record(new[] { "Person" }, new object[] { node });

var mapped = record.AsObject<TestMappedClass>();

mapped.Label.Should().Be("Test");
}

[Fact]
public void ShouldCaptureMultipleNodeLabelsIntoString()
{
var node = new Node(1, new[] { "Alpha", "Bravo", "Charlie" }, new Dictionary<string, object>());
var record = new Record(new[] { "Person" }, new object[] { node });

var mapped = record.AsObject<TestMappedClass>();

mapped.Label.Should().Be("Alpha,Bravo,Charlie");
}

[Fact]
public void ShouldCaptureRelationshipType()
{
var node = new Relationship(1, 2, 3, "ACTED_IN", new Dictionary<string, object>());
var record = new Record(new[] { "Relationship" }, new object[] { node });

var mapped = record.AsObject<TestMappedClass>();

mapped.RelationshipType.Should().Be("ACTED_IN");
}

class CustomMapper : IMappingProvider
{
/// <inheritdoc />
public void CreateMappers(IMappingRegistry registry)
{
registry.RegisterMapping<TestMappedClass>(
b => b
.Map(
x => x.Label,
"Person",
EntityMappingSource.NodeLabel,
x => string.Join("|", ((string[])x).Select(y => y.ToUpper())))
.Map(
x => x.Labels,
"Person",
EntityMappingSource.NodeLabel,
x => ((string[])x).Select(y => y.Replace("a", "x")).ToList())
.Map(
x => x.RelationshipType,
"Relationship",
EntityMappingSource.RelationshipType,
x => x?.ToString()?.ToLower()));
}
}

[Fact]
public void ShouldCaptureAndConvertLabels()
{
RecordObjectMapping.RegisterProvider<CustomMapper>();
var node = new Node(1, new[] { "Alpha", "Bravo", "Charlie" }, new Dictionary<string, object>());
var record = new Record(new[] { "Person" }, new object[] { node });

var mapped = record.AsObject<TestMappedClass>();

mapped.Label.Should().Be("ALPHA|BRAVO|CHARLIE");
mapped.Labels.Should().BeEquivalentTo(new[] { "Alphx", "Brxvo", "Chxrlie" });
}

[Fact]
public void ShouldCaptureAndConvertRelationshipType()
{
RecordObjectMapping.RegisterProvider<CustomMapper>();
var node = new Relationship(1, 2, 3, "ACTED_IN", new Dictionary<string, object>());
var record = new Record(new[] { "Relationship" }, new object[] { node });

var mapped = record.AsObject<TestMappedClass>();

mapped.RelationshipType.Should().Be("acted_in");
}
}
}
58 changes: 58 additions & 0 deletions Neo4j.Driver/Neo4j.Driver.Tests/Mapping/MappingBuilderTests.cs
@@ -0,0 +1,58 @@
// Copyright (c) "Neo4j"
// Neo4j Sweden AB [http://neo4j.com]
//
// This file is part of Neo4j.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using FluentAssertions;
using Neo4j.Driver.Preview.Mapping;
using Xunit;

namespace Neo4j.Driver.Tests.Mapping
{
public class MappingBuilderTests
{
private class TestClass
{
public int Settable { get; set; }
public int NotSettable { get; } = -1;
public int NotAProperty = 0x6060B017;
}

[Fact]
public void ShouldThrowIfNotAMemberExpression()
{
var subject = new MappingBuilder<TestClass>();
var act = () => subject.Map(x => "something", "foo");
act.Should().Throw<ArgumentException>();
}

[Fact]
public void ShouldThrowIfNotAPropertyExpression()
{
var subject = new MappingBuilder<TestClass>();
var act = () => subject.Map(x => x.NotAProperty, "foo");
act.Should().Throw<ArgumentException>();
}

[Fact]
public void ShouldThrowIfPropertyDoesNotHaveASetter()
{
var subject = new MappingBuilder<TestClass>();
var act = () => subject.Map(x => x.NotSettable, "foo");
act.Should().Throw<ArgumentException>();
}
}
}