package de.digitalcollections.iiif.presentation.model.impl.jackson;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import com.revinate.assertj.json.JsonPathAssert;
import de.digitalcollections.iiif.presentation.model.api.v2.Canvas;
import de.digitalcollections.iiif.presentation.model.api.v2.Collection;
import de.digitalcollections.iiif.presentation.model.api.v2.Image;
import de.digitalcollections.iiif.presentation.model.api.v2.ImageService;
import de.digitalcollections.iiif.presentation.model.api.v2.Manifest;
import de.digitalcollections.iiif.presentation.model.api.v2.Metadata;
import de.digitalcollections.iiif.presentation.model.api.v2.PropertyValue;
import de.digitalcollections.iiif.presentation.model.api.v2.SeeAlso;
import de.digitalcollections.iiif.presentation.model.api.v2.Sequence;
import de.digitalcollections.iiif.presentation.model.api.v2.Service;
import de.digitalcollections.iiif.presentation.model.api.v2.Thumbnail;
import de.digitalcollections.iiif.presentation.model.api.v2.references.CollectionReference;
import de.digitalcollections.iiif.presentation.model.api.v2.references.ManifestReference;
import de.digitalcollections.iiif.presentation.model.impl.jackson.v2.IiifPresentationApiObjectMapper;
import de.digitalcollections.iiif.presentation.model.impl.v2.CanvasImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.CollectionImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.ImageImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.ImageResourceImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.ImageServiceImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.ManifestImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.MetadataImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.PhysicalDimensionsServiceImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.PropertyValueLocalizedImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.PropertyValueSimpleImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.SeeAlsoImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.ServiceImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.ThumbnailImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.references.CollectionReferenceImpl;
import de.digitalcollections.iiif.presentation.model.impl.v2.references.ManifestReferenceImpl;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.apache.commons.io.IOUtils;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Assert;
import static org.junit.Assert.assertEquals;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IiifPresentationApiObjectMapperTest {
private static final Logger LOGGER = LoggerFactory.getLogger(IiifPresentationApiObjectMapperTest.class);
static ObjectMapper objectMapper;
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private static final String expectedMultiLanguageMetadataJson = "";
@BeforeClass
public static void setupClass() {
objectMapper = new IiifPresentationApiObjectMapper();
}
@Test
public void testJsonToMinimalManifest() throws JsonProcessingException, IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("manifest_minimal.json"), DEFAULT_CHARSET);
Manifest manifest = objectMapper.readValue(json, ManifestImpl.class);
Assert.assertTrue(manifest.getId().equals(URI.create("http://example.com/iiif/presentation/test-obj/manifest")));
PropertyValueLocalizedImpl manifestLabel = (PropertyValueLocalizedImpl) manifest.getLabel();
Assert.assertTrue(manifestLabel.getValues("en").get(0).equals("testLabel"));
Assert.assertTrue(manifestLabel.getValues("de").get(0).equals("täschtLäibel"));
Assert.assertTrue(manifest.getType().equals("sc:Manifest"));
Assert.assertTrue(manifest.getContext().equals("http://iiif.io/api/presentation/2/context.json"));
assertEquals(manifest.getThumbnail().getId(),
URI.create("http://example.com/iiif/image/test-obj/full/200,/0/default.jpg"));
}
@Test
public void testJsonToCollection() throws JsonProcessingException, IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("collection.json"), DEFAULT_CHARSET);
Collection collection = objectMapper.readValue(json, CollectionImpl.class);
Assert.assertTrue(collection.getId().equals(
URI.create("https://api.digitale-sammlungen.de/iiif/presentation/v2/collection/bsbmult00000001")));
PropertyValueLocalizedImpl label = (PropertyValueLocalizedImpl) collection.getLabel();
Assert.assertTrue(label.getValues("de").get(0).equals("Der gerade Weg"));
Assert.assertTrue(collection.getType().equals("sc:Collection"));
}
@Test
public void testJsonToMetadata() throws JsonProcessingException, IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("manifest_metadata.json"), DEFAULT_CHARSET);
Manifest manifest = objectMapper.readValue(json, ManifestImpl.class);
Assert.assertTrue(manifest.getId().equals(URI.create("http://example.com/iiif/presentation/test-obj/manifest")));
Assert.assertEquals("testLabel", manifest.getLabel().getValues().get(0));
Assert.assertTrue(manifest.getType().equals("sc:Manifest"));
Assert.assertTrue(manifest.getContext().equals("http://iiif.io/api/presentation/2/context.json"));
Assert.assertNotNull(manifest.getMetadata());
}
@Test
public void testJsonToFullFledgedMetadata() throws IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("manifest.json"), DEFAULT_CHARSET);
Manifest manifest = objectMapper.readValue(json, ManifestImpl.class);
PropertyValueLocalizedImpl description = (PropertyValueLocalizedImpl) manifest.getDescription();
Assert.assertTrue(description.getValues(Locale.GERMAN).get(0).startsWith("303. Bändchen"));
Assert
.assertEquals("Die Mechanik der festen, flüssigen und gasförmigen Körper; 1. Teil; Die Mechanik der festen Körper",
manifest.getLabel().getValues().get(0));
Sequence sequence = manifest.getSequences().get(0);
Assert.assertEquals("Current Page Order", sequence.getLabel().getValues().get(0));
PropertyValueLocalizedImpl firstCanvasLabel = (PropertyValueLocalizedImpl) sequence.getCanvases().get(0).getLabel();
Assert.assertEquals("Umschlag vorne", firstCanvasLabel.getValues(Locale.GERMAN).get(0));
Assert.assertEquals("Front Cover", firstCanvasLabel.getValues(Locale.ENGLISH).get(0));
Assert.assertEquals("Umschlag vorne", firstCanvasLabel.getValues().get(0));
}
@Test
public void testManifestToJson() throws JsonProcessingException {
Manifest manifest = new ManifestImpl("testId", new PropertyValueSimpleImpl("testLabel"));
Thumbnail thumb = new ThumbnailImpl();
thumb.setId(URI.create("http://example.com/iiif/test/thumb"));
Service service = new ServiceImpl();
service.setId("htp://example.com/iiif/test");
thumb.setService(service);
manifest.setThumbnail(thumb);
String jsonString = objectMapper.writeValueAsString(manifest);
ReadContext ctx = JsonPath.parse(jsonString);
Assert.assertEquals("testId", ctx.read("$['@id']"));
Assert.assertEquals("testLabel", ctx.read("$.label"));
Assert.assertEquals("http://iiif.io/api/presentation/2/context.json", ctx.read("$['@context']"));
Assert.assertEquals("sc:Manifest", ctx.read("$['@type']"));
}
@Test
public void testMetadataSimpleToJson() throws JsonProcessingException {
MetadataImpl metadata = new MetadataImpl(new PropertyValueSimpleImpl("testLabel"),
new PropertyValueSimpleImpl("testValue"));
String jsonString = objectMapper.writeValueAsString(metadata);
ReadContext ctx = JsonPath.parse(jsonString);
Assert.assertEquals("testLabel", ctx.read("$.label"));
Assert.assertEquals("testValue", ctx.read("$.value"));
}
@Test
public void testMetadataMultilanguageToJson() throws JsonProcessingException {
PropertyValueLocalizedImpl labelProp = new PropertyValueLocalizedImpl();
PropertyValueLocalizedImpl valueProp = new PropertyValueLocalizedImpl();
labelProp.addValue(Locale.GERMAN, "Deutscher Schlüssel");
valueProp.addValue(Locale.GERMAN, "Deutscher Wert");
labelProp.addValue(Locale.ENGLISH, "English Key");
valueProp.addValue(Locale.ENGLISH, "English Value");
Metadata metadata = new MetadataImpl(labelProp, valueProp);
String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(metadata);
LOGGER.debug(jsonString);
ReadContext ctx = JsonPath.parse(jsonString);
Assert.assertEquals(new Long(2), ctx.read("$.label.size()", Long.class));
Assert.assertEquals(new Long(2), ctx.read("$.value.size()", Long.class));
String[] germanKey = ctx.read("$.label[?(@['@language']=='de')]['@value']", String[].class);
Assert.assertEquals("Deutscher Schlüssel", germanKey[0]);
String[] englishKey = ctx.read("$.label[?(@['@language']=='en')]['@value']", String[].class);
Assert.assertEquals("English Key", englishKey[0]);
}
@Test
public void testCollectionToJson() throws JsonProcessingException {
PropertyValue labelProp = new PropertyValueSimpleImpl("some label");
List<Metadata> metadata = new ArrayList<>();
metadata.add(new MetadataImpl(new PropertyValueSimpleImpl("some key"), new PropertyValueSimpleImpl("some value")));
Collection coll = new CollectionImpl(URI.create("http://example.com/collection/some-collection"), labelProp, metadata);
List<ManifestReference> manifests = new ArrayList<>();
manifests.add(new ManifestReferenceImpl(URI.create("http://example.com/manifest/some-manifest"),
new PropertyValueSimpleImpl("some label")));
manifests.add(new ManifestReferenceImpl(URI.create("http://example.com/manifest/some-other-manifest")));
coll.setManifests(manifests);
List<CollectionReference> subColls = new ArrayList<>();
subColls.add(new CollectionReferenceImpl(URI.create("http://example.com/collection/some-other-collection"),
new PropertyValueSimpleImpl("some label")));
subColls.add(new CollectionReferenceImpl(URI.create("http://example.com/collection/yet-another-collection")));
coll.setSubCollections(subColls);
String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(coll);
DocumentContext ctx = JsonPath.parse(jsonString);
JsonPathAssert.assertThat(ctx).jsonPathAsInteger("$.collections.length()").isEqualTo(2);
JsonPathAssert.assertThat(ctx).jsonPathAsInteger("$.manifests.length()").isEqualTo(2);
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.label").isEqualTo("some label");
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.metadata[0].label").isEqualTo("some key");
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.manifests[0]['@type']").isEqualTo("sc:Manifest");
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.collections[0]['@type']").isEqualTo("sc:Collection");
}
@Test
public void testSeeAlsoToJson() throws JsonProcessingException {
SeeAlso seeAlso = new SeeAlsoImpl();
seeAlso.setId(URI.create("http://example.com/test"));
seeAlso.setFormat("application/json");
seeAlso.setProfile(URI.create("http://example.com/profile"));
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(seeAlso);
DocumentContext ctx = JsonPath.parse(json);
JsonPathAssert.assertThat(ctx).jsonPathAsString("$['@id']").isEqualTo("http://example.com/test");
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.format").isEqualTo("application/json");
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.profile").isEqualTo("http://example.com/profile");
}
@Test
public void testSeeAlsoFromJson() throws IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("manifest_seealso.json"), DEFAULT_CHARSET);
Manifest manifest = objectMapper.readValue(json, ManifestImpl.class);
assertThat(manifest.getSeeAlso()).hasSize(2);
assertThat(manifest.getSeeAlso().get(0).getFormat()).isEqualTo("application/json");
assertThat(manifest.getSeeAlso().get(0).getProfile().toASCIIString()).
isEqualTo("http://iiif.io/some-new-api/profile");
assertThat(manifest.getSeeAlso().get(1).getFormat()).isNull();
}
@Test
public void testBroken() throws IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("broken.json"), DEFAULT_CHARSET);
Manifest manifest = objectMapper.readValue(json, Manifest.class);
assertThat(manifest.getLabel()).isNotNull();
}
@Test
public void testReadNavDate() throws IOException {
String json = IOUtils.
toString(this.getClass().getClassLoader().getResourceAsStream("navdate.json"), DEFAULT_CHARSET);
Manifest manifest = objectMapper.readValue(json, Manifest.class);
LocalDateTime ldt = LocalDateTime.ofInstant(manifest.getNavDate(), ZoneId.systemDefault());
assertThat(ldt.getYear()).isEqualTo(1848);
assertThat(ldt.getMonthValue()).isEqualTo(1);
assertThat(ldt.getDayOfMonth()).isEqualTo(1);
}
@Test
public void testWriteNavDate() throws IOException {
Manifest manifest = new ManifestImpl("testId", new PropertyValueSimpleImpl("testLabel"));
manifest.setNavDate(LocalDateTime.of(1789, 7, 14, 12, 0).toInstant(ZoneOffset.UTC));
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(manifest);
DocumentContext ctx = JsonPath.parse(json);
JsonPathAssert.assertThat(ctx).jsonPathAsString("$['navDate']").isEqualTo("1789-07-14T12:00:00Z");
}
@Test
public void testAddPhysicalDimensionsService() throws IOException {
ImageService imageService = new ImageServiceImpl();
imageService.setContext("http://iiif.io/api/image/2/context.json");
imageService.setProfile("http://iiif.io/api/image/2/level1.json");
imageService.setId("http://some.url.org");
Image image = new ImageImpl("http://foo.org");
image.setResource(new ImageResourceImpl("http://someresource.io"));
image.getResource().setService(imageService);
image.getResource().setHeight(100);
image.getResource().setWidth(100);
image.setOn(URI.create("http://foo.org"));
List<Image> images = Collections.singletonList(image);
Canvas canvas = new CanvasImpl(URI.create("http://dummy.org/canvas"), new PropertyValueSimpleImpl("dummy"), 800, 600);
canvas.setImages(images);
List<Service> services = new ArrayList();
services.add(new PhysicalDimensionsServiceImpl(0.025, "in"));
canvas.setServices(services);
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(canvas);
DocumentContext ctx = JsonPath.parse(json);
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.services[0].physicalUnits").isEqualTo("in");
JsonPathAssert.assertThat(ctx).jsonPathAsString("$.images[0].resource.service.profile").isEqualTo("http://iiif.io/api/image/2/level1.json");
Canvas deserialized = objectMapper.readValue(json, Canvas.class);
assertThat(deserialized.getServices().get(0).getProfile()).contains("physdim");
assertThat(((PhysicalDimensionsServiceImpl) deserialized.getServices().get(0)).getPhysicalUnits()).isEqualTo("in");
}
}