Skip to content

Commit 9854066

Browse files
Mapping preview (#729)
Record to object mapping added
1 parent 7b8ef91 commit 9854066

25 files changed

+2230
-15
lines changed

Neo4j.Driver/.editorconfig

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,11 @@ dotnet_naming_symbols.types_and_namespaces_symbols.applicable_kinds = namespace,
369369
dotnet_naming_symbols.type_parameters_symbols.applicable_accessibilities = *
370370
dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter
371371
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *
372-
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
372+
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
373373
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field
374374
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance
375375
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_accessibilities = *
376-
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
376+
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
377377
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_applicable_kinds = unity_serialised_field
378378
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_required_modifiers = instance
379379
dotnet_separate_import_directive_groups = false
@@ -663,8 +663,8 @@ resharper_line_break_before_requires_clause = do_not_change
663663
resharper_linkage_specification_braces = end_of_line
664664
resharper_linkage_specification_indentation = none
665665
resharper_local_function_body = block_body
666-
resharper_macro_block_begin =
667-
resharper_macro_block_end =
666+
resharper_macro_block_begin =
667+
resharper_macro_block_end =
668668
resharper_max_array_initializer_elements_on_line = 10000
669669
resharper_max_attribute_length_for_same_line = 38
670670
resharper_max_enum_members_on_line = 1
@@ -698,7 +698,7 @@ resharper_parentheses_non_obvious_operations = none, shift, bitwise_and, bitwise
698698
resharper_parentheses_redundancy_style = remove_if_not_clarifies_precedence
699699
resharper_parentheses_same_type_operations = false
700700
resharper_pi_attributes_indent = align_by_first_attribute
701-
resharper_place_accessorholder_attribute_on_same_line = if_owner_is_single_line
701+
resharper_place_accessorholder_attribute_on_same_line = false
702702
resharper_place_accessor_attribute_on_same_line = if_owner_is_single_line
703703
resharper_place_comments_at_first_column = false
704704
resharper_place_constructor_initializer_on_same_line = true
@@ -734,7 +734,7 @@ resharper_resx_attribute_indent = single_indent
734734
resharper_resx_blank_line_after_pi = true
735735
resharper_resx_indent_text = OneIndent
736736
resharper_resx_keep_user_linebreaks = true
737-
resharper_resx_linebreak_before_elements =
737+
resharper_resx_linebreak_before_elements =
738738
resharper_resx_max_blank_lines_between_tags = 0
739739
resharper_resx_pi_attribute_style = do_not_touch
740740
resharper_resx_space_before_self_closing = false
@@ -963,7 +963,7 @@ resharper_xml_attribute_indent = align_by_first_attribute
963963
resharper_xml_blank_line_after_pi = true
964964
resharper_xml_indent_text = OneIndent
965965
resharper_xml_keep_user_linebreaks = true
966-
resharper_xml_linebreak_before_elements =
966+
resharper_xml_linebreak_before_elements =
967967
resharper_xml_max_blank_lines_between_tags = 2
968968
resharper_xml_pi_attribute_style = do_not_touch
969969
resharper_xml_space_before_self_closing = true

Neo4j.Driver/Neo4j.Driver.Tests/.editorconfig

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[*]
1+
[*]
22
charset = utf-8-bom
33
end_of_line = crlf
44
indent_size = 4
@@ -369,11 +369,11 @@ dotnet_naming_symbols.types_and_namespaces_symbols.applicable_kinds = namespace,
369369
dotnet_naming_symbols.type_parameters_symbols.applicable_accessibilities = *
370370
dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter
371371
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *
372-
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
372+
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
373373
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field
374374
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance
375375
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_accessibilities = *
376-
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
376+
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
377377
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_applicable_kinds = unity_serialised_field
378378
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_required_modifiers = instance
379379
dotnet_separate_import_directive_groups = false
@@ -663,8 +663,8 @@ resharper_line_break_before_requires_clause = do_not_change
663663
resharper_linkage_specification_braces = end_of_line
664664
resharper_linkage_specification_indentation = none
665665
resharper_local_function_body = block_body
666-
resharper_macro_block_begin =
667-
resharper_macro_block_end =
666+
resharper_macro_block_begin =
667+
resharper_macro_block_end =
668668
resharper_max_array_initializer_elements_on_line = 10000
669669
resharper_max_attribute_length_for_same_line = 38
670670
resharper_max_enum_members_on_line = 1
@@ -698,7 +698,7 @@ resharper_parentheses_non_obvious_operations = none, shift, bitwise_and, bitwise
698698
resharper_parentheses_redundancy_style = remove_if_not_clarifies_precedence
699699
resharper_parentheses_same_type_operations = false
700700
resharper_pi_attributes_indent = align_by_first_attribute
701-
resharper_place_accessorholder_attribute_on_same_line = if_owner_is_single_line
701+
resharper_place_accessorholder_attribute_on_same_line = false
702702
resharper_place_accessor_attribute_on_same_line = if_owner_is_single_line
703703
resharper_place_comments_at_first_column = false
704704
resharper_place_constructor_initializer_on_same_line = true
@@ -734,7 +734,7 @@ resharper_resx_attribute_indent = single_indent
734734
resharper_resx_blank_line_after_pi = true
735735
resharper_resx_indent_text = OneIndent
736736
resharper_resx_keep_user_linebreaks = true
737-
resharper_resx_linebreak_before_elements =
737+
resharper_resx_linebreak_before_elements =
738738
resharper_resx_max_blank_lines_between_tags = 0
739739
resharper_resx_pi_attribute_style = do_not_touch
740740
resharper_resx_space_before_self_closing = false
@@ -963,7 +963,7 @@ resharper_xml_attribute_indent = align_by_first_attribute
963963
resharper_xml_blank_line_after_pi = true
964964
resharper_xml_indent_text = OneIndent
965965
resharper_xml_keep_user_linebreaks = true
966-
resharper_xml_linebreak_before_elements =
966+
resharper_xml_linebreak_before_elements =
967967
resharper_xml_max_blank_lines_between_tags = 2
968968
resharper_xml_pi_attribute_style = do_not_touch
969969
resharper_xml_space_before_self_closing = true
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) "Neo4j"
2+
// Neo4j Sweden AB [http://neo4j.com]
3+
//
4+
// This file is part of Neo4j.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License").
7+
// You may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
using System.Collections.Generic;
19+
using FluentAssertions;
20+
using Neo4j.Driver.Preview.Mapping;
21+
using Xunit;
22+
using Record = Neo4j.Driver.Internal.Result.Record;
23+
24+
namespace Neo4j.Driver.Tests.Mapping
25+
{
26+
public class DictAsRecordTests
27+
{
28+
[Fact]
29+
public void ShouldReturnCorrectValues()
30+
{
31+
var originalRecord = new Record(new[] {"name", "age"}, new object[] {"Bob", 42});
32+
var dict = new Dictionary<string, object>
33+
{
34+
{"key1", "value1"},
35+
{"key2", "value2"}
36+
};
37+
38+
var subject = new DictAsRecord(dict, originalRecord);
39+
40+
subject.Record.Should().BeSameAs(originalRecord);
41+
subject.Keys.Should().BeEquivalentTo(dict.Keys);
42+
subject.Values.Should().BeEquivalentTo(dict);
43+
subject[0].Should().Be("value1");
44+
subject[1].Should().Be("value2");
45+
subject["key1"].Should().Be("value1");
46+
subject["key2"].Should().Be("value2");
47+
}
48+
}
49+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright (c) "Neo4j"
2+
// Neo4j Sweden AB [http://neo4j.com]
3+
//
4+
// This file is part of Neo4j.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License").
7+
// You may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
using System.Collections.Generic;
19+
using System.Linq;
20+
using FluentAssertions;
21+
using Neo4j.Driver.Internal.Types;
22+
using Neo4j.Driver.Preview.Mapping;
23+
using Xunit;
24+
using Record = Neo4j.Driver.Internal.Result.Record;
25+
26+
namespace Neo4j.Driver.Tests.Mapping
27+
{
28+
public class LabelCaptureTests
29+
{
30+
public class TestMappedClass
31+
{
32+
[MappingSource("Person", EntityMappingSource.NodeLabel)]
33+
public string Label { get; set; }
34+
35+
[MappingSource("Person", EntityMappingSource.NodeLabel)]
36+
public List<string> Labels { get; set; }
37+
38+
[MappingSource("Relationship", EntityMappingSource.RelationshipType)]
39+
public string RelationshipType { get; set; }
40+
}
41+
42+
public LabelCaptureTests()
43+
{
44+
RecordObjectMapping.Reset();
45+
}
46+
47+
[Fact]
48+
public void ShouldCaptureSingleNodeLabel()
49+
{
50+
var node = new Node(1, new[] { "Test" }, new Dictionary<string, object>());
51+
var record = new Record(new[] { "Person" }, new object[] { node });
52+
53+
var mapped = record.AsObject<TestMappedClass>();
54+
55+
mapped.Label.Should().Be("Test");
56+
}
57+
58+
[Fact]
59+
public void ShouldCaptureMultipleNodeLabelsIntoString()
60+
{
61+
var node = new Node(1, new[] { "Alpha", "Bravo", "Charlie" }, new Dictionary<string, object>());
62+
var record = new Record(new[] { "Person" }, new object[] { node });
63+
64+
var mapped = record.AsObject<TestMappedClass>();
65+
66+
mapped.Label.Should().Be("Alpha,Bravo,Charlie");
67+
}
68+
69+
[Fact]
70+
public void ShouldCaptureRelationshipType()
71+
{
72+
var node = new Relationship(1, 2, 3, "ACTED_IN", new Dictionary<string, object>());
73+
var record = new Record(new[] { "Relationship" }, new object[] { node });
74+
75+
var mapped = record.AsObject<TestMappedClass>();
76+
77+
mapped.RelationshipType.Should().Be("ACTED_IN");
78+
}
79+
80+
class CustomMapper : IMappingProvider
81+
{
82+
/// <inheritdoc />
83+
public void CreateMappers(IMappingRegistry registry)
84+
{
85+
registry.RegisterMapping<TestMappedClass>(
86+
b => b
87+
.Map(
88+
x => x.Label,
89+
"Person",
90+
EntityMappingSource.NodeLabel,
91+
x => string.Join("|", ((string[])x).Select(y => y.ToUpper())))
92+
.Map(
93+
x => x.Labels,
94+
"Person",
95+
EntityMappingSource.NodeLabel,
96+
x => ((string[])x).Select(y => y.Replace("a", "x")).ToList())
97+
.Map(
98+
x => x.RelationshipType,
99+
"Relationship",
100+
EntityMappingSource.RelationshipType,
101+
x => x?.ToString()?.ToLower()));
102+
}
103+
}
104+
105+
[Fact]
106+
public void ShouldCaptureAndConvertLabels()
107+
{
108+
RecordObjectMapping.RegisterProvider<CustomMapper>();
109+
var node = new Node(1, new[] { "Alpha", "Bravo", "Charlie" }, new Dictionary<string, object>());
110+
var record = new Record(new[] { "Person" }, new object[] { node });
111+
112+
var mapped = record.AsObject<TestMappedClass>();
113+
114+
mapped.Label.Should().Be("ALPHA|BRAVO|CHARLIE");
115+
mapped.Labels.Should().BeEquivalentTo(new[] { "Alphx", "Brxvo", "Chxrlie" });
116+
}
117+
118+
[Fact]
119+
public void ShouldCaptureAndConvertRelationshipType()
120+
{
121+
RecordObjectMapping.RegisterProvider<CustomMapper>();
122+
var node = new Relationship(1, 2, 3, "ACTED_IN", new Dictionary<string, object>());
123+
var record = new Record(new[] { "Relationship" }, new object[] { node });
124+
125+
var mapped = record.AsObject<TestMappedClass>();
126+
127+
mapped.RelationshipType.Should().Be("acted_in");
128+
}
129+
}
130+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) "Neo4j"
2+
// Neo4j Sweden AB [http://neo4j.com]
3+
//
4+
// This file is part of Neo4j.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License").
7+
// You may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
using System;
19+
using FluentAssertions;
20+
using Neo4j.Driver.Preview.Mapping;
21+
using Xunit;
22+
23+
namespace Neo4j.Driver.Tests.Mapping
24+
{
25+
public class MappingBuilderTests
26+
{
27+
private class TestClass
28+
{
29+
public int Settable { get; set; }
30+
public int NotSettable { get; } = -1;
31+
public int NotAProperty = 0x6060B017;
32+
}
33+
34+
[Fact]
35+
public void ShouldThrowIfNotAMemberExpression()
36+
{
37+
var subject = new MappingBuilder<TestClass>();
38+
var act = () => subject.Map(x => "something", "foo");
39+
act.Should().Throw<ArgumentException>();
40+
}
41+
42+
[Fact]
43+
public void ShouldThrowIfNotAPropertyExpression()
44+
{
45+
var subject = new MappingBuilder<TestClass>();
46+
var act = () => subject.Map(x => x.NotAProperty, "foo");
47+
act.Should().Throw<ArgumentException>();
48+
}
49+
50+
[Fact]
51+
public void ShouldThrowIfPropertyDoesNotHaveASetter()
52+
{
53+
var subject = new MappingBuilder<TestClass>();
54+
var act = () => subject.Map(x => x.NotSettable, "foo");
55+
act.Should().Throw<ArgumentException>();
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)