Skip to content

Commit e5fb853

Browse files
committed
Merge branch 'release/2.0.0' into master
OnTopic Data Transfer 2.0.0 is a major release primarily focused on support for OnTopic 5.0.0's new topic references feature. It includes changes to the JSON serialization format—though it also maintains backward compatibility with the legacy format. New Features - Full integration of OnTopic 5.0.0's new topic references feature, including support for `BaseTopic` and merging topic references based on `LastModified` (2cfbc52, d0cb983). - The `Import()` now tracks any associations that it is not able to resolve and attempts to resolve them after the initial `Import()` has completed, thus accounting for associations to topics that weren't yet imported because they occur later in the interchange data (4a75ff6). This prevents the need for calling `Import()` twice to ensure that there aren't any unresolved associations. - Configured `SourceLink` with references to GitHub commits so that packages can be properly debugged by implementers (8e1a5cc). - The NuGet packages now include the XML documentation, thus allowing implementers to benefit from IntelliSense annotations in Visual Studio (cbc66d4). - Added icon to NuGet packages to make them easier to recognize, and consistently branded (d65a81a). Breaking Changes The following changes impact the interchange format, but maintain backward compatibility for derserializing legacy JSON files. - Marked `DerivedTopicKey` as deprecated, and no longer write it during `Export()` (4705b29, 6c33fb8). - Renamed `AttributeData` to `RecordData` and `AttributeDataCollection` to `RecordDataCollection` to maintain parity with the `TrackedRecord(Collection)` in OnTopic, and to provide base support for both attributes as well as topic references (a5df9b1). - Renamed `RelationshipData` to `KeyValuesPair` and `RelationshipDataCollection` to `MultiMap` to maintain parity with the `KeyValuesPair<T>` and `TopicRelationshipMultiMap` in OnTopic (bc15631). The JSON now writes to `Relationships: [{ …, Values: […]}]` instead of `Relationships: [{ …, Relationships: […]}]`. Code Improvements - Updated to OnTopic 5.0.0, with accommodations for breaking changes, such as the rename of `Topic.DerivedTopic` to `BaseTopic` and `Topic.Relationships.SetTopic()` to `SetValue()` (2f75a73). - Updated to `System.Json.Text` 5.0.0, which allows us to take advantage of .NET 5 annotations, such as `[JsonInclude]` and `[JsonIgnore()]`, while maintaining compatibility with .NET Core 3.x (439b41c). - Implemented the latest version of Microsoft's code analysis library (`NetAnalyzers`), as well as the feedback it exposed, including nullable reference annotations (7fa983c). For full release notes, see #1.
2 parents 574624f + 2ca4d96 commit e5fb853

25 files changed

+1158
-415
lines changed

Directory.Build.props

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Project>
2+
3+
<PropertyGroup>
4+
<LangVersion>9.0</LangVersion>
5+
<Nullable>enable</Nullable>
6+
<AnalysisLevel>latest</AnalysisLevel>
7+
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
8+
</PropertyGroup>
9+
10+
<PropertyGroup>
11+
<Company>Ignia</Company>
12+
<Product>OnTopic</Product>
13+
<Copyright>©2021 Ignia, LLC</Copyright>
14+
<Authors>Ignia</Authors>
15+
<PackageProjectUrl>https://github.com/Ignia/Topics-Library</PackageProjectUrl>
16+
<UseFullSemVerForNuGet>true</UseFullSemVerForNuGet>
17+
<NeutralLanguage>en</NeutralLanguage>
18+
<IncludeSymbols>true</IncludeSymbols>
19+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
20+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
21+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
22+
<PackageIcon>Icon.png</PackageIcon>
23+
</PropertyGroup>
24+
25+
<ItemGroup>
26+
<None Include="../Icon.png" Pack="true" PackagePath=""/>
27+
</ItemGroup>
28+
29+
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
30+
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
31+
</PropertyGroup>
32+
33+
</Project>

Icon.png

5.33 KB
Loading

OnTopic.Data.Transfer.Tests/DeserializationTest.cs

+137-52
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Linq;
88
using System.Text.Json;
99
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
using OnTopic.Data.Transfer.Converters;
1011

1112
namespace OnTopic.Data.Transfer.Tests {
1213

@@ -38,77 +39,146 @@ public void Deserialize_TopicData_ReturnsExpectedResults() {
3839
$"\"Key\":\"{sourceData.Key}\"," +
3940
$"\"UniqueKey\":\"{sourceData.UniqueKey}\"," +
4041
$"\"ContentType\":\"{sourceData.ContentType}\"," +
41-
$"\"DerivedTopicKey\":null," +
4242
$"\"Attributes\":[]," +
4343
$"\"Relationships\":[]," +
4444
$"\"Children\":[]" +
4545
$"}}";
4646

4747
var topicData = JsonSerializer.Deserialize<TopicData>(json);
4848

49-
Assert.AreEqual<string>(sourceData.Key, topicData.Key);
50-
Assert.AreEqual<string>(sourceData.UniqueKey, topicData.UniqueKey);
51-
Assert.AreEqual<string>(sourceData.ContentType, topicData.ContentType);
52-
Assert.AreEqual<string>(sourceData.DerivedTopicKey, topicData.DerivedTopicKey);
53-
Assert.AreEqual<int>(0, topicData.Relationships.Count);
54-
Assert.AreEqual<int>(0, topicData.Attributes.Count);
55-
Assert.AreEqual<int>(0, topicData.Children.Count);
49+
Assert.AreEqual<string?>(sourceData.Key, topicData?.Key);
50+
Assert.AreEqual<string?>(sourceData.UniqueKey, topicData?.UniqueKey);
51+
Assert.AreEqual<string?>(sourceData.ContentType, topicData?.ContentType);
52+
Assert.AreEqual<int?>(0, topicData?.Relationships.Count);
53+
Assert.AreEqual<int?>(0, topicData?.Attributes.Count);
54+
Assert.AreEqual<int?>(0, topicData?.Children.Count);
55+
56+
}
57+
58+
/*==========================================================================================================================
59+
| TEST: DESERIALIZE: DERIVED TOPIC KEY: RETURNS EXPECTED RESULTS
60+
\-------------------------------------------------------------------------------------------------------------------------*/
61+
/// <summary>
62+
/// Creates a json string with a legacy <c>DerivedTopicKey</c> and attempts to deserialize it as a <see cref="TopicData"/>
63+
/// class.
64+
/// </summary>
65+
[TestMethod]
66+
#pragma warning disable CS0618 // Type or member is obsolete
67+
public void Deserialize_DerivedTopicKey_ReturnsExpectedResults() {
68+
69+
var sourceData = new TopicData() {
70+
Key = "Test",
71+
UniqueKey = "Root:Test",
72+
ContentType = "Container",
73+
DerivedTopicKey = "Root:Meta:Test"
74+
};
75+
76+
var json = $"{{" +
77+
$"\"Key\":\"{sourceData.Key}\"," +
78+
$"\"UniqueKey\":\"{sourceData.UniqueKey}\"," +
79+
$"\"ContentType\":\"{sourceData.ContentType}\"," +
80+
$"\"DerivedTopicKey\":\"{sourceData.DerivedTopicKey}\"," +
81+
$"\"Attributes\":[]," +
82+
$"\"Relationships\":[]," +
83+
$"\"Children\":[]" +
84+
$"}}";
85+
86+
var topicData = JsonSerializer.Deserialize<TopicData>(json);
87+
88+
Assert.AreEqual<string?>(sourceData.Key, topicData?.Key);
89+
Assert.AreEqual<string?>(sourceData.UniqueKey, topicData?.UniqueKey);
90+
Assert.AreEqual<string?>(sourceData.ContentType, topicData?.ContentType);
91+
Assert.AreEqual<string?>(sourceData.DerivedTopicKey, topicData?.DerivedTopicKey);
92+
Assert.AreEqual<int?>(0, topicData?.Relationships.Count);
93+
Assert.AreEqual<int?>(0, topicData?.Attributes.Count);
94+
Assert.AreEqual<int?>(0, topicData?.Children.Count);
95+
96+
}
97+
#pragma warning restore CS0618 // Type or member is obsolete
98+
99+
/*==========================================================================================================================
100+
| TEST: DESERIALIZE: KEY/VALUES PAIR: RETURNS EXPECTED RESULTS
101+
\-------------------------------------------------------------------------------------------------------------------------*/
102+
/// <summary>
103+
/// Creates a JSON string and attempts to deserialize it as a <see cref="KeyValuesPair"/> class.
104+
/// </summary>
105+
[TestMethod]
106+
public void Deserialize_KeyValuesPair_ReturnsExpectedResults() {
107+
108+
var sourceData = new KeyValuesPair() {
109+
Key = "Test"
110+
};
111+
sourceData.Values.Add("Root:Web");
112+
113+
var json = $"{{" +
114+
$"\"Key\":\"{sourceData.Key}\"," +
115+
$"\"Values\":[\"Root:Web\"]" +
116+
$"}}";
117+
118+
var keyValuesPair = JsonSerializer.Deserialize<KeyValuesPair>(json);
119+
120+
Assert.AreEqual<string?>(sourceData.Key, keyValuesPair?.Key);
121+
Assert.AreEqual<int?>(sourceData.Values.Count, keyValuesPair?.Values.Count);
122+
Assert.AreEqual<string?>(sourceData.Values.FirstOrDefault(), keyValuesPair?.Values.FirstOrDefault());
56123

57124
}
58125

59126
/*==========================================================================================================================
60127
| TEST: DESERIALIZE: RELATIONSHIP DATA: RETURNS EXPECTED RESULTS
61128
\-------------------------------------------------------------------------------------------------------------------------*/
62129
/// <summary>
63-
/// Creates a json string and attempts to deserialize it as a <see cref="RelationshipData"/> class.
130+
/// Creates a JSON string representing the legacy <c>RelationshipData</c> class (which used a <c>Relationships</c> array),
131+
/// and attempts to deserialize it as a <see cref="KeyValuesPair"/> class, ensuring that the <see cref="
132+
/// KeyValuesPairConverter"/> properly translates the <c>Relationships</c> array to the <see cref="KeyValuesPair.Values"/>
133+
/// collection.
64134
/// </summary>
65135
[TestMethod]
66136
public void Deserialize_RelationshipData_ReturnsExpectedResults() {
67137

68-
var sourceData = new RelationshipData() {
138+
var sourceData = new KeyValuesPair() {
69139
Key = "Test"
70140
};
71-
sourceData.Relationships.Add("Root:Web");
141+
sourceData.Values.Add("Root:Web");
72142

73143
var json = $"{{" +
74144
$"\"Key\":\"{sourceData.Key}\"," +
75145
$"\"Relationships\":[\"Root:Web\"]" +
76146
$"}}";
77147

78-
var relationshipData = JsonSerializer.Deserialize<RelationshipData>(json);
148+
var keyValuesPair = JsonSerializer.Deserialize<KeyValuesPair>(json);
79149

80-
Assert.AreEqual<string>(sourceData.Key, relationshipData.Key);
81-
Assert.AreEqual<int>(sourceData.Relationships.Count, relationshipData.Relationships.Count);
82-
Assert.AreEqual<string>(sourceData.Relationships.FirstOrDefault(), relationshipData.Relationships.FirstOrDefault());
150+
Assert.AreEqual<string?>(sourceData.Key, keyValuesPair?.Key);
151+
Assert.AreEqual<int?>(sourceData.Values.Count, keyValuesPair?.Values.Count);
152+
Assert.AreEqual<string?>(sourceData.Values.FirstOrDefault(), keyValuesPair?.Values.FirstOrDefault());
83153

84154
}
85155

86156
/*==========================================================================================================================
87-
| TEST: DESERIALIZE: ATTRIBUTE DATA: RETURNS EXPECTED RESULTS
157+
| TEST: DESERIALIZE: RECORD DATA: RETURNS EXPECTED RESULTS
88158
\-------------------------------------------------------------------------------------------------------------------------*/
89159
/// <summary>
90-
/// Creates a json string and attempts to deserialize it as a <see cref="AttributeData"/> class.
160+
/// Creates a json string and attempts to deserialize it as a <see cref="RecordData"/> class.
91161
/// </summary>
92162
[TestMethod]
93-
public void Deserialize_AttributeData_ReturnsExpectedResults() {
163+
public void Deserialize_RecordData_ReturnsExpectedResults() {
94164

95-
var sourceData = new AttributeData() {
165+
var sourceData = new RecordData() {
96166
Key = "Test",
97-
LastModified = DateTime.Now
167+
LastModified = new DateTime(2021, 02, 16, 16, 06, 25)
98168
};
99169

100170
var json = $"{{" +
101171
$"\"Key\":\"{sourceData.Key}\"," +
102172
$"\"Value\":null," +
103-
$"\"LastModified\":\"{sourceData.LastModified:o}\"" +
173+
$"\"LastModified\":\"{sourceData.LastModified:s}\"" +
104174
$"}}";
105175

106176

107-
var attributeData = JsonSerializer.Deserialize<AttributeData>(json);
177+
var recordData = JsonSerializer.Deserialize<RecordData>(json);
108178

109-
Assert.AreEqual<string>(sourceData.Key, attributeData.Key);
110-
Assert.AreEqual<string>(sourceData.Value, attributeData.Value);
111-
Assert.AreEqual<DateTime>(sourceData.LastModified, attributeData.LastModified);
179+
Assert.AreEqual<string?>(sourceData.Key, recordData?.Key);
180+
Assert.AreEqual<string?>(sourceData.Value, recordData?.Value);
181+
Assert.AreEqual<DateTime?>(sourceData.LastModified, recordData?.LastModified);
112182

113183
}
114184

@@ -121,25 +191,32 @@ public void Deserialize_AttributeData_ReturnsExpectedResults() {
121191
[TestMethod]
122192
public void Deserialize_TopicGraph_ReturnsExpectedResults() {
123193

194+
var lastModified = new DateTime(2021, 02, 16, 16, 06, 25);
195+
124196
var sourceTopicData = new TopicData() {
125197
Key = "Test",
126198
UniqueKey = "Root:Test",
127199
ContentType = "Container"
128200
};
129-
var sourceRelationshipData= new RelationshipData() {
201+
var sourceRelationshipData= new KeyValuesPair() {
130202
Key = "Test"
131203
};
132-
var sourceAttributeData = new AttributeData() {
204+
var sourceAttributeData = new RecordData() {
205+
Key = "Test",
206+
LastModified = lastModified
207+
};
208+
var sourceReferenceData = new RecordData() {
133209
Key = "Test",
134-
LastModified = DateTime.Now
210+
Value = "Root:Reference",
211+
LastModified = lastModified
135212
};
136213
var sourceChildTopicData = new TopicData() {
137214
Key = "Child",
138215
UniqueKey = "Root:Test:Child",
139216
ContentType = "Container"
140217
};
141218

142-
sourceRelationshipData.Relationships.Add("Root:Web");
219+
sourceRelationshipData.Values.Add("Root:Web");
143220
sourceTopicData.Relationships.Add(sourceRelationshipData);
144221
sourceTopicData.Attributes.Add(sourceAttributeData);
145222
sourceTopicData.Children.Add(sourceChildTopicData);
@@ -148,26 +225,31 @@ public void Deserialize_TopicGraph_ReturnsExpectedResults() {
148225
$"\"Key\":\"{sourceTopicData.Key}\"," +
149226
$"\"UniqueKey\":\"{sourceTopicData.UniqueKey}\"," +
150227
$"\"ContentType\":\"{sourceTopicData.ContentType}\"," +
151-
$"\"DerivedTopicKey\":null," +
152228
$"\"Attributes\":[" +
153229
$"{{" +
154230
$"\"Key\":\"{sourceAttributeData.Key}\"," +
155231
$"\"Value\":null," +
156-
$"\"LastModified\":\"{sourceAttributeData.LastModified:o}\"" +
232+
$"\"LastModified\":\"{sourceAttributeData.LastModified:s}\"" +
157233
$"}}"+
158234
$"]," +
159235
$"\"Relationships\":[" +
160236
$"{{" +
161237
$"\"Key\":\"{sourceRelationshipData.Key}\"," +
162-
$"\"Relationships\":[\"Root:Web\"]" +
238+
$"\"Values\":[\"Root:Web\"]" +
163239
$"}}" +
164240
$"]," +
241+
$"\"References\":[" +
242+
$"{{" +
243+
$"\"Key\":\"{sourceReferenceData.Key}\"," +
244+
$"\"Value\":\"{sourceReferenceData.Value}\"," +
245+
$"\"LastModified\":\"{sourceReferenceData.LastModified:s}\"" +
246+
$"}}"+
247+
$"]," +
165248
$"\"Children\":[" +
166249
$"{{" +
167250
$"\"Key\":\"{sourceChildTopicData.Key}\"," +
168251
$"\"UniqueKey\":\"{sourceChildTopicData.UniqueKey}\"," +
169252
$"\"ContentType\":\"{sourceChildTopicData.ContentType}\"," +
170-
$"\"DerivedTopicKey\":null," +
171253
$"\"Attributes\":[]," +
172254
$"\"Relationships\":[]," +
173255
$"\"Children\":[]" +
@@ -176,31 +258,34 @@ public void Deserialize_TopicGraph_ReturnsExpectedResults() {
176258
$"}}";
177259

178260

179-
var topicData = JsonSerializer.Deserialize<TopicData>(json);
180-
var relationshipData = topicData.Relationships.FirstOrDefault();
181-
var attributeData = topicData.Attributes.FirstOrDefault();
182-
var childTopicData = topicData.Children.FirstOrDefault();
183-
184-
Assert.AreEqual<string>(sourceTopicData.Key, topicData.Key);
185-
Assert.AreEqual<string>(sourceTopicData.UniqueKey, topicData.UniqueKey);
186-
Assert.AreEqual<string>(sourceTopicData.ContentType, topicData.ContentType);
187-
Assert.AreEqual<string>(sourceTopicData.DerivedTopicKey, topicData.DerivedTopicKey);
261+
var topicData = JsonSerializer.Deserialize<TopicData>(json);
262+
var relationshipData = topicData?.Relationships.FirstOrDefault();
263+
var referenceData = topicData?.References.FirstOrDefault();
264+
var attributeData = topicData?.Attributes.FirstOrDefault();
265+
var childTopicData = topicData?.Children.FirstOrDefault();
266+
267+
Assert.AreEqual<string?>(sourceTopicData.Key, topicData?.Key);
268+
Assert.AreEqual<string?>(sourceTopicData.UniqueKey, topicData?.UniqueKey);
269+
Assert.AreEqual<string?>(sourceTopicData.ContentType, topicData?.ContentType);
188270
Assert.AreEqual<int>(1, sourceTopicData.Relationships.Count);
189271
Assert.AreEqual<int>(1, sourceTopicData.Attributes.Count);
190272
Assert.AreEqual<int>(1, sourceTopicData.Children.Count);
191273

192-
Assert.AreEqual<string>(sourceRelationshipData.Key, relationshipData.Key);
193-
Assert.AreEqual<int?>(sourceRelationshipData.Relationships.Count, relationshipData.Relationships.Count);
194-
Assert.AreEqual<string>(sourceRelationshipData.Relationships.FirstOrDefault(), relationshipData.Relationships.FirstOrDefault());
274+
Assert.AreEqual<string?>(sourceRelationshipData.Key, relationshipData?.Key);
275+
Assert.AreEqual<int?>(sourceRelationshipData.Values.Count, relationshipData?.Values.Count);
276+
Assert.AreEqual<string?>(sourceRelationshipData.Values.FirstOrDefault(), relationshipData?.Values.FirstOrDefault());
277+
278+
Assert.AreEqual<string?>(sourceReferenceData.Key, referenceData?.Key);
279+
Assert.AreEqual<string?>(sourceReferenceData.Value, referenceData?.Value);
280+
Assert.AreEqual<DateTime?>(sourceReferenceData.LastModified, referenceData?.LastModified);
195281

196-
Assert.AreEqual<string>(sourceAttributeData.Key, attributeData.Key);
197-
Assert.AreEqual<string>(sourceAttributeData.Value, attributeData.Value);
198-
Assert.AreEqual<DateTime>(sourceAttributeData.LastModified, attributeData.LastModified);
282+
Assert.AreEqual<string?>(sourceAttributeData.Key, attributeData?.Key);
283+
Assert.AreEqual<string?>(sourceAttributeData.Value, attributeData?.Value);
284+
Assert.AreEqual<DateTime?>(sourceAttributeData.LastModified, attributeData?.LastModified);
199285

200-
Assert.AreEqual<string>(sourceChildTopicData.Key, childTopicData.Key);
201-
Assert.AreEqual<string>(sourceChildTopicData.UniqueKey, childTopicData.UniqueKey);
202-
Assert.AreEqual<string>(sourceChildTopicData.ContentType, childTopicData.ContentType);
203-
Assert.AreEqual<string>(sourceChildTopicData.DerivedTopicKey, childTopicData.DerivedTopicKey);
286+
Assert.AreEqual<string?>(sourceChildTopicData.Key, childTopicData?.Key);
287+
Assert.AreEqual<string?>(sourceChildTopicData.UniqueKey, childTopicData?.UniqueKey);
288+
Assert.AreEqual<string?>(sourceChildTopicData.ContentType, childTopicData?.ContentType);
204289
Assert.AreEqual<int>(0, sourceChildTopicData.Relationships.Count);
205290
Assert.AreEqual<int>(0, sourceChildTopicData.Children.Count);
206291
}

0 commit comments

Comments
 (0)