-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from digirati-co-uk/feature/imageapi_ensure_co…
…ntext Move EnsureContext method to own class + add imageApi to known list
- Loading branch information
Showing
4 changed files
with
222 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace IIIF.Tests; | ||
|
||
public class ContextHelperTests | ||
{ | ||
[Fact] | ||
public void EnsureContext_AddsContext_IfNoExisting() | ||
{ | ||
// Arrange | ||
var jsonLdBase = new TestJsonLdBase(); | ||
const string customContext = "http://my-custom-context"; | ||
|
||
// Act | ||
jsonLdBase.EnsureContext(customContext); | ||
|
||
// Assert | ||
jsonLdBase.Context.Should().BeOfType<string>() | ||
.And.Subject.Should().Be(customContext); | ||
} | ||
|
||
[Fact] | ||
public void EnsureContext_AddsContext_IfOneExisting_WithoutReordering() | ||
{ | ||
// Arrange | ||
const string context = "http://existing-context"; | ||
const string customContext = "http://my-custom-context"; | ||
var jsonLdBase = new TestJsonLdBase { Context = context }; | ||
|
||
var expected = new List<string> { context, customContext }; | ||
|
||
// Act | ||
jsonLdBase.EnsureContext(customContext); | ||
|
||
// Assert | ||
(jsonLdBase.Context as List<string>).Should().ContainInOrder(expected); | ||
} | ||
|
||
[Theory] | ||
[InlineData(IIIF.Presentation.Context.Presentation2Context)] | ||
[InlineData(IIIF.Presentation.Context.Presentation3Context)] | ||
[InlineData(IIIF.ImageApi.V2.ImageService2.Image2Context)] | ||
[InlineData(IIIF.ImageApi.V3.ImageService3.Image3Context)] | ||
[InlineData("http://my-custom-context")] | ||
public void EnsureContext_NoOp_IfContextAlreadyExistsAsSingle(string context) | ||
{ | ||
// Arrange | ||
var jsonLdBase = new TestJsonLdBase { Context = context }; | ||
|
||
// Act | ||
jsonLdBase.EnsureContext(context); | ||
|
||
// Assert | ||
jsonLdBase.Context.Should().BeOfType<string>() | ||
.And.Subject.Should().Be(context); | ||
} | ||
|
||
[Theory] | ||
[InlineData(IIIF.Presentation.Context.Presentation2Context)] | ||
[InlineData(IIIF.Presentation.Context.Presentation3Context)] | ||
[InlineData(IIIF.ImageApi.V2.ImageService2.Image2Context)] | ||
[InlineData(IIIF.ImageApi.V3.ImageService3.Image3Context)] | ||
[InlineData("http://my-custom-context")] | ||
public void EnsureContext_NoOp_IfContextAlreadyExistsInList(string context) | ||
{ | ||
// Arrange | ||
const string customContext = "http://existing-context"; | ||
var jsonLdBase = new TestJsonLdBase { Context = customContext }; | ||
jsonLdBase.EnsureContext(context); | ||
|
||
var expected = new List<string> { customContext, context }; | ||
|
||
// Act | ||
jsonLdBase.EnsureContext(customContext); | ||
|
||
// Assert | ||
(jsonLdBase.Context as List<string>).Should().ContainInOrder(expected); | ||
} | ||
|
||
[Theory] | ||
[InlineData(IIIF.Presentation.Context.Presentation2Context)] | ||
[InlineData(IIIF.Presentation.Context.Presentation3Context)] | ||
[InlineData(IIIF.ImageApi.V2.ImageService2.Image2Context)] | ||
[InlineData(IIIF.ImageApi.V3.ImageService3.Image3Context)] | ||
public void EnsureContext_AlwaysReordersIIIFContextsToLast_IfOthersAddedAfter(string iiifContext) | ||
{ | ||
// Arrange | ||
const string customContext = "http://my-custom-context"; | ||
var jsonLdBase = new TestJsonLdBase { Context = iiifContext }; | ||
|
||
var expected = new List<string> { customContext, iiifContext }; | ||
|
||
// Act | ||
jsonLdBase.EnsureContext(customContext); | ||
|
||
// Assert | ||
(jsonLdBase.Context as List<string>).Should().ContainInOrder(expected); | ||
} | ||
|
||
[Theory] | ||
[InlineData(IIIF.Presentation.Context.Presentation2Context)] | ||
[InlineData(IIIF.Presentation.Context.Presentation3Context)] | ||
[InlineData(IIIF.ImageApi.V2.ImageService2.Image2Context)] | ||
[InlineData(IIIF.ImageApi.V3.ImageService3.Image3Context)] | ||
public void EnsureContext_AlwaysReordersIIIFContextsToLast_IfMultipleAdds(string iiifContext) | ||
{ | ||
// Arrange | ||
const string context = "http://existing-context"; | ||
const string customContext = "http://my-custom-context"; | ||
var jsonLdBase = new TestJsonLdBase { Context = context }; | ||
|
||
var expected = new List<string> { context, customContext, iiifContext }; | ||
|
||
// Act | ||
jsonLdBase.EnsureContext(iiifContext); | ||
jsonLdBase.EnsureContext(customContext); | ||
|
||
// Assert | ||
(jsonLdBase.Context as List<string>).Should().ContainInOrder(expected); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(SampleContexts))] | ||
public void EnsureContext_Throws_IfMultipleIIIFContextsAdded(string first, string second) | ||
{ | ||
// Arrange | ||
var jsonLdBase = new TestJsonLdBase { Context = first }; | ||
|
||
// Act | ||
Action action = () => jsonLdBase.EnsureContext(second); | ||
|
||
// Assert | ||
action.Should().Throw<InvalidOperationException>(); | ||
} | ||
|
||
public static IEnumerable<object[]> SampleContexts => | ||
new List<object[]> | ||
{ | ||
new object[] { IIIF.Presentation.Context.Presentation2Context, IIIF.Presentation.Context.Presentation3Context }, | ||
new object[] { IIIF.ImageApi.V2.ImageService2.Image2Context, IIIF.ImageApi.V3.ImageService3.Image3Context }, | ||
new object[] { IIIF.Presentation.Context.Presentation2Context, IIIF.ImageApi.V3.ImageService3.Image3Context }, | ||
new object[] { IIIF.ImageApi.V3.ImageService3.Image3Context , IIIF.Presentation.Context.Presentation3Context }, | ||
}; | ||
|
||
private class TestJsonLdBase : JsonLdBase | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
global using FluentAssertions; | ||
global using Xunit; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace IIIF; | ||
|
||
public static class ContextHelper | ||
{ | ||
// This is a list of known IIIF contexts that must be last in Contexts list | ||
// Only 1 can be present in any given Context list | ||
private static List<string> knownContexts = new() | ||
{ | ||
Presentation.Context.Presentation2Context, | ||
Presentation.Context.Presentation3Context, | ||
ImageApi.V2.ImageService2.Image2Context, | ||
ImageApi.V3.ImageService3.Image3Context, | ||
}; | ||
|
||
/// <summary> | ||
/// Adds specified Context to list. | ||
/// The IIIF context must be last in the list, to override any that come before it. | ||
/// </summary> | ||
public static void EnsureContext(this JsonLdBase resource, string contextToEnsure) | ||
{ | ||
if (resource.Context == null) | ||
{ | ||
resource.Context = contextToEnsure; | ||
return; | ||
} | ||
|
||
var workingContexts = GetWorkingContexts(resource); | ||
if (workingContexts.Contains(contextToEnsure)) | ||
{ | ||
// Context already added - no-op | ||
SetContext(resource, workingContexts); | ||
return; | ||
} | ||
workingContexts.Add(contextToEnsure); | ||
|
||
if (workingContexts.Intersect(knownContexts).Count() > 1) | ||
{ | ||
throw new InvalidOperationException( | ||
"You cannot have multiple IIIF contexts (Presentation or Image) in the same resource."); | ||
} | ||
|
||
var iiifContext = workingContexts.FirstOrDefault(wc => knownContexts.Contains(wc)); | ||
|
||
// If we have an IIIF context it must be last in list | ||
if (!string.IsNullOrEmpty(iiifContext) && workingContexts.Count > 1) | ||
{ | ||
workingContexts.Remove(iiifContext); | ||
workingContexts.Add(iiifContext); | ||
} | ||
|
||
// Now JSON-LD rules. The @context is the only Presentation 3 element that has this. | ||
SetContext(resource, workingContexts); | ||
} | ||
|
||
private static void SetContext(JsonLdBase resource, IReadOnlyList<string> workingContexts) | ||
=> resource.Context = workingContexts.Count == 1 ? workingContexts[0] : workingContexts; | ||
|
||
private static List<string> GetWorkingContexts(JsonLdBase resource) | ||
{ | ||
if (resource.Context is List<string> existingContexts) return existingContexts; | ||
|
||
if (resource.Context is string singleContext) return new List<string> { singleContext }; | ||
|
||
return new List<string>(1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters