Skip to content

Commit 37d7a82

Browse files
committed
Translate UniqueKey to TopicID in attributes on Import()
Some types of attributes—such as `TokenizedTopicList`, `TopicList`, and `TopicReference`—create pointers to other topics. These can be stored in a variety of formats, including topic key, unique key, or topic ID. If the latter, that can introduce problems when exporting the data, as those IDs won't be maintained when importing them into a new database. To mitigate this, these are translated from `TopicID` to `UniqueKey` on `Export()` (0993ea3). To complement this, I've introduced a new `GetTopicID()` helper function and corresponding `getAttributeValue()` local function into the `Import()` extension method. If an attribute ends with `ID`, begins with `Root`, and maps to a topic with the same `UniqueKey` in the topic graph, then the value is replaced with the topic's `Id` on import. There's a _very_ minor risk of false positives during this process, and we'd need to come up with pretty contrived scenarios where that would occur (e.g., an attribute with the key `Kid` and value `Root` would have the value replaced with the `TopicID` of the root topic). The far greater risk remains in the `Export()` scenario (as discussed in 0993ea3).
1 parent 0993ea3 commit 37d7a82

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

OnTopic.Data.Transfer.Tests/TopicExtensionsTest.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,5 +583,46 @@ public void Import_TopicDataWithChild_SkipsOrphanedChild() {
583583

584584
}
585585

586+
/*==========================================================================================================================
587+
| TEST: IMPORT: TOPIC DATA WITH TOPIC POINTER: MAPS TOPIC ID
588+
\-------------------------------------------------------------------------------------------------------------------------*/
589+
/// <summary>
590+
/// Creates a <see cref="TopicData"/> with an arbitrary <see cref="AttributeData"/> that points to another topic. Confirms
591+
/// that it is converted to a <c>TopicID</c> if valid, and otherwise left as is.
592+
/// </summary>
593+
[TestMethod]
594+
public void Import_TopicDataWithTopicPointer_MapsTopicID() {
595+
596+
var rootTopic = TopicFactory.Create("Root", "Container");
597+
var topic = TopicFactory.Create("Topic", "Container", rootTopic);
598+
var siblingTopic = TopicFactory.Create("SiblingTopic", "Container", 5, rootTopic);
599+
600+
var topicData = new TopicData() {
601+
Key = topic.Key,
602+
UniqueKey = topic.GetUniqueKey(),
603+
ContentType = topic.ContentType
604+
};
605+
606+
topicData.Attributes.Add(
607+
new AttributeData() {
608+
Key = "SomeId",
609+
Value = siblingTopic.GetUniqueKey()
610+
}
611+
);
612+
613+
topicData.Attributes.Add(
614+
new AttributeData() {
615+
Key = "InitialBid",
616+
Value = "6"
617+
}
618+
);
619+
620+
topic.Import(topicData);
621+
622+
Assert.AreEqual<string>("5", topic.Attributes.GetValue("SomeId"));
623+
Assert.AreEqual<string>("6", topic.Attributes.GetValue("InitialBid"));
624+
625+
}
626+
586627
} //Class
587628
} //Namespace

OnTopic.Data.Transfer/Interchange/TopicExtensions.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ public static void Import(this Topic topic, TopicData topicData, [NotNull]Import
212212
if (matchedAttribute?.LastModified >= attribute.LastModified && isStrategy(ImportStrategy.Merge)) continue;
213213
topic.Attributes.SetValue(
214214
attribute.Key,
215-
attribute.Value
215+
getAttributeValue(attribute)
216216
);
217217
}
218218

@@ -305,6 +305,16 @@ bool useCustomMergeRules(AttributeData attribute) =>
305305
(attribute.Key == "LastModified" && !options!.LastModifiedStrategy.Equals(LastModifiedImportStrategy.Inherit)) ||
306306
(attribute.Key == "LastModifiedBy" && !options!.LastModifiedByStrategy.Equals(LastModifiedImportStrategy.Inherit));
307307

308+
/*------------------------------------------------------------------------------------------------------------------------
309+
| Get attribute value
310+
\-----------------------------------------------------------------------------------------------------------------------*/
311+
string? getAttributeValue(AttributeData attribute) =>
312+
attribute.Key.EndsWith("ID", StringComparison.InvariantCultureIgnoreCase)?
313+
GetTopicId(topic, attribute.Value) :
314+
attribute.Value;
315+
316+
}
317+
308318
/*==========================================================================================================================
309319
| GET UNIQUE KEY
310320
\-------------------------------------------------------------------------------------------------------------------------*/
@@ -322,6 +332,20 @@ bool useCustomMergeRules(AttributeData attribute) =>
322332
return uniqueKey;
323333
}
324334

335+
/*==========================================================================================================================
336+
| GET TOPIC ID
337+
\-------------------------------------------------------------------------------------------------------------------------*/
338+
/// <summary>
339+
/// Given a <c>UniqueKey</c>, lookup the topic in the topic graph and return the <c>TopicID</c>. If no value can be
340+
/// found, the original <c>UniqueKey</c> is returned.
341+
/// </summary>
342+
/// <param name="topic">The source <see cref="Topic"/> to operate off of.</param>
343+
/// <param name="uniqueKey">The <see cref="Topic.GetUniqueKey"/> to retrieve the <see cref="Topic.Id"/> for.</param>
344+
private static string? GetTopicId(Topic topic, string? uniqueKey) {
345+
if (!String.IsNullOrEmpty(uniqueKey) && uniqueKey!.StartsWith("Root", StringComparison.InvariantCultureIgnoreCase)) {
346+
return topic.GetByUniqueKey(uniqueKey)?.Id.ToString(CultureInfo.CurrentCulture)?? uniqueKey;
347+
}
348+
return uniqueKey;
325349
}
326350

327351
} //Class

0 commit comments

Comments
 (0)