Skip to content

Commit 562945c

Browse files
committed
Introduced optional excludeLastModified parameter for GetAttributes()
In a previous feature, we introduced the ability to optionally exclude the byline (`LastModifiedBy`) and dateline (`LastModified`) as part of a `Save()` operation if no other attributes had been modified. This was supported by a new `AttributeValueCollection.IsDirty(excludeLastModified)`. As an extension of this, it's now an optional `excludeLastModified` parameter off of `GetAttributes()`. This allows the caller to specify whether or not `GetAttributes()` should exclude `LastModified*` attributes or not. This makes it easier to conditionally exclude these based e.g. on the result of `IsDirty()`. This is relevant to the `bugfix/extended-attributes-mismatch` branch because `IsDirty()` isn't able to detect `IsExtendedAttributeMismatch()`, which requires a reference to the `AttributeDescriptor`, and is therefore much more expensive to evaluate. As such, we can't just wrap the indexed attributes in a call to `IsDirty()` to determine as a shorthand for excluding the byline and dateline. Instead, we need to still process these—in case they include any `IsExtendedAttributeMismatch()`s—while having an easy way to exclude the byline and dateline. The `excludeLastModified` parameter allows for this. This includes a unit test to validate the functionality, as well as an extension to the `GetAttributesProxy()` class on `StubTopicRepository`. Finally, it requires updating (and potentially repaginating) some XMLDoc references to the `GetAttributes()`, mostly in `TopicRepositoryBaseTest`.
1 parent a3d4798 commit 562945c

3 files changed

Lines changed: 48 additions & 11 deletions

File tree

OnTopic.TestDoubles/StubTopicRepository.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,12 @@ public override void Move(Topic topic, Topic target, Topic? sibling) {
168168
| METHOD: GET ATTRIBUTES (PROXY)
169169
\-------------------------------------------------------------------------------------------------------------------------*/
170170
/// <inheritdoc cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?)" />
171-
public IEnumerable<AttributeValue> GetAttributesProxy(Topic topic, bool? isExtendedAttribute, bool? isDirty = null) =>
172-
base.GetAttributes(topic, isExtendedAttribute, isDirty);
171+
public IEnumerable<AttributeValue> GetAttributesProxy(
172+
Topic topic,
173+
bool? isExtendedAttribute,
174+
bool? isDirty = null,
175+
bool excludeLastModified = false
176+
) => base.GetAttributes(topic, isExtendedAttribute, isDirty, excludeLastModified);
173177

174178
/*==========================================================================================================================
175179
| METHOD: GET UNMATCHED ATTRIBUTES (PROXY)

OnTopic.Tests/TopicRepositoryBaseTest.cs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,35 @@ public void GetAttributes_ExtendedAttributeMismatch_ReturnsNothing() {
174174

175175
}
176176

177+
/*==========================================================================================================================
178+
| TEST: GET ATTRIBUTES: EXCLUDE LAST MODIFIED: RETURNS OTHER ATTRIBUTES
179+
\-------------------------------------------------------------------------------------------------------------------------*/
180+
/// <summary>
181+
/// Retrieves a list of attributes from a topic, filtering by <c>excludeLastModified</c>. Confirms that <see
182+
/// cref="AttributeValue"/>s are not returned which start with <c>LastModified</c>.
183+
/// </summary>
184+
[TestMethod]
185+
public void GetAttributes_ExcludeLastModified_ReturnsOtherAttributes() {
186+
187+
var topic = TopicFactory.Create("Test", "ContentTypes");
188+
189+
topic.Attributes.SetDateTime("LastModified", DateTime.Now);
190+
topic.Attributes.SetValue("LastModifiedBy", "Unit Tests");
191+
192+
var attributes = _topicRepository.GetAttributesProxy(topic, null, excludeLastModified: true);
193+
194+
//Expected to return Key and ContentType, butnot LastModified or LastModifiedBy
195+
Assert.AreEqual<int>(2, attributes.Count());
196+
197+
}
198+
177199
/*==========================================================================================================================
178200
| TEST: GET ATTRIBUTES: ARBITRARY ATTRIBUTE WITH SHORT VALUE: RETURNS AS INDEXED ATTRIBUTE
179201
\-------------------------------------------------------------------------------------------------------------------------*/
180202
/// <summary>
181203
/// Sets an arbitrary (unmatched) attribute on a <see cref="Topic"/> with a value shorter than 255 characters, then
182204
/// ensures that it is returned as an an <i>indexed</i> <see cref="AttributeValue"/> when calling <see
183-
/// cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?)"/>.
205+
/// cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?, Boolean)"/>.
184206
/// </summary>
185207
[TestMethod]
186208
public void GetAttributes_ArbitraryAttributeWithShortValue_ReturnsAsIndexedAttributes() {
@@ -201,7 +223,7 @@ public void GetAttributes_ArbitraryAttributeWithShortValue_ReturnsAsIndexedAttri
201223
/// <summary>
202224
/// Sets an arbitrary (unmatched) attribute on a <see cref="Topic"/> with a value longer than 255 characters, then
203225
/// ensures that it is returned as an an <see cref="AttributeDescriptor.IsExtendedAttribute"/> when calling <see
204-
/// cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?)"/>.
226+
/// cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?, Boolean)"/>.
205227
/// </summary>
206228
[TestMethod]
207229
public void GetAttributes_ArbitraryAttributeWithLongValue_ReturnsAsExtendedAttributes() {
@@ -342,7 +364,7 @@ public void GetContentTypeDescriptor_GetInvalidContentType_ReturnsNull() {
342364
| TEST: SAVE: CONTENT TYPE DESCRIPTOR: UPDATES CONTENT TYPE CACHE
343365
\-------------------------------------------------------------------------------------------------------------------------*/
344366
/// <summary>
345-
/// Loads the <see cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?)"/>, then saves a new <see
367+
/// Loads the <see cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?, Boolean)"/>, then saves a new <see
346368
/// cref="ContentTypeDescriptor"/> via <see cref="TopicRepositoryBase.Save(Topic, Boolean, Boolean)"/>, and ensures that
347369
/// it is immediately reflected in the <see cref="TopicRepositoryBase"/> cache of <see cref="ContentTypeDescriptor"/>s.
348370
/// </summary>
@@ -362,9 +384,9 @@ public void Save_ContentTypeDescriptor_UpdatesContentTypeCache() {
362384
| TEST: DELETE: CONTENT TYPE DESCRIPTOR: UPDATES CONTENT TYPE CACHE
363385
\-------------------------------------------------------------------------------------------------------------------------*/
364386
/// <summary>
365-
/// Loads the <see cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?)"/>, then deletes one of the <see
366-
/// cref="ContentTypeDescriptor"/>s via <see cref="TopicRepositoryBase.Delete(Topic, Boolean)"/>, and ensures that it is
367-
/// immediately reflected in the <see cref="TopicRepositoryBase"/> cache of <see cref="ContentTypeDescriptor"/>s.
387+
/// Loads the <see cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?, Boolean)"/>, then deletes one of the
388+
/// <see cref="ContentTypeDescriptor"/>s via <see cref="TopicRepositoryBase.Delete(Topic, Boolean)"/>, and ensures that it
389+
/// is immediately reflected in the <see cref="TopicRepositoryBase"/> cache of <see cref="ContentTypeDescriptor"/>s.
368390
/// </summary>
369391
[TestMethod]
370392
public void Delete_ContentTypeDescriptor_UpdatesContentTypeCache() {
@@ -382,8 +404,8 @@ public void Delete_ContentTypeDescriptor_UpdatesContentTypeCache() {
382404
| TEST: MOVE: CONTENT TYPE DESCRIPTOR: UPDATES CONTENT TYPE CACHE
383405
\-------------------------------------------------------------------------------------------------------------------------*/
384406
/// <summary>
385-
/// Loads the <see cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?)"/>, then moves one of the <see
386-
/// cref="ContentTypeDescriptor"/>s via <see cref="TopicRepositoryBase.Move(Topic, Topic)"/>, and ensures that it is
407+
/// Loads the <see cref="TopicRepositoryBase.GetAttributes(Topic, Boolean?, Boolean?, Boolean)"/>, then moves one of the
408+
/// <see cref="ContentTypeDescriptor"/>s via <see cref="TopicRepositoryBase.Move(Topic, Topic)"/>, and ensures that it is
387409
/// immediately reflected in the <see cref="TopicRepositoryBase"/> cache of <see cref="ContentTypeDescriptor"/>s.
388410
/// </summary>
389411
[TestMethod]

OnTopic/Repositories/TopicRepositoryBase.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,13 @@ public virtual void Delete([ValidatedNotNull, NotNull]Topic topic, bool isRecurs
493493
/// Whether or not to filter by <see cref="AttributeValue.IsDirty"/>. If <c>null</c>, all <see cref="AttributeValue"/>s
494494
/// are returned.
495495
/// </param>
496-
protected IEnumerable<AttributeValue> GetAttributes(Topic topic, bool? isExtendedAttribute, bool? isDirty = null) {
496+
/// <param name="excludeLastModified">Exclude any attributes that start with <c>LastModified</c>.</param>
497+
protected IEnumerable<AttributeValue> GetAttributes(
498+
Topic topic,
499+
bool? isExtendedAttribute,
500+
bool? isDirty = null,
501+
bool excludeLastModified = false
502+
) {
497503

498504
/*------------------------------------------------------------------------------------------------------------------------
499505
| Validate input
@@ -520,6 +526,11 @@ protected IEnumerable<AttributeValue> GetAttributes(Topic topic, bool? isExtende
520526
var key = attributeValue.Key;
521527
var attribute = (AttributeDescriptor?)null;
522528

529+
//Optionally exclude LastModified attributes
530+
if (excludeLastModified && attributeValue.Key.StartsWith("LastModified", StringComparison.InvariantCultureIgnoreCase)) {
531+
continue;
532+
}
533+
523534
//Reset cached attribute descriptors just in case a new attribute has been added
524535
if (!contentType.AttributeDescriptors.Contains(key)) {
525536
contentType.ResetAttributeDescriptors();

0 commit comments

Comments
 (0)