Skip to content

Commit

Permalink
Add ExternalService for unknown Service elements
Browse files Browse the repository at this point in the history
  • Loading branch information
donaldgray committed Nov 18, 2024
1 parent 2d0bef3 commit 0bb9967
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 42 deletions.
20 changes: 20 additions & 0 deletions src/IIIF/IIIF.Tests/Serialisation/ManifestSerialisationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,28 @@ public void CanDeserialiseSerialisedManifest()

var deserialised = serialisedManifest.FromJson<Manifest>();

var xx = deserialised.AsJson();

deserialised.Should().BeEquivalentTo(sampleManifest);
}

[Fact]
public void CanDeserialiseUnknownServices()
{
var serialisedManifest = "{\"@context\": [\"http://iiif.io/api/presentation/3/context.json\"],\"id\": \"https://iiif.example/12345\",\"type\": \"Manifest\",\"services\": [{\"id\": \"https://iiif.example.org/1234#tracking\",\"type\": \"Text\",\"profile\": \"http://universalviewer.io/tracking-extensions-profile\",\"label\": {\"en\": [\"Format: Monograph, Institution: n/a, foobarbaz\"]}}]}";
var expectedServices = new List<ExternalService>
{
new ExternalService("Text")
{
Id = "https://iiif.example.org/1234#tracking",
Profile = "http://universalviewer.io/tracking-extensions-profile",
Label = new LanguageMap("en", "Format: Monograph, Institution: n/a, foobarbaz"),
}
};

var deserialised = serialisedManifest.FromJson<Manifest>();
deserialised.Services.Should().BeEquivalentTo(expectedServices);
}

[Fact]
public void CanDeserialiseSerialisedManifest_Stream()
Expand Down
10 changes: 10 additions & 0 deletions src/IIIF/IIIF/Presentation/V2/ExternalService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace IIIF.Presentation.V2;

/// <summary>
/// Represents a generic, unknown <see cref="IService"/> reference
/// </summary>
public class ExternalService : ResourceBase, IService
{
[JsonProperty(PropertyName = "@type", Order = 3)]
public override string? Type { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Newtonsoft.Json;

namespace IIIF.Presentation.V3.Annotation;
namespace IIIF.Presentation.V3.Annotation;

public class PaintingAnnotation : Annotation
{
Expand Down
14 changes: 14 additions & 0 deletions src/IIIF/IIIF/Presentation/V3/ExternalService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace IIIF.Presentation.V3;

/// <summary>
/// Represents a generic, unknown <see cref="IService"/> reference
/// </summary>
public class ExternalService : ResourceBase, IService
{
public override string Type { get; }

public ExternalService(string type)
{
Type = type;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using IIIF.Auth.V2;
using IIIF.Presentation.V3.Content;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace IIIF.Serialisation.Deserialisation;
Expand Down
81 changes: 44 additions & 37 deletions src/IIIF/IIIF/Serialisation/Deserialisation/ServiceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ServiceConverter : ReadOnlyConverter<IService>
{
IService? service = null;
var atType = jsonObject["@type"];
var type = jsonObject["type"];
if (atType != null)
service = atType.Value<string>() switch
{
Expand All @@ -34,53 +35,59 @@ public class ServiceConverter : ReadOnlyConverter<IService>
"AuthTokenService1" => new Auth.V1.AuthTokenService(),
"AutoCompleteService1" => new Search.V1.AutoCompleteService(),
nameof(ImageService2) => new ImageService2(),
_ => null
_ => null,
};
if (service != null) return service;

if (service == null)
{
var type = jsonObject["type"];
if (type != null)
service = type.Value<string>() switch
{
nameof(ImageService3) => new ImageService3(),
nameof(AuthAccessService2) => new AuthAccessService2(),
nameof(AuthAccessTokenService2) => new AuthAccessTokenService2(),
nameof(AuthLogoutService2) => new AuthLogoutService2(),
nameof(AuthProbeService2) => new AuthProbeService2(),
_ => null
};
}

if (service == null)
{
var profile = jsonObject["profile"].Value<string>();
service = profile switch
if (type != null)
service = type.Value<string>() switch
{
Auth.V1.AuthLogoutService.AuthLogout1Profile => new Auth.V1.AuthLogoutService(),
Auth.V1.AuthTokenService.AuthToken1Profile => new Auth.V1.AuthTokenService(),
Auth.V0.AuthLogoutService.AuthLogout0Profile => new Auth.V0.AuthLogoutService(),
Auth.V0.AuthTokenService.AuthToken0Profile => new Auth.V0.AuthTokenService(),
Search.V2.AutoCompleteService.AutoComplete2Profile => new Search.V2.AutoCompleteService(),
Search.V1.AutoCompleteService.AutoCompleteService1Profile => new Search.V1.AutoCompleteService(),
Search.V2.SearchService.Search2Profile => new Search.V2.SearchService(),
nameof(ImageService3) => new ImageService3(),
nameof(AuthAccessService2) => new AuthAccessService2(),
nameof(AuthAccessTokenService2) => new AuthAccessTokenService2(),
nameof(AuthLogoutService2) => new AuthLogoutService2(),
nameof(AuthProbeService2) => new AuthProbeService2(),
_ => null
};
if (service != null) return service;

if (service == null)
{
const string auth0 = "http://iiif.io/api/auth/0/";
const string auth1 = "http://iiif.io/api/auth/1/";

if (profile.StartsWith(auth0))
service = new Auth.V0.AuthCookieService(profile);
else if (profile.StartsWith(auth1)) service = new Auth.V1.AuthCookieService(profile);
}
}
var profile = jsonObject["profile"].Value<string>();
service = profile switch
{
Auth.V1.AuthLogoutService.AuthLogout1Profile => new Auth.V1.AuthLogoutService(),
Auth.V1.AuthTokenService.AuthToken1Profile => new Auth.V1.AuthTokenService(),
Auth.V0.AuthLogoutService.AuthLogout0Profile => new Auth.V0.AuthLogoutService(),
Auth.V0.AuthTokenService.AuthToken0Profile => new Auth.V0.AuthTokenService(),
Search.V2.AutoCompleteService.AutoComplete2Profile => new Search.V2.AutoCompleteService(),
Search.V1.AutoCompleteService.AutoCompleteService1Profile => new Search.V1.AutoCompleteService(),
Search.V2.SearchService.Search2Profile => new Search.V2.SearchService(),
_ => null
};
if (service != null) return service;


const string auth0 = "http://iiif.io/api/auth/0/";
const string auth1 = "http://iiif.io/api/auth/1/";

if (profile.StartsWith(auth0)) return new Auth.V0.AuthCookieService(profile);
if (profile.StartsWith(auth1)) return new Auth.V1.AuthCookieService(profile);

// TODO handle ResourceBase items

if (service == null) service = new V2ServiceReference();
if (atType != null)
{
// if there's @id and @type only, service reference
if (jsonObject.Count == 2 && jsonObject["@id"] != null)
return new V2ServiceReference();
else
return new Presentation.V2.ExternalService();
}

if (type != null)
{
return new Presentation.V3.ExternalService(type.Value<string>());
}

return service;
}
Expand Down

0 comments on commit 0bb9967

Please sign in to comment.