diff --git a/src/main/java/org/springframework/hateoas/client/JsonPathLinkDiscoverer.java b/src/main/java/org/springframework/hateoas/client/JsonPathLinkDiscoverer.java index 7bead059..56d6502e 100644 --- a/src/main/java/org/springframework/hateoas/client/JsonPathLinkDiscoverer.java +++ b/src/main/java/org/springframework/hateoas/client/JsonPathLinkDiscoverer.java @@ -35,6 +35,7 @@ import org.springframework.util.Assert; import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.PathNotFoundException; /** * {@link LinkDiscoverer} that uses {@link JsonPath} to find links inside a representation. @@ -108,10 +109,14 @@ public class JsonPathLinkDiscoverer implements LinkDiscoverer { Assert.notNull(relation, "LinkRelation must not be null!"); try { + Object parseResult = getExpression(relation).read(representation); return createLinksFrom(parseResult, relation); - } catch (IOException e) { - throw new RuntimeException(e); + + } catch (IOException o_O) { + throw new RuntimeException(o_O); + } catch (PathNotFoundException o_O) { + return Links.NONE; } } diff --git a/src/main/java/org/springframework/hateoas/client/LinkDiscoverer.java b/src/main/java/org/springframework/hateoas/client/LinkDiscoverer.java index 0e215e30..573561f6 100644 --- a/src/main/java/org/springframework/hateoas/client/LinkDiscoverer.java +++ b/src/main/java/org/springframework/hateoas/client/LinkDiscoverer.java @@ -31,76 +31,112 @@ import org.springframework.plugin.core.Plugin; */ public interface LinkDiscoverer extends Plugin { + /** + * Finds a single link with the given {@link LinkRelation} in the given {@link String} representation. + * + * @param rel must not be {@literal null}. + * @param representation must not be {@literal null}. + * @return the first link with the given relation type found, or {@link Optional#empty()} if none was found. + */ + Optional findLinkWithRel(LinkRelation rel, String representation); + /** * Finds a single link with the given relation type in the given {@link String} representation. * * @param rel must not be {@literal null} or empty. * @param representation must not be {@literal null}. - * @return the first link with the given relation type found, or {@literal null} if none was found. + * @return the first {@link Link} with the given link relation found, or {@link Optional#empty()} if none was found. */ default Optional findLinkWithRel(String rel, String representation) { return findLinkWithRel(LinkRelation.of(rel), representation); } - Optional findLinkWithRel(LinkRelation rel, String representation); - /** - * Finds a single link with the given relation type in the given {@link InputStream} representation. + * Finds a single link with the given relation in the given {@link String} representation. * - * @param rel must not be {@literal null} or empty. + * @param relation must not be {@literal null}. * @param representation must not be {@literal null}. - * @return the first link with the given relation type found, or {@literal null} if none was found. + * @return the first link with the given relation type found. + * @throws IllegalArgumentException if no {@link Link} for the given {@link LinkRelation} can be found. */ - default Optional findLinkWithRel(String rel, InputStream representation) { - return findLinkWithRel(LinkRelation.of(rel), representation); + default Link findRequiredLinkWithRel(LinkRelation relation, String representation) { + + return findLinkWithRel(relation, representation).orElseThrow( + () -> new IllegalArgumentException(String.format("Did not find link with relation '%s'!", relation.value()))); } /** * Finds a single link with the given {@link LinkRelation} in the given {@link InputStream} representation. * - * @param rel must not be {@literal null}. + * @param relation must not be {@literal null}. * @param representation must not be {@literal null}. - * @return the first link with the given relation type found, or {@literal null} if none was found. + * @return the first {@link Link} with the given {@link LinkRelation} found, or {@link Optional#empty()} if none was + * found. */ - Optional findLinkWithRel(LinkRelation rel, InputStream representation); + Optional findLinkWithRel(LinkRelation relation, InputStream representation); + + /** + * Finds a single link with the given relation type in the given {@link InputStream} representation. + * + * @param relation must not be {@literal null} or empty. + * @param representation must not be {@literal null}. + * @return the first link with the given relation type found, or {@link Optional#empty()} if none was found. + */ + default Optional findLinkWithRel(String relation, InputStream representation) { + return findLinkWithRel(LinkRelation.of(relation), representation); + } + + /** + * Finds a single link with the given relation type in the given {@link InputStream} representation. + * + * @param relation must not be {@literal null} or empty. + * @param representation must not be {@literal null}. + * @return the first link with the given relation type found. + * @throws IllegalArgumentException if no {@link Link} for the given {@link LinkRelation} can be found. + */ + default Link findRequiredLinkWithRel(LinkRelation relation, InputStream representation) { + + return findLinkWithRel(relation, representation).orElseThrow( + () -> new IllegalArgumentException(String.format("Did not find link with relation '%s'!", relation.value()))); + } /** * Returns all links with the given link relation found in the given {@link String} representation. * - * @param rel must not be {@literal null} or empty. + * @param relation must not be {@literal null} or empty. * @param representation must not be {@literal null}. * @return will never be {@literal null}. */ - default Links findLinksWithRel(String rel, String representation) { - return findLinksWithRel(LinkRelation.of(rel), representation); + default Links findLinksWithRel(String relation, String representation) { + return findLinksWithRel(LinkRelation.of(relation), representation); } /** * Returns all links with the given {@link LinkRelation} found in the given {@link String} representation. * - * @param rel must not be {@literal null}. + * @param relation must not be {@literal null}. * @param representation must not be {@literal null}. * @return will never be {@literal null}. */ - Links findLinksWithRel(LinkRelation rel, String representation); + Links findLinksWithRel(LinkRelation relation, String representation); /** * Returns all links with the given link relation found in the given {@link InputStream} representation. * - * @param rel must not be {@literal null} or empty. + * @param relation must not be {@literal null} or empty. * @param representation must not be {@literal null}. * @return will never be {@literal null}. */ - default Links findLinksWithRel(String rel, InputStream representation) { - return findLinksWithRel(LinkRelation.of(rel), representation); + default Links findLinksWithRel(String relation, InputStream representation) { + return findLinksWithRel(LinkRelation.of(relation), representation); } /** * Returns all links with the given {@link LinkRelation} found in the given {@link InputStream} representation. * - * @param rel must not be {@literal null}. + * @param relation must not be {@literal null}. * @param representation must not be {@literal null}. * @return will never be {@literal null}. */ - Links findLinksWithRel(LinkRelation rel, InputStream representation); + Links findLinksWithRel(LinkRelation relation, InputStream representation); } diff --git a/src/main/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscoverer.java b/src/main/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscoverer.java index 78a138af..45f3a9d6 100644 --- a/src/main/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscoverer.java +++ b/src/main/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscoverer.java @@ -78,7 +78,8 @@ public class UberLinkDiscoverer implements LinkDiscoverer { @Override public Links findLinksWithRel(LinkRelation rel, String representation) { - return getLinks(representation).stream().filter(it -> it.hasRel(rel)) // + return getLinks(representation).stream() // + .filter(it -> it.hasRel(rel)) // .collect(Links.collector()); } diff --git a/src/test/java/org/springframework/hateoas/server/core/AbstractLinkDiscovererUnitTest.java b/src/test/java/org/springframework/hateoas/client/LinkDiscovererUnitTest.java similarity index 72% rename from src/test/java/org/springframework/hateoas/server/core/AbstractLinkDiscovererUnitTest.java rename to src/test/java/org/springframework/hateoas/client/LinkDiscovererUnitTest.java index 83b4d7fa..a0e81f9c 100755 --- a/src/test/java/org/springframework/hateoas/server/core/AbstractLinkDiscovererUnitTest.java +++ b/src/test/java/org/springframework/hateoas/client/LinkDiscovererUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.hateoas.server.core; +package org.springframework.hateoas.client; import static org.assertj.core.api.Assertions.*; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import org.junit.Test; import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkRelation; import org.springframework.hateoas.Links; -import org.springframework.hateoas.client.LinkDiscoverer; /** * Base class for unit tests for {@link LinkDiscoverer} implementations. * * @author Oliver Gierke */ -public abstract class AbstractLinkDiscovererUnitTest { +public abstract class LinkDiscovererUnitTest { @Test public void findsSingleLink() { @@ -79,6 +81,27 @@ public abstract class AbstractLinkDiscovererUnitTest { assertThat(getDiscoverer().findLinkWithRel("something", getInputStringWithoutLinkContainer())).isEmpty(); } + @Test // #840 + public void throwsExceptionForRequiredLinkNotFoundInString() { + + LinkDiscoverer discoverer = getDiscoverer(); + + assertThatExceptionOfType(IllegalArgumentException.class) // + .isThrownBy(() -> discoverer.findRequiredLinkWithRel(LinkRelation.of("something-obscure"), getInputString())); + } + + @Test // #840 + public void throwsExceptionForRequiredLinkNotFoundInInputStream() throws IOException { + + LinkDiscoverer discoverer = getDiscoverer(); + + try (InputStream stream = new ByteArrayInputStream(getInputString().getBytes(StandardCharsets.UTF_8))) { + + assertThatExceptionOfType(IllegalArgumentException.class) // + .isThrownBy(() -> discoverer.findRequiredLinkWithRel(LinkRelation.of("something-obscure"), stream)); + } + } + /** * Return the {@link LinkDiscoverer} to be tested. * diff --git a/src/test/java/org/springframework/hateoas/LinkDiscoverersUnitTest.java b/src/test/java/org/springframework/hateoas/client/LinkDiscoverersUnitTest.java similarity index 98% rename from src/test/java/org/springframework/hateoas/LinkDiscoverersUnitTest.java rename to src/test/java/org/springframework/hateoas/client/LinkDiscoverersUnitTest.java index 14af03e6..fe1fa218 100755 --- a/src/test/java/org/springframework/hateoas/LinkDiscoverersUnitTest.java +++ b/src/test/java/org/springframework/hateoas/client/LinkDiscoverersUnitTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.hateoas; +package org.springframework.hateoas.client; import static org.assertj.core.api.Assertions.*; diff --git a/src/test/java/org/springframework/hateoas/mediatype/alps/AlpsLinkDiscoverUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/alps/AlpsLinkDiscoverUnitTest.java index 13f25e9d..0a22d9b2 100755 --- a/src/test/java/org/springframework/hateoas/mediatype/alps/AlpsLinkDiscoverUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/alps/AlpsLinkDiscoverUnitTest.java @@ -24,9 +24,9 @@ import java.util.Optional; import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.hateoas.Link; +import org.springframework.hateoas.client.LinkDiscovererUnitTest; import org.springframework.hateoas.client.LinkDiscoverer; import org.springframework.hateoas.mediatype.alps.AlpsLinkDiscoverer; -import org.springframework.hateoas.server.core.AbstractLinkDiscovererUnitTest; import org.springframework.util.StreamUtils; /** @@ -35,7 +35,7 @@ import org.springframework.util.StreamUtils; * @author Greg Turnquist * @author Oliver Gierke */ -public class AlpsLinkDiscoverUnitTest extends AbstractLinkDiscovererUnitTest { +public class AlpsLinkDiscoverUnitTest extends LinkDiscovererUnitTest { LinkDiscoverer discoverer = new AlpsLinkDiscoverer(); diff --git a/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererUnitTest.java index 9831e8f5..cd6f1a81 100755 --- a/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererUnitTest.java @@ -25,9 +25,9 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.client.LinkDiscovererUnitTest; import org.springframework.hateoas.client.LinkDiscoverer; import org.springframework.hateoas.mediatype.hal.HalLinkDiscoverer; -import org.springframework.hateoas.server.core.AbstractLinkDiscovererUnitTest; /** * Unit tests for {@link HalLinkDiscoverer}. @@ -35,7 +35,7 @@ import org.springframework.hateoas.server.core.AbstractLinkDiscovererUnitTest; * @author Oliver Gierke * @author Greg Turnquist */ -public class HalLinkDiscovererUnitTest extends AbstractLinkDiscovererUnitTest { +public class HalLinkDiscovererUnitTest extends LinkDiscovererUnitTest { static final LinkDiscoverer discoverer = new HalLinkDiscoverer(); diff --git a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererUnitTest.java index 50e33b1d..e6beb1fb 100644 --- a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererUnitTest.java @@ -24,16 +24,16 @@ import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; +import org.springframework.hateoas.client.LinkDiscovererUnitTest; import org.springframework.hateoas.client.LinkDiscoverer; import org.springframework.hateoas.mediatype.hal.forms.HalFormsLinkDiscoverer; -import org.springframework.hateoas.server.core.AbstractLinkDiscovererUnitTest; /** * Unit tests for {@link HalFormsLinkDiscoverer}. * * @author Greg Turnquist */ -public class HalFormsLinkDiscovererUnitTest extends AbstractLinkDiscovererUnitTest { +public class HalFormsLinkDiscovererUnitTest extends LinkDiscovererUnitTest { static final LinkDiscoverer discoverer = new HalFormsLinkDiscoverer(); diff --git a/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererUnitTest.java index 13d2d330..a57ed615 100644 --- a/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererUnitTest.java @@ -23,17 +23,17 @@ import java.io.IOException; import org.junit.Before; import org.junit.Test; import org.springframework.core.io.ClassPathResource; +import org.springframework.hateoas.client.LinkDiscovererUnitTest; import org.springframework.hateoas.client.LinkDiscoverer; import org.springframework.hateoas.mediatype.hal.HalLinkDiscoverer; import org.springframework.hateoas.mediatype.uber.UberLinkDiscoverer; -import org.springframework.hateoas.server.core.AbstractLinkDiscovererUnitTest; /** * Unit tests for {@link HalLinkDiscoverer}. * * @author Oliver Gierke */ -public class UberLinkDiscovererUnitTest extends AbstractLinkDiscovererUnitTest { +public class UberLinkDiscovererUnitTest extends LinkDiscovererUnitTest { LinkDiscoverer discoverer = new UberLinkDiscoverer(); String sample;