diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/ContextList.java b/src/main/java/info/freelibrary/iiif/presentation/v3/ContextList.java index 1d916bba..8457e5b5 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/ContextList.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/ContextList.java @@ -1,8 +1,6 @@ package info.freelibrary.iiif.presentation.v3; -import static info.freelibrary.util.Constants.SINGLE_INSTANCE; - import java.io.Serializable; import java.net.URI; import java.util.ArrayList; @@ -10,7 +8,6 @@ import java.util.Collection; import java.util.Comparator; import java.util.List; -import java.util.NoSuchElementException; import java.util.function.Predicate; import java.util.function.UnaryOperator; @@ -62,16 +59,15 @@ public ContextList(final List aUriList) { super.addAll(aUriList); if (!super.contains(PRESENTATION_CONTEXT_URI)) { - super.add(0, PRESENTATION_CONTEXT_URI); + super.add(PRESENTATION_CONTEXT_URI); } else { super.sort(myComparator); } } /** - * Adds a new context URI at the supplied index position. If the supplied context is not the IIIF Presentation - * context and the supplied index position is zero, it will be added at position one instead. Only the default - * context lives at position zero. + * Adds a new context URI at the supplied index position. The IIIF Presentation context URI cannot be added, because + * it exists in the list already. * * @param aIndex An index position at which to add the supplied URI * @param aURI A URI to add at the supplied index position @@ -79,12 +75,9 @@ public ContextList(final List aUriList) { @Override public void add(final int aIndex, final URI aURI) { if (!PRESENTATION_CONTEXT_URI.equals(aURI)) { - if (aIndex == 0) { - super.add(1, aURI); - LOGGER.warn(MessageCodes.JPA_150, aURI); - } else { - super.add(aIndex, aURI); - } + super.add(aIndex, aURI); + } else { + LOGGER.warn(MessageCodes.JPA_150); } } @@ -129,31 +122,29 @@ public boolean addAll(final int aIndex, final Collection aCollect } /** - * If the supplied URI is not the default IIIF Presentation context, it is added at index position one. The first - * index position (i.e., zero) is reserved for the default IIIF Presentation context. + * Adds a new context to the list. * * @param aURI A context URI to add at the beginning of the list + * @throws UnsupportedOperationException If the default IIIF Presentation context URI was passed */ - @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) + @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) // JDK 21, but releasing with 17 public void addFirst(final URI aURI) { - if (!PRESENTATION_CONTEXT_URI.equals(aURI)) { - super.add(1, aURI); - } // Ignore if passing the default URI, because that already lives at index position zero + if (PRESENTATION_CONTEXT_URI.equals(aURI)) { + throw new UnsupportedOperationException(LOGGER.getMessage(MessageCodes.JPA_150)); + } + + super.add(0, aURI); } /** - * Adds the supplied context URI as the last in the list, unless the supplied context is the default IIIF - * Presentation context (in which case it's ignored -- the list already contains the default context). + * Unsupported operation. The last context URI is hard-coded. * * @param aURI A context URI to add at the end of the list + * @throws UnsupportedOperationException because the last context URI cannot be changed */ - @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) + @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) // JDK 21, but releasing with 17 public void addLast(final URI aURI) { - if (!PRESENTATION_CONTEXT_URI.equals(aURI)) { - super.add(aURI); // Adding, by default, adds as the last item - } else { - LOGGER.warn(MessageCodes.JPA_149); - } + throw new UnsupportedOperationException(LOGGER.getMessage(MessageCodes.JPA_150)); } /** @@ -162,7 +153,7 @@ public void addLast(final URI aURI) { @Override public void clear() { super.clear(); - super.add(0, PRESENTATION_CONTEXT_URI); + super.add(PRESENTATION_CONTEXT_URI); } @Override @@ -193,10 +184,11 @@ public int hashCode() { * * @param aIndex The index position of the URI to remove from the list * @return The URI removed from the list + * @throws IndexOutOfBoundsException If trying to remove the last context URI (which is required) */ @Override public URI remove(final int aIndex) { - if (aIndex == 0) { + if (aIndex == size() - 1) { throw new IndexOutOfBoundsException(LOGGER.getMessage(MessageCodes.JPA_039, PRESENTATION_CONTEXT_URI)); } @@ -234,32 +226,27 @@ public boolean removeAll(final Collection aCollection) { * @param aFilter A filter to use to remove URIs from the list * @return True if the URIs were removed */ - @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) + @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) // JDK 21, but releasing with 17 public boolean removeIf(final Predicate aFilter) { final boolean result = super.removeIf(aFilter); // If the filter removes our required default context, we add it back - if (!PRESENTATION_CONTEXT_URI.equals(get(0))) { - super.add(0, PRESENTATION_CONTEXT_URI); + if (!PRESENTATION_CONTEXT_URI.equals(get(size() - 1))) { + super.add(PRESENTATION_CONTEXT_URI); } return result; } /** - * Removes the last context URI, unless the last URI is the default context. In that case, a - * {@link NoSuchElementException} is thrown. + * Unsupported operation. The last context URI (the URI for the IIIF Presentation context) cannot be removed. * * @return The context URI that was removed - * @throws NoSuchElementException If the list only has the required IIIF Presentation context + * @throws UnsupportedOperationException because the last context URI cannot be removed */ - @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) + @SuppressWarnings({ PMD.MISSING_OVERRIDE, Sonar.OVERRIDE_REQUIRED }) // JDK 21, but releasing with 17 public URI removeLast() { - if (size() == SINGLE_INSTANCE) { - throw new NoSuchElementException(LOGGER.getMessage(MessageCodes.JPA_039, PRESENTATION_CONTEXT_URI)); - } - - return remove(size() - 1); + throw new UnsupportedOperationException(LOGGER.getMessage(MessageCodes.JPA_039, PRESENTATION_CONTEXT_URI)); } /** @@ -275,14 +262,12 @@ public void replaceAll(final UnaryOperator anOperator) { super.removeAll(List.of(PRESENTATION_CONTEXT_URI)); // Add back a single instance of our default context URI - if (!PRESENTATION_CONTEXT_URI.equals(get(0))) { - super.add(0, PRESENTATION_CONTEXT_URI); - } + super.add(PRESENTATION_CONTEXT_URI); } /** - * Retains the contexts in the supplied collection and the default context (if it's also not included in the - * supplied collection). + * Retains the contexts in the supplied collection and the default context (regardless of whether or not it exists + * in the supplied collection). * * @param aCollection A collection of URIs to retain, removing the rest * @return Whether the URIs were successfully retained @@ -292,8 +277,8 @@ public boolean retainAll(final Collection aCollection) { final boolean result = super.retainAll(aCollection); // If we haven't added retained the required context, we add it back - if (!PRESENTATION_CONTEXT_URI.equals(get(0))) { - super.add(0, PRESENTATION_CONTEXT_URI); + if (!PRESENTATION_CONTEXT_URI.equals(get(size() - 1))) { + super.add(PRESENTATION_CONTEXT_URI); } return result; @@ -306,21 +291,25 @@ public boolean retainAll(final Collection aCollection) { * @param aIndex An index position of the URI to set * @param aURI A URI to set at the supplied index position * @return The context URI that used to be at the supplied index position + * @throws IndexOutOfBoundsException If an invalid index position is used */ @Override public URI set(final int aIndex, final URI aURI) { - if (PRESENTATION_CONTEXT_URI.equals(aURI)) { - if (aIndex != 0) { - throw new IndexOutOfBoundsException(LOGGER.getMessage(MessageCodes.JPA_149)); + if (!PRESENTATION_CONTEXT_URI.equals(aURI)) { + if (aIndex != size() - 1) { + return super.set(aIndex, aURI); } - return aURI; + throw new IndexOutOfBoundsException(LOGGER.getMessage(MessageCodes.JPA_149)); } - if (aIndex != 0) { - return super.set(aIndex, aURI); + + // We're trying to set the default IIIF Presentation context URI at the wrong index? It's supplied by default. + if (aIndex != size() - 1) { + throw new IndexOutOfBoundsException(LOGGER.getMessage(MessageCodes.JPA_150)); } - throw new IndexOutOfBoundsException(LOGGER.getMessage(MessageCodes.JPA_151, aURI)); + // We're setting the IIIF Presentation in the index position where it already lives + return PRESENTATION_CONTEXT_URI; } /** @@ -350,9 +339,9 @@ public int compare(final URI aFirstURI, final URI aSecondURI) { if (!PRESENTATION_CONTEXT_URI.equals(aFirstURI) || !PRESENTATION_CONTEXT_URI.equals(aSecondURI)) { if (PRESENTATION_CONTEXT_URI.equals(aFirstURI)) { - result = -1; - } else if (PRESENTATION_CONTEXT_URI.equals(aSecondURI)) { result = 1; + } else if (PRESENTATION_CONTEXT_URI.equals(aSecondURI)) { + result = -1; } } diff --git a/src/main/resources/iiif_presentation_messages.xml b/src/main/resources/iiif_presentation_messages.xml index 68fbc439..716b58a7 100644 --- a/src/main/resources/iiif_presentation_messages.xml +++ b/src/main/resources/iiif_presentation_messages.xml @@ -119,8 +119,7 @@ {} is not a valid navPlace type A physical dimensions service must contain scale and units Supplied Optional was unexpectedly empty - The IIIF Presentation context URI can only exist as the first context in the list - Context '{}' was added at list position 1 because 0 is reserved for the default context - The '{}' context cannot be set as the first context; this position is reserved for the default - IIIF Presentation context + The last URI (i.e., the IIIF Presentation context) cannot be overwritten by another URI + The default context URI cannot be set or added; it exists in the ContextList by default + diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/ContextListTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/ContextListTest.java index a8b7153c..c25e626b 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/ContextListTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/ContextListTest.java @@ -7,16 +7,12 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.List; -import java.util.NoSuchElementException; import java.util.function.Predicate; import java.util.function.UnaryOperator; @@ -42,7 +38,7 @@ public class ContextListTest extends AbstractTest { ContextList.PRESENTATION_CONTEXT_URI); /** - * Test method for {@link ContextList#addAll(Collection)}. + * Tests {@link ContextList#addAll(Collection)}. */ @Test public final void testAddAllCollectionOfQextendsURI() { @@ -54,7 +50,7 @@ public final void testAddAllCollectionOfQextendsURI() { } /** - * Test method for {@link ContextList#addAll(int, Collection)}. + * Tests {@link ContextList#addAll(int, Collection)}. */ @Test public final void testAddAllCollectionWithDefaultURI() { @@ -67,7 +63,7 @@ public final void testAddAllCollectionWithDefaultURI() { } /** - * Test method for {@link ContextList#addAll(int, Collection)}. + * Tests {@link ContextList#addAll(int, Collection)}. */ @Test public final void testAddAllCollectionWithoutDefaultURI() { @@ -80,7 +76,7 @@ public final void testAddAllCollectionWithoutDefaultURI() { } /** - * Test method for {@link ContextList#addAll(int, Collection)}. + * Tests {@link ContextList#addAll(int, Collection)}. */ @Test public final void testAddAllIntCollectionOfQextendsURI() { @@ -97,7 +93,7 @@ public final void testAddAllIntCollectionOfQextendsURI() { } /** - * Test method for {@link ContextList#add(URI)}. + * Tests {@link ContextList#add(URI)}. */ @Test public final void testAddFalse() { @@ -108,35 +104,27 @@ public final void testAddFalse() { } /** - * Test method for {@link ContextList#addFirst(URI)}. + * Tests {@link ContextList#addFirst(URI)}. */ @Test - public final void testAddFirstDefaultURI() { - final ContextList contexts = new ContextList(); + public final void testAddFirst() { + final ContextList list = new ContextList(); + final URI uri = URI.create(getURL()); - assertEquals(1, contexts.size()); - contexts.addFirst(ContextList.PRESENTATION_CONTEXT_URI); - assertEquals(1, contexts.size()); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); + list.addFirst(uri); + assertEquals(uri, list.get(0)); } /** - * Test method for {@link ContextList#addFirst(URI)}. + * Tests {@link ContextList#addFirst(URI)}. */ - @Test - public final void testAddFirstURI() { - final ContextList contexts = new ContextList(); - final URI uri = URI.create(getURL()); - - assertEquals(1, contexts.size()); - contexts.addFirst(uri); - assertEquals(2, contexts.size()); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); - assertEquals(uri, contexts.get(1)); + @Test(expected = UnsupportedOperationException.class) + public final void testAddFirstDefaultURI() { + new ContextList().addFirst(PRESENTATION_CONTEXT_URI); } /** - * Test method for {@link ContextList#add(int, URI)}. + * Tests {@link ContextList#add(int, URI)}. */ @Test public final void testAddIntURI() { @@ -147,11 +135,10 @@ public final void testAddIntURI() { contexts.add(1, uri); assertEquals(2, contexts.size()); assertEquals(uri, contexts.get(1)); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); } /** - * Test method for {@link ContextList#add(int, URI)}. + * Tests {@link ContextList#add(int, URI)}. */ @Test public final void testAddIntUriZeroIndex() { @@ -161,49 +148,19 @@ public final void testAddIntUriZeroIndex() { assertEquals(1, contexts.size()); contexts.add(0, uri); assertEquals(2, contexts.size()); - assertEquals(uri, contexts.get(1)); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); + assertEquals(uri, contexts.get(0)); } /** - * Test method for {@link ContextList#addLast(URI)}. + * Tests {@link ContextList#addLast(URI)}. */ - @Test - public final void testAddLastDefaultURI() { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final PrintStream current = new PrintStream(out, true, StandardCharsets.UTF_8); - final PrintStream previous = System.out; - final ContextList contexts = new ContextList(); - - System.setOut(current); - - assertEquals(1, contexts.size()); - contexts.addLast(ContextList.PRESENTATION_CONTEXT_URI); - assertEquals(1, contexts.size()); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); - - System.setOut(previous); - - assertTrue(out.toString().contains(LOGGER.getMessage(MessageCodes.JPA_149))); - } - - /** - * Test method for {@link ContextList#addLast(URI)}. - */ - @Test - public final void testAddLastURI() { - final ContextList contexts = new ContextList(); - final URI uri = URI.create(getURL()); - - assertEquals(1, contexts.size()); - contexts.addLast(uri); - assertEquals(2, contexts.size()); - assertEquals(uri, contexts.get(1)); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); + @Test(expected = UnsupportedOperationException.class) + public final void testAddLast() { + new ContextList().addLast(PRESENTATION_CONTEXT_URI); } /** - * Test method for {@link ContextList#add(int, URI)}. + * Tests {@link ContextList#add(int, URI)}. */ @Test public final void testAddPresURI() { @@ -216,7 +173,7 @@ public final void testAddPresURI() { } /** - * Test method for {@link ContextList#add(URI)}. + * Tests {@link ContextList#add(URI)}. */ @Test public final void testAddURI() { @@ -231,7 +188,7 @@ public final void testAddURI() { } /** - * Test method for {@link ContextList#clear()}. + * Tests {@link ContextList#clear()}. */ @Test public final void testClear() { @@ -243,7 +200,7 @@ public final void testClear() { } /** - * Test method for {@link ContextList#ContextList()}. + * Tests {@link ContextList#ContextList()}. */ @Test public final void testContextList() { @@ -254,18 +211,7 @@ public final void testContextList() { } /** - * Test method for {@link ContextList#ContextList(List)}. - */ - @Test - public final void testContextListListOfURI() { - final ContextList contexts = new ContextList(myContexts); - - assertEquals(12, contexts.size()); - assertEquals(ContextList.PRESENTATION_CONTEXT_URI, contexts.get(0)); - } - - /** - * Test method for {@link ContextList#equals(Object)}. + * Tests {@link ContextList#equals(Object)}. */ @Test public final void testEqualsNull() { @@ -273,7 +219,7 @@ public final void testEqualsNull() { } /** - * Test method for {@link ContextList#equals(Object)}. + * Tests {@link ContextList#equals(Object)}. */ @Test public final void testEqualsObject() { @@ -284,7 +230,7 @@ public final void testEqualsObject() { } /** - * Test method for {@link ContextList#equals(Object)}. + * Tests {@link ContextList#equals(Object)}. */ @Test public final void testEqualsString() { @@ -292,7 +238,7 @@ public final void testEqualsString() { } /** - * Test method for {@link ContextList#hashCode()}. + * Tests {@link ContextList#hashCode()}. */ @Test public final void testHashCode() { @@ -303,14 +249,14 @@ public final void testHashCode() { } /** - * Test method for {@link ContextList#removeAll(Collection)}. + * Tests {@link ContextList#removeAll(Collection)}. */ @Test public final void testRemoveAllCollectionOfQ() { final ContextList contexts = new ContextList(myContexts); - final URI uri1 = contexts.get(5); - final URI uri2 = contexts.get(8); - final URI uri3 = contexts.get(11); + final URI uri1 = contexts.get(3); + final URI uri2 = contexts.get(5); + final URI uri3 = contexts.get(7); final List list = List.of(uri1, uri2, uri3); assertEquals(12, contexts.size()); @@ -319,7 +265,7 @@ public final void testRemoveAllCollectionOfQ() { } /** - * Test method for {@link ContextList#remove(Object)}. + * Tests {@link ContextList#remove(Object)}. */ @Test public final void testRemoveDefContextObject() { @@ -327,7 +273,7 @@ public final void testRemoveDefContextObject() { } /** - * Test method for {@link ContextList#removeIf(Predicate)}. + * Tests {@link ContextList#removeIf(Predicate)}. */ @Test public final void testRemoveIfPredicateOfQsuperURI() { @@ -340,7 +286,7 @@ public final void testRemoveIfPredicateOfQsuperURI() { } /** - * Test method for {@link ContextList#removeIf(Predicate)}. + * Tests {@link ContextList#removeIf(Predicate)}. */ @Test public final void testRemoveIfPredicateOfQsuperUriNoDefault() { @@ -352,7 +298,7 @@ public final void testRemoveIfPredicateOfQsuperUriNoDefault() { } /** - * Test method for {@link ContextList#remove(int)}. + * Tests {@link ContextList#remove(int)}. */ @Test public final void testRemoveInt() { @@ -367,28 +313,23 @@ public final void testRemoveInt() { } /** - * Test method for {@link ContextList#removeLast()}. + * Tests {@link ContextList#remove(int)}. */ - @Test - public final void testRemoveLast() { - final ContextList contexts = new ContextList(myContexts); - final URI uri = contexts.get(contexts.size() - 1); - - assertTrue(contexts.contains(uri)); - contexts.removeLast(); - assertFalse(contexts.contains(uri)); + @Test(expected = IndexOutOfBoundsException.class) + public final void testRemoveIntException() { + new ContextList().remove(0); } /** - * Test method for {@link ContextList#removeLast()}. + * Tests {@link ContextList#removeLast()}. */ - @Test(expected = NoSuchElementException.class) - public final void testRemoveLastWhenEmpty() { - new ContextList().removeLast(); + @Test(expected = UnsupportedOperationException.class) + public final void testRemoveLast() { + new ContextList(myContexts).removeLast(); } /** - * Test method for {@link ContextList#remove(Object)}. + * Tests {@link ContextList#remove(Object)}. */ @Test public final void testRemoveObject() { @@ -401,15 +342,7 @@ public final void testRemoveObject() { } /** - * Test method for {@link ContextList#remove(int)}. - */ - @Test(expected = IndexOutOfBoundsException.class) - public final void testRemoveZeroIndex() { - new ContextList().remove(0); - } - - /** - * Test method for {@link ContextList#replaceAll(UnaryOperator)}. + * Tests {@link ContextList#replaceAll(UnaryOperator)}. */ @Test public final void testReplaceAllUnaryOperatorOfURI() { @@ -423,7 +356,7 @@ public final void testReplaceAllUnaryOperatorOfURI() { } /** - * Test method for {@link ContextList#retainAll(Collection)}. + * Tests {@link ContextList#retainAll(Collection)}. */ @Test public final void testRetainAllCollectionOfQ() { @@ -437,7 +370,7 @@ public final void testRetainAllCollectionOfQ() { } /** - * Test method for {@link ContextList#set(int, URI)}. + * Tests {@link ContextList#set(int, URI)}. */ @Test public final void testSetIntURI() { @@ -450,31 +383,33 @@ public final void testSetIntURI() { } /** - * Test method for {@link ContextList#set(int, URI)}. + * Tests {@link ContextList#set(int, URI)}. */ @Test(expected = IndexOutOfBoundsException.class) - public final void testSetIntURIException() { - new ContextList(myContexts).set(1, PRESENTATION_CONTEXT_URI); + public final void testSetIntUriException() { + new ContextList(myContexts).set(5, PRESENTATION_CONTEXT_URI); } /** - * Test method for {@link ContextList#set(int, URI)}. + * Tests {@link ContextList#set(int, URI)}. */ @Test(expected = IndexOutOfBoundsException.class) - public final void testSetIntURIException2() { - new ContextList(myContexts).set(0, URI.create(getURL())); + public final void testSetIntURIException() { + final ContextList list = new ContextList(myContexts); + list.set(list.size() - 1, URI.create(getURL())); } /** - * Test method for {@link ContextList#set(int, URI)}. + * Tests {@link ContextList#set(int, URI)}. */ @Test - public final void testSetIntUriStatusQuo() { - assertEquals(PRESENTATION_CONTEXT_URI, new ContextList(myContexts).set(0, PRESENTATION_CONTEXT_URI)); + public final void testSetIntUriWithDefaultUri() { + final ContextList list = new ContextList(myContexts); + assertEquals(PRESENTATION_CONTEXT_URI, list.set(list.size() - 1, PRESENTATION_CONTEXT_URI)); } /** - * Test method for {@link ContextList#sort(Comparator)}. + * Tests {@link ContextList#sort(Comparator)}. */ @Test(expected = UnsupportedOperationException.class) public final void testSortComparatorOfQsuperURI() { diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/cookbooks/RoundTripTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/cookbooks/RoundTripTest.java index 8a7aa028..107cc04b 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/cookbooks/RoundTripTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/cookbooks/RoundTripTest.java @@ -976,6 +976,84 @@ public final void test0306LinkingAnnotationsToManifestsManifest() throws IOExcep assertEquals(myTestName, expected, found); } + /** + * Tests the 0318 navPlace and navDate fixture (cf. https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0318NavPlaceNavDateCollection() throws IOException { + final String expected = getExpected("0318-navPlace-navDate/collection"); + final String found = JSON.readValue(expected, Collection.class).toString(); + + assertEquals(myTestName, expected, found); + } + + /** + * Tests the 0318 navPlace and navDate fixture (cf. https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0318NavPlaceNavDateManifest1() throws IOException { + final String expected = getExpected("0318-navPlace-navDate/manifest-1"); + final String found = JSON.readValue(expected, Manifest.class).toString(); + + assertEquals(myTestName, expected, found); + } + + /** + * Tests the 0318 navPlace and navDate fixture (cf. https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0318NavPlaceNavDateManifest2() throws IOException { + final String expected = getExpected("0318-navPlace-navDate/manifest-2"); + final String found = JSON.readValue(expected, Manifest.class).toString(); + + assertEquals(myTestName, expected, found); + } + + /** + * Tests the 0318 navPlace and navDate fixture (cf. https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0318NavPlaceNavDateManifest3() throws IOException { + final String expected = getExpected("0318-navPlace-navDate/manifest-3"); + final String found = JSON.readValue(expected, Manifest.class).toString(); + + assertEquals(myTestName, expected, found); + } + + /** + * Tests the 0318 navPlace and navDate fixture (cf. https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0318NavPlaceNavDateManifest4() throws IOException { + final String expected = getExpected("0318-navPlace-navDate/manifest-4"); + final String found = JSON.readValue(expected, Manifest.class).toString(); + + assertEquals(myTestName, expected, found); + } + + /** + * Tests the 0318 navPlace and navDate fixture (cf. https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0318NavPlaceNavDateManifest5() throws IOException { + final String expected = getExpected("0318-navPlace-navDate/manifest-5"); + final String found = JSON.readValue(expected, Manifest.class).toString(); + + assertEquals(myTestName, expected, found); + } + /** * Tests the 0326 annotating image layer fixture (cf. * https://iiif.io/api/cookbook/recipe/0326-annotating-image-layer/). @@ -990,6 +1068,20 @@ public final void test0326AnnotatingImageLayer() throws IOException { assertEquals(myTestName, expected, found); } + /** + * Tests the 0346 multi-lingual annotation body fixture (cf. + * https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/). + * + * @throws IOException If there is trouble reading the manifest file + */ + @Test + public final void test0346MultilingualAnnotationBody() throws IOException { + final String expected = getExpected("0346-multilingual-annotation-body/manifest"); + final String found = JSON.readValue(expected, Manifest.class).toString(); + + assertEquals(myTestName, expected, found); + } + /** * Tests the 0377 image in annotation fixture (cf. https://iiif.io/api/cookbook/recipe/0377-image-in-annotation/). * diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/utils/TestUtils.java b/src/test/java/info/freelibrary/iiif/presentation/v3/utils/TestUtils.java index 80670f0d..ef01f4b9 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/utils/TestUtils.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/utils/TestUtils.java @@ -1,6 +1,7 @@ package info.freelibrary.iiif.presentation.v3.utils; +import static info.freelibrary.iiif.presentation.v3.utils.JsonKeys.BODY; import static info.freelibrary.iiif.presentation.v3.utils.JsonKeys.CONTEXT; import static java.nio.charset.StandardCharsets.UTF_8; @@ -45,7 +46,7 @@ public final class TestUtils { public static final String TEST_DIR = "src/test/resources/json"; /** The JSON properties that are okay to collapse. */ - private static final List COLLAPSIBLES = Arrays.asList(CONTEXT); + private static final List COLLAPSIBLES = Arrays.asList(CONTEXT, BODY); /** The logger for the test utilities. */ private static final Logger LOGGER = LoggerFactory.getLogger(TestUtils.class, MessageCodes.BUNDLE); diff --git a/src/test/resources/cookbook/0022-linking-with-a-hotspot/manifest.json b/src/test/resources/cookbook/0022-linking-with-a-hotspot/manifest.json index a9a7fc6a..6aff827f 100644 --- a/src/test/resources/cookbook/0022-linking-with-a-hotspot/manifest.json +++ b/src/test/resources/cookbook/0022-linking-with-a-hotspot/manifest.json @@ -43,7 +43,7 @@ ], "annotations": [ { - "id": "https://iiif.io/api/cookbook/recipe/0022-linking-with-a-hotspot/page/p2/1", + "id": "https://iiif.io/api/cookbook/recipe/0022-linking-with-a-hotspot/page/p1/2", "type": "AnnotationPage", "items": [ { diff --git a/src/test/resources/cookbook/0135-annotating-point-in-canvas/manifest.json b/src/test/resources/cookbook/0135-annotating-point-in-canvas/manifest.json index 354d8db9..ca964d25 100644 --- a/src/test/resources/cookbook/0135-annotating-point-in-canvas/manifest.json +++ b/src/test/resources/cookbook/0135-annotating-point-in-canvas/manifest.json @@ -59,11 +59,6 @@ { "id": "https://iiif.io/api/cookbook/recipe/0135-annotating-point-in-canvas/annotation/p0002-tag", "type": "Annotation", - "label": { - "en": [ - "Annotation containing the name of the place annotated using the PointSelector." - ] - }, "motivation": "tagging", "body": { "type": "TextualBody", diff --git a/src/test/resources/cookbook/0139-geolocate-canvas-fragment/manifest.json b/src/test/resources/cookbook/0139-geolocate-canvas-fragment/manifest.json index f8dc9aaa..6508b43c 100644 --- a/src/test/resources/cookbook/0139-geolocate-canvas-fragment/manifest.json +++ b/src/test/resources/cookbook/0139-geolocate-canvas-fragment/manifest.json @@ -35,11 +35,6 @@ "id": "https://iiif.io/api/cookbook/recipe/0139-geolocate-canvas-fragment/content.json", "type": "Annotation", "motivation": "painting", - "label": { - "en": [ - "Pamphlet Cover" - ] - }, "body": { "id": "https://iiif.io/api/image/3.0/example/reference/43153e2ec7531f14dd1c9b2fc401678a-88695674/full/max/0/default.jpg", "type": "Image", @@ -68,11 +63,6 @@ "id": "https://iiif.io/api/cookbook/recipe/0139-geolocate-canvas-fragment/geoAnno.json", "type": "Annotation", "motivation": "tagging", - "label": { - "en": [ - "Annotation containing GeoJSON-LD coordinates that place the map depiction onto a Leaflet web map." - ] - }, "body": { "id": "https://iiif.io/api/cookbook/recipe/0139-geolocate-canvas-fragment/geo.json", "type": "Feature", diff --git a/src/test/resources/cookbook/0318-navPlace-navDate/collection.json b/src/test/resources/cookbook/0318-navPlace-navDate/collection.json new file mode 100644 index 00000000..99e29982 --- /dev/null +++ b/src/test/resources/cookbook/0318-navPlace-navDate/collection.json @@ -0,0 +1,202 @@ +{ + "@context": [ + "http://iiif.io/api/extension/navplace/context.json", + "http://iiif.io/api/presentation/3/context.json" + ], + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/collection.json", + "type": "Collection", + "label": { + "en": [ + "NavPlace and NavDate Collection" + ] + }, + "summary": { + "en": [ + "A collection of items related to Rome." + ] + }, + "requiredStatement": { + "label": { + "en": [ + "Attribution" + ] + }, + "value": { + "en": [ + "Objects from the Yale Center for British Art" + ] + } + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-1.json", + "type": "Manifest", + "label": { + "en": [ + "Castel Sant'Angelo, Rome" + ] + }, + "navDate": "1776-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/1", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/1", + "type": "Feature", + "properties": { + "label": { + "en": [ + "Castel Sant'Angelo, Rome" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.4663, + 41.9031 + ] + } + } + ] + } + }, + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-2.json", + "type": "Manifest", + "label": { + "en": [ + "The Colosseum" + ] + }, + "navDate": "1776-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/2", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/2", + "type": "Feature", + "properties": { + "label": { + "en": [ + "The Colosseum" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.492222, + 41.890278 + ] + } + } + ] + } + }, + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-3.json", + "type": "Manifest", + "label": { + "en": [ + "The Arch of Titus from the Forum, Rome, ca. 1725" + ] + }, + "navDate": "1725-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/3", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/3", + "type": "Feature", + "properties": { + "label": { + "en": [ + "The Arch of Titus from the Forum, Rome, ca. 1725" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.488585, + 41.890717 + ] + } + } + ] + } + }, + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-4.json", + "type": "Manifest", + "label": { + "en": [ + "The Temple of Vesta, Rome, 1849" + ] + }, + "navDate": "1849-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/4", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/4", + "type": "Feature", + "properties": { + "label": { + "en": [ + "The Temple of Vesta, Rome, 1849" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.4862, + 41.8917 + ] + } + } + ] + } + }, + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-5.json", + "type": "Manifest", + "label": { + "en": [ + "A View of Trajan's Forum, Rome, 1821" + ] + }, + "navDate": "1821-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/5", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/5", + "type": "Feature", + "properties": { + "label": { + "en": [ + "A View of Trajan's Forum, Rome, 1821" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.485869, + 41.895419 + ] + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/test/resources/cookbook/0318-navPlace-navDate/manifest-1.json b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-1.json new file mode 100644 index 00000000..e59b017b --- /dev/null +++ b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-1.json @@ -0,0 +1,79 @@ +{ + "@context": [ + "http://iiif.io/api/extension/navplace/context.json", + "http://iiif.io/api/presentation/3/context.json" + ], + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-1.json", + "type": "Manifest", + "label": { + "en": [ + "Castel Sant'Angelo, Rome" + ] + }, + "navDate": "1776-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/1", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/1", + "type": "Feature", + "properties": { + "label": { + "en": [ + "Castel Sant'Angelo, Rome" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.4663, + 41.9031 + ] + } + } + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/1", + "type": "Canvas", + "height": 1516, + "width": 2048, + "label": { + "en": [ + "Castel Sant'Angelo, Rome" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno-page/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno/1", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-Castel_Sant_Angelo_Rome/full/max/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 1516, + "width": 2048, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-Castel_Sant_Angelo_Rome", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/1" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/cookbook/0318-navPlace-navDate/manifest-2.json b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-2.json new file mode 100644 index 00000000..97f369a9 --- /dev/null +++ b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-2.json @@ -0,0 +1,79 @@ +{ + "@context": [ + "http://iiif.io/api/extension/navplace/context.json", + "http://iiif.io/api/presentation/3/context.json" + ], + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-2.json", + "type": "Manifest", + "label": { + "en": [ + "The Colosseum" + ] + }, + "navDate": "1776-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/2", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/2", + "type": "Feature", + "properties": { + "label": { + "en": [ + "The Colosseum" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.492222, + 41.890278 + ] + } + } + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/2", + "type": "Canvas", + "height": 1529, + "width": 2048, + "label": { + "en": [ + "The Colosseum" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno-page/2", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno/2", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-The_Colosseum/full/max/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 1529, + "width": 2048, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-The_Colosseum", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/2" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/cookbook/0318-navPlace-navDate/manifest-3.json b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-3.json new file mode 100644 index 00000000..89a7e6a3 --- /dev/null +++ b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-3.json @@ -0,0 +1,79 @@ +{ + "@context": [ + "http://iiif.io/api/extension/navplace/context.json", + "http://iiif.io/api/presentation/3/context.json" + ], + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-3.json", + "type": "Manifest", + "label": { + "en": [ + "The Arch of Titus from the Forum, Rome, ca. 1725" + ] + }, + "navDate": "1725-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/3", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/3", + "type": "Feature", + "properties": { + "label": { + "en": [ + "The Arch of Titus from the Forum, Rome, ca. 1725" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.488585, + 41.890717 + ] + } + } + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/3", + "type": "Canvas", + "height": 2875, + "width": 2048, + "label": { + "en": [ + "The Arch of Titus from the Forum, Rome, ca. 1725" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno-page/3", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno/3", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-The_Arch_of_Titus_from_the_Forum_Rome/full/max/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 2875, + "width": 2048, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-The_Arch_of_Titus_from_the_Forum_Rome", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/3" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/cookbook/0318-navPlace-navDate/manifest-4.json b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-4.json new file mode 100644 index 00000000..93c2dd4d --- /dev/null +++ b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-4.json @@ -0,0 +1,79 @@ +{ + "@context": [ + "http://iiif.io/api/extension/navplace/context.json", + "http://iiif.io/api/presentation/3/context.json" + ], + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-4.json", + "type": "Manifest", + "label": { + "en": [ + "The Temple of Vesta, Rome, 1849" + ] + }, + "navDate": "1849-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/4", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/4", + "type": "Feature", + "properties": { + "label": { + "en": [ + "The Temple of Vesta, Rome, 1849" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.4862, + 41.8917 + ] + } + } + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/4", + "type": "Canvas", + "height": 2875, + "width": 2048, + "label": { + "en": [ + "The Temple of Vesta, Rome, 1849" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno-page/4", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno/4", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-The_Temple_of_Vesta_Rome/full/max/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 2875, + "width": 2048, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-The_Temple_of_Vesta_Rome", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/4" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/cookbook/0318-navPlace-navDate/manifest-5.json b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-5.json new file mode 100644 index 00000000..cc359e4e --- /dev/null +++ b/src/test/resources/cookbook/0318-navPlace-navDate/manifest-5.json @@ -0,0 +1,79 @@ +{ + "@context": [ + "http://iiif.io/api/extension/navplace/context.json", + "http://iiif.io/api/presentation/3/context.json" + ], + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/manifest-5.json", + "type": "Manifest", + "label": { + "en": [ + "A View of Trajan's Forum, Rome, 1821" + ] + }, + "navDate": "1821-01-01T00:00:00+00:00", + "navPlace": { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature-collection/5", + "type": "FeatureCollection", + "features": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/feature/5", + "type": "Feature", + "properties": { + "label": { + "en": [ + "A View of Trajan's Forum, Rome, 1821" + ] + } + }, + "geometry": { + "type": "Point", + "coordinates": [ + 12.485869, + 41.895419 + ] + } + } + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/5", + "type": "Canvas", + "height": 3005, + "width": 2048, + "label": { + "en": [ + "A View of Trajan's Forum, Rome, 1821" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno-page/5", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/anno/5", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-A_View_of_Trajans_Forum_Rome/full/max/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 3005, + "width": 2048, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/71b9228e087f15c75b628214cd9f647d-A_View_of_Trajans_Forum_Rome", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "https://iiif.io/api/cookbook/recipe/0318-navPlace-navDate/canvas/5" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/cookbook/0346-multilingual-annotation-body/manifest.json b/src/test/resources/cookbook/0346-multilingual-annotation-body/manifest.json new file mode 100644 index 00000000..235f3bce --- /dev/null +++ b/src/test/resources/cookbook/0346-multilingual-annotation-body/manifest.json @@ -0,0 +1,82 @@ +{ + "@context": "http://iiif.io/api/presentation/3/context.json", + "id": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/manifest.json", + "type": "Manifest", + "label": { + "en": [ + "Koto, chess, calligraphy, and painting" + ], + "ja": [ + "琴棋書画図屏風" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/canvas/p1", + "type": "Canvas", + "height": 31722, + "width": 70399, + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/page/p1/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/annotation/p0001-image", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/36ca0a3370db128ec984b33d71a1543d-100320001004/full/full/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 31722, + "width": 70399, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/36ca0a3370db128ec984b33d71a1543d-100320001004", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/canvas/p1" + } + ] + } + ], + "annotations": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/page/p2/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/annotation/p0001-comment", + "type": "Annotation", + "motivation": "commenting", + "body": [ + { + "type": "Choice", + "items": [ + { + "type": "TextualBody", + "value": "Koto with a cover being carried", + "language": "en", + "format": "text/plain" + }, + { + "type": "TextualBody", + "value": "袋に収められた琴", + "language": "ja", + "format": "text/plain" + } + ] + } + ], + "target": "https://iiif.io/api/cookbook/recipe/0346-multilingual-annotation-body/canvas/p1#xywh=1650,1200,925,1250" + } + ] + } + ] + } + ] +} \ No newline at end of file