diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvas.java b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvas.java index 2f613f98..4ce3115c 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvas.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvas.java @@ -4,12 +4,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -17,10 +15,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonSetter; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import com.fasterxml.jackson.databind.type.TypeFactory; import info.freelibrary.util.Constants; @@ -44,7 +39,6 @@ import info.freelibrary.iiif.presentation.v3.utils.JSON; import info.freelibrary.iiif.presentation.v3.utils.JsonKeys; import info.freelibrary.iiif.presentation.v3.utils.MessageCodes; -import info.freelibrary.iiif.presentation.v3.utils.json.JsonParsingException; /** * A virtual container that represents a page or view and has content resources associated with it or with parts of it. @@ -68,9 +62,6 @@ abstract class AbstractCanvas> extends NavigableReso /** A temporal constant. */ private static final String TEMPORAL = "temporal"; - /** A Jackson serialization filter name for width and height. */ - private static final String WIDTH_HEIGHT_FILTER = "JPv3WidthHeightFilter"; - /** A zero (non-existent) duration. */ private static final float ZERO_DURATION = 0.0f; @@ -142,6 +133,27 @@ protected AbstractCanvas(final String aID, final Label aLabel) { super(ResourceTypes.CANVAS, aID, aLabel, CanvasBehavior.class); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final AbstractCanvas other) { + return Objects.equals(myDuration, other.myDuration) && Objects.equals(myHeight, other.myHeight) && + Objects.equals(myWidth, other.myWidth) && + Objects.equals(myOtherAnnotations, other.myOtherAnnotations) && + Objects.equals(myPaintingPageList, other.myPaintingPageList) && + Objects.equals(mySupplementingPageList, other.mySupplementingPageList) && super.equals(other); + } + + return false; + } + /** * Gets the duration of the canvas. * @@ -228,6 +240,12 @@ public int getWidth() { return myWidth; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myDuration, myHeight, myWidth, myOtherAnnotations, myPaintingPageList, + mySupplementingPageList); + } + /** * Sets the canvas' behaviors. * @@ -411,37 +429,6 @@ public T setWidthHeight(final int aWidth, final int aHeight) { return (T) this; } - /** - * Converts the canvas to its string/JSON representation. - * - * @return A string representation of the canvas - */ - @Override - public String toString() { - final SimpleFilterProvider filterProvider = new SimpleFilterProvider(); - final Set filtered = new HashSet<>(); - - // Don't write duration if it's zero - if (myDuration == ZERO_DURATION) { - filtered.add(JsonKeys.DURATION); - } - - // Don't write width and height if they're both zero - if (myHeight == 0 && myWidth == 0) { - filtered.add(JsonKeys.HEIGHT); - filtered.add(JsonKeys.WIDTH); - } - - // These are the things we filter when we serialize to JSON - filterProvider.addFilter(WIDTH_HEIGHT_FILTER, SimpleBeanPropertyFilter.serializeAllExcept(filtered)); - - try { - return JSON.getWriter(filterProvider).writeValueAsString(this); - } catch (final JsonProcessingException details) { - throw new JsonParsingException(details); - } - } - /** * Gets the manifest context. The manifest can either have a single context or an array of contexts (Cf. * https://iiif.io/api/presentation/3.0/#46-linked-data-context-and-extensions) diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvasAnnotation.java b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvasAnnotation.java index 6a59876d..c818bc52 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvasAnnotation.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractCanvasAnnotation.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonSetter; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.Logger; import info.freelibrary.util.LoggerFactory; import info.freelibrary.util.warnings.JDK; @@ -129,6 +130,26 @@ public boolean bodyHasChoice() { return myBodyHasChoice; } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final AbstractCanvasAnnotation other) { + return Objects.equals(myBodyHasChoice, other.myBodyHasChoice) && + Objects.equals(myMotivation, other.myMotivation) && + ListUtils.equals(myResources, other.myResources) && Objects.equals(myTarget, other.myTarget) && + Objects.equals(myTimeMode, other.myTimeMode) && super.equals(other); + } + + return false; + } + /** * Gets the content resources associated with this annotation. * @@ -171,6 +192,11 @@ public Optional getTimeMode() { return Optional.ofNullable(myTimeMode); } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myBodyHasChoice, myMotivation, myResources, myTarget, myTimeMode); + } + /** * Sets the annotation resource's behaviors. The supplied behaviors are checked for compatibility with the resource. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractContentResource.java b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractContentResource.java index f08f8c1b..89dcd081 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractContentResource.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractContentResource.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.warnings.JDK; import info.freelibrary.iiif.presentation.v3.annotations.WebAnnotation; @@ -73,6 +74,24 @@ protected AbstractContentResource(final String aType, final String aID, : MediaType.parse(aID).orElse(null); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final AbstractContentResource other) { + return Objects.equals(myFormat, other.myFormat) && ListUtils.equals(myAnnotations, other.myAnnotations) && + ListUtils.equals(myLanguages, other.myLanguages) && super.equals(other); + } + + return false; + } + /** * Gets the content resource's annotations. * @@ -113,6 +132,11 @@ public List getLanguages() { return myLanguages; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myFormat, myAnnotations, myLanguages); + } + /** * Sets the content resource's annotation pages from an array. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractResource.java b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractResource.java index 162facf5..ab838c6d 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractResource.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/AbstractResource.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import info.freelibrary.util.I18nRuntimeException; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.Logger; import info.freelibrary.util.LoggerFactory; import info.freelibrary.util.warnings.JDK; @@ -154,6 +155,32 @@ protected AbstractResource(final String aType, final String aID, final Label aLa myLabel = Objects.requireNonNull(aLabel); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final AbstractResource other) { + return Objects.equals(myType, other.myType) && Objects.equals(myBehaviorClass, other.myBehaviorClass) && + ListUtils.equals(myBehaviors, other.myBehaviors) && + ListUtils.equals(myHomepages, other.myHomepages) && Objects.equals(myID, other.myID) && + Objects.equals(myLabel, other.myLabel) && ListUtils.equals(myMetadata, other.myMetadata) && + ListUtils.equals(myPartOfs, other.myPartOfs) && ListUtils.equals(myProviders, other.myProviders) && + ListUtils.equals(myRenderings, other.myRenderings) && + Objects.equals(myRequiredStatement, other.myRequiredStatement) && + Objects.equals(myRights, other.myRights) && Objects.equals(mySeeAlsoRefs, other.mySeeAlsoRefs) && + ListUtils.equals(myServices, other.myServices) && Objects.equals(mySummary, other.mySummary) && + ListUtils.equals(myThumbnails, other.myThumbnails); + } + + return false; + } + /** * Gets the resource's behaviors. * @@ -347,6 +374,13 @@ public String getType() { return myType; } + @Override + public int hashCode() { + return Objects.hash(myType, myBehaviorClass, myBehaviors, myHomepages, myID, myLabel, myMetadata, myPartOfs, + myProviders, myRenderings, myRequiredStatement, myRights, mySeeAlsoRefs, myServices, mySummary, + myThumbnails); + } + @Override @JsonIgnore public T setBehaviors(final Behavior... aBehaviorArray) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationCollection.java b/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationCollection.java index 1823ed81..e6f5f18b 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationCollection.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationCollection.java @@ -2,6 +2,7 @@ package info.freelibrary.iiif.presentation.v3; import java.util.List; +import java.util.Objects; import java.util.Optional; import com.fasterxml.jackson.annotation.JsonGetter; @@ -44,6 +45,25 @@ public AnnotationCollection(final String aID, final Label aLabel) { super(ResourceTypes.ANNOTATION_COLLECTION, aID, aLabel, ResourceBehavior.class); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final AnnotationCollection other) { + return Objects.equals(myFirstAnnotationPage, other.myFirstAnnotationPage) && + Objects.equals(myLastAnnotationPage, other.myLastAnnotationPage) && + Objects.equals(myViewingDirection, other.myViewingDirection); + } + + return false; + } + /** * Gets the collection's first annotation page. * @@ -76,6 +96,11 @@ public ViewingDirection getViewingDirection() { return myViewingDirection; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myFirstAnnotationPage, myLastAnnotationPage, this.myViewingDirection); + } + @Override @JsonIgnore public AnnotationCollection setBehaviors(final Behavior... aBehaviorArray) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationPage.java b/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationPage.java index 6f64c8e2..36761e78 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationPage.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/AnnotationPage.java @@ -111,6 +111,24 @@ public final AnnotationPage addAnnotations(final List aAnnotationList) { return this; } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final AnnotationPage other) { + return Objects.equals(myAnnotations, other.myAnnotations) && + Objects.equals(myNextAnnotationPage, other.myNextAnnotationPage) && super.equals(other); + } + + return false; + } + /** * Gets the annotation page's annotations. * @@ -140,6 +158,11 @@ public > Optional> getNextPage() { return Optional.ofNullable((AnnotationPage) myNextAnnotationPage); } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myAnnotations, myNextAnnotationPage); + } + /** * Removes the external context from an annotation page so that it can be used inside a manifest. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/Canvas.java b/src/main/java/info/freelibrary/iiif/presentation/v3/Canvas.java index 7e4572d6..e4a9b280 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/Canvas.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/Canvas.java @@ -2,6 +2,7 @@ package info.freelibrary.iiif.presentation.v3; import java.util.List; +import java.util.Objects; import java.util.Optional; import com.fasterxml.jackson.annotation.JsonGetter; @@ -77,6 +78,24 @@ private Canvas() { super(); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final Canvas other) { + return Objects.equals(myAccompanyingCanvas, other.myAccompanyingCanvas) && + Objects.equals(myPlaceholderCanvas, other.myPlaceholderCanvas) && super.equals(other); + } + + return false; + } + /** * Gets canvas' accompanying canvas. * @@ -108,6 +127,11 @@ public Optional getPlaceholderCanvas() { return myPlaceholderCanvas; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myPlaceholderCanvas, myAccompanyingCanvas); + } + @Override public final Canvas paintWith(final boolean aChoice, final ContentResource... aContentArray) { return super.paint(this, aChoice, aContentArray); diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/Collection.java b/src/main/java/info/freelibrary/iiif/presentation/v3/Collection.java index f47d57ea..42bc9e9a 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/Collection.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/Collection.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.core.JsonProcessingException; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.warnings.Eclipse; import info.freelibrary.util.warnings.PMD; @@ -74,6 +75,27 @@ private Collection() { super(ResourceTypes.COLLECTION, CollectionBehavior.class); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final Collection other) { + return Objects.equals(myAccompanyingCanvas, other.myAccompanyingCanvas) && + Objects.equals(myPlaceholderCanvas, other.myPlaceholderCanvas) && + Objects.equals(myViewingDirection, other.myViewingDirection) && + ListUtils.equals(myServiceDefinitions, other.myServiceDefinitions) && + ListUtils.equals(myItems, other.myItems) && super.equals(other); + } + + return false; + } + /** * Gets the collection's accompanying canvas. * @@ -145,6 +167,12 @@ public ViewingDirection getViewingDirection() { return myViewingDirection; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myAccompanyingCanvas, myPlaceholderCanvas, myViewingDirection, + myServiceDefinitions, myItems); + } + /** * Sets the collection's accompanying canvas. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/ImageContent.java b/src/main/java/info/freelibrary/iiif/presentation/v3/ImageContent.java index 8222444e..06589be7 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/ImageContent.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/ImageContent.java @@ -2,6 +2,7 @@ package info.freelibrary.iiif.presentation.v3; import java.util.List; +import java.util.Objects; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -51,6 +52,24 @@ private ImageContent() { super(ResourceTypes.IMAGE, ResourceBehavior.class); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final ImageContent other) { + return Objects.equals(myHeight, other.myHeight) && Objects.equals(myWidth, other.myWidth) && + super.equals(other); + } + + return false; + } + /** * Gets the image's height. * @@ -75,6 +94,11 @@ public int getWidth() { return myWidth; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myHeight, myWidth); + } + @Override @JsonIgnore public ImageContent setBehaviors(final Behavior... aBehaviorArray) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/Manifest.java b/src/main/java/info/freelibrary/iiif/presentation/v3/Manifest.java index b8f04c8c..3a775435 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/Manifest.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/Manifest.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.core.JsonProcessingException; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.warnings.JDK; import info.freelibrary.util.warnings.PMD; @@ -126,6 +127,30 @@ public Manifest addRanges(final Range... aRangeArray) { return this; } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final Manifest other) { + return Objects.equals(myAccompanyingCanvas, other.myAccompanyingCanvas) && + Objects.equals(myPlaceholderCanvas, other.myPlaceholderCanvas) && + ListUtils.equals(myCanvases, other.myCanvases) && + ListUtils.equals(myAnnotations, other.myAnnotations) && + ListUtils.equals(myRanges, other.myRanges) && + ListUtils.equals(myServiceDefinitions, myServiceDefinitions) && + Objects.equals(myStart, other.myStart) && + Objects.equals(myViewingDirection, other.myViewingDirection) && super.equals(other); + } + + return false; + } + /** * Gets the manifest's accompanying canvas. * @@ -238,6 +263,12 @@ public ViewingDirection getViewingDirection() { return myViewingDirection; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myAccompanyingCanvas, myPlaceholderCanvas, myCanvases, myAnnotations, + myRanges, myServiceDefinitions, myStart, myViewingDirection); + } + /** * Sets the manifest's accompanying canvas. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/NavigableResource.java b/src/main/java/info/freelibrary/iiif/presentation/v3/NavigableResource.java index e7183367..00ff06f5 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/NavigableResource.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/NavigableResource.java @@ -113,6 +113,24 @@ public T clearContexts() { return (T) this; } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final NavigableResource other) { + return Objects.equals(myNavDate, other.myNavDate) && Objects.equals(myNavPlace, other.myNavPlace) && + super.equals(other); + } + + return false; + } + /** * Gets the primary context. * @@ -158,6 +176,11 @@ public NavPlace getNavPlace() { return myNavPlace; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myNavDate, myNavPlace); + } + /** * Remove the supplied context. This will not remove the default required context though. If that's supplied, an * {@link UnsupportedOperationException} will be thrown. diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/PaintingAnnotation.java b/src/main/java/info/freelibrary/iiif/presentation/v3/PaintingAnnotation.java index cc9d4036..f32df8d2 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/PaintingAnnotation.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/PaintingAnnotation.java @@ -2,6 +2,7 @@ package info.freelibrary.iiif.presentation.v3; import java.net.URI; +import java.util.Objects; import java.util.Optional; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -122,6 +123,23 @@ private PaintingAnnotation() { super(); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final PaintingAnnotation other) { + return Objects.equals(myStylesheet, other.myStylesheet) && super.equals(other); + } + + return false; + } + /** * Gets the specific resource's CSS stylesheet. * @@ -131,6 +149,11 @@ public Optional getStylesheet() { return Optional.ofNullable(myStylesheet); } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myStylesheet); + } + @Override public final PaintingAnnotation setMotivation(final Motivation aMotivation) { if (!Purpose.PAINTING.toString().equalsIgnoreCase(aMotivation.toString())) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/Range.java b/src/main/java/info/freelibrary/iiif/presentation/v3/Range.java index a75a796e..5ad540e3 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/Range.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/Range.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import info.freelibrary.util.I18nRuntimeException; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.warnings.PMD; import info.freelibrary.iiif.presentation.v3.ids.Minter; @@ -112,6 +113,27 @@ public Range clearItems() { return this; } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final Range other) { + return Objects.equals(myAccompanyingCanvas, other.myAccompanyingCanvas) && + Objects.equals(myPlaceholderCanvas, other.myPlaceholderCanvas) && + Objects.equals(myViewingDirection, other.myViewingDirection) && + ListUtils.equals(myItems, other.myItems) && Objects.equals(myStart, other.myStart) && + Objects.equals(mySupplementaryAnnotations, other.mySupplementaryAnnotations) && super.equals(other); + } + + return false; + } + /** * Gets the range's accompanying canvas. * @@ -176,6 +198,12 @@ public ViewingDirection getViewingDirection() { return myViewingDirection; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myAccompanyingCanvas, myPlaceholderCanvas, myViewingDirection, myItems, + myStart, myViewingDirection); + } + /** * Sets the range's accompanying canvas. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/SoundContent.java b/src/main/java/info/freelibrary/iiif/presentation/v3/SoundContent.java index ee1836d6..6cf6960f 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/SoundContent.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/SoundContent.java @@ -2,6 +2,7 @@ package info.freelibrary.iiif.presentation.v3; import java.util.List; +import java.util.Objects; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -48,6 +49,23 @@ private SoundContent() { super(ResourceTypes.SOUND, ResourceBehavior.class); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final SoundContent other) { + return Objects.equals(myDuration, other.myDuration) && super.equals(other); + } + + return false; + } + /** * Gets the duration of the sound content. * @@ -60,6 +78,11 @@ public float getDuration() { return myDuration; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myDuration); + } + @Override @JsonIgnore public SoundContent setBehaviors(final Behavior... aBehaviorArray) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/SupplementingAnnotation.java b/src/main/java/info/freelibrary/iiif/presentation/v3/SupplementingAnnotation.java index 87d35acc..1db49a9d 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/SupplementingAnnotation.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/SupplementingAnnotation.java @@ -131,6 +131,23 @@ private SupplementingAnnotation() { super(); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final SupplementingAnnotation other) { + return Objects.equals(myTextGranularity, other.myTextGranularity) && super.equals(other); + } + + return false; + } + /** * Gets the supplementing annotation's text granularity if it exists. * @@ -140,6 +157,11 @@ public Optional getTextGranularity() { return Optional.ofNullable(myTextGranularity); } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myTextGranularity); + } + @Override public final SupplementingAnnotation setMotivation(final Motivation aMotivation) { if (!Purpose.SUPPLEMENTING.toString().equalsIgnoreCase(aMotivation.toString())) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/VideoContent.java b/src/main/java/info/freelibrary/iiif/presentation/v3/VideoContent.java index 192a0e27..e6f5cb4d 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/VideoContent.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/VideoContent.java @@ -2,6 +2,7 @@ package info.freelibrary.iiif.presentation.v3; import java.util.List; +import java.util.Objects; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -54,6 +55,24 @@ private VideoContent() { super(ResourceTypes.VIDEO, ResourceBehavior.class); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final VideoContent other) { + return Objects.equals(myHeight, other.myHeight) && Objects.equals(myWidth, other.myWidth) && + Objects.equals(myDuration, other.myDuration) && super.equals(other); + } + + return false; + } + /** * Gets the duration of the video content. * @@ -90,6 +109,11 @@ public int getWidth() { return myWidth; } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), myHeight, myWidth, myDuration); + } + @Override @JsonIgnore public VideoContent setBehaviors(final Behavior... aBehaviorArray) { diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/Target.java b/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/Target.java index a8d973c9..d584a868 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/Target.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/Target.java @@ -1,6 +1,7 @@ package info.freelibrary.iiif.presentation.v3.annotations; +import java.util.Objects; import java.util.Optional; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -54,6 +55,23 @@ public Target(final String aURI) { myURI = UriUtils.checkID(aURI, false); } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final Target other) { + return Objects.equals(mySpecificResource, other.mySpecificResource) && Objects.equals(myURI, other.myURI); + } + + return false; + } + /** * Gets the optional specific resources if there is one, else an empty optional. * @@ -72,4 +90,9 @@ public String getURI() { return mySpecificResource != null ? StringUtils.format("{}#{}", mySpecificResource.getSource(), mySpecificResource.getSelector()) : myURI; } + + @Override + public int hashCode() { + return Objects.hash(mySpecificResource, myURI); + } } diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/WebAnnotation.java b/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/WebAnnotation.java index 6033b15a..f70fa867 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/WebAnnotation.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/annotations/WebAnnotation.java @@ -13,6 +13,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import info.freelibrary.util.I18nRuntimeException; +import info.freelibrary.util.ListUtils; import info.freelibrary.util.warnings.PMD; import info.freelibrary.iiif.presentation.v3.Annotation; @@ -149,6 +150,26 @@ public boolean bodyHasChoice() { return myBodyHasChoice; } + @Override + public boolean equals(final Object aObject) { + if (this == aObject) { + return true; + } + + if (aObject == null || getClass() != aObject.getClass()) { + return false; + } + + if (aObject instanceof final WebAnnotation other) { + return myBodyHasChoice == other.myBodyHasChoice && Objects.equals(myID, other.myID) && + Objects.equals(myLabel, other.myLabel) && Objects.equals(myMotivation, other.myMotivation) && + ListUtils.equals(myResources, other.myResources) && Objects.equals(myTarget, other.myTarget) && + Objects.equals(myTimeMode, other.myTimeMode); + } + + return false; + } + /** * Gets the resources associated with this annotation. * @@ -213,6 +234,11 @@ public Optional getTimeMode() { return Optional.ofNullable(myTimeMode); } + @Override + public int hashCode() { + return Objects.hash(myBodyHasChoice, myID, myLabel, myMotivation, myResources, myTarget, myTimeMode); + } + /** * Sets an array of resources for this annotation. * diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/utils/I18nUtils.java b/src/main/java/info/freelibrary/iiif/presentation/v3/utils/I18nUtils.java index d2f97c70..378aaf9b 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/utils/I18nUtils.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/utils/I18nUtils.java @@ -35,8 +35,6 @@ public final class I18nUtils { /** An undefined I18n value. */ public static final String UNDEFINED = "und"; - // <[a-zA-Z0-9\\-]+\\s*\\/?\\s*> - // <[a-zA-Z0-9\-]+\s*(\/\s*)?> /** A regex pattern that will match any tag. */ private static final Pattern ANY_TAG_PATTERN = Pattern.compile("<[a-zA-Z0-9\\-]+\\s*(\\/\\s*)?>", Pattern.DOTALL); diff --git a/src/main/java/info/freelibrary/iiif/presentation/v3/utils/JSON.java b/src/main/java/info/freelibrary/iiif/presentation/v3/utils/JSON.java index b35b4d58..85327915 100644 --- a/src/main/java/info/freelibrary/iiif/presentation/v3/utils/JSON.java +++ b/src/main/java/info/freelibrary/iiif/presentation/v3/utils/JSON.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @@ -183,16 +182,6 @@ public static ObjectWriter getWriter(final Class aClass) { return MAPPER.writerFor(aClass); } - /** - * Gets a filter provider writer from the JSON mapper. - * - * @param aProvider A filter provider - * @return An object writer - */ - public static ObjectWriter getWriter(final FilterProvider aProvider) { - return MAPPER.writer(aProvider); - } - /** * Gets a writer for the supplied Java type. * diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/AccompanyingCanvasTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/AccompanyingCanvasTest.java index 5d3b2cae..0ad7bcd1 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/AccompanyingCanvasTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/AccompanyingCanvasTest.java @@ -68,7 +68,7 @@ public final void testAccompanyingCanvasMinter() { final Minter minter = MinterFactory.getMinter(id); final AccompanyingCanvas canvas = new AccompanyingCanvas(minter); - assertTrue(Pattern.compile(id + NOID_PATTERN).matcher(canvas.getID().toString()).matches()); + assertTrue(Pattern.compile(id + NOID_PATTERN).matcher(canvas.getID()).matches()); } /** @@ -94,7 +94,7 @@ public final void testAccompanyingCanvasMinterLabelAsString() { final Label label = new Label(StringUtils.format(LABEL, id)); final AccompanyingCanvas canvas = new AccompanyingCanvas(minter, label); - assertTrue(Pattern.compile(id + NOID_PATTERN).matcher(canvas.getID().toString()).matches()); + assertTrue(Pattern.compile(id + NOID_PATTERN).matcher(canvas.getID()).matches()); } /** diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/CanvasContentTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/CanvasContentTest.java index 9793fe4b..bc5d791c 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/CanvasContentTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/CanvasContentTest.java @@ -4,9 +4,11 @@ import static info.freelibrary.iiif.presentation.v3.utils.TestUtils.format; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.UUID; import org.junit.Before; @@ -14,6 +16,11 @@ import info.freelibrary.util.StringUtils; +import info.freelibrary.iiif.presentation.v3.properties.Behavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.BehaviorList; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.CanvasBehavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.InvalidBehaviorException; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.ResourceBehavior; import info.freelibrary.iiif.presentation.v3.utils.JSON; /** @@ -56,4 +63,57 @@ public final void testDeSerialization() throws IOException { assertEquals(format(json), format(manifest.toString())); } + /** + * Tests {@link CanvasContent#setBehaviors(Behavior...)}. + */ + @Test + public final void testSetBehaviorsBehaviorArray() { + final List behaviors = new CanvasContent(myID).setBehaviors(ResourceBehavior.HIDDEN).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link CanvasContent#setBehaviors(Behavior...)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorArrayInvalid() { + new CanvasContent(myID).setBehaviors(CanvasBehavior.NON_PAGED); + } + + /** + * Tests {@link CanvasContent#setBehaviors(List)}. + */ + @Test + public final void testSetBehaviorsBehaviorList() { + final CanvasContent content = new CanvasContent(myID); + final List behaviors = content.setBehaviors(List.of(ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link CanvasContent#setBehaviors(List)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorListInvalid() { + new CanvasContent(myID).setBehaviors(List.of(CanvasBehavior.NON_PAGED)); + } + + /** + * Tests {@link CanvasContent#setBehaviors(List)} with an explicit {@code BehaviorList}. + */ + @Test + public final void testSetBehaviorsRealBehaviorList() { + final List behaviors = new CanvasContent(myID) + .setBehaviors(new BehaviorList(ResourceBehavior.class, ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } } diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/CollectionTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/CollectionTest.java index b0f4994f..6ebd9cd2 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/CollectionTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/CollectionTest.java @@ -81,17 +81,6 @@ public void testFromManifest() throws IOException { JSON.readValue(expected, Collection.class); } - /** - * Tests reading a collection document from a JSON string. - */ - @Test - public void testFromString() throws IOException { - final String expected = format(StringUtils.read(TEST_FILE1)); - final String found = JSON.readValue(expected, Collection.class).toString(); - - assertEquals(expected, found); - } - /** * Tests that an empty collection doesn't return a null manifests list. */ @@ -126,19 +115,6 @@ public void testNavDate2() { assertEquals(navDate, collection.getNavDate()); } - /** - * Tests reading a collection. - * - * @throws IOException If there is trouble reading the test JSON file. - */ - @Test - public void testReadingCollection() throws IOException { - final String expected = format(StringUtils.read(TEST_FILE1)); - final String found = JSON.readValue(expected, Collection.class).toString(); - - assertEquals(expected, found); - } - /** * Test setting collection behaviors. */ diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/DatasetContentTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/DatasetContentTest.java new file mode 100644 index 00000000..f1dee3fd --- /dev/null +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/DatasetContentTest.java @@ -0,0 +1,88 @@ + +package info.freelibrary.iiif.presentation.v3; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import info.freelibrary.iiif.presentation.v3.properties.Behavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.BehaviorList; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.CanvasBehavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.InvalidBehaviorException; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.ResourceBehavior; + +/** + * Tests of {@code DatasetContent}. + */ +public class DatasetContentTest { + + /** A test ID. */ + private String myID; + + /** + * Sets up testing environment. + */ + @Before + public final void setup() { + myID = "https://" + UUID.randomUUID().toString(); + } + + /** + * Tests {@link DatasetContent#setBehaviors(Behavior...)}. + */ + @Test + public final void testSetBehaviorsBehaviorArray() { + final List behaviors = new DatasetContent(myID).setBehaviors(ResourceBehavior.HIDDEN).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link DatasetContent#setBehaviors(Behavior...)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorArrayInvalid() { + new DatasetContent(myID).setBehaviors(CanvasBehavior.NON_PAGED); + } + + /** + * Tests {@link DatasetContent#setBehaviors(List)}. + */ + @Test + public final void testSetBehaviorsBehaviorList() { + final DatasetContent content = new DatasetContent(myID); + final List behaviors = content.setBehaviors(List.of(ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link DatasetContent#setBehaviors(List)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorListInvalid() { + new DatasetContent(myID).setBehaviors(List.of(CanvasBehavior.NON_PAGED)); + } + + /** + * Tests {@link DatasetContent#setBehaviors(List)} with an explicit {@code BehaviorList}. + */ + @Test + public final void testSetBehaviorsRealBehaviorList() { + final List behaviors = new DatasetContent(myID) + .setBehaviors(new BehaviorList(ResourceBehavior.class, ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } +} diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/ImageContentTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/ImageContentTest.java index c1bd9c00..92274116 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/ImageContentTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/ImageContentTest.java @@ -2,11 +2,21 @@ package info.freelibrary.iiif.presentation.v3; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import java.util.List; +import java.util.UUID; + +import org.junit.Before; import org.junit.Test; +import info.freelibrary.iiif.presentation.v3.properties.Behavior; import info.freelibrary.iiif.presentation.v3.properties.Label; import info.freelibrary.iiif.presentation.v3.properties.MediaType; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.BehaviorList; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.CanvasBehavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.InvalidBehaviorException; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.ResourceBehavior; import info.freelibrary.iiif.presentation.v3.services.ImageService3; /** @@ -23,6 +33,17 @@ public class ImageContentTest { /** A test image service. */ private static final ImageService3 SERVICE = new ImageService3("https://example.org/service"); + /** A test ID. */ + private String myID; + + /** + * Sets up testing environment. + */ + @Before + public final void setup() { + myID = "https://" + UUID.randomUUID().toString(); + } + /** * Tests image content constructor. */ @@ -31,6 +52,60 @@ public void testImageContentString() { assertEquals(IMAGE_URI, new ImageContent(IMAGE_URI).getID()); } + /** + * Tests {@link ImageContent#setBehaviors(Behavior...)}. + */ + @Test + public final void testSetBehaviorsBehaviorArray() { + final List behaviors = new ImageContent(myID).setBehaviors(ResourceBehavior.HIDDEN).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link ImageContent#setBehaviors(Behavior...)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorArrayInvalid() { + new ImageContent(myID).setBehaviors(CanvasBehavior.NON_PAGED); + } + + /** + * Tests {@link ImageContent#setBehaviors(List)}. + */ + @Test + public final void testSetBehaviorsBehaviorList() { + final ImageContent content = new ImageContent(myID); + final List behaviors = content.setBehaviors(List.of(ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link ImageContent#setBehaviors(List)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorListInvalid() { + new ImageContent(myID).setBehaviors(List.of(CanvasBehavior.NON_PAGED)); + } + + /** + * Tests {@link ImageContent#setBehaviors(List)} with an explicit {@code BehaviorList}. + */ + @Test + public final void testSetBehaviorsRealBehaviorList() { + final List behaviors = new ImageContent(myID) + .setBehaviors(new BehaviorList(ResourceBehavior.class, ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + /** * Tests setting media type. */ diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/ModelContentTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/ModelContentTest.java new file mode 100644 index 00000000..6f013657 --- /dev/null +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/ModelContentTest.java @@ -0,0 +1,88 @@ + +package info.freelibrary.iiif.presentation.v3; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import info.freelibrary.iiif.presentation.v3.properties.Behavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.BehaviorList; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.CanvasBehavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.InvalidBehaviorException; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.ResourceBehavior; + +/** + * Tests of {@link ModelContent}. + */ +public class ModelContentTest { + + /** A test ID. */ + private String myID; + + /** + * Sets up testing environment. + */ + @Before + public final void setup() { + myID = "https://" + UUID.randomUUID().toString(); + } + + /** + * Tests {@link ModelContent#setBehaviors(Behavior...)}. + */ + @Test + public final void testSetBehaviorsBehaviorArray() { + final List behaviors = new ModelContent(myID).setBehaviors(ResourceBehavior.HIDDEN).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link ModelContent#setBehaviors(Behavior...)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorArrayInvalid() { + new ModelContent(myID).setBehaviors(CanvasBehavior.NON_PAGED); + } + + /** + * Tests {@link ModelContent#setBehaviors(List)}. + */ + @Test + public final void testSetBehaviorsBehaviorList() { + final ModelContent content = new ModelContent(myID); + final List behaviors = content.setBehaviors(List.of(ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link ModelContent#setBehaviors(List)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorListInvalid() { + new ModelContent(myID).setBehaviors(List.of(CanvasBehavior.NON_PAGED)); + } + + /** + * Tests {@link ModelContent#setBehaviors(List)} with an explicit {@code BehaviorList}. + */ + @Test + public final void testSetBehaviorsRealBehaviorList() { + final List behaviors = new ModelContent(myID) + .setBehaviors(new BehaviorList(ResourceBehavior.class, ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } +} diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/SoundContentTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/SoundContentTest.java index 77e2de26..a3ee2c17 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/SoundContentTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/SoundContentTest.java @@ -3,9 +3,11 @@ import static info.freelibrary.iiif.presentation.v3.utils.TestUtils.format; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.UUID; import org.junit.Before; @@ -13,6 +15,11 @@ import info.freelibrary.util.StringUtils; +import info.freelibrary.iiif.presentation.v3.properties.Behavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.BehaviorList; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.CanvasBehavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.InvalidBehaviorException; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.ResourceBehavior; import info.freelibrary.iiif.presentation.v3.utils.JSON; /** @@ -44,6 +51,60 @@ public final void testFixture0003() throws IOException { assertEquals(expected, format(found)); } + /** + * Tests {@link SoundContent#setBehaviors(Behavior...)}. + */ + @Test + public final void testSetBehaviorsBehaviorArray() { + final List behaviors = new SoundContent(myID).setBehaviors(ResourceBehavior.HIDDEN).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link SoundContent#setBehaviors(Behavior...)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorArrayInvalid() { + new SoundContent(myID).setBehaviors(CanvasBehavior.NON_PAGED); + } + + /** + * Tests {@link SoundContent#setBehaviors(List)}. + */ + @Test + public final void testSetBehaviorsBehaviorList() { + final SoundContent content = new SoundContent(myID); + final List behaviors = content.setBehaviors(List.of(ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link SoundContent#setBehaviors(List)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorListInvalid() { + new SoundContent(myID).setBehaviors(List.of(CanvasBehavior.NON_PAGED)); + } + + /** + * Tests {@link SoundContent#setBehaviors(List)} with an explicit {@code BehaviorList}. + */ + @Test + public final void testSetBehaviorsRealBehaviorList() { + final List behaviors = new SoundContent(myID) + .setBehaviors(new BehaviorList(ResourceBehavior.class, ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + /** * Test method for {@link SoundContent#getDuration()}. */ diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/VideoContentTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/VideoContentTest.java index a7092b28..75d92455 100644 --- a/src/test/java/info/freelibrary/iiif/presentation/v3/VideoContentTest.java +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/VideoContentTest.java @@ -3,9 +3,11 @@ import static info.freelibrary.iiif.presentation.v3.utils.TestUtils.format; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.UUID; import org.junit.Before; @@ -13,6 +15,11 @@ import info.freelibrary.util.StringUtils; +import info.freelibrary.iiif.presentation.v3.properties.Behavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.BehaviorList; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.CanvasBehavior; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.InvalidBehaviorException; +import info.freelibrary.iiif.presentation.v3.properties.behaviors.ResourceBehavior; import info.freelibrary.iiif.presentation.v3.utils.JSON; /** @@ -44,6 +51,60 @@ public final void testFixture0003() throws IOException { assertEquals(expected, format(found)); } + /** + * Tests {@link VideoContent#setBehaviors(Behavior...)}. + */ + @Test + public final void testSetBehaviorsBehaviorArray() { + final List behaviors = new VideoContent(myID).setBehaviors(ResourceBehavior.HIDDEN).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link VideoContent#setBehaviors(Behavior...)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorArrayInvalid() { + new VideoContent(myID).setBehaviors(CanvasBehavior.NON_PAGED); + } + + /** + * Tests {@link VideoContent#setBehaviors(List)}. + */ + @Test + public final void testSetBehaviorsBehaviorList() { + final VideoContent content = new VideoContent(myID); + final List behaviors = content.setBehaviors(List.of(ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + + /** + * Tests {@link VideoContent#setBehaviors(List)} with a bad behavior. + */ + @Test(expected = InvalidBehaviorException.class) + public final void testSetBehaviorsBehaviorListInvalid() { + new VideoContent(myID).setBehaviors(List.of(CanvasBehavior.NON_PAGED)); + } + + /** + * Tests {@link VideoContent#setBehaviors(List)} with an explicit {@code BehaviorList}. + */ + @Test + public final void testSetBehaviorsRealBehaviorList() { + final List behaviors = new VideoContent(myID) + .setBehaviors(new BehaviorList(ResourceBehavior.class, ResourceBehavior.HIDDEN)).getBehaviors(); + + assertEquals(1, behaviors.size()); + assertEquals(ResourceBehavior.HIDDEN, behaviors.get(0)); + assertTrue(behaviors instanceof BehaviorList); + } + /** * Tests setting and getting video content duration. */ diff --git a/src/test/java/info/freelibrary/iiif/presentation/v3/utils/JSONTest.java b/src/test/java/info/freelibrary/iiif/presentation/v3/utils/JSONTest.java new file mode 100644 index 00000000..ed77269e --- /dev/null +++ b/src/test/java/info/freelibrary/iiif/presentation/v3/utils/JSONTest.java @@ -0,0 +1,300 @@ + +package info.freelibrary.iiif.presentation.v3.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import info.freelibrary.util.StringUtils; + +import info.freelibrary.iiif.presentation.v3.AnnotationPage; +import info.freelibrary.iiif.presentation.v3.DatasetContent; +import info.freelibrary.iiif.presentation.v3.ResourceTypes; +import info.freelibrary.iiif.presentation.v3.annotations.BookmarkingAnnotation; +import info.freelibrary.iiif.presentation.v3.annotations.Purpose; +import info.freelibrary.iiif.presentation.v3.annotations.Target; +import info.freelibrary.iiif.presentation.v3.annotations.WebAnnotation; + +/** + * Tests of the {@link JSON} utility class. + */ +public class JSONTest { + + /** A test JSON object. */ + private static final String TEST_JSON = """ + { + "id" : "{}", + "type" : "Dataset" + } + """; + + /** An ID used in testing. */ + private String myID; + + /** + * Sets up the testing environment. + */ + @Before + public final void setUp() { + myID = "https://" + UUID.randomUUID().toString(); + } + + /** + * Test method for {@link JSON#convertValue(Object, Class)}. + */ + @Test + public final void testConvertValueObjectClassOfT() { + final DatasetContent datasetContent = new DatasetContent(myID); + final ObjectNode objNode = JSON.createObjectNode(); + + objNode.put(JsonKeys.ID, myID); + objNode.put(JsonKeys.TYPE, ResourceTypes.DATASET); + + assertEquals(datasetContent, JSON.convertValue(objNode, DatasetContent.class)); + } + + /** + * Test method for {@link JSON#convertValue(Object, JavaType)}. + */ + @Test + public final void testConvertValueObjectJavaType() { + final JavaType type = JSON.getTypeFactory().constructParametricType(AnnotationPage.class, WebAnnotation.class); + final BookmarkingAnnotation annotation = new BookmarkingAnnotation(myID, new Target(myID)); + final AnnotationPage page = new AnnotationPage<>(myID); + final ObjectNode annoNode = JSON.createObjectNode(); + final ObjectNode rootNode = JSON.createObjectNode(); + + page.addAnnotations(annotation); + + rootNode.put(JsonKeys.ID, myID); + rootNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION_PAGE); + annoNode.put(JsonKeys.ID, myID); + annoNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION); + annoNode.put(JsonKeys.MOTIVATION, Purpose.BOOKMARKING.toString()); + annoNode.put(JsonKeys.TARGET, myID); + rootNode.putArray(JsonKeys.ITEMS).add(annoNode); + + assertEquals(page, JSON.convertValue(rootNode, type)); + } + + /** + * Test method for {@link JSON#convertValue(Object, TypeReference)}. + */ + @Test + public final void testConvertValueObjectTypeReferenceOfT() { + final TypeReference> typeRef = new TypeReference<>() {}; + final BookmarkingAnnotation annotation = new BookmarkingAnnotation(myID, new Target(myID)); + final AnnotationPage page = new AnnotationPage<>(myID); + final ObjectNode annoNode = JSON.createObjectNode(); + final ObjectNode rootNode = JSON.createObjectNode(); + + page.addAnnotations(annotation); + + rootNode.put(JsonKeys.ID, myID); + rootNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION_PAGE); + annoNode.put(JsonKeys.ID, myID); + annoNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION); + annoNode.put(JsonKeys.MOTIVATION, Purpose.BOOKMARKING.toString()); + annoNode.put(JsonKeys.TARGET, myID); + rootNode.putArray(JsonKeys.ITEMS).add(annoNode); + + assertEquals(page, JSON.convertValue(rootNode, typeRef)); + } + + /** + * Test method for {@link JSON#createArrayNode()}. + */ + @Test + public final void testCreateArrayNode() { + assertTrue(JSON.createArrayNode() instanceof ArrayNode); + } + + /** + * Test method for {@link JSON#createObjectNode()}. + */ + @Test + public final void testCreateObjectNode() { + assertTrue(JSON.createObjectNode() instanceof ObjectNode); + } + + /** + * Test method for {@link JSON#getPrettyWriter()}. + */ + @Test + public final void testGetPrettyWriter() throws JsonProcessingException { + final ObjectWriter writer = JSON.getPrettyWriter(); + final String json = StringUtils.format(TEST_JSON, myID); + + assertEquals(json.trim(), writer.writeValueAsString(JSON.readValue(json, DatasetContent.class))); + } + + /** + * Test method for {@link JSON#getReader()}. + */ + @Test + public final void testGetReader() throws IOException { + final ObjectWriter writer = JSON.getPrettyWriter(); + final String json = StringUtils.format(TEST_JSON, myID); + + assertEquals(json.trim(), writer.writeValueAsString(JSON.getReader().readValue(json, DatasetContent.class))); + } + + /** + * Test method for {@link JSON#getReader(Class)}. + */ + @Test + public final void testGetReaderClassOfT() throws JsonProcessingException { + final ObjectWriter writer = JSON.getPrettyWriter(); + final String json = StringUtils.format(TEST_JSON, myID); + + assertEquals(json.trim(), writer.writeValueAsString(JSON.getReader(DatasetContent.class).readValue(json))); + } + + /** + * Test method for {@link JSON#getReader(JavaType)}. + */ + @Test + public final void testGetReaderJavaType() throws IOException { + final JavaType type = JSON.getTypeFactory().constructParametricType(AnnotationPage.class, WebAnnotation.class); + final BookmarkingAnnotation annotation = new BookmarkingAnnotation(myID, new Target(myID)); + final AnnotationPage page = new AnnotationPage<>(myID); + final ObjectNode annoNode = JSON.createObjectNode(); + final ObjectNode rootNode = JSON.createObjectNode(); + + page.addAnnotations(annotation); + + rootNode.put(JsonKeys.ID, myID); + rootNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION_PAGE); + annoNode.put(JsonKeys.ID, myID); + annoNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION); + annoNode.put(JsonKeys.MOTIVATION, Purpose.BOOKMARKING.toString()); + annoNode.put(JsonKeys.TARGET, myID); + rootNode.putArray(JsonKeys.ITEMS).add(annoNode); + + assertEquals(page, JSON.getReader(type).readValue(rootNode)); + } + + /** + * Test method for {@link JSON#getReader(TypeReference)}. + */ + @Test + public final void testGetReaderTypeReferenceOfT() throws IOException { + final TypeReference> typeRef = new TypeReference<>() {}; + final BookmarkingAnnotation annotation = new BookmarkingAnnotation(myID, new Target(myID)); + final AnnotationPage page = new AnnotationPage<>(myID); + final ObjectNode annoNode = JSON.createObjectNode(); + final ObjectNode rootNode = JSON.createObjectNode(); + + page.addAnnotations(annotation); + + rootNode.put(JsonKeys.ID, myID); + rootNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION_PAGE); + annoNode.put(JsonKeys.ID, myID); + annoNode.put(JsonKeys.TYPE, ResourceTypes.ANNOTATION); + annoNode.put(JsonKeys.MOTIVATION, Purpose.BOOKMARKING.toString()); + annoNode.put(JsonKeys.TARGET, myID); + rootNode.putArray(JsonKeys.ITEMS).add(annoNode); + + assertEquals(page, JSON.getReader(typeRef).readValue(rootNode)); + } + + /** + * Test method for {@link JSON#getTypeFactory()}. + */ + @Test + public final void testGetTypeFactory() { + assertTrue(JSON.getTypeFactory() instanceof TypeFactory); + } + + /** + * Test method for {@link JSON#getWriter()}. + */ + @Test + public final void testGetWriter() { + assertTrue(JSON.getWriter() instanceof ObjectWriter); + } + + /** + * Test method for {@link JSON#getWriter(java.lang.Class)}. + */ + @Test + public final void testGetWriterClassOfT() { + assertTrue(JSON.getWriter(DatasetContent.class).canSerialize(DatasetContent.class)); + } + + /** + * Test method for {@link JSON#getWriter(JavaType)}. + */ + @Test + public final void testGetWriterJavaType() { + final JavaType type = JSON.getTypeFactory().constructParametricType(AnnotationPage.class, WebAnnotation.class); + assertTrue(JSON.getWriter(type).canSerialize(AnnotationPage.class)); + } + + /** + * Test method for {@link JSON#getWriter(TypeReference)}. + */ + @Test + public final void testGetWriterTypeReferenceOfT() { + final TypeReference> typeRef = new TypeReference<>() {}; + assertTrue(JSON.getWriter(typeRef).canSerialize(AnnotationPage.class)); + } + + /** + * Test method for {@link JSON#readValue(String, Class)}. + */ + @Test + public final void testReadValueStringClassOfT() { + final String json = StringUtils.format(TEST_JSON, myID).trim(); + assertEquals(json, JSON.readValue(json, DatasetContent.class).toString()); + } + + /** + * Test method for {@link JSON#readValue(String, JavaType)}. + */ + @Test + public final void testReadValueStringJavaType() throws IOException { + final JavaType type = JSON.getTypeFactory().constructType(DatasetContent.class); + final String json = StringUtils.format(TEST_JSON, myID).trim(); + + assertEquals(json, JSON.getReader(type).readValue(json).toString()); + } + + /** + * Test method for {@link JSON#readValue(String, TypeReference)}. + */ + @Test + public final void testReadValueStringTypeReferenceOfT() throws IOException { + final TypeReference typeRef = new TypeReference<>() {}; + final String json = StringUtils.format(TEST_JSON, myID).trim(); + + assertEquals(json, JSON.getReader(typeRef).readValue(json).toString()); + } + + /** + * Test method for {@link JSON#valueToTree(Object)}. + */ + @Test + public final void testValueToTree() { + final JavaType type = JSON.getTypeFactory().constructType(DatasetContent.class); + final String json = StringUtils.format(TEST_JSON, myID).trim(); + final JsonNode root = JSON.valueToTree(JSON.readValue(json, type)); + + assertEquals(json, root.toPrettyString()); + } + +}