From 31118a56eb6e1bbe13bfc782963a13c7514546f6 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Tue, 6 Nov 2018 11:57:25 +0100 Subject: [PATCH 1/5] ci: add openjdk11 to build matrix --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cd057b3..de1c1a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: java jdk: - openjdk8 - oraclejdk8 +- openjdk11 addons: apt: packages: From 8a7796f2e9255f3ac29cecb65828d68b062f60f1 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Wed, 7 Nov 2018 13:31:00 +0100 Subject: [PATCH 2/5] pom: update versions of jacoco-maven-plugin, maven-javadoc-plugin and maven-surefire-plugin (openjdk build fix) --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index db392e8..38d88b5 100644 --- a/pom.xml +++ b/pom.xml @@ -49,14 +49,14 @@ 1.8 23.0 2.9.7 - 0.7.9 + 0.8.2 1.5.0 4.12 3.7.0 1.6 - 2.10.4 + 3.0.1 3.0.1 - 2.20.1 + 2.22.1 1.6.7 0.9.10 0.8 From 5e6a23133ea618cdcee3ef89591191dd8daa9e43 Mon Sep 17 00:00:00 2001 From: Ralf Eichinger Date: Tue, 27 Nov 2018 16:30:29 +0100 Subject: [PATCH 3/5] Fix issue #4 (javadocs) --- .gitignore | 1 + pom.xml | 9 -- .../iiif/model/auth/AccessCookieService.java | 3 + .../iiif/model/image/ImageApiProfile.java | 104 ++++++++++-------- .../iiif/model/image/ImageApiSelector.java | 46 ++++---- .../iiif/model/image/RegionRequest.java | 82 ++++++++------ .../iiif/model/image/RotationRequest.java | 10 +- .../iiif/model/image/SizeRequest.java | 41 +++++-- .../IiifIndexedListSerializer.java | 18 ++- .../iiif/model/sharedcanvas/Canvas.java | 7 +- .../iiif/model/sharedcanvas/Collection.java | 14 ++- .../iiif/model/sharedcanvas/Range.java | 27 +++-- .../iiif/model/sharedcanvas/Resource.java | 15 ++- 13 files changed, 229 insertions(+), 148 deletions(-) diff --git a/.gitignore b/.gitignore index 612c5bc..c0335e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target .idea *.iml +/nb-configuration.xml \ No newline at end of file diff --git a/pom.xml b/pom.xml index 38d88b5..ae79ce4 100644 --- a/pom.xml +++ b/pom.xml @@ -164,15 +164,6 @@ org.apache.maven.plugins maven-javadoc-plugin ${version.maven-javadoc-plugin} - - ch.raffael.mddoclet.MarkdownDoclet - - ch.raffael.markdown-doclet - markdown-doclet - 1.4 - - true - attach-javadocs diff --git a/src/main/java/de/digitalcollections/iiif/model/auth/AccessCookieService.java b/src/main/java/de/digitalcollections/iiif/model/auth/AccessCookieService.java index ee9dffb..4a22111 100644 --- a/src/main/java/de/digitalcollections/iiif/model/auth/AccessCookieService.java +++ b/src/main/java/de/digitalcollections/iiif/model/auth/AccessCookieService.java @@ -24,6 +24,7 @@ @JsonPropertyOrder({"@context", "@id", "profile", "label", "header", "description", "confirmLabel", "failureHeader", "failureDescription", "service"}) public class AccessCookieService extends Service { + public static final String CONTEXT = "http://iiif.io/api/auth/1/context.json"; @JsonProperty("profile") @@ -50,6 +51,8 @@ public AccessCookieService(@JsonProperty("@id") String identifier, @JsonProperty /** * Create a new access cookie service from an (optional) identifier and an authentication pattern. * + * @param identifier (optional) identifier + * @param pattern authentication pattern * @throws IllegalArgumentException If the auth pattern is not "external" and no identifier is provided. */ public AccessCookieService(URI identifier, AuthPattern pattern) throws IllegalArgumentException { diff --git a/src/main/java/de/digitalcollections/iiif/model/image/ImageApiProfile.java b/src/main/java/de/digitalcollections/iiif/model/image/ImageApiProfile.java index 523562f..fe6070a 100644 --- a/src/main/java/de/digitalcollections/iiif/model/image/ImageApiProfile.java +++ b/src/main/java/de/digitalcollections/iiif/model/image/ImageApiProfile.java @@ -26,6 +26,7 @@ * and http://iiif.io/api/image/2.1/compliance/ for an overview of the available compliance levels. */ public class ImageApiProfile extends Profile { + public enum Format { JPG(MimeType.fromTypename("image/jpeg")), TIF(MimeType.fromTypename("image/tiff")), @@ -63,10 +64,11 @@ public String toString() { } public static class Feature { + private enum ImageApiFeature { - BASE_URI_REDIRECT, CANONICAL_LINK_HEADER, CORS, JSONLD_MEDIA_TYPE, MIRRORING, PROFILE_LINK_HEADER, - REGION_BY_PCT, REGION_BY_PX, REGION_SQUARE, ROTATION_ARBITRARY, ROTATION_BY_90S, SIZE_ABOVE_FULL, - SIZE_BY_WH_LISTED, SIZE_BY_FORCED_WH, SIZE_BY_H, SIZE_BY_PCT, SIZE_BY_W, SIZE_BY_WH, SIZE_BY_CONFINED_WH, + BASE_URI_REDIRECT, CANONICAL_LINK_HEADER, CORS, JSONLD_MEDIA_TYPE, MIRRORING, PROFILE_LINK_HEADER, + REGION_BY_PCT, REGION_BY_PX, REGION_SQUARE, ROTATION_ARBITRARY, ROTATION_BY_90S, SIZE_ABOVE_FULL, + SIZE_BY_WH_LISTED, SIZE_BY_FORCED_WH, SIZE_BY_H, SIZE_BY_PCT, SIZE_BY_W, SIZE_BY_WH, SIZE_BY_CONFINED_WH, SIZE_BY_DISTORTED_WH, OTHER } @@ -168,59 +170,62 @@ public boolean equals(Object obj) { } Feature other = (Feature) obj; return Objects.equals(this.imageApiFeature, other.imageApiFeature) - && Objects.equals(this.customFeature, other.customFeature); + && Objects.equals(this.customFeature, other.customFeature); } } public static final ImageApiProfile LEVEL_ZERO = new ImageApiProfile("http://iiif.io/api/image/2/level0.json"); + static { LEVEL_ZERO.addFormat(Format.JPG); LEVEL_ZERO.addQuality(Quality.DEFAULT); } public static final ImageApiProfile LEVEL_ONE = new ImageApiProfile("http://iiif.io/api/image/2/level1.json"); + static { LEVEL_ONE.addFeature( - Feature.REGION_BY_PX, - Feature.SIZE_BY_W, - Feature.SIZE_BY_H, - Feature.SIZE_BY_PCT, - Feature.BASE_URI_REDIRECT, - Feature.CORS, - Feature.JSONLD_MEDIA_TYPE); + Feature.REGION_BY_PX, + Feature.SIZE_BY_W, + Feature.SIZE_BY_H, + Feature.SIZE_BY_PCT, + Feature.BASE_URI_REDIRECT, + Feature.CORS, + Feature.JSONLD_MEDIA_TYPE); LEVEL_ONE.addFormat(Format.JPG); LEVEL_ONE.addQuality(Quality.DEFAULT); } public static final ImageApiProfile LEVEL_TWO = new ImageApiProfile("http://iiif.io/api/image/2/level2.json"); + static { LEVEL_TWO.addFeature( - Feature.REGION_BY_PX, - Feature.REGION_BY_PCT, - Feature.SIZE_BY_W, - Feature.SIZE_BY_H, - Feature.SIZE_BY_PCT, - Feature.SIZE_BY_CONFINED_WH, - Feature.SIZE_BY_DISTORTED_WH, - Feature.SIZE_BY_WH, - Feature.ROTATION_BY_90S, - Feature.BASE_URI_REDIRECT, - Feature.CORS, - Feature.JSONLD_MEDIA_TYPE); + Feature.REGION_BY_PX, + Feature.REGION_BY_PCT, + Feature.SIZE_BY_W, + Feature.SIZE_BY_H, + Feature.SIZE_BY_PCT, + Feature.SIZE_BY_CONFINED_WH, + Feature.SIZE_BY_DISTORTED_WH, + Feature.SIZE_BY_WH, + Feature.ROTATION_BY_90S, + Feature.BASE_URI_REDIRECT, + Feature.CORS, + Feature.JSONLD_MEDIA_TYPE); LEVEL_TWO.addFormat(Format.JPG, Format.PNG); LEVEL_TWO.addQuality(Quality.DEFAULT, Quality.COLOR, Quality.GRAY, Quality.BITONAL); } public static final Set V1_PROFILES = ImmutableSet.of( - "http://library.stanford.edu/iiif/image-api/compliance.html#level0", - "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0", - "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level0", - "http://library.stanford.edu/iiif/image-api/compliance.html#level1", - "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", - "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", - "http://library.stanford.edu/iiif/image-api/compliance.html#level2", - "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2", - "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2"); + "http://library.stanford.edu/iiif/image-api/compliance.html#level0", + "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0", + "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level0", + "http://library.stanford.edu/iiif/image-api/compliance.html#level1", + "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", + "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", + "http://library.stanford.edu/iiif/image-api/compliance.html#level2", + "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2", + "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2"); @JsonProperty("@context") public static final String CONTEXT = "http://iiif.io/api/image/2/context.json"; @@ -247,12 +252,15 @@ public static ImageApiProfile fromUrl(String url) { return LEVEL_TWO; } else if (V1_PROFILES.contains(url)) { String lvl = url.split("#level")[1]; - if (lvl.equals("0")) { - return new ImageApiProfile(url, LEVEL_ZERO); - } else if (lvl.equals("1")) { - return new ImageApiProfile(url, LEVEL_ONE); - } else if (lvl.equals("2")) { - return new ImageApiProfile(url, LEVEL_TWO); + switch (lvl) { + case "0": + return new ImageApiProfile(url, LEVEL_ZERO); + case "1": + return new ImageApiProfile(url, LEVEL_ONE); + case "2": + return new ImageApiProfile(url, LEVEL_TWO); + default: + break; } } return new ImageApiProfile(url); @@ -348,13 +356,17 @@ public void setMaxWidth(Integer maxWidth) { this.maxWidth = maxWidth; } - /** Merge multiple profiles into one. - Useful for image servers that want to consolidate the limits given in a info.json. */ + /** + * Merge multiple profiles into one. Useful for image servers that want to consolidate the limits given in a info.json. + * + * @param profiles profiles to be merged + * @return merged profile + */ public static ImageApiProfile merge(List profiles) { return profiles.stream() - .filter(ImageApiProfile.class::isInstance) - .map(ImageApiProfile.class::cast) - .reduce(new ImageApiProfile(), ImageApiProfile::merge); + .filter(ImageApiProfile.class::isInstance) + .map(ImageApiProfile.class::cast) + .reduce(new ImageApiProfile(), ImageApiProfile::merge); } private Stream streamNotNull(Collection src) { @@ -365,7 +377,11 @@ private Stream streamNotNull(Collection src) { } } - /** Merge two profiles. */ + /** + * Merge two profiles. + * @param other profile to be merged + * @return merged profile + */ public ImageApiProfile merge(ImageApiProfile other) { ImageApiProfile merged = new ImageApiProfile(); streamNotNull(this.features).forEach(merged::addFeature); diff --git a/src/main/java/de/digitalcollections/iiif/model/image/ImageApiSelector.java b/src/main/java/de/digitalcollections/iiif/model/image/ImageApiSelector.java index d71dacb..9166a70 100644 --- a/src/main/java/de/digitalcollections/iiif/model/image/ImageApiSelector.java +++ b/src/main/java/de/digitalcollections/iiif/model/image/ImageApiSelector.java @@ -23,15 +23,16 @@ */ @JsonTypeName(ImageApiSelector.TYPE) public class ImageApiSelector implements Selector { + public static String CONTEXT = "http://iiif.io/api/annex/openannotation/context.json"; public static final String TYPE = "iiif:ImageApiSelector"; private static final Pattern REQUEST_PAT = Pattern.compile( - "/?(?[^/]+)" + - "/(?[^/]+)" + - "/(?[^/]+)" + - "/(?[^/]+)" + - "/(?[^/]+?)\\.(?[^/]+?)$"); + "/?(?[^/]+)" + + "/(?[^/]+)" + + "/(?[^/]+)" + + "/(?[^/]+)" + + "/(?[^/]+?)\\.(?[^/]+?)$"); private String identifier; private RegionRequest region; @@ -88,13 +89,13 @@ public URI asImageApiUri(URI baseUri) { @Override public String toString() { return String.format( - "%s%s/%s/%s/%s.%s", - identifier != null ? urlEncode(identifier) + "/" : "", - Objects.toString(region, "full"), - Objects.toString(size, "full"), - Objects.toString(rotation, "0"), - Objects.toString(quality, "default"), - Objects.toString(format, "jpg")); + "%s%s/%s/%s/%s.%s", + identifier != null ? urlEncode(identifier) + "/" : "", + Objects.toString(region, "full"), + Objects.toString(size, "full"), + Objects.toString(rotation, "0"), + Objects.toString(quality, "default"), + Objects.toString(format, "jpg")); } /** The spec says we have to urlencode values, but only characters outside of the US ASCII range and gen-delims @@ -103,7 +104,7 @@ public String toString() { * Great and pragmatic choice for readability, more code for us :-) */ private static String urlEncode(String str) { Set excluded = ImmutableSet.of( - ":","!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="); + ":", "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="); String encoded = new Encoded(str).toString(); for (String ex : excluded) { encoded = encoded.replaceAll(new Encoded(ex).toString(), ex); @@ -111,13 +112,14 @@ private static String urlEncode(String str) { return encoded; } - /** Create the canonical of the Image API request. + /** + * Create the canonical of the Image API request.See http://iiif.io/api/image/2.1/#canonical-uri-syntax * - * See http://iiif.io/api/image/2.1/#canonical-uri-syntax * @param nativeSize Native size of the image the selector is applied to * @param profile Image API profile used * @param defaultQuality The native/default quality of the image the selector is applied to * @return The canonical form of the Image API request + * @throws de.digitalcollections.iiif.model.image.ResolvingException if RegionRequest can not be instantiated from canonical form of region */ public String getCanonicalForm(Dimension nativeSize, ImageApiProfile profile, Quality defaultQuality) throws ResolvingException { Dimension scaleReference = nativeSize; @@ -126,13 +128,13 @@ public String getCanonicalForm(Dimension nativeSize, ImageApiProfile profile, Qu scaleReference = new Dimension((int) canonicalRegion.getWidth(), (int) canonicalRegion.getHeight()); } return String.format( - "%s%s/%s/%s/%s.%s", - identifier != null ? urlEncode(identifier) + "/" : "", - region.getCanonicalForm(nativeSize), - size.getCanonicalForm(scaleReference, profile), - rotation.toString(), - quality.equals(defaultQuality) ? "default" : quality.toString(), - format.toString()); + "%s%s/%s/%s/%s.%s", + identifier != null ? urlEncode(identifier) + "/" : "", + region.getCanonicalForm(nativeSize), + size.getCanonicalForm(scaleReference, profile), + rotation.toString(), + quality.equals(defaultQuality) ? "default" : quality.toString(), + format.toString()); } public String getIdentifier() { diff --git a/src/main/java/de/digitalcollections/iiif/model/image/RegionRequest.java b/src/main/java/de/digitalcollections/iiif/model/image/RegionRequest.java index 1f89c3f..306dbfa 100644 --- a/src/main/java/de/digitalcollections/iiif/model/image/RegionRequest.java +++ b/src/main/java/de/digitalcollections/iiif/model/image/RegionRequest.java @@ -12,8 +12,10 @@ import java.util.stream.Stream; public class RegionRequest { + /** We use BigDecimals for the relative region, since we want to preserve the precision of the request **/ private class RelativeBox { + final BigDecimal x; final BigDecimal y; final BigDecimal w; @@ -36,9 +38,9 @@ public boolean equals(Object o) { } RelativeBox that = (RelativeBox) o; return Objects.equal(x, that.x) - && Objects.equal(y, that.y) - && Objects.equal(w, that.w) - && Objects.equal(h, that.h); + && Objects.equal(y, that.y) + && Objects.equal(w, that.w) + && Objects.equal(h, that.h); } @Override @@ -56,6 +58,8 @@ public int hashCode() { /** * Parse an IIIF Image API compliant region request string * + * @param str region request string + * @return resulting RegionRequest instance * @throws ResolvingException if the request string is malformed. */ @JsonCreator @@ -72,16 +76,16 @@ public static RegionRequest fromString(String str) throws ResolvingException { } if (matcher.group(1) == null) { return new RegionRequest( - Integer.valueOf(matcher.group(2)), - Integer.valueOf(matcher.group(3)), - Integer.valueOf(matcher.group(4)), - Integer.valueOf(matcher.group(5))); + Integer.valueOf(matcher.group(2)), + Integer.valueOf(matcher.group(3)), + Integer.valueOf(matcher.group(4)), + Integer.valueOf(matcher.group(5))); } else { return new RegionRequest( - new BigDecimal(matcher.group(2)), - new BigDecimal(matcher.group(3)), - new BigDecimal(matcher.group(4)), - new BigDecimal(matcher.group(5))); + new BigDecimal(matcher.group(2)), + new BigDecimal(matcher.group(3)), + new BigDecimal(matcher.group(4)), + new BigDecimal(matcher.group(5))); } } @@ -93,7 +97,8 @@ public RegionRequest() { } /** - * Pass 'true' to create a region that selects a square region from the image, i.e. the 'square' syntax. + * Pass 'true' to create a region that selects a square region from the image, i.e.the 'square' syntax. + * @param square true, if square region should be selected */ public RegionRequest(boolean square) { this.square = square; @@ -107,10 +112,14 @@ private RegionRequest(BigDecimal x, BigDecimal y, BigDecimal width, BigDecimal h } /** - * Create a RegionRequest request that is expressed using relative values, i.e. the "pct:x,y,w,h" syntax + * Create a RegionRequest request that is expressed using relative values, i.e.the "pct:x,y,w,h" syntax * * The values must be between 0.0 and 100.0. * + * @param x relative upper left x position of region + * @param y relative upper left y position of region + * @param width relative width of region + * @param height relative height of region * @throws ResolvingException if the values fall outside of the allowed range */ public RegionRequest(double x, double y, double width, double height) throws ResolvingException { @@ -119,6 +128,10 @@ public RegionRequest(double x, double y, double width, double height) throws Res /** * Create a RegionRequest request that is expressed using absolute values. + * @param x absolute upper left x position of region + * @param y absolute upper left y position of region + * @param width absolute width of region + * @param height absolute height of region */ public RegionRequest(int x, int y, int width, int height) { this.absoluteBox = new Rectangle(x, y, width, height); @@ -126,19 +139,21 @@ public RegionRequest(int x, int y, int width, int height) { /** * Returns the requested region + * @return get a Rectangle2D instance representing the region */ public Rectangle2D getRegion() { if (isRelative()) { return new Rectangle2D.Double( - relativeBox.x.doubleValue(), relativeBox.y.doubleValue(), - relativeBox.w.doubleValue(), relativeBox.h.doubleValue()); + relativeBox.x.doubleValue(), relativeBox.y.doubleValue(), + relativeBox.w.doubleValue(), relativeBox.h.doubleValue()); } else { return absoluteBox; } } /** - * Returns whether the region is epxressed in relative terms. + * Returns whether the region is expressed in relative terms. + * @return true, if region is defined in relative values */ public boolean isRelative() { return relativeBox != null; @@ -146,6 +161,7 @@ public boolean isRelative() { /** * Returns whether a square region is selected. + * @return true, if region should be square */ public boolean isSquare() { return square; @@ -153,6 +169,7 @@ public boolean isSquare() { /** * Create an IIIF Image API compliant region request string + * @return iiif image api compliant region request string */ @Override @JsonValue @@ -172,9 +189,9 @@ public String toString() { public String getCanonicalForm(Dimension imageDims) throws ResolvingException { Rectangle resolved = this.resolve(imageDims); boolean isFull = resolved.x == 0 - && resolved.y == 0 - && resolved.width == imageDims.width - && resolved.height == imageDims.height; + && resolved.y == 0 + && resolved.width == imageDims.width + && resolved.height == imageDims.height; if (isFull) { return "full"; } else { @@ -184,19 +201,22 @@ public String getCanonicalForm(Dimension imageDims) throws ResolvingException { /** * Resolve the region request into an actual region that can be used for cropping the image + * @param imageDims actual image dimensions + * @return Rectangle representing th actual region + * @throws de.digitalcollections.iiif.model.image.ResolvingException if rectangle is outside image dimensions */ public Rectangle resolve(Dimension imageDims) throws ResolvingException { if (square) { if (imageDims.width > imageDims.height) { return new Rectangle( - (imageDims.width - imageDims.height) / 2, - 0, - imageDims.height, imageDims.height); + (imageDims.width - imageDims.height) / 2, + 0, + imageDims.height, imageDims.height); } else if (imageDims.height > imageDims.width) { return new Rectangle( - 0, - (imageDims.height - imageDims.width) / 2, - imageDims.width, imageDims.width); + 0, + (imageDims.height - imageDims.width) / 2, + imageDims.width, imageDims.width); } } if (absoluteBox == null && relativeBox == null) { @@ -205,10 +225,10 @@ public Rectangle resolve(Dimension imageDims) throws ResolvingException { Rectangle rect; if (isRelative()) { rect = new Rectangle( - (int) Math.round(relativeBox.x.doubleValue() / 100. * imageDims.getWidth()), - (int) Math.round(relativeBox.y.doubleValue() / 100. * imageDims.getHeight()), - (int) Math.round(relativeBox.w.doubleValue() / 100. * imageDims.getWidth()), - (int) Math.round(relativeBox.h.doubleValue() / 100. * imageDims.getHeight())); + (int) Math.round(relativeBox.x.doubleValue() / 100. * imageDims.getWidth()), + (int) Math.round(relativeBox.y.doubleValue() / 100. * imageDims.getHeight()), + (int) Math.round(relativeBox.w.doubleValue() / 100. * imageDims.getWidth()), + (int) Math.round(relativeBox.h.doubleValue() / 100. * imageDims.getHeight())); } else { rect = absoluteBox; } @@ -234,8 +254,8 @@ public boolean equals(Object o) { } RegionRequest that = (RegionRequest) o; return square == that.square - && Objects.equal(absoluteBox, that.absoluteBox) - && Objects.equal(relativeBox, that.relativeBox); + && Objects.equal(absoluteBox, that.absoluteBox) + && Objects.equal(relativeBox, that.relativeBox); } @Override diff --git a/src/main/java/de/digitalcollections/iiif/model/image/RotationRequest.java b/src/main/java/de/digitalcollections/iiif/model/image/RotationRequest.java index 4f1ad32..2412254 100644 --- a/src/main/java/de/digitalcollections/iiif/model/image/RotationRequest.java +++ b/src/main/java/de/digitalcollections/iiif/model/image/RotationRequest.java @@ -8,6 +8,7 @@ import java.util.regex.Pattern; public class RotationRequest { + // Matches floating point values private static final Pattern PATTERN = Pattern.compile("^(!)?([0-9]*\\.?[0-9]+)$"); BigDecimal rotation; @@ -16,6 +17,8 @@ public class RotationRequest { /** * Parse a rotation request from an IIIF Image API compliant rotation string. * + * @param str iiif image api compliant rotation string + * @return RotationRequest represented by th given string * @throws ResolvingException if the rotation string is malformed */ @JsonCreator @@ -25,8 +28,8 @@ public static RotationRequest fromString(String str) throws ResolvingException { throw new ResolvingException("Bad format: " + str); } return new RotationRequest( - new BigDecimal(matcher.group(2)), - !(matcher.group(1) == null)); + new BigDecimal(matcher.group(2)), + !(matcher.group(1) == null)); } public RotationRequest(int rotation) throws ResolvingException { @@ -58,6 +61,7 @@ public boolean isMirror() { /** * Create an IIIF Image API compatible rotation string. + * @return IIIF Image API compatible rotation string represented by this instance */ @JsonValue @Override @@ -79,7 +83,7 @@ public boolean equals(Object o) { } RotationRequest that = (RotationRequest) o; return mirror == that.mirror - && Objects.equal(rotation, that.rotation); + && Objects.equal(rotation, that.rotation); } @Override diff --git a/src/main/java/de/digitalcollections/iiif/model/image/SizeRequest.java b/src/main/java/de/digitalcollections/iiif/model/image/SizeRequest.java index f8450b3..c3d78d4 100644 --- a/src/main/java/de/digitalcollections/iiif/model/image/SizeRequest.java +++ b/src/main/java/de/digitalcollections/iiif/model/image/SizeRequest.java @@ -24,6 +24,8 @@ public class SizeRequest { /** * Parse an IIIF Image API compliant size request string * + * @param str IIIF Image API compliant size request string + * @return parsed SizeRequest * @throws ResolvingException if the request string is malformed */ @JsonCreator @@ -68,7 +70,9 @@ public SizeRequest() { /** * Create a size request for the maximum supported size of the image region, if isMax is true. - * If isMax is false, ise it behaves identically to the default constructor. + * If isMax is false, it behaves identically to the default constructor. + * + * @param isMax true causes a size request for the maximum supported size of the image region */ public SizeRequest(boolean isMax) { this.max = isMax; @@ -76,10 +80,10 @@ public SizeRequest(boolean isMax) { /** * Create a size request for a given width or height. + * One of both can be null (the other value will be determined based on the aspect ratio of the image region), but not both at once. * - * One of both can be null (the other value will be determined based on the aspect ratio of the image region), but - * not both at once. - * + * @param width width of size request + * @param height height of size request * @throws ResolvingException if neither width nor height are specified */ public SizeRequest(Integer width, Integer height) throws ResolvingException { @@ -93,6 +97,10 @@ public SizeRequest(Integer width, Integer height) throws ResolvingException { /** * Create a size request for a given width and height and signal that the server can decide to render smaller * resolutions as it deems neccessary. + * @param width width of size request + * @param height height of size request + * @param bestFit true, if server can decide to render smaller resolutions as it deems neccessary + * @throws de.digitalcollections.iiif.model.image.ResolvingException if params can not be resolved to Size Request */ public SizeRequest(int width, int height, boolean bestFit) throws ResolvingException { this(width, height); @@ -102,6 +110,7 @@ public SizeRequest(int width, int height, boolean bestFit) throws ResolvingExcep /** * Create a size request that scaled both dimensions according to a fixed percentage, maintaining the aspect ratio. * + * @param percentage scaling percentage, maintaining aspect ratio * @throws ResolvingException if the percentage is not between 0 and 100 */ public SizeRequest(BigDecimal percentage) throws ResolvingException { @@ -113,6 +122,7 @@ public SizeRequest(BigDecimal percentage) throws ResolvingException { /** * Return whether the maximum resolution was requested. + * @return true, if maximum resolution was requested */ public boolean isMax() { return max; @@ -120,6 +130,7 @@ public boolean isMax() { /** * Return whether the server can decide to render smaller resolutions than desired. + * @return true, if the server can decide to render smaller resolutions than desired */ public boolean isBestFit() { return bestFit; @@ -127,6 +138,7 @@ public boolean isBestFit() { /** * Get the requested width + * @return requested width */ public Integer getWidth() { return width; @@ -134,6 +146,7 @@ public Integer getWidth() { /** * Get the requested height + * @return requested height */ public Integer getHeight() { return height; @@ -141,6 +154,7 @@ public Integer getHeight() { /** * Get the requested percentage to be used for scaling + * @return requested percentage to be used for scaling */ public BigDecimal getPercentage() { return percentage; @@ -148,8 +162,12 @@ public BigDecimal getPercentage() { /** * Get the canonical form of this request. + * @see IIIF Image API specification * - * @see http://iiif.io/api/image/2.1/#canonical-uri-syntax + * @param nativeSize native size of request + * @param profile image api profile + * @return canonical form of this request + * @throws de.digitalcollections.iiif.model.image.ResolvingException if nativeSize can not be converted to canonical form */ public String getCanonicalForm(Dimension nativeSize, ImageApiProfile profile) throws ResolvingException { Dimension resolved = this.resolve(nativeSize, profile); @@ -175,6 +193,11 @@ public Dimension resolve(Dimension nativeSize, ImageApiProfile profile) throws R /** * Resolve the request to dimensions that can be used for scaling, based on the native size of the image region * and the available profile. + * @param nativeSize native size of the image region + * @param availableSizes available sizes + * @param profile image api profile + * @return resolved dimension + * @throws de.digitalcollections.iiif.model.image.ResolvingException if params can not be resolved to Dimension */ public Dimension resolve(Dimension nativeSize, List availableSizes, ImageApiProfile profile) throws ResolvingException { double aspect = (double) nativeSize.width / (double) nativeSize.height; @@ -263,8 +286,11 @@ public Dimension resolve(Dimension nativeSize, List availableSizes, I } /** - * Like {@link #resolve(Dimension, ImageApiProfile)}, but can be used with a {@link Rectangle}, e.g. as returned - * from {@link RegionRequest#resolve(Dimension)}. + * Like {@link #resolve(Dimension, ImageApiProfile)}, but can be used with a {@link Rectangle}, e.g. as returned from {@link RegionRequest#resolve(Dimension)}. + * @param region image region + * @param profile image api profile + * @return resolved size dimension + * @throws de.digitalcollections.iiif.model.image.ResolvingException if rectangle region can not be resolved */ public Dimension resolve(Rectangle region, ImageApiProfile profile) throws ResolvingException { return resolve( @@ -274,6 +300,7 @@ public Dimension resolve(Rectangle region, ImageApiProfile profile) throws Resol /** * Create an IIIF Image API compliant size request string + * @return String representation of size request */ @JsonCreator @JsonValue diff --git a/src/main/java/de/digitalcollections/iiif/model/jackson/serialization/IiifIndexedListSerializer.java b/src/main/java/de/digitalcollections/iiif/model/jackson/serialization/IiifIndexedListSerializer.java index f511919..3425940 100644 --- a/src/main/java/de/digitalcollections/iiif/model/jackson/serialization/IiifIndexedListSerializer.java +++ b/src/main/java/de/digitalcollections/iiif/model/jackson/serialization/IiifIndexedListSerializer.java @@ -15,7 +15,7 @@ import java.util.List; /** - * This is a custom serializer for `List` that has some special cases required by + * This is a custom serializer for `List<Object>` that has some special cases required by * the IIIF specification, namely that some fields should not be encoded as arrays if * they only contain a single element. * @@ -23,9 +23,10 @@ * to it where possible. */ public final class IiifIndexedListSerializer extends AsArraySerializerBase> { + private static final ImmutableSet UNWRAP_FIELDS = ImmutableSet.of( - "service", "profile", "within", "logo", "description", "viewingHint", - "@type", "license", "rendering", "seeAlso", "related", "thumbnail"); + "service", "profile", "within", "logo", "description", "viewingHint", + "@type", "license", "rendering", "seeAlso", "related", "thumbnail"); private final IndexedListSerializer defaultSerializer; @@ -35,24 +36,21 @@ public IiifIndexedListSerializer(IndexedListSerializer defaultSerializer, TypeFa } private IiifIndexedListSerializer(IiifIndexedListSerializer src, BeanProperty prop, - TypeSerializer vts, JsonSerializer valueSerializer, - Boolean unwrapSingle) { + TypeSerializer vts, JsonSerializer valueSerializer, + Boolean unwrapSingle) { super(src, prop, vts, valueSerializer, unwrapSingle); this.defaultSerializer = src.defaultSerializer; } - - @Override public AsArraySerializerBase> withResolved(BeanProperty property, TypeSerializer vts, - JsonSerializer elementSerializer, Boolean unwrapSingle) { + JsonSerializer elementSerializer, Boolean unwrapSingle) { return new IiifIndexedListSerializer(this, property, vts, elementSerializer, unwrapSingle); } @Override public final void serialize(List value, JsonGenerator gen, SerializerProvider provider) - throws IOException - { + throws IOException { final int len = value.size(); String currentName = gen.getOutputContext().getCurrentName(); // Special case: Unwrap certain fields diff --git a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Canvas.java b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Canvas.java index ecac2ac..cac4246 100644 --- a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Canvas.java +++ b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Canvas.java @@ -28,6 +28,7 @@ * See http://iiif.io/api/presentation/2.1/#canvas */ public class Canvas extends Resource { + public static final String TYPE = "sc:Canvas"; private List images; @@ -57,6 +58,7 @@ public List getImages() { /** * Sets the image annotations on this canvas. Must all be instances of {@link ImageContent} * + * @param images image annotations on this canvas * @throws IllegalArgumentException if at least one of the image annotations is not an {@link ImageContent} */ public void setImages(List images) throws IllegalArgumentException { @@ -94,8 +96,8 @@ public Canvas addImage(ImageContent first, ImageContent... rest) { } this.images.add(wrapImageInAnnotation(first)); this.images.addAll(Arrays.stream(rest) - .map(this::wrapImageInAnnotation) - .collect(Collectors.toList())); + .map(this::wrapImageInAnnotation) + .collect(Collectors.toList())); // If we only have one image, set width/height from the image content by default if (this.images.size() == 1 && this.getWidth() == null && this.getHeight() == null) { this.setWidthFromImage(this.images.get(0)); @@ -116,7 +118,6 @@ public Integer getHeight() { return height; } - public void setWidth(Integer width) { this.width = width; } diff --git a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Collection.java b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Collection.java index e8ba93c..9d918f3 100644 --- a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Collection.java +++ b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Collection.java @@ -27,6 +27,7 @@ * See http://iiif.io/api/presentation/2.1/#collection */ public class Collection extends Resource implements Pageable, PageContainer { + public static final String TYPE = "sc:Collection"; private OffsetDateTime navDate; @@ -111,7 +112,6 @@ public Collection addManifest(Manifest first, Manifest... rest) { return this; } - public List getMembers() { return members; } @@ -127,11 +127,12 @@ private void checkMember(Resource member) { } } - /** - * Set the list of member resources. Must be either instances of {@link Manifest} or {@link Collection}. + * Set the list of member resources. + * Must be either instances of {@link Manifest} or {@link Collection}. * All {@link Collection} members must have at least one {@link de.digitalcollections.iiif.model.enums.ViewingHint}. * + * @param members member resources * @throws IllegalArgumentException if at least one member is not a {@link Manifest} or {@link Collection} or is a * {@link Collection} and does not have at least one {@link de.digitalcollections.iiif.model.enums.ViewingHint} */ @@ -140,11 +141,14 @@ public void setMembers(List members) { this.members = members; } - /** - * Adds one or more member resources. Must be either instances of {@link Manifest} or {@link Collection}. + * Adds one or more member resources. + * Must be either instances of {@link Manifest} or {@link Collection}. * All {@link Collection} members must have at least one {@link de.digitalcollections.iiif.model.enums.ViewingHint}. * + * @param first first member + * @param rest other members + * @return this collection with added members * @throws IllegalArgumentException if at least one member is not a {@link Manifest} or {@link Collection} or is a * {@link Collection} and does not have at least one {@link de.digitalcollections.iiif.model.enums.ViewingHint} */ diff --git a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Range.java b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Range.java index 0c97e1e..1af755e 100644 --- a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Range.java +++ b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Range.java @@ -28,6 +28,7 @@ * See http://iiif.io/api/presentation/2.1/#range */ public class Range extends Resource { + public static final String TYPE = "sc:Range"; private ViewingDirection viewingDirection; @@ -95,8 +96,8 @@ private void checkIdOnly(Resource res) { Completeness completeness = ModelUtilities.getCompleteness(res, res.getClass()); if (completeness != Completeness.ID_AND_TYPE && completeness != Completeness.ID_ONLY) { throw new IllegalArgumentException( - "Member resource must only have an identifier and no other field." + - " Use add(URI first, URI... rest) for convenience."); + "Member resource must only have an identifier and no other field." + + " Use add(URI first, URI... rest) for convenience."); } } @@ -117,7 +118,7 @@ public Range addCanvas(Canvas first, Canvas... rest) { public Range addCanvas(String idOfFirst, String... idsOfRest) { return this.addCanvas(new Canvas(idOfFirst), - Arrays.stream(idsOfRest).map(Canvas::new).toArray(Canvas[]::new)); + Arrays.stream(idsOfRest).map(Canvas::new).toArray(Canvas[]::new)); } public List getRanges() { @@ -141,7 +142,7 @@ public Range addRange(Range first, Range... rest) { public Range addRange(String first, String... rest) { return this.addRange(new Range(first), - Arrays.stream(rest).map(Range::new).toArray(Range[]::new)); + Arrays.stream(rest).map(Range::new).toArray(Range[]::new)); } public List getMembers() { @@ -158,9 +159,11 @@ private void checkMember(Resource res) { } /** - * Sets the member resources. Must be either instances of {@link Range} or {@link Canvas}. + * Sets the member resources. + * Must be either instances of {@link Range} or {@link Canvas}. * All members must have an identifier and a label. * + * @param members member resources * @throws IllegalArgumentException if at least one member is not a {@link Range} or {@link Canvas} or does not have * an identifier and a label; */ @@ -170,19 +173,23 @@ public void setMembers(List members) { } /** - * Adds one or more member resources. Must be either instances of {@link Range} or {@link Canvas}. + * Adds one or more member resources. + * Must be either instances of {@link Range} or {@link Canvas}. * All members must have an identifier and a label. * + * @param first first member + * @param rest other members + * @return this instance with added members * @throws IllegalArgumentException if at least one member is not a {@link Range} or {@link Canvas} or does not have * an identifier and a label; */ - public Range addMember(Resource first, Resource... rest) throws IllegalArgumentException{ + public Range addMember(Resource first, Resource... rest) throws IllegalArgumentException { if (this.members == null) { this.members = new ArrayList<>(); } - List members = Lists.asList(first, rest); - members.forEach(this::checkMember); - this.members.addAll(members); + List membersToAdd = Lists.asList(first, rest); + membersToAdd.forEach(this::checkMember); + this.members.addAll(membersToAdd); return this; } } diff --git a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Resource.java b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Resource.java index 08ed613..d0d4ba5 100644 --- a/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Resource.java +++ b/src/main/java/de/digitalcollections/iiif/model/sharedcanvas/Resource.java @@ -24,9 +24,10 @@ /** * Abstract IIIF resource, most other resources are based on this. + * @param a resource type, e.g. Canvas, Annotation */ @JsonPropertyOrder({"@context", "@id", "@type", "label", "description", "metadata", "thumbnail", "service"}) -public abstract class Resource implements Choice { +public abstract class Resource implements Choice { public static final String CONTEXT = "http://iiif.io/api/presentation/2/context.json"; @@ -353,6 +354,7 @@ public List getRenderings() { /** * Sets the renderings. All renderings must have both a profile and a format. * + * @param renderings list of renderings with profile and format * @throws IllegalArgumentException if at least one rendering does not have both a profile and a format. */ public void setRenderings(List renderings) throws IllegalArgumentException { @@ -363,15 +365,18 @@ public void setRenderings(List renderings) throws IllegalArgumentE /** * Add one or more renderings. All renderings must have both a profile and a format. * + * @param first first rendering + * @param rest list of other renderings + * @return current instance * @throws IllegalArgumentException if at least one rendering does not have both a profile and a format. */ public Resource addRendering(OtherContent first, OtherContent... rest) { if (renderings == null) { this.renderings = new ArrayList<>(); } - List renderings = Lists.asList(first, rest); - renderings.forEach(this::verifyRendering); - this.renderings.addAll(renderings); + List renderingsToAdd = Lists.asList(first, rest); + renderingsToAdd.forEach(this::verifyRendering); + this.renderings.addAll(renderingsToAdd); return this; } @@ -427,10 +432,12 @@ public void setIsDefaultChoice(boolean is) { this.isDefault = is; } + @Override public List getAlternatives() { return alternatives; } + @Override public void setAlternatives(List alternatives) { this.alternatives = alternatives; } From 86b8331986fc6e166ce6f4cf480274ba94d04c62 Mon Sep 17 00:00:00 2001 From: Ralf Eichinger Date: Tue, 27 Nov 2018 16:41:08 +0100 Subject: [PATCH 4/5] Add all contributing developers --- pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pom.xml b/pom.xml index f1981d1..755c09b 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,19 @@ johannes.baiter@gmail.com jbaiter + + Ralf Eichinger + ralf.eichinger@gmail.com + datazuul + + + Matthias Lindinger + morpheus-87 + + + Stefan Schweter + stefan-it + https://travis-ci.org/dbmdz/iiif-apis From 45b8acbb1d04591f5abd923bb7e3417fe771e8ea Mon Sep 17 00:00:00 2001 From: Ralf Eichinger Date: Tue, 27 Nov 2018 16:44:22 +0100 Subject: [PATCH 5/5] Bump version to 0.3.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 755c09b..712d532 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ de.digitalcollections.iiif iiif-apis - 0.3.4-SNAPSHOT + 0.3.4 jar DigitalCollections: IIIF API Library