From 0768c1a6260af401c3e57e6865ebdd8cbe484d33 Mon Sep 17 00:00:00 2001 From: "hendra.saputra" Date: Wed, 28 Oct 2020 21:52:00 +0000 Subject: [PATCH 1/2] Update to latest release of Spring and Spring hateoas --- README.asciidoc | 26 ++--- .../serialize/JacksonHydraSerializer.java | 2 +- .../hydra/serialize/LdContextFactory.java | 23 ++-- hydra-spring/pom.xml | 2 +- ...esMixin.java => CollectionModelMixin.java} | 19 ++-- .../spring/hydra/JacksonHydraModule.java | 20 ++-- .../spring/hydra/LinkListSerializer.java | 78 +++++++------ ...sourcesMixin.java => PagedModelMixin.java} | 19 ++-- .../hydra/PagedResourcesSerializer.java | 50 +++++---- ...xin.java => RepresentationModelMixin.java} | 13 +-- .../spring/hydra/ResourceMixin.java | 9 +- .../spring/hydra/ResourceSerializer.java | 10 +- .../spring/hydra/ResourcesSerializer.java | 10 +- .../test/DummyEventControllerExposed.java | 22 ++-- .../sample/test/EventResourceExposed.java | 2 +- pom.xml | 26 ++--- spring-hateoas-ext/pom.xml | 3 +- .../hypermedia/ResourceSupportVisitor.java | 7 +- .../escalon/hypermedia/ResourceTraversal.java | 18 +-- .../de/escalon/hypermedia/action/Options.java | 2 +- .../hypermedia/action/ResourceHandler.java | 2 +- .../hypermedia/affordance/Affordance.java | 18 +-- .../hypermedia/affordance/TypedResource.java | 2 +- .../hypermedia/spring/AffordanceBuilder.java | 34 +++--- .../spring/AffordanceBuilderFactory.java | 106 +++++++++++------- .../hypermedia/spring/siren/SirenAction.java | 14 +-- .../spring/siren/SirenMessageConverter.java | 8 +- .../hypermedia/spring/siren/SirenUtils.java | 74 ++++++------ .../spring/uber/AbstractUberNode.java | 6 +- .../spring/uber/NullValueSerializer.java | 12 +- .../UberJackson2HttpMessageConverter.java | 8 +- .../spring/uber/UberJsonLinkDiscoverer.java | 2 +- .../hypermedia/spring/uber/UberUtils.java | 33 +++--- .../xhtml/XhtmlResourceMessageConverter.java | 24 ++-- .../hypermedia/spring/xhtml/XhtmlWriter.java | 9 +- .../hypermedia/affordance/AffordanceTest.java | 5 +- .../spring/AffordanceBuilderFactoryTest.java | 58 +++++----- .../sample/test/DummyEventController.java | 32 +++--- .../hypermedia/spring/sample/test/Event.java | 10 +- .../spring/sample/test/EventResource.java | 6 +- .../spring/sample/test/ReviewController.java | 6 +- .../siren/SirenMessageConverterTest.java | 24 ++-- .../spring/siren/SirenUtilsTest.java | 48 ++++---- .../spring/uber/AbstractUberNodeTest.java | 14 +-- .../hypermedia/spring/uber/UberUtilsTest.java | 25 +++-- .../spring/xhtml/XhtmlWriterTest.java | 11 +- 46 files changed, 497 insertions(+), 455 deletions(-) rename hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/{ResourcesMixin.java => CollectionModelMixin.java} (83%) rename hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/{PagedResourcesMixin.java => PagedModelMixin.java} (83%) rename hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/{ResourceSupportMixin.java => RepresentationModelMixin.java} (78%) diff --git a/README.asciidoc b/README.asciidoc index 3ccaa8f6..09e17305 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -106,10 +106,10 @@ Look into the https://github.com/dschulten/hydra-java/blob/master/hydra-sample/s The tests in https://github.com/dschulten/hydra-java/blob/master/hydra-jsonld/src/test/java/de/escalon/hypermedia/hydra/serialize/JacksonHydraSerializerTest.java[JacksonHydraSerializerTest] demonstrate the usage of `@Vocab`, `@Expose` and `@Term`. == Features of hydra-spring -The conversion of a spring-hateoas Resource to hydra does the following: +The conversion of a spring-hateoas EntityModel to hydra does the following: -- renders a spring-hateoas `List` in a `Resource` in json-ld style -- renders spring-hateoas `Resources` as `hydra:Collection`. If you use this feature, make sure you have a `@Term(define = "hydra", as = "http://www.w3.org/ns/hydra/core#")` annotation in your context. +- renders a spring-hateoas `List` in a `EntityModel` in json-ld style +- renders spring-hateoas `CollectionModel` as `hydra:Collection`. If you use this feature, make sure you have a `@Term(define = "hydra", as = "http://www.w3.org/ns/hydra/core#")` annotation in your context. - renders spring-hateoas `PagedResources` as `hydra:Collection` with a `hydra:PartialCollectionView`. If you use this feature, make sure you have a `@Term(define = "hydra", as = "http://www.w3.org/ns/hydra/core#")` annotation in your context. - renders response with `"@vocab" : "http://schema.org/"` by default, a different `@vocab` can be defined on a class or package using the `@Vocab` annotation. - supports vocabularies in addition to the default vocabulary via terms in the `@context`. Use `@Term` in conjunction with `@Terms` on a class or package for this. @@ -219,7 +219,7 @@ AffordanceBuilder.linkTo(methodOn(Foo.class).getBars()).rel("bars") // rel() ins In the following we use `AffordanceBuilder` to add a `self` rel that can be used with GET, PUT and DELETE to an event bean. -First we wrap the event into a `Resource` so we can add affordances to it. Then we use the `linkTo-methodOn` technique three times to describe that the self rel can be used to get, update and delete the event. +First we wrap the event into a `EntityModel` so we can add affordances to it. Then we use the `linkTo-methodOn` technique three times to describe that the self rel can be used to get, update and delete the event. [source, Java] ---- @@ -232,9 +232,9 @@ First we wrap the event into a `Resource` so we can add affordances to it. Then public class EventController { @RequestMapping(value = "/{eventId}", method = RequestMethod.GET) - public @ResponseBody Resource getEvent(@PathVariable Integer eventId) { + public @ResponseBody EntityModel getEvent(@PathVariable Integer eventId) { // get the event from some backend, then: - Resource eventResource = new Resource(event); + EntityModel eventResource = new EntityModel(event); // using AffordanceBuilder.linkTo and AffordanceBuilder.methodOn // instead of ControllerLinkBuilder methods @@ -249,7 +249,7 @@ First we wrap the event into a `Resource` so we can add affordances to it. Then } @RequestMapping(value = "/{eventId}", method = RequestMethod.GET) - public @ResponseBody Resource getEvent(@PathVariable Integer eventId) { + public @ResponseBody EntityModel getEvent(@PathVariable Integer eventId) { ... } @@ -328,15 +328,15 @@ When rendered with the `HydraMessageConverter`, the resulting json-ld event obje === Specifying Property Value Requirements (from V. 0.2.0) -Now let us tell the client a range of possible values for a property. We want to allow clients to add reviews for the work performed at an event. For this, we add a `Resource` to the `Event`, so that we can define an affordance on the creative work which allows clients to send reviews. +Now let us tell the client a range of possible values for a property. We want to allow clients to add reviews for the work performed at an event. For this, we add a `EntityModel` to the `Event`, so that we can define an affordance on the creative work which allows clients to send reviews. [source, Java] ---- public class Event { ... - private final Resource workPerformed; + private final EntityModel workPerformed; - public Resource getWorkPerformed() { + public EntityModel getWorkPerformed() { return workPerformed; } ... @@ -344,11 +344,11 @@ Now let us tell the client a range of possible values for a property. We want to // in EventController: @RequestMapping(value = "/{eventId}", method = RequestMethod.GET) - public @ResponseBody Resource getEvent(@PathVariable Integer eventId) { + public @ResponseBody EntityModel getEvent(@PathVariable Integer eventId) { // with an event from backend do this: - event.getWorkPerformed() // <-- must be a Resource + event.getWorkPerformed() // <-- must be a EntityModel .add(linkTo(methodOn(ReviewController.class) // <-- must use AffordanceBuilder.linkTo here .addReview(event.id, new Review(null, new Rating(3)))) // <-- default ratingValue 3 .withRel("review")); @@ -538,7 +538,7 @@ The `SirenMessageConverter` renders Spring Hateoas Responses as https://github.c * in order to produce more expressive Siren actions, use the `linkTo-methodOn` idiom of `AffordanceBuilder` to point to your methods, as shown above for the sample `EventController` in the section AffordanceBuilder. * possible values found by `AffordanceBuilder` are treated as checkbox or radio button fields, following the technique discussed in the https://groups.google.com/forum/#!topic/siren-hypermedia/8mbOX44gguU[Siren group]. * field types can be defined via the value of the `@Input` annotation on method parameters (e.g. `@Input(Type.DATE)`). -* nested `Resource` objects are shown as embedded representations +* nested `EntityModel` objects are shown as embedded representations * distinguishes navigational and embedded links by a default list of navigational rels. This list can be customized via `SirenMessageConverter.addNavigationalRels`. * for sub-entities the property name is used as relation name. The Siren class name is derived from the Java class name. The rel names can be customized using a `DocumentationProvider` implementation, e.g. the `JsonLdDocumentationProvider` from hydra-jsonld will make use of `@Expose` and `@Vocab` annotations on your response bean packages. * relies on `XhtmlMessageConverter` to process incoming form-urlencoded requests and on `MappingJackson2HttpMessageConverter` for json requests. diff --git a/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/JacksonHydraSerializer.java b/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/JacksonHydraSerializer.java index 98fec9d6..ae796640 100644 --- a/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/JacksonHydraSerializer.java +++ b/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/JacksonHydraSerializer.java @@ -186,7 +186,7 @@ protected void serializeType(Object bean, JsonGenerator jgen, SerializerProvider } // adds @type attribute, reflecting the simple name of the class or the exposed annotation on the class. final Expose classExpose = findAnnotation(bean.getClass(), Expose.class); - // TODO allow to search up the hierarchy for ResourceSupport mixins and cache found result? + // TODO allow to search up the hierarchy for RepresentationModel mixins and cache found result? final Class mixin = provider.getConfig() .findMixInClassFor(bean.getClass()); final Expose mixinExpose = findAnnotation(mixin, Expose.class); diff --git a/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/LdContextFactory.java b/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/LdContextFactory.java index c1ea829a..fb3bb7c8 100644 --- a/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/LdContextFactory.java +++ b/hydra-jsonld/src/main/java/de/escalon/hypermedia/hydra/serialize/LdContextFactory.java @@ -31,10 +31,9 @@ public class LdContextFactory { /** * Gets vocab for given bean. * - * @param bean - * to inspect for vocab - * @param mixInClass - * for bean which might define a vocab or has a context provider + * @param mixinSource to inspect from + * @param bean to inspect for vocab + * @param mixInClass for bean which might define a vocab or has a context provider * @return explicitly defined vocab or http://schema.org */ public String getVocab(MixinSource mixinSource, Object bean, Class mixInClass) { @@ -74,7 +73,7 @@ public Map getTerms(MixinSource mixinSource, Object bean, Class< bean = proxyUnwrapper.unwrapProxy(bean); } - Map termsMap = new LinkedHashMap(); + Map termsMap = new LinkedHashMap<>(); if (bean != null) { final Class beanClass = bean.getClass(); termsMap.putAll(termsFromClass(beanClass)); @@ -140,7 +139,7 @@ private boolean returnsEnumCollection( Method method ) { ParameterizedType pt = (ParameterizedType) t; if ( pt.getActualTypeArguments().length == 1 ) { Type arg = pt.getActualTypeArguments()[0]; - return Class.class.isInstance( arg ) && Enum.class.isAssignableFrom( (Class) arg ); + return arg instanceof Class && Enum.class.isAssignableFrom( (Class) arg); } } } @@ -164,7 +163,7 @@ private Map getAnnotatedTerms(AnnotatedElement annotatedElement, if (annotatedTerms != null && annotatedTerm != null) { throw new IllegalStateException("found both @Terms and @Term in " + name + ", use either one or the other"); } - Map annotatedTermsMap = new LinkedHashMap(); + Map annotatedTermsMap = new LinkedHashMap<>(); if (annotatedTerms != null) { final Term[] terms = annotatedTerms.value(); for (Term term : terms) { @@ -186,17 +185,17 @@ private void collectTerms(String name, Map annotatedTermsMap, Te if (!reverse) { annotatedTermsMap.put(define, as); } else { - Map reverseTerm = new LinkedHashMap(); + Map reverseTerm = new LinkedHashMap<>(); reverseTerm.put(JsonLdKeywords.AT_REVERSE, as); annotatedTermsMap.put(define, reverseTerm); } } private Object getNestedContextProviderFromMixin(MixinSource mixinSource, Object bean, Class mixinClass) { - // TODO does not consider Collection or Collection to find mixin of + // TODO does not consider Collection or Collection to find mixin of // object wrapped in resource // TODO does not consider package of object wrapped in resource - // TODO: we do not know Resources here + // TODO: we do not know CollectionModel here if (mixinClass == null) { return null; } @@ -256,7 +255,7 @@ private Method getContextProvider(Class beanClass) { private void addEnumTerms(Map termsMap, Expose expose, String name, Enum value) throws NoSuchFieldException { if (value != null) { - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); if (expose != null) { map.put(JsonLdKeywords.AT_ID, expose.value()); } @@ -269,7 +268,7 @@ private void addEnumTerms(Map termsMap, Expose expose, String na termsMap.put(value.toString(), enumValueExpose.value()); } else { // might use upperToCamelCase if nothing is exposed - final String camelCaseEnumValue = WordUtils.capitalizeFully(value.toString(), new char[]{'_'}) + final String camelCaseEnumValue = WordUtils.capitalizeFully(value.toString(), '_') .replaceAll("_", ""); termsMap.put(value.toString(), camelCaseEnumValue); } diff --git a/hydra-spring/pom.xml b/hydra-spring/pom.xml index bcaa0ff9..ed43ebdf 100644 --- a/hydra-spring/pom.xml +++ b/hydra-spring/pom.xml @@ -110,7 +110,7 @@ junit - com.intellij + org.jetbrains annotations diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesMixin.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/CollectionModelMixin.java similarity index 83% rename from hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesMixin.java rename to hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/CollectionModelMixin.java index d6b5c014..c0528b15 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesMixin.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/CollectionModelMixin.java @@ -13,25 +13,26 @@ package de.escalon.hypermedia.spring.hydra; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import de.escalon.hypermedia.hydra.mapping.ContextProvider; import de.escalon.hypermedia.hydra.mapping.Expose; import de.escalon.hypermedia.hydra.mapping.Term; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resources; import java.util.Collection; -import java.util.List; + +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.Links; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** - * Mixin for json-ld serialization of Resources. Created by dschulten on 14.09.2014. + * Mixin for json-ld serialization of CollectionModel. Created by dschulten on 14.09.2014. */ @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) @Term(define = "hydra", as = "http://www.w3.org/ns/hydra/core#") @Expose("hydra:Collection") -public abstract class ResourcesMixin extends Resources { +public abstract class CollectionModelMixin extends CollectionModel { @Override @JsonProperty("hydra:member") @@ -43,7 +44,7 @@ public Collection getContent() { @Override @JsonSerialize(using = LinkListSerializer.class) @JsonUnwrapped - public List getLinks() { + public Links getLinks() { return super.getLinks(); } } diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/JacksonHydraModule.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/JacksonHydraModule.java index b42b8050..0a0186fb 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/JacksonHydraModule.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/JacksonHydraModule.java @@ -23,10 +23,10 @@ import de.escalon.hypermedia.affordance.TypedResource; import de.escalon.hypermedia.hydra.serialize.JacksonHydraSerializer; import de.escalon.hypermedia.hydra.serialize.ProxyUnwrapper; -import org.springframework.hateoas.PagedResources; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.PagedModel; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; /** @@ -43,13 +43,13 @@ public JacksonHydraModule() { public JacksonHydraModule(ProxyUnwrapper proxyUnwrapper) { super("json-hydra-module", new Version(1, 0, 0, null, "de.escalon.hypermedia", "hydra-spring")); this.proxyUnwrapper = proxyUnwrapper; - setMixInAnnotation(ResourceSupport.class, ResourceSupportMixin.class); - setMixInAnnotation(Resources.class, ResourcesMixin.class); - setMixInAnnotation(PagedResources.class, PagedResourcesMixin.class); - setMixInAnnotation(Resource.class, ResourceMixin.class); + setMixInAnnotation(RepresentationModel.class, RepresentationModelMixin.class); + setMixInAnnotation(CollectionModel.class, CollectionModelMixin.class); + setMixInAnnotation(PagedModel.class, PagedModelMixin.class); + setMixInAnnotation(EntityModel.class, ResourceMixin.class); setMixInAnnotation(TypedResource.class, TypedResourceMixin.class); - addSerializer(Resource.class, new ResourceSerializer()); - addSerializer(PagedResources.class, new PagedResourcesSerializer(proxyUnwrapper)); + addSerializer(EntityModel.class, new ResourceSerializer()); + addSerializer(PagedModel.class, new PagedResourcesSerializer(proxyUnwrapper)); } diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/LinkListSerializer.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/LinkListSerializer.java index ef7b764c..bed5fd79 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/LinkListSerializer.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/LinkListSerializer.java @@ -13,30 +13,21 @@ package de.escalon.hypermedia.spring.hydra; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; import de.escalon.hypermedia.PropertyUtils; import de.escalon.hypermedia.action.Cardinality; import de.escalon.hypermedia.action.Input; -import de.escalon.hypermedia.affordance.*; +import de.escalon.hypermedia.affordance.ActionDescriptor; +import de.escalon.hypermedia.affordance.ActionInputParameter; +import de.escalon.hypermedia.affordance.Affordance; +import de.escalon.hypermedia.affordance.DataType; +import de.escalon.hypermedia.affordance.PartialUriTemplateComponents; +import de.escalon.hypermedia.affordance.TypedResource; import de.escalon.hypermedia.hydra.mapping.Expose; import de.escalon.hypermedia.hydra.serialize.JacksonHydraSerializer; import de.escalon.hypermedia.hydra.serialize.JsonLdKeywords; import de.escalon.hypermedia.hydra.serialize.LdContext; import de.escalon.hypermedia.hydra.serialize.LdContextFactory; import de.escalon.hypermedia.spring.SpringActionInputParameter; -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.hateoas.IanaRels; -import org.springframework.hateoas.Link; -import org.springframework.util.Assert; import java.beans.BeanInfo; import java.beans.IntrospectionException; @@ -48,12 +39,36 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.hateoas.IanaLinkRelations; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkRelation; +import org.springframework.hateoas.Links; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; /** * Serializer to convert Link to json-ld representation. Created by dschulten on 19.09.2014. */ -public class LinkListSerializer extends StdSerializer> { +public class LinkListSerializer extends StdSerializer { Logger LOG = LoggerFactory.getLogger(LinkListSerializer.class); @@ -65,7 +80,7 @@ public LinkListSerializer() { } @Override - public void serialize(List links, JsonGenerator jgen, + public void serialize(Links links, JsonGenerator jgen, SerializerProvider serializerProvider) throws IOException { try { @@ -83,7 +98,7 @@ public void serialize(List links, JsonGenerator jgen, if (affordance.getUriTemplateComponents() .hasVariables()) { // TODO resolve rel against context - if ("hydra:search".equals(affordance.getRel()) + if ("hydra:search".equals(affordance.getRel().value()) || Cardinality.SINGLE == affordance .getCardinality()) { templatedLinks.add(affordance); @@ -111,7 +126,7 @@ public void serialize(List links, JsonGenerator jgen, } else { simpleLinks.add(link); } - if ("self".equals(link.getRel())) { + if ("self".equals(link.getRel().value())) { selfRel = link; } } @@ -121,8 +136,8 @@ public void serialize(List links, JsonGenerator jgen, // only optional unsatisfied variables ActionDescriptor actionDescriptorForHttpGet = getActionDescriptorForHttpGet(templatedLink); // TODO handle rev here - String rel = templatedLink.getRel(); - writeIriTemplate(rel, templatedLink.getHref(), templatedLink.getVariableNames(), + LinkRelation rel = templatedLink.getRel(); + writeIriTemplate(rel.value(), templatedLink.getHref(), templatedLink.getVariableNames(), actionDescriptorForHttpGet, jgen); } @SuppressWarnings("unchecked") @@ -166,7 +181,7 @@ public void serialize(List links, JsonGenerator jgen, jgen.writeStringField("hydra:object", selfRel.getHref()); } } else if (collectionAffordance.getRel() != null) { - jgen.writeStringField("hydra:property", collectionAffordance.getRel()); + jgen.writeStringField("hydra:property", collectionAffordance.getRel().value()); if (collectionHolder != null) { // can't use writeObjectField, it won't inherit the context stack writeCollectionHolder("hydra:subject", collectionHolder, jgen); @@ -193,12 +208,12 @@ public void serialize(List links, JsonGenerator jgen, } for (Affordance affordance : affordances) { - final String rel = affordance.getRel(); + final LinkRelation rel = affordance.getRel(); List actionDescriptors = affordance.getActionDescriptors(); if (!actionDescriptors.isEmpty()) { - if (!Link.REL_SELF.equals(rel)) { - jgen.writeObjectFieldStart(rel); // begin rel + if (!IanaLinkRelations.SELF.equals(rel)) { + jgen.writeObjectFieldStart(rel.value()); // begin rel } jgen.writeStringField(JsonLdKeywords.AT_ID, affordance.getHref()); jgen.writeArrayFieldStart("hydra:operation"); @@ -210,18 +225,18 @@ public void serialize(List links, JsonGenerator jgen, if (!actionDescriptors.isEmpty()) { jgen.writeEndArray(); // end hydra:operation - if (!Link.REL_SELF.equals(rel)) { + if (!IanaLinkRelations.SELF.equals(rel)) { jgen.writeEndObject(); // end rel } } } for (Link simpleLink : simpleLinks) { - final String rel = simpleLink.getRel(); - if (Link.REL_SELF.equals(rel)) { + final LinkRelation rel = simpleLink.getRel(); + if (IanaLinkRelations.SELF.isSameAs(rel)) { jgen.writeStringField("@id", simpleLink.getHref()); } else { - String linkAttributeName = IanaRels.isIanaRel(rel) ? IANA_REL_PREFIX + rel : rel; + String linkAttributeName = IanaLinkRelations.isIanaRel(rel) ? IANA_REL_PREFIX + rel.value() : rel.value(); jgen.writeObjectFieldStart(linkAttributeName); jgen.writeStringField("@id", simpleLink.getHref()); jgen.writeEndObject(); @@ -338,7 +353,6 @@ private void recurseSupportedProperties(JsonGenerator jgen, String currentVocab, Map properties = new HashMap(); // collect supported properties from ctor - Constructor[] constructors = valueType.getConstructors(); // find default ctor Constructor constructor = PropertyUtils.findDefaultCtor(constructors); @@ -520,7 +534,7 @@ private void recurseSupportedProperties(JsonGenerator jgen, String currentVocab, private String getPropertyOrClassNameInVocab(@Nullable String currentVocab, String propertyOrClassName, String vocabulary, String vocabularyPrefixWithColon) { - Assert.notNull(vocabulary); + Assert.notNull(vocabulary, "Vocabulary should be not null"); String ret; if (vocabulary.equals(currentVocab)) { ret = propertyOrClassName; diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesMixin.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedModelMixin.java similarity index 83% rename from hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesMixin.java rename to hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedModelMixin.java index 6315f729..9c065a14 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesMixin.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedModelMixin.java @@ -1,17 +1,18 @@ package de.escalon.hypermedia.spring.hydra; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import de.escalon.hypermedia.hydra.mapping.ContextProvider; import de.escalon.hypermedia.hydra.mapping.Expose; import de.escalon.hypermedia.hydra.mapping.Term; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.PagedResources; import java.util.Collection; -import java.util.List; + +import org.springframework.hateoas.Links; +import org.springframework.hateoas.PagedModel; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * Mixin for json-ld serialization of PagedResources. @@ -19,7 +20,7 @@ @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) @Term(define = "hydra", as = "http://www.w3.org/ns/hydra/core#") @Expose("hydra:Collection") -public abstract class PagedResourcesMixin extends PagedResources { +public abstract class PagedModelMixin extends PagedModel { @Override @JsonProperty("hydra:member") @ContextProvider @@ -30,7 +31,7 @@ public Collection getContent() { @Override @JsonSerialize(using = LinkListSerializer.class) @JsonUnwrapped - public List getLinks() { + public Links getLinks() { return super.getLinks(); } diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesSerializer.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesSerializer.java index 46bdf32d..8c814f80 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesSerializer.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/PagedResourcesSerializer.java @@ -22,8 +22,12 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.util.NameTransformer; import de.escalon.hypermedia.hydra.serialize.*; + +import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; -import org.springframework.hateoas.PagedResources; +import org.springframework.hateoas.LinkRelation; +import org.springframework.hateoas.Links; +import org.springframework.hateoas.PagedModel; import java.io.IOException; import java.util.*; @@ -31,16 +35,21 @@ import static de.escalon.hypermedia.hydra.serialize.JacksonHydraSerializer.KEY_LD_CONTEXT; /** - * Serializer for Resources. Created by dschulten on 15.09.2014. + * Serializer for CollectionModel. Created by dschulten on 15.09.2014. */ @SuppressWarnings("unused") -public class PagedResourcesSerializer extends StdSerializer { +public class PagedResourcesSerializer extends StdSerializer { private final static Set navigationRels = new HashSet(); static { - Collections.addAll(navigationRels, Link.REL_FIRST, Link.REL_NEXT, Link.REL_PREVIOUS, Link.REL_LAST); + Collections.addAll( + navigationRels, + IanaLinkRelations.FIRST.value(), + IanaLinkRelations.NEXT.value(), + IanaLinkRelations.PREVIOUS.value(), + IanaLinkRelations.LAST.value()); } private final LdContextFactory ldContextFactory; @@ -48,14 +57,14 @@ public class PagedResourcesSerializer extends StdSerializer { @SuppressWarnings("unused") public PagedResourcesSerializer(ProxyUnwrapper proxyUnwrapper) { - super(PagedResources.class); + super(PagedModel.class); this.ldContextFactory = new LdContextFactory(); this.proxyUnwrapper = proxyUnwrapper; ldContextFactory.setProxyUnwrapper(proxyUnwrapper); } @Override - public void serialize(PagedResources pagedResources, JsonGenerator jgen, SerializerProvider serializerProvider) + public void serialize(PagedModel pagedResources, JsonGenerator jgen, SerializerProvider serializerProvider) throws IOException { @@ -76,10 +85,10 @@ public void serialize(PagedResources pagedResources, JsonGenerator jgen, Seriali } // TODO: filter next/previous/first/last from link list - maybe create new PagedResources without them? - List links = pagedResources.getLinks(); + Links links = pagedResources.getLinks(); List filteredLinks = new ArrayList(); for (Link link : links) { - String rel = link.getRel(); + String rel = link.getRel().value(); if (navigationRels.contains(rel)) { continue; } else { @@ -87,7 +96,7 @@ public void serialize(PagedResources pagedResources, JsonGenerator jgen, Seriali } } - PagedResources toRender = new PagedResources(pagedResources.getContent(), pagedResources.getMetadata(), + PagedModel toRender = new PagedModel(pagedResources.getContent(), pagedResources.getMetadata(), filteredLinks); jgen.writeStartObject(); @@ -101,18 +110,18 @@ public void serialize(PagedResources pagedResources, JsonGenerator jgen, Seriali serializer.unwrappingSerializer(NameTransformer.NOP) .serialize(toRender, jgen, serializerProvider); - PagedResources.PageMetadata metadata = pagedResources.getMetadata(); + PagedModel.PageMetadata metadata = pagedResources.getMetadata(); jgen.writeNumberField("hydra:totalItems", metadata.getTotalElements()); // begin hydra:view jgen.writeObjectFieldStart("hydra:view"); jgen.writeStringField(JsonLdKeywords.AT_TYPE, "hydra:PartialCollectionView"); - writeRelLink(pagedResources, jgen, Link.REL_NEXT); - writeRelLink(pagedResources, jgen, "previous"); + writeRelLink(pagedResources, jgen, IanaLinkRelations.NEXT); + writeRelLink(pagedResources, jgen, IanaLinkRelations.PREV); // must also translate prev to its synonym previous - writeRelLink(pagedResources, jgen, Link.REL_PREVIOUS, "previous"); - writeRelLink(pagedResources, jgen, Link.REL_FIRST); - writeRelLink(pagedResources, jgen, Link.REL_LAST); + writeRelLink(pagedResources, jgen, IanaLinkRelations.PREVIOUS, "previous"); + writeRelLink(pagedResources, jgen, IanaLinkRelations.FIRST); + writeRelLink(pagedResources, jgen, IanaLinkRelations.LAST); jgen.writeEndObject(); // end hydra:view @@ -173,15 +182,14 @@ protected void serializeContext(Object bean, JsonGenerator jgen, } } - private void writeRelLink(PagedResources value, JsonGenerator jgen, String rel) throws IOException { - writeRelLink(value, jgen, rel, rel); + private void writeRelLink(PagedModel value, JsonGenerator jgen, LinkRelation rel) throws IOException { + writeRelLink(value, jgen, rel, rel.value()); } - private void writeRelLink(PagedResources value, JsonGenerator jgen, String rel, String hydraPredicate) throws + private void writeRelLink(PagedModel value, JsonGenerator jgen, LinkRelation rel, String hydraPredicate) throws IOException { - Link link = value.getLink(rel); - if (link != null) { - jgen.writeStringField("hydra:" + hydraPredicate, link.getHref()); + if (rel != null) { + jgen.writeStringField("hydra:" + hydraPredicate, rel.value()); } } diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSupportMixin.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/RepresentationModelMixin.java similarity index 78% rename from hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSupportMixin.java rename to hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/RepresentationModelMixin.java index dab9be83..f14a6ad9 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSupportMixin.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/RepresentationModelMixin.java @@ -13,23 +13,22 @@ package de.escalon.hypermedia.spring.hydra; +import org.springframework.hateoas.Links; +import org.springframework.hateoas.RepresentationModel; + import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.ResourceSupport; - -import java.util.List; /** - * Mixin for json-ld serialization of ResourceSupport. Created by dschulten on 14.09.2014. + * Mixin for json-ld serialization of RepresentationModel. Created by dschulten on 14.09.2014. */ @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) -public class ResourceSupportMixin extends ResourceSupport { +public class RepresentationModelMixin extends RepresentationModel { @Override @JsonSerialize(using = LinkListSerializer.class) @JsonUnwrapped - public List getLinks() { + public Links getLinks() { return super.getLinks(); } diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceMixin.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceMixin.java index d78c4cd9..4bc8124c 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceMixin.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceMixin.java @@ -17,15 +17,16 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import de.escalon.hypermedia.hydra.mapping.ContextProvider; import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resource; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.Links; import java.util.List; /** - * Mixin for json-ld serialization of Resource. Created by dschulten on 14.09.2014. + * Mixin for json-ld serialization of EntityModel. Created by dschulten on 14.09.2014. */ @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) -public abstract class ResourceMixin extends Resource { +public abstract class ResourceMixin extends EntityModel { @SuppressWarnings("unused") public ResourceMixin(T content, Link... links) { @@ -40,7 +41,7 @@ public ResourceMixin(T content, Iterable links) { @Override @JsonSerialize(using = LinkListSerializer.class) @JsonUnwrapped - public List getLinks() { + public Links getLinks() { return super.getLinks(); } diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSerializer.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSerializer.java index 840a4929..34bf89da 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSerializer.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourceSerializer.java @@ -21,21 +21,21 @@ import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.util.NameTransformer; -import org.springframework.hateoas.Resource; +import org.springframework.hateoas.EntityModel; import java.io.IOException; /** - * Serializer for json-ld representation of Resource. Created by dschulten on 15.09.2014. + * Serializer for json-ld representation of EntityModel. Created by dschulten on 15.09.2014. */ -public class ResourceSerializer extends StdSerializer { +public class ResourceSerializer extends StdSerializer { public ResourceSerializer() { - super(Resource.class); + super(EntityModel.class); } @Override - public void serialize(Resource value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + public void serialize(EntityModel value, JsonGenerator jgen, SerializerProvider provider) throws IOException { final SerializationConfig config = provider.getConfig(); JavaType javaType = config.constructType(value.getClass()); diff --git a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesSerializer.java b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesSerializer.java index a9db3682..dc7f4ad4 100644 --- a/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesSerializer.java +++ b/hydra-spring/src/main/java/de/escalon/hypermedia/spring/hydra/ResourcesSerializer.java @@ -20,23 +20,23 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; import java.io.IOException; /** - * Serializer for Resources. Created by dschulten on 15.09.2014. + * Serializer for CollectionModel. Created by dschulten on 15.09.2014. */ @SuppressWarnings("unused") -public class ResourcesSerializer extends StdSerializer { +public class ResourcesSerializer extends StdSerializer { @SuppressWarnings("unused") public ResourcesSerializer() { - super(Resources.class); + super(CollectionModel.class); } @Override - public void serialize(Resources value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + public void serialize(CollectionModel value, JsonGenerator jgen, SerializerProvider provider) throws IOException { final SerializationConfig config = provider.getConfig(); JavaType javaType = config.constructType(value.getClass()); diff --git a/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventControllerExposed.java b/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventControllerExposed.java index df025ba0..23bef0d1 100644 --- a/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventControllerExposed.java +++ b/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventControllerExposed.java @@ -16,9 +16,9 @@ import de.escalon.hypermedia.action.Input; import de.escalon.hypermedia.hydra.mapping.Expose; import de.escalon.hypermedia.spring.AffordanceBuilder; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -42,13 +42,13 @@ public class DummyEventControllerExposed extends DummyEventController { @RequestMapping(value = "/regex/{eventId:.+}", method = RequestMethod.GET) public @ResponseBody - Resource getEventWithRegexPathVariableMapping(@PathVariable @Expose("ex:eventId") Integer eventId) { - Resource resource = new Resource(getEvents().get(eventId)); + EntityModel getEventWithRegexPathVariableMapping(@PathVariable @Expose("ex:eventId") Integer eventId) { + EntityModel resource = new EntityModel(getEvents().get(eventId)); resource.add(linkTo(ReviewController.class).withRel("review")); return resource; } - public static class FooResource extends ResourceSupport { + public static class FooResource extends RepresentationModel { private Pageable pageable; public FooResource(Pageable pageable) { @@ -126,7 +126,7 @@ public List getStrings() { } @RequestMapping("/query") - public HttpEntity> findList(@Input(include = {"offset", "size"}) Pageable pageable, + public HttpEntity> findList(@Input(include = {"offset", "size"}) Pageable pageable, @RequestParam(required = false) Integer foo1, @RequestParam(required = false) Integer foo2) { @@ -135,19 +135,19 @@ public HttpEntity> findList(@Input(include = {"offset", " .linkTo(methodOn(this.getClass()).findList(null, null, null)) .withRel("template")); - return new HttpEntity>(new Resources(Collections.singleton(fooResource))); + return new HttpEntity>(new CollectionModel(Collections.singleton(fooResource))); } @RequestMapping(method = RequestMethod.GET, params = {"evtName"}) public @ResponseBody - Resource findEventByName(@RequestParam("evtName") @Expose("http://schema.org/name") String eventName) { - Resource ret = null; + EntityModel findEventByName(@RequestParam("evtName") @Expose("http://schema.org/name") String eventName) { + EntityModel ret = null; for (Event event : getEvents()) { if (event.getWorkPerformed() .getContent().name.startsWith(eventName)) { - Resource resource = new Resource(event); + EntityModel resource = new EntityModel(event); resource.add(linkTo(ReviewController.class).withRel("review")); ret = resource; break; diff --git a/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResourceExposed.java b/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResourceExposed.java index d8023888..561bbcb4 100644 --- a/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResourceExposed.java +++ b/hydra-spring/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResourceExposed.java @@ -16,7 +16,7 @@ import de.escalon.hypermedia.hydra.mapping.Expose; /** - * Sample Event derived from ResourceSupport. Created by dschulten on 13.09.2014. + * Sample Event derived from RepresentationModel. Created by dschulten on 13.09.2014. */ @Expose("Event") public class EventResourceExposed extends EventResource { diff --git a/pom.xml b/pom.xml index c8da1527..f3c3969e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,9 @@ UTF-8 - 4.3.12.RELEASE - 2.9.8 + 5.2.9.RELEASE + 1.1.2.RELEASE + 2.10.5 2014 @@ -95,7 +96,7 @@ org.springframework.hateoas spring-hateoas - 0.24.0.RELEASE + ${spring.hateoas.version} de.escalon.hypermedia @@ -115,13 +116,13 @@ org.apache.commons commons-lang3 - 3.1 + 3.11 junit junit - 4.12 + 4.13.1 test @@ -180,7 +181,7 @@ com.github.jsonld-java jsonld-java - 0.11.1 + 0.13.2 com.jayway.jsonpath @@ -191,19 +192,18 @@ javax.servlet javax.servlet-api - 3.1.0 + 4.0.1 provided - com.intellij + org.jetbrains annotations - 12.0 - provided + 20.1.0 org.springframework.plugin spring-plugin-core - 1.2.0.RELEASE + 2.0.0.RELEASE false @@ -218,8 +218,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.8 + 1.8 diff --git a/spring-hateoas-ext/pom.xml b/spring-hateoas-ext/pom.xml index 082c5d4e..223e6850 100644 --- a/spring-hateoas-ext/pom.xml +++ b/spring-hateoas-ext/pom.xml @@ -20,6 +20,7 @@ com.damnhandy handy-uri-templates 2.1.4 + test org.springframework.hateoas @@ -42,7 +43,7 @@ javax.servlet-api - com.intellij + org.jetbrains annotations diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceSupportVisitor.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceSupportVisitor.java index fa137112..5629b4d3 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceSupportVisitor.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceSupportVisitor.java @@ -1,15 +1,14 @@ package de.escalon.hypermedia; -import org.springframework.hateoas.Link; - import java.util.Collection; -import java.util.List; + +import org.springframework.hateoas.Links; /** * Created by Dietrich on 07.05.2016. */ public interface ResourceSupportVisitor { - boolean visitLinks(List links); + boolean visitLinks(Links links); boolean visitEnterCollection(Collection collection); diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceTraversal.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceTraversal.java index d74a3f8e..37c37666 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceTraversal.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/ResourceTraversal.java @@ -1,9 +1,9 @@ package de.escalon.hypermedia; import de.escalon.hypermedia.affordance.DataType; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; @@ -30,23 +30,23 @@ public void traverseResource(ResourceSupportVisitor visitor, Object object) { try { // TODO: move all returns to else branch of property descriptor handling - if (object instanceof Resource) { - Resource resource = (Resource) object; + if (object instanceof EntityModel) { + EntityModel resource = (EntityModel) object; if(!visitor.visitLinks(resource.getLinks())) { return; } traverseResource(visitor, resource.getContent()); return; - } else if (object instanceof Resources) { - Resources resources = (Resources) object; + } else if (object instanceof CollectionModel) { + CollectionModel resources = (CollectionModel) object; if(!visitor.visitLinks(resources.getLinks())) { return; } traverseResource(visitor, resources.getContent()); return; - } else if (object instanceof ResourceSupport) { - ResourceSupport resource = (ResourceSupport) object; + } else if (object instanceof RepresentationModel) { + RepresentationModel resource = (RepresentationModel) object; if(!visitor.visitLinks(resource.getLinks())) { return; } diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/Options.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/Options.java index 09eb24cf..7850350e 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/Options.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/Options.java @@ -28,7 +28,7 @@ public interface Options { * DetailOptions implementation which needs a personId for that: *
      * @RequestMapping("/customer/{personId}/details")
-     * public HttpEntity<Resource<List<String>> showDetails(
+     * public HttpEntity<EntityModel<List<String>> showDetails(
      *     @PathVariable Long personId,
      *     @RequestParam("detail")
      *     @Select(options = DetailOptions.class, args = "personId")
diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/ResourceHandler.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/ResourceHandler.java
index ade33e59..bac81d5d 100644
--- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/ResourceHandler.java
+++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/action/ResourceHandler.java
@@ -7,7 +7,7 @@
 
 /**
  * Allows to explicitly qualify a method handler as resource with defined cardinality. Normally a Collection or a
- * Resources return type (optionally wrapped into an HttpEntity) or the presence of a POST method implicitly qualifies a
+ * CollectionModel return type (optionally wrapped into an HttpEntity) or the presence of a POST method implicitly qualifies a
  * resource a collection. Created by Dietrich on 02.05.2015.
  */
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/Affordance.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/Affordance.java
index 21c05b85..ddf9530f 100644
--- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/Affordance.java
+++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/Affordance.java
@@ -18,8 +18,10 @@
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonUnwrapped;
 import de.escalon.hypermedia.action.Cardinality;
-import org.springframework.aop.DynamicIntroductionAdvice;
+
+import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.Link;
+import org.springframework.hateoas.LinkRelation;
 import org.springframework.hateoas.TemplateVariable;
 import org.springframework.hateoas.UriTemplate;
 import org.springframework.util.Assert;
@@ -441,8 +443,8 @@ public Affordance withRel(String rel) {
     @Override
     public Affordance withSelfRel() {
         if (!linkParams.get(REL.paramName)
-                .contains(Link.REL_SELF)) {
-            linkParams.add(REL.paramName, Link.REL_SELF);
+                .contains(IanaLinkRelations.SELF.value())) {
+            linkParams.add(REL.paramName, IanaLinkRelations.SELF.value());
         }
         return new Affordance(this.getHref(), linkParams, actionDescriptors);
     }
@@ -456,7 +458,7 @@ public Affordance withSelfRel() {
      */
     @Override
     public Affordance expand(Object... arguments) {
-        UriTemplate template = new UriTemplate(partialUriTemplate.asComponents()
+        UriTemplate template = UriTemplate.of(partialUriTemplate.asComponents()
                 .toString());
         String expanded = template.expand(arguments)
                 .toASCIIString();
@@ -493,7 +495,7 @@ public PartialUriTemplateComponents getUriTemplateComponents() {
      */
     @Override
     public Affordance expand(Map arguments) {
-        UriTemplate template = new UriTemplate(partialUriTemplate.asComponents()
+        UriTemplate template = UriTemplate.of(partialUriTemplate.asComponents()
                 .toString());
         String expanded = template.expand(arguments)
                 .toASCIIString();
@@ -544,8 +546,10 @@ public List getRels() {
      * @return first defined rel or null
      */
     @Override
-    public String getRel() {
-        return linkParams.getFirst(REL.paramName);
+    public LinkRelation getRel() {
+        if (linkParams.getFirst(REL.paramName) != null)
+            return LinkRelation.of(linkParams.getFirst(REL.paramName));
+        else return null;
     }
 
     /**
diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/TypedResource.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/TypedResource.java
index 464698ef..e5d7b4aa 100644
--- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/TypedResource.java
+++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/affordance/TypedResource.java
@@ -3,7 +3,7 @@
 import org.springframework.util.Assert;
 
 /**
- * Resource of a certain semantic type which may or may not be identifiable.
+ * EntityModel of a certain semantic type which may or may not be identifiable.
  */
 public class TypedResource {
 
diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilder.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilder.java
index 91e45986..0d8dae2e 100644
--- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilder.java
+++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilder.java
@@ -14,10 +14,12 @@
 package de.escalon.hypermedia.spring;
 
 import de.escalon.hypermedia.affordance.*;
-import org.springframework.hateoas.Identifiable;
+
+import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.Link;
-import org.springframework.hateoas.LinkBuilder;
-import org.springframework.hateoas.core.DummyInvocationUtils;
+import org.springframework.hateoas.LinkRelation;
+import org.springframework.hateoas.server.LinkBuilder;
+import org.springframework.hateoas.server.core.DummyInvocationUtils;
 import org.springframework.util.Assert;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
@@ -82,7 +84,7 @@ public static AffordanceBuilder linkTo(Class controller, Object... parameters
     }
 
     /**
-     * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Method, Object...)
+     * @see org.springframework.hateoas.server.MethodLinkBuilderFactory#linkTo(Method, Object...)
      */
     public static AffordanceBuilder linkTo(Method method, Object... parameters) {
         return linkTo(method.getDeclaringClass(), method, parameters);
@@ -105,7 +107,7 @@ public static AffordanceBuilder linkTo(Class controller, Map param
     }
 
     /**
-     * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Class, Method, Object...)
+     * @see org.springframework.hateoas.server.MethodLinkBuilderFactory#linkTo(Class, Method, Object...)
      */
     public static AffordanceBuilder linkTo(Class controller, Method method, Object... parameters) {
         return FACTORY.linkTo(controller, method, parameters);
@@ -266,7 +268,7 @@ public AffordanceBuilder rel(String rel) {
      * not belong to the product, but to an order. You can express that by saying:
      * 
      * TypedResource order = new TypedResource("http://schema.org/Order"); // holds the ordered items
-     * Resource<Product> product = new Resource<>(); // has a loose relationship to ordered items
+     * EntityModel<Product> product = new EntityModel<>(); // has a loose relationship to ordered items
      * product.add(linkTo(methodOn(OrderController.class).postOrderedItem()
      *    .rel(order, "orderedItem")); // order has ordered items, not product has ordered items
      * 
@@ -338,10 +340,6 @@ public AffordanceBuilder slash(Object object) { return this; } - if (object instanceof Identifiable) { - return slash((Identifiable) object); - } - String urlPart = object.toString(); // make sure one cannot delete the fragment @@ -384,15 +382,6 @@ public AffordanceBuilder slash(Object object) { return new AffordanceBuilder(mergedUriComponents, actionDescriptors); } - @Override - public AffordanceBuilder slash(Identifiable identifiable) { - if (identifiable == null) { - return this; - } - - return slash(identifiable.getId()); - } - @Override public URI toUri() { PartialUriTemplate partialUriTemplate = new PartialUriTemplate(partialUriTemplateComponents.toString()); @@ -413,9 +402,14 @@ public Affordance withRel(String rel) { return rel(rel).build(); } + @Override + public Link withRel(final LinkRelation rel) { + return rel(rel.value()).build(); + } + @Override public Affordance withSelfRel() { - return rel(Link.REL_SELF).build(); + return rel(IanaLinkRelations.SELF.value()).build(); } @Override diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilderFactory.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilderFactory.java index 3fc67984..111c3114 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilderFactory.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/AffordanceBuilderFactory.java @@ -22,25 +22,45 @@ import de.escalon.hypermedia.affordance.ActionInputParameter; import de.escalon.hypermedia.affordance.DataType; import de.escalon.hypermedia.affordance.PartialUriTemplate; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.jetbrains.annotations.NotNull; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.hateoas.MethodLinkBuilderFactory; -import org.springframework.hateoas.Resources; -import org.springframework.hateoas.core.AnnotationMappingDiscoverer; -import org.springframework.hateoas.core.DummyInvocationUtils; -import org.springframework.hateoas.core.MappingDiscoverer; -import org.springframework.hateoas.core.MethodParameters; -import org.springframework.hateoas.mvc.ControllerLinkBuilder; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.server.MethodLinkBuilderFactory; +import org.springframework.hateoas.server.core.AnnotationMappingDiscoverer; +import org.springframework.hateoas.server.core.DummyInvocationUtils; +import org.springframework.hateoas.server.core.LastInvocationAware; +import org.springframework.hateoas.server.core.MappingDiscoverer; +import org.springframework.hateoas.server.core.MethodInvocation; +import org.springframework.hateoas.server.core.MethodParameters; import org.springframework.http.HttpEntity; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.*; - -import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; -import java.lang.reflect.*; -import java.util.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; /** * Factory for {@link AffordanceBuilder}s in a Spring MVC rest service. Normally one should use the static methods of @@ -50,14 +70,15 @@ public class AffordanceBuilderFactory implements MethodLinkBuilderFactory controller, Method method, Object... parameters) { - + public AffordanceBuilder linkTo(@NotNull Class controller, @NotNull Method method, Object... parameters) { String pathMapping = MAPPING_DISCOVERER.getMapping(controller, method); Map requestParamNames = getRequestParamNames(method); @@ -71,7 +92,7 @@ public AffordanceBuilder linkTo(Class controller, Method method, Object... pa .build() .toString() + mapping); - Map values = new HashMap(); + Map values = new HashMap<>(); Iterator variableNames = partialUriTemplate.getVariableNames() .iterator(); // there may be more or less mapping variables than arguments @@ -118,21 +139,23 @@ private String join(Map... params) { return ret.toString(); } + @NotNull @Override - public AffordanceBuilder linkTo(Class target) { + public AffordanceBuilder linkTo(@NotNull Class target) { return linkTo(target, new Object[0]); } + @NotNull @Override - public AffordanceBuilder linkTo(Class controller, Object... parameters) { - Assert.notNull(controller); + public AffordanceBuilder linkTo(@NotNull Class controller, Object... parameters) { + Assert.notNull(controller, "Controller should be not null"); String mapping = MAPPING_DISCOVERER.getMapping(controller); PartialUriTemplate partialUriTemplate = new PartialUriTemplate(mapping == null ? "/" : mapping); - Map values = new HashMap(); + Map values = new HashMap<>(); Iterator names = partialUriTemplate.getVariableNames() .iterator(); // there may be more or less mapping variables than arguments @@ -145,21 +168,24 @@ public AffordanceBuilder linkTo(Class controller, Object... parameters) { return new AffordanceBuilder().slash(partialUriTemplate.expand(values)); } + @NotNull @Override - public AffordanceBuilder linkTo(Class controller, Map parameters) { + public AffordanceBuilder linkTo(@NotNull Class controller, @NotNull Map parameters) { String mapping = MAPPING_DISCOVERER.getMapping(controller); PartialUriTemplate partialUriTemplate = new PartialUriTemplate(mapping == null ? "/" : mapping); return new AffordanceBuilder().slash(partialUriTemplate.expand(parameters)); } + @NotNull @Override - public AffordanceBuilder linkTo(Object invocationValue) { - - Assert.isInstanceOf(DummyInvocationUtils.LastInvocationAware.class, invocationValue); - DummyInvocationUtils.LastInvocationAware invocations = (DummyInvocationUtils.LastInvocationAware) - invocationValue; + public AffordanceBuilder linkTo(@NotNull Object invocationValue) { + Assert.isInstanceOf(LastInvocationAware.class, invocationValue); + LastInvocationAware invocations = DummyInvocationUtils.getLastInvocationAware(invocationValue); + if (invocations == null) { + throw new IllegalStateException(String.format("Could not obtain previous invocation from %s!", invocationValue)); + } - DummyInvocationUtils.MethodInvocation invocation = invocations.getLastInvocation(); + MethodInvocation invocation = invocations.getLastInvocation(); Method invokedMethod = invocation.getMethod(); String pathMapping = MAPPING_DISCOVERER.getMapping(invokedMethod); @@ -175,8 +201,7 @@ public AffordanceBuilder linkTo(Object invocationValue) { .build() .toString() + mapping); - - Map values = new HashMap(); + Map values = new HashMap<>(); Iterator variableNames = partialUriTemplate.getVariableNames() .iterator(); while (classMappingParameters.hasNext()) { @@ -201,11 +226,11 @@ public AffordanceBuilder linkTo(Object invocationValue) { } private Map getInputBeanParamNames(Method invokedMethod) { - MethodParameters parameters = new MethodParameters(invokedMethod); + MethodParameters parameters = MethodParameters.of(invokedMethod); final List inputParams = parameters.getParametersWith(Input.class); - Map ret = new LinkedHashMap(inputParams.size()); + Map ret = new LinkedHashMap<>(inputParams.size()); for (MethodParameter inputParam : inputParams) { Class parameterType = inputParam.getParameterType(); // only use @Input param which is a bean or map and has no other annotations @@ -214,7 +239,7 @@ private Map getInputBeanParamNames(Method invokedMethod) { !(DataType.isSingleValueType(parameterType) || DataType.isArrayOrCollection(parameterType))) { Input inputAnnotation = inputParam.getParameterAnnotation(Input.class); - Set explicitlyIncludedParams = new LinkedHashSet(inputParams.size()); + Set explicitlyIncludedParams = new LinkedHashSet<>(inputParams.size()); Collections.addAll(explicitlyIncludedParams, inputAnnotation.include()); Collections.addAll(explicitlyIncludedParams, inputAnnotation.hidden()); @@ -254,7 +279,7 @@ private Map getInputBeanParamNames(Method invokedMethod) { @NotNull private Set getWritablePropertyNames(Class parameterType) { - Set inputBeanPropertyNames = new LinkedHashSet(); + Set inputBeanPropertyNames = new LinkedHashSet<>(); Map propertyDescriptors = PropertyUtils.getPropertyDescriptors (parameterType); for (PropertyDescriptor propertyDescriptor : propertyDescriptors.values()) { @@ -280,9 +305,9 @@ private void assertInputAnnotationConsistency(MethodParameter inputParam, Set getRequestParamNames(Method invokedMethod) { - MethodParameters parameters = new MethodParameters(invokedMethod); + MethodParameters parameters = MethodParameters.of(invokedMethod); final List requestParams = parameters.getParametersWith(RequestParam.class); - Map params = new LinkedHashMap(requestParams.size()); + Map params = new LinkedHashMap<>(requestParams.size()); for (MethodParameter requestParam : requestParams) { RequestParam requestParamAnnotation = requestParam.getParameterAnnotation(RequestParam.class); params.put(requestParam.getParameterName(), requestParamAnnotation.value() @@ -384,8 +409,7 @@ private boolean containsCollection(Type genericReturnType) { if (HttpEntity.class.isAssignableFrom(cls)) { Type[] typeArguments = t.getActualTypeArguments(); ret = containsCollection(typeArguments[0]); - } else if (Resources.class.isAssignableFrom(cls) || - Collection.class.isAssignableFrom(cls)) { + } else if (CollectionModel.class.isAssignableFrom(cls) || Collection.class.isAssignableFrom(cls)) { ret = true; } else { ret = false; @@ -399,7 +423,7 @@ private boolean containsCollection(Type genericReturnType) { ret = false; } else if (genericReturnType instanceof Class) { Class cls = (Class) genericReturnType; - ret = Resources.class.isAssignableFrom(cls) || + ret = CollectionModel.class.isAssignableFrom(cls) || Collection.class.isAssignableFrom(cls); } else { ret = false; @@ -447,8 +471,8 @@ private static Map getActionInputParameters(Class< Assert.notNull(method, "MethodInvocation must not be null!"); - MethodParameters parameters = new MethodParameters(method); - Map result = new HashMap(); + MethodParameters parameters = MethodParameters.of(method); + Map result = new HashMap<>(); for (MethodParameter parameter : parameters.getParametersWith(annotation)) { final int parameterIndex = parameter.getParameterIndex(); diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenAction.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenAction.java index 42c750ad..3dbd4634 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenAction.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenAction.java @@ -1,22 +1,22 @@ package de.escalon.hypermedia.spring.siren; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; /** * Created by Dietrich on 17.04.2016. */ -@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY) +@JsonInclude @JsonPropertyOrder({"name", "title", "method", "href", "type", "fields"}) public class SirenAction extends AbstractSirenEntity { - private String name; - private String method; - private String href; - private String type; - private List fields; + private final String name; + private final String method; + private final String href; + private final String type; + private final List fields; /** * @param sirenClasses diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenMessageConverter.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenMessageConverter.java index d725ed05..2866fc82 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenMessageConverter.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenMessageConverter.java @@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import de.escalon.hypermedia.spring.DocumentationProvider; -import org.springframework.hateoas.RelProvider; +import org.springframework.hateoas.server.LinkRelationProvider; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -38,7 +38,7 @@ public SirenMessageConverter() { * @param relProvider * to determine siren class */ - public void setRelProvider(RelProvider relProvider) { + public void setRelProvider(LinkRelationProvider relProvider) { sirenUtils.setRelProvider(relProvider); } @@ -116,8 +116,8 @@ protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws I * @return the JSON encoding to use (never {@code null}) */ protected JsonEncoding getJsonEncoding(MediaType contentType) { - if (contentType != null && contentType.getCharSet() != null) { - Charset charset = contentType.getCharSet(); + if (contentType != null && contentType.getCharset() != null) { + Charset charset = contentType.getCharset(); for (JsonEncoding encoding : JsonEncoding.values()) { if (charset.name() .equals(encoding.getJavaName())) { diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenUtils.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenUtils.java index 4a086e54..18f2ea7c 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenUtils.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/siren/SirenUtils.java @@ -1,8 +1,5 @@ package de.escalon.hypermedia.spring.siren; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; @@ -25,7 +22,8 @@ import de.escalon.hypermedia.spring.SpringActionInputParameter; import org.springframework.core.MethodParameter; import org.springframework.hateoas.*; -import org.springframework.hateoas.core.DefaultRelProvider; +import org.springframework.hateoas.server.LinkRelationProvider; +import org.springframework.hateoas.server.core.DefaultLinkRelationProvider; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -38,9 +36,9 @@ public class SirenUtils { "id")); private String requestMediaType; - private Set navigationalRels = new HashSet(Arrays.asList("self", "next", "previous", "prev")); + private final Set navigationalRels = new HashSet<>(Arrays.asList("self", "next", "previous", "prev")); - private RelProvider relProvider = new DefaultRelProvider(); + private LinkRelationProvider relProvider = new DefaultLinkRelationProvider(); private DocumentationProvider documentationProvider = new DefaultDocumentationProvider(); @@ -49,8 +47,8 @@ public void toSirenEntity(SirenEntityContainer objectNode, Object object) { return; } try { - if (object instanceof Resource) { - Resource resource = (Resource) object; + if (object instanceof EntityModel) { + EntityModel resource = (EntityModel) object; objectNode.setLinks(this.toSirenLinks( getNavigationalLinks(resource.getLinks()))); objectNode.setEmbeddedLinks(this.toSirenEmbeddedLinks( @@ -58,25 +56,23 @@ public void toSirenEntity(SirenEntityContainer objectNode, Object object) { objectNode.setActions(this.toSirenActions(getActions(resource.getLinks()))); toSirenEntity(objectNode, resource.getContent()); return; - } else if (object instanceof Resources) { - Resources resources = (Resources) object; - - objectNode.setLinks(this.toSirenLinks(getNavigationalLinks(resources.getLinks()))); + } else if (object instanceof CollectionModel) { + CollectionModel resources = (CollectionModel) object; + objectNode.setLinks(this.toSirenLinks( + getNavigationalLinks(resources.getLinks()))); Collection content = resources.getContent(); toSirenEntity(objectNode, content); objectNode.setActions(this.toSirenActions(getActions(resources.getLinks()))); return; - } else if (object instanceof ResourceSupport) { - ResourceSupport resource = (ResourceSupport) object; + } else if (object instanceof RepresentationModel) { + RepresentationModel resource = (RepresentationModel) object; objectNode.setLinks(this.toSirenLinks( getNavigationalLinks(resource.getLinks()))); objectNode.setEmbeddedLinks(this.toSirenEmbeddedLinks( getEmbeddedLinks(resource.getLinks()))); objectNode.setActions(this.toSirenActions( getActions(resource.getLinks()))); - // wrap object attributes below to avoid endless loop - } else if (object instanceof Collection) { Collection collection = (Collection) object; for (Object item : collection) { @@ -98,7 +94,7 @@ public void toSirenEntity(SirenEntityContainer objectNode, Object object) { String docUrl = documentationProvider.getDocumentationUrl(key, content); traverseAttribute(objectNode, propertiesNode, key, docUrl, content); } - } else { // bean or ResourceSupport + } else { // bean or RepresentationModel objectNode.setSirenClasses(getSirenClasses(object)); Map propertiesNode = new HashMap(); createRecursiveSirenEntitiesFromPropertiesAndFields(objectNode, propertiesNode, object); @@ -111,7 +107,7 @@ public void toSirenEntity(SirenEntityContainer objectNode, Object object) { private List getSirenClasses(Object object) { List sirenClasses; - String sirenClass = relProvider.getItemResourceRelFor(object.getClass()); + String sirenClass = relProvider.getItemResourceRelFor(object.getClass()).value(); if (sirenClass != null) { sirenClasses = Collections.singletonList(sirenClass); } else { @@ -120,8 +116,8 @@ private List getSirenClasses(Object object) { return sirenClasses; } - private List getEmbeddedLinks(List links) { - List ret = new ArrayList(); + private List getEmbeddedLinks(Links links) { + List ret = new ArrayList<>(); for (Link link : links) { if (!navigationalRels.contains(link.getRel())) { if (link instanceof Affordance) { @@ -143,17 +139,17 @@ private List getEmbeddedLinks(List links) { return ret; } - private List getNavigationalLinks(List links) { - List ret = new ArrayList(); + private List getNavigationalLinks(Links links) { + List ret = new ArrayList<>(); for (Link link : links) { - if (navigationalRels.contains(link.getRel())) { + if (navigationalRels.contains(link.getRel().value())) { ret.add(link); } } return ret; } - private List getActions(List links) { + private List getActions(Links links) { List ret = new ArrayList(); for (Link link : links) { if (link instanceof Affordance) { @@ -221,9 +217,9 @@ private void traverseAttribute(SirenEntityContainer objectNode, Map collection = (Collection) content; @@ -262,16 +258,16 @@ private void traverseSingleSubEntity(SirenEntityContainer objectNode, Object con throws InvocationTargetException, IllegalAccessException { Object bean; - List links; - if (content instanceof Resource) { - bean = ((Resource) content).getContent(); - links = ((Resource) content).getLinks(); - } else if (content instanceof ResourceSupport) { + Links links; + if (content instanceof EntityModel) { + bean = ((EntityModel) content).getContent(); + links = ((EntityModel) content).getLinks(); + } else if (content instanceof RepresentationModel) { bean = content; - links = ((ResourceSupport) content).getLinks(); + links = ((RepresentationModel) content).getLinks(); } else { bean = content; - links = Collections.emptyList(); + links = Links.NONE; } Map properties = new HashMap(); @@ -326,7 +322,7 @@ private List toSirenActions(List links) { } // no support for non-query fields in siren if (queryOnly) { - String baseUri = new UriTemplate(link.getHref()).expand() + String baseUri = UriTemplate.of(link.getHref()).expand() .toASCIIString(); SirenAction sirenAction = new SirenAction(null, null, null, "GET", baseUri, null, fields); @@ -483,8 +479,8 @@ private void addSirenFieldsForMethodParameter(List sirenFields, Meth } } else { Object callValueBean; - if (propertyValue instanceof Resource) { - callValueBean = ((Resource) propertyValue).getContent(); + if (propertyValue instanceof EntityModel) { + callValueBean = ((EntityModel) propertyValue).getContent(); } else { callValueBean = propertyValue; } @@ -542,7 +538,7 @@ private List toSirenLinks(List links) { if (link instanceof Affordance) { ret.add(new SirenLink(null, ((Affordance) link).getRels(), link.getHref(), null, null)); } else { - ret.add(new SirenLink(null, Collections.singletonList(link.getRel()), link.getHref(), null, null)); + ret.add(new SirenLink(null, Collections.singletonList(link.getRel().value()), link.getHref(), null, null)); } } return ret; @@ -556,7 +552,7 @@ private List toSirenEmbeddedLinks(List links) { ret.add(new SirenEmbeddedLink(null, ((Affordance) link).getRels(), link .getHref(), null, null)); } else { - ret.add(new SirenEmbeddedLink(null, Collections.singletonList(link.getRel()), link + ret.add(new SirenEmbeddedLink(null, Collections.singletonList(link.getRel().value()), link .getHref(), null, null)); } } @@ -585,7 +581,7 @@ public void setRequestMediaType(String requestMediaType) { this.requestMediaType = requestMediaType; } - public void setRelProvider(RelProvider relProvider) { + public void setRelProvider(LinkRelationProvider relProvider) { this.relProvider = relProvider; } diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/AbstractUberNode.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/AbstractUberNode.java index bd69e99a..5693d620 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/AbstractUberNode.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/AbstractUberNode.java @@ -27,7 +27,7 @@ public abstract class AbstractUberNode implements Iterable { - protected List data = new ArrayList(); + protected List data = new ArrayList<>(); public AbstractUberNode() { super(); @@ -45,8 +45,8 @@ public void addData(UberNode item) { public void addLink(Link link) { List actionDescriptors = UberUtils.getActionDescriptors(link); List rels = UberUtils.getRels(link); - PartialUriTemplateComponents partialUriTemplateComponents = new PartialUriTemplate(link.getHref()).expand - (Collections.emptyMap()); + PartialUriTemplateComponents partialUriTemplateComponents = new PartialUriTemplate(link.getHref()) + .expand(Collections.emptyMap()); for (ActionDescriptor actionDescriptor : actionDescriptors) { UberNode uberLink = UberUtils.toUberLink(link.getHref(), actionDescriptor, rels); data.add(uberLink); diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/NullValueSerializer.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/NullValueSerializer.java index d31ae23b..ef260201 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/NullValueSerializer.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/NullValueSerializer.java @@ -13,22 +13,20 @@ package de.escalon.hypermedia.spring.uber; -import com.fasterxml.jackson.core.JsonGenerationException; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.NonTypedScalarSerializerBase; - -import java.io.IOException; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; -public class NullValueSerializer extends NonTypedScalarSerializerBase { +public class NullValueSerializer extends StdSerializer { protected NullValueSerializer() { super(UberNode.NullValue.class); } @Override - public void serialize(UberNode.NullValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException, - JsonGenerationException { + public void serialize(UberNode.NullValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException { jgen.writeNull(); } } diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJackson2HttpMessageConverter.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJackson2HttpMessageConverter.java index 2b5ed3d0..75b67534 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJackson2HttpMessageConverter.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJackson2HttpMessageConverter.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import de.escalon.hypermedia.spring.HypermediaTypes; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.RepresentationModel; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -46,7 +46,7 @@ public UberJackson2HttpMessageConverter() { @Override protected boolean supports(Class clazz) { final boolean ret; - if (ResourceSupport.class.isAssignableFrom(clazz) + if (RepresentationModel.class.isAssignableFrom(clazz) || Collection.class.isAssignableFrom(clazz) || Map.class.isAssignableFrom(clazz)) { ret = true; } else { @@ -93,8 +93,8 @@ protected void writeInternal(Object t, HttpOutputMessage outputMessage) throws I * @return the JSON encoding to use (never {@code null}) */ protected JsonEncoding getJsonEncoding(MediaType contentType) { - if (contentType != null && contentType.getCharSet() != null) { - Charset charset = contentType.getCharSet(); + if (contentType != null && contentType.getCharset() != null) { + Charset charset = contentType.getCharset(); for (JsonEncoding encoding : JsonEncoding.values()) { if (charset.name() .equals(encoding.getJavaName())) { diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJsonLinkDiscoverer.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJsonLinkDiscoverer.java index 2cc2b1e4..ed1a180b 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJsonLinkDiscoverer.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberJsonLinkDiscoverer.java @@ -14,7 +14,7 @@ package de.escalon.hypermedia.spring.uber; import de.escalon.hypermedia.spring.HypermediaTypes; -import org.springframework.hateoas.core.JsonPathLinkDiscoverer; +import org.springframework.hateoas.client.JsonPathLinkDiscoverer; public class UberJsonLinkDiscoverer extends JsonPathLinkDiscoverer { diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberUtils.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberUtils.java index c1f8f1f0..1e1f04af 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberUtils.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/uber/UberUtils.java @@ -23,9 +23,9 @@ import de.escalon.hypermedia.spring.SpringActionInputParameter; import org.springframework.core.MethodParameter; import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.util.Assert; import org.springframework.web.bind.annotation.RequestMethod; @@ -63,13 +63,13 @@ public static void toUberData(AbstractUberNode objectNode, Object object) { try { // TODO: move all returns to else branch of property descriptor handling - if (object instanceof Resource) { - Resource resource = (Resource) object; + if (object instanceof EntityModel) { + EntityModel resource = (EntityModel) object; objectNode.addLinks(resource.getLinks()); toUberData(objectNode, resource.getContent()); return; - } else if (object instanceof Resources) { - Resources resources = (Resources) object; + } else if (object instanceof CollectionModel) { + CollectionModel resources = (CollectionModel) object; // TODO set name using EVO see HypermediaSupportBeanDefinitionRegistrar @@ -78,8 +78,8 @@ public static void toUberData(AbstractUberNode objectNode, Object object) { Collection content = resources.getContent(); toUberData(objectNode, content); return; - } else if (object instanceof ResourceSupport) { - ResourceSupport resource = (ResourceSupport) object; + } else if (object instanceof RepresentationModel) { + RepresentationModel resource = (RepresentationModel) object; objectNode.addLinks(resource.getLinks()); @@ -231,15 +231,12 @@ public static UberNode toUberLink(String href, ActionDescriptor actionDescriptor Assert.notNull(actionDescriptor, "actionDescriptor must not be null"); UberNode uberLink = new UberNode(); uberLink.setRel(rels); - PartialUriTemplateComponents partialUriTemplateComponents = new PartialUriTemplate(href).expand(Collections - .emptyMap()); + PartialUriTemplateComponents partialUriTemplateComponents = new PartialUriTemplate(href).expand(Collections.emptyMap()); uberLink.setUrl(partialUriTemplateComponents.toString()); uberLink.setTemplated(partialUriTemplateComponents.hasVariables() ? Boolean.TRUE : null); uberLink.setModel(getModelProperty(href, actionDescriptor)); - if (actionDescriptor != null) { - RequestMethod requestMethod = RequestMethod.valueOf(actionDescriptor.getHttpMethod()); - uberLink.setAction(UberAction.forRequestMethod(requestMethod)); - } + RequestMethod requestMethod = RequestMethod.valueOf(actionDescriptor.getHttpMethod()); + uberLink.setAction(UberAction.forRequestMethod(requestMethod)); return uberLink; } @@ -458,7 +455,7 @@ public static List getRels(Link link) { if (link instanceof Affordance) { rels = ((Affordance) link).getRels(); } else { - rels = Arrays.asList(link.getRel()); + rels = Arrays.asList(link.getRel().value()); } return rels; } @@ -486,8 +483,8 @@ private static void addUberFieldsForMethodParameter(List fields, Meth } } else { Object callValueBean; - if (propertyValue instanceof Resource) { - callValueBean = ((Resource) propertyValue).getContent(); + if (propertyValue instanceof EntityModel) { + callValueBean = ((EntityModel) propertyValue).getContent(); } else { callValueBean = propertyValue; } diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlResourceMessageConverter.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlResourceMessageConverter.java index b139d418..e6fa612e 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlResourceMessageConverter.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlResourceMessageConverter.java @@ -19,9 +19,9 @@ import de.escalon.hypermedia.affordance.DataType; import de.escalon.hypermedia.spring.DefaultDocumentationProvider; import de.escalon.hypermedia.spring.DocumentationProvider; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -46,7 +46,7 @@ /** * Message converter which represents a restful API as xhtml which can be used by the browser or a rest client. Converts - * java beans and spring-hateoas Resources to xhtml and maps the body of x-www-form-urlencoded requests to RequestBody + * java beans and spring-hateoas CollectionModel to xhtml and maps the body of x-www-form-urlencoded requests to RequestBody * method parameters. The media-type xhtml does not officially support methods other than GET or POST, therefore we must * "tunnel" other methods when this converter is used with the browser. Spring's {@link * org.springframework.web.filter.HiddenHttpMethodFilter} allows to do that with relative ease. @@ -106,7 +106,7 @@ protected Object readInternal(Class clazz, HttpInputMessage inputMessage) thr // TODO recognize this more safely or make the filter mandatory MediaType contentType = inputMessage.getHeaders() .getContentType(); - Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : this.charset; + Charset charset = contentType.getCharset() != null ? contentType.getCharset() : this.charset; ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) inputMessage; HttpServletRequest servletRequest = servletServerHttpRequest.getServletRequest(); is = getBodyFromServletRequestParameters(servletRequest, charset.displayName(Locale.US)); @@ -284,16 +284,16 @@ private void writeResource(XhtmlWriter writer, Object object) { return; } try { - if (object instanceof Resource) { - Resource resource = (Resource) object; + if (object instanceof EntityModel) { + EntityModel resource = (EntityModel) object; writer.beginListItem(); writeResource(writer, resource.getContent()); writer.writeLinks(resource.getLinks()); writer.endListItem(); - } else if (object instanceof Resources) { - Resources resources = (Resources) object; + } else if (object instanceof CollectionModel) { + CollectionModel resources = (CollectionModel) object; // TODO set name using EVO see HypermediaSupportBeanDefinitionRegistrar writer.beginListItem(); @@ -306,8 +306,8 @@ private void writeResource(XhtmlWriter writer, Object object) { writer.writeLinks(resources.getLinks()); writer.endListItem(); - } else if (object instanceof ResourceSupport) { - ResourceSupport resource = (ResourceSupport) object; + } else if (object instanceof RepresentationModel) { + RepresentationModel resource = (RepresentationModel) object; writer.beginListItem(); writeObject(writer, resource); @@ -319,7 +319,7 @@ private void writeResource(XhtmlWriter writer, Object object) { for (Object item : collection) { writeResource(writer, item); } - } else { // TODO: write li for simple objects in Resources Collection + } else { // TODO: write li for simple objects in CollectionModel Collection writeObject(writer, object); } } catch (Exception ex) { diff --git a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriter.java b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriter.java index f8b87aa8..679da984 100644 --- a/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriter.java +++ b/spring-hateoas-ext/src/main/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriter.java @@ -15,6 +15,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.convert.Property; import org.springframework.hateoas.Link; +import org.springframework.hateoas.Links; import org.springframework.hateoas.TemplateVariable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -246,7 +247,7 @@ public static OptionalAttributes attr() { } - public void writeLinks(List links) throws IOException { + public void writeLinks(Links links) throws IOException { for (Link link : links) { if (link instanceof Affordance) { @@ -279,7 +280,7 @@ public void writeLinks(List links) throws IOException { // GET without params is simple writeAnchor(OptionalAttributes.attr("href", affordance.expand() .getHref()) - .and("rel", affordance.getRel()), affordance.getRel()); + .and("rel", affordance.getRel().value()), affordance.getRel().value()); endDiv(); } else { appendForm(affordance, actionDescriptor); @@ -384,11 +385,11 @@ private void appendLinkWithoutActionDescriptor(Link link) throws IOException { input(variableName, Type.TEXT); } } else { - String rel = link.getRel(); + String rel = link.getRel().value(); String title = (rel != null ? rel : link.getHref()); // TODO: write html instead of anchor here? writeAnchor(OptionalAttributes.attr("href", link.getHref()) - .and("rel", link.getRel()), title); + .and("rel", link.getRel().value()), title); } } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/affordance/AffordanceTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/affordance/AffordanceTest.java index f0130555..b3f8133b 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/affordance/AffordanceTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/affordance/AffordanceTest.java @@ -16,6 +16,7 @@ import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; +import org.springframework.hateoas.LinkRelation; import java.util.HashMap; import java.util.Map; @@ -38,7 +39,7 @@ public void testConstructorWithoutRels() { public void testConstructorWithSingleRel() { final Affordance affordance = new Affordance("http://localhost/things/{id}", "thing"); assertEquals("http://localhost/things/{id}", affordance.getHref()); - assertEquals("thing", affordance.getRel()); + assertEquals(LinkRelation.of("thing"), affordance.getRel()); Assert.assertThat(affordance.getRels(), Matchers.contains("thing")); } @@ -47,7 +48,7 @@ public void testConstructorWithRels() { final Affordance affordance = new Affordance("http://localhost/things/{id}", "start", "http://example.net/relation/other"); assertEquals("http://localhost/things/{id}", affordance.getHref()); - assertEquals("start", affordance.getRel()); + assertEquals(LinkRelation.of("start"), affordance.getRel()); Assert.assertThat(affordance.getRels(), Matchers.contains("start", "http://example.net/relation/other")); } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/AffordanceBuilderFactoryTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/AffordanceBuilderFactoryTest.java index 14f7b91e..51ba3aa0 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/AffordanceBuilderFactoryTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/AffordanceBuilderFactoryTest.java @@ -17,8 +17,8 @@ import de.escalon.hypermedia.affordance.Affordance; import org.junit.Before; import org.junit.Test; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockServletContext; import org.springframework.stereotype.Controller; @@ -32,6 +32,7 @@ import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; @@ -55,8 +56,8 @@ enum EventStatus { static class EventControllerSample { static class EventQbe { - List description = Arrays.asList("concert"); - List status = Arrays.asList(EventStatus.SCHEDULED); + List description = Collections.singletonList("concert"); + List status = Collections.singletonList(EventStatus.SCHEDULED); public void setStatus(List status) { this.status = status; @@ -80,38 +81,37 @@ public List getDescription() { @RequestMapping(value = "/{eventId}", method = RequestMethod.GET) public @ResponseBody - Resource getEvent(@PathVariable String eventId) { + EntityModel getEvent(@PathVariable String eventId) { return null; } @RequestMapping(value = "/query", method = RequestMethod.GET) public @ResponseBody - Resources queryEvent(@Input EventQbe query) { + CollectionModel queryEvent(@Input EventQbe query) { return null; } @RequestMapping(value = "/simplequery", method = RequestMethod.GET) public @ResponseBody - Resources simpleQueryEvent(@RequestParam("q") String query, - @RequestParam(value = "offset", defaultValue = "0") Long offset) { + CollectionModel simpleQueryEvent( + @RequestParam("q") String query, + @RequestParam(value = "offset", defaultValue = "0") Long offset) { return null; } - - @RequestMapping(value = "/queryexcludes", method = RequestMethod.GET) public @ResponseBody - Resources queryEventWithExcludes(@Input(exclude = "status") EventQbe query) { + CollectionModel queryEventWithExcludes(@Input(exclude = "status") EventQbe query) { return null; } @RequestMapping(value = "/queryincludes", method = RequestMethod.GET) public @ResponseBody - Resources queryEventWithIncludes(@Input(include = "status") EventQbe query) { + CollectionModel queryEventWithIncludes(@Input(include = "status") EventQbe query) { return null; } @@ -119,7 +119,7 @@ Resources queryEventWithIncludes(@Input(include = "status") EventQbe que @RequestMapping(value = "/querymap", method = RequestMethod.GET) public @ResponseBody - Resources queryEventByMap(@Input(include = "description", hidden = "status", readOnly = "donttouch") + CollectionModel queryEventByMap(@Input(include = "description", hidden = "status", readOnly = "donttouch") MultiValueMap query) { return null; } @@ -128,14 +128,14 @@ Resources queryEventByMap(@Input(include = "description", hidden = "stat @RequestMapping(value = "/wrongqueryinclude", method = RequestMethod.GET) public @ResponseBody - Resources queryEventWithWrongInclude(@Input(include = "foo") EventQbe query) { + CollectionModel queryEventWithWrongInclude(@Input(include = "foo") EventQbe query) { return null; } @RequestMapping(value = "/wrongqueryexclude", method = RequestMethod.GET) public @ResponseBody - Resources queryEventWithWrongExclude(@Input(exclude = "foo") EventQbe query) { + CollectionModel queryEventWithWrongExclude(@Input(exclude = "foo") EventQbe query) { return null; } } @@ -169,8 +169,9 @@ public void testLinkToMethodWithInputBean() throws Exception { @Test public void testLinkToMethodInvocation() throws Exception { - final Affordance affordance = factory.linkTo(AffordanceBuilder.methodOn(EventControllerSample.class) - .getEvent((String) null)) + final Affordance affordance = factory.linkTo( + AffordanceBuilder.methodOn(EventControllerSample.class) + .getEvent(null)) .rel("foo") .build(); assertEquals("http://example.com/events/{eventId}", affordance.getHref()); @@ -187,11 +188,12 @@ public void testLinkToControllerClass() throws Exception { @Test public void testLinkToMethodNoArgsBuild() throws Exception { final Method getEventMethod = ReflectionUtils.findMethod(EventControllerSample.class, "getEvent", String.class); + assert getEventMethod != null; final Affordance affordance = factory.linkTo(getEventMethod, new Object[0]) .rel("foo") .build(); assertEquals("http://example.com/events/{eventId}", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -202,7 +204,7 @@ public void testLinkToMethodInvocationNoArgsBuild() throws Exception { .rel("foo") .build(); assertEquals("http://example.com/events/{eventId}", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -213,7 +215,7 @@ public void testLinkToMethodInvocationBeanInput() throws Exception { .rel("foo") .build(); assertEquals("http://example.com/events/query{?description,status}", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -228,7 +230,7 @@ public void testLinkToMethodInvocationNamedRequestParam() throws Exception { // full uritemplate assertEquals("http://example.com/events/simplequery{?q,offset}", affordance.getUriTemplateComponents().toString()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -243,7 +245,7 @@ public void testLinkToMethodInvocationNamedRequestParamWithValue() throws Except // full uritemplate assertEquals("http://example.com/events/simplequery?q=foo{&offset}", affordance.getUriTemplateComponents().toString()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -258,7 +260,7 @@ public void testLinkToMethodInvocationNamedRequestParamWithAllValues() throws Ex // full uritemplate with all values assertEquals("http://example.com/events/simplequery?q=foo&offset=2", affordance.getUriTemplateComponents().toString()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @@ -270,7 +272,7 @@ public void testLinkToMethodInvocationBeanInputWithExcludes() throws Exception { .rel("foo") .build(); assertEquals("http://example.com/events/queryexcludes{?description}", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -281,7 +283,7 @@ public void testLinkToMethodInvocationBeanInputWithIncludes() throws Exception { .rel("foo") .build(); assertEquals("http://example.com/events/queryincludes{?status}", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -292,7 +294,7 @@ public void testLinkToMethodInvocationMapInput() throws Exception { .rel("foo") .build(); assertEquals("http://example.com/events/querymap{?description,status,donttouch}", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test(expected = IllegalStateException.class) @@ -321,7 +323,7 @@ public void testLinkToControllerClassNoArgsBuild() throws Exception { .rel("foo") .build(); assertEquals("http://example.com/events", affordance.getHref()); - assertEquals("foo", affordance.getRel()); + assertEquals("foo", affordance.getRel().value()); } @Test @@ -333,6 +335,6 @@ public void testLinkToMethodInvocationReverseRel() throws Exception { .build(); assertEquals("http://example.com/events/{eventId}", affordance.getHref()); assertEquals("schema:parent", affordance.getRev()); - assertEquals("ex:children", affordance.getRel()); + assertEquals("ex:children", affordance.getRel().value()); } } \ No newline at end of file diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventController.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventController.java index ac8e8f12..46d22bee 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventController.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/DummyEventController.java @@ -14,8 +14,8 @@ package de.escalon.hypermedia.spring.sample.test; import de.escalon.hypermedia.affordance.Affordance; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -47,11 +47,11 @@ public ResponseEntity addEvent(@RequestBody Event event) { @RequestMapping(method = RequestMethod.GET) public @ResponseBody - Resources> getResourcesOfResourceOfEvent() { - List> eventResourcesList = new ArrayList>(); + CollectionModel> getResourcesOfResourceOfEvent() { + List> eventResourcesList = new ArrayList>(); // each resource has links for (Event event : getEvents()) { - Resource eventResource = new Resource(event); + EntityModel eventResource = new EntityModel(event); eventResource.add(linkTo(methodOn(this.getClass()) .getEvent(event.id)) .and(linkTo(methodOn(this.getClass()) @@ -75,7 +75,7 @@ Resources> getResourcesOfResourceOfEvent() { methodOn(this.getClass()).getEventWithRegexPathVariableMapping(null)).withRel("ex:regex"); final Affordance postEventAffordance = linkTo(methodOn(this.getClass()).addEvent(null)).withSelfRel(); - return new Resources>(eventResourcesList, + return new CollectionModel>(eventResourcesList, eventByNameAffordance, eventWithRegexAffordance, postEventAffordance); } @@ -83,10 +83,10 @@ Resources> getResourcesOfResourceOfEvent() { @RequestMapping("/list") public @ResponseBody - List> getListOfResourceOfEvent() { - List> eventResourcesList = new ArrayList>(); + List> getListOfResourceOfEvent() { + List> eventResourcesList = new ArrayList>(); for (Event event : getEvents()) { - Resource eventResource = new Resource(event); + EntityModel eventResource = new EntityModel(event); eventResource.add(linkTo(this.getClass()).slash(event.id) .withSelfRel()); eventResource.add(linkTo(methodOn(ReviewController.class) @@ -102,8 +102,8 @@ List> getListOfResourceOfEvent() { @RequestMapping(value = "/{eventId}", method = RequestMethod.GET) public @ResponseBody - Resource getEvent(@PathVariable Integer eventId) { - Resource resource = new Resource(getEvents().get(eventId)); + EntityModel getEvent(@PathVariable Integer eventId) { + EntityModel resource = new EntityModel(getEvents().get(eventId)); resource.add(linkTo(ReviewController.class).withRel("review")); return resource; } @@ -111,8 +111,8 @@ Resource getEvent(@PathVariable Integer eventId) { @RequestMapping(value = "/regex/{eventId:.+}", method = RequestMethod.GET) public @ResponseBody - Resource getEventWithRegexPathVariableMapping(@PathVariable Integer eventId) { - Resource resource = new Resource(getEvents().get(eventId)); + EntityModel getEventWithRegexPathVariableMapping(@PathVariable Integer eventId) { + EntityModel resource = new EntityModel(getEvents().get(eventId)); resource.add(linkTo(ReviewController.class).withRel("review")); return resource; } @@ -120,12 +120,12 @@ Resource getEventWithRegexPathVariableMapping(@PathVariable Integer event @RequestMapping(method = RequestMethod.GET, params = {"evtName"}) public @ResponseBody - Resource findEventByName(@RequestParam("evtName") String eventName) { - Resource ret = null; + EntityModel findEventByName(@RequestParam("evtName") String eventName) { + EntityModel ret = null; for (Event event : getEvents()) { if (event.getWorkPerformed() .getContent().name.startsWith(eventName)) { - Resource resource = new Resource(event); + EntityModel resource = new EntityModel(event); resource.add(linkTo(ReviewController.class).withRel("review")); ret = resource; break; diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/Event.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/Event.java index dab67db1..8ef2924f 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/Event.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/Event.java @@ -16,7 +16,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import de.escalon.hypermedia.action.Select; -import org.springframework.hateoas.Resource; +import org.springframework.hateoas.EntityModel; /** * Sample Event. Created by dschulten on 11.09.2014. @@ -28,13 +28,13 @@ public class Event { public final String location; private EventStatusType eventStatus; - private final Resource workPerformed; + private final EntityModel workPerformed; private String typicalAgeRange; public Event(int id, String performer, CreativeWork workPerformed, String location, EventStatusType eventStatus) { this.id = id; this.performer = performer; - this.workPerformed = new Resource(workPerformed); + this.workPerformed = new EntityModel(workPerformed); this.location = location; this.eventStatus = eventStatus; } @@ -48,7 +48,7 @@ public Event(@JsonProperty("performer") String performer, this.id = 0; this.performer = performer; this.location = location; - this.workPerformed = new Resource(workPerformed); + this.workPerformed = new EntityModel(workPerformed); this.eventStatus = eventStatus; this.typicalAgeRange = typicalAgeRange; } @@ -57,7 +57,7 @@ public void setEventStatus(EventStatusType eventStatus) { this.eventStatus = eventStatus; } - public Resource getWorkPerformed() { + public EntityModel getWorkPerformed() { return workPerformed; } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResource.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResource.java index e6a75812..b1ee3ef9 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResource.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/EventResource.java @@ -13,12 +13,12 @@ package de.escalon.hypermedia.spring.sample.test; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.RepresentationModel; /** - * Sample Event derived from ResourceSupport. Created by dschulten on 13.09.2014. + * Sample Event derived from RepresentationModel. Created by dschulten on 13.09.2014. */ -public class EventResource extends ResourceSupport { +public class EventResource extends RepresentationModel { public int id; public String performer; diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/ReviewController.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/ReviewController.java index 2dcb772f..0071a515 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/ReviewController.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/sample/test/ReviewController.java @@ -15,7 +15,7 @@ import de.escalon.hypermedia.action.Action; import de.escalon.hypermedia.spring.AffordanceBuilder; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -39,8 +39,8 @@ public class ReviewController { @RequestMapping(value = "/events/{eventId}", method = RequestMethod.GET) @ResponseBody - public Resources getReviews(@PathVariable int eventId, @RequestParam(required = false) String ratingValue) { - final Resources reviewResources = new Resources(reviews.get(eventId)); + public CollectionModel getReviews(@PathVariable int eventId, @RequestParam(required = false) String ratingValue) { + final CollectionModel reviewResources = new CollectionModel(reviews.get(eventId)); reviewResources.add(AffordanceBuilder.linkTo(AffordanceBuilder.methodOn(DummyEventController.class) .getEvent((Integer) null)) // pass null to create template .withRel("hydra:search")); diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenMessageConverterTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenMessageConverterTest.java index ddbae613..36fdabb5 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenMessageConverterTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenMessageConverterTest.java @@ -16,10 +16,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; -import org.springframework.hateoas.core.Relation; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.server.core.Relation; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.test.context.ContextConfiguration; @@ -77,7 +77,7 @@ public String getName() { static class DummyCustomersController { @RequestMapping("/{customerId}") - public ResponseEntity> getCustomer(@PathVariable String customerId) { + public ResponseEntity> getCustomer(@PathVariable String customerId) { return null; } } @@ -111,14 +111,14 @@ public Integer getQuantity() { } } - class Order extends ResourceSupport { + class Order extends RepresentationModel { private final int orderNumber = 42; private final int itemCount = 3; private final String status = "pending"; - private final Resource customer = - new Resource(new Customer()); + private final EntityModel customer = + new EntityModel(new Customer()); public Order() { customer.add(linkTo(methodOn(DummyCustomersController.class) @@ -139,7 +139,7 @@ public String getStatus() { return status; } - public Resource getCustomer() { + public EntityModel getCustomer() { return customer; } } @@ -149,12 +149,12 @@ public Resource getCustomer() { static class DummyOrderController { @RequestMapping("/{orderNumber}") - public ResponseEntity> getOrder(@PathVariable int orderNumber) { + public ResponseEntity> getOrder(@PathVariable int orderNumber) { return null; } @RequestMapping("/{orderNumber}/items") - public ResponseEntity> getOrderItems(@PathVariable int orderNumber) { + public ResponseEntity> getOrderItems(@PathVariable int orderNumber) { return null; } @@ -164,7 +164,7 @@ public ResponseEntity addOrderItems(@PathVariable int orderNumber, @Reques } @RequestMapping - public ResponseEntity> getOrders(@RequestParam("a") List attr) { + public ResponseEntity> getOrders(@RequestParam("a") List attr) { return null; } } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenUtilsTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenUtilsTest.java index c0222d1e..ee8b1830 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenUtilsTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/siren/SirenUtilsTest.java @@ -6,12 +6,12 @@ import org.junit.Before; import org.junit.Test; import org.springframework.hateoas.Link; -import org.springframework.hateoas.PagedResources; -import org.springframework.hateoas.PagedResources.PageMetadata; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.Resources; -import org.springframework.hateoas.core.EmbeddedWrapper; -import org.springframework.hateoas.core.Relation; +import org.springframework.hateoas.PagedModel; +import org.springframework.hateoas.PagedModel.PageMetadata; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.server.core.EmbeddedWrapper; +import org.springframework.hateoas.server.core.Relation; import java.util.*; @@ -119,9 +119,9 @@ public class ProfileResource { private final String firstName; private final String lastName; @JsonUnwrapped - private final Resources embeddeds; + private final CollectionModel embeddeds; - public ProfileResource(String firstName, String lastName, Resources embeddeds) { + public ProfileResource(String firstName, String lastName, CollectionModel embeddeds) { this.firstName = firstName; this.lastName = lastName; this.embeddeds = embeddeds; @@ -135,22 +135,22 @@ public String getLastName() { return lastName; } - public Resources getEmbeddeds() { + public CollectionModel getEmbeddeds() { return embeddeds; } } // @Test // public void testEmbeddedResource() { -// Resource primary = new Resource(new Email("neo@matrix.net", "primary")); -// Resource home = new Resource(new Email("t.anderson@matrix.net", "home")); +// EntityModel primary = new EntityModel(new Email("neo@matrix.net", "primary")); +// EntityModel home = new EntityModel(new Email("t.anderson@matrix.net", "home")); // // EmbeddedWrappers wrappers = new EmbeddedWrappers(true); // // List embeddeds = Arrays.asList(wrappers.wrap(primary), wrappers.wrap(home)); // -// Resources embeddedEmails = new Resources(embeddeds, new Link("self")); -// // return ResponseEntity.ok(new Resource(new ProfileResource("Thomas", "Anderson", embeddedEmails), linkTo +// CollectionModel embeddedEmails = new CollectionModel(embeddeds, new Link("self")); +// // return ResponseEntity.ok(new EntityModel(new ProfileResource("Thomas", "Anderson", embeddedEmails), linkTo // (ProfileController.class).withSelfRel())); // } @@ -159,13 +159,13 @@ public void testNestedResourceToEmbeddedRepresentation() throws Exception { class Customer { private final String name = "Peter Joseph"; - private final Resource
address = new Resource
(new Address()); + private final EntityModel
address = new EntityModel
(new Address()); public String getName() { return name; } - public Resource
getAddress() { + public EntityModel
getAddress() { address.add(new Link("http://example.com/customer/123/address/geolocation", "geolocation")); return address; } @@ -198,7 +198,7 @@ public String getName() { return name; } } - Resource customerResource = new Resource(new Customer()); + EntityModel customerResource = new EntityModel(new Customer()); customerResource.add(new Link("http://api.example.com/customers/123/address", "address")); SirenEntity entity = new SirenEntity(); @@ -214,9 +214,9 @@ public String getName() { @Test public void testListOfResource() { - List> addresses = new ArrayList>(); + List> addresses = new ArrayList>(); for (int i = 0; i < 4; i++) { - addresses.add(new Resource
(new Address())); + addresses.add(new EntityModel
(new Address())); } SirenEntity entity = new SirenEntity(); sirenUtils.toSirenEntity(entity, addresses); @@ -235,7 +235,7 @@ public void testResources() { addresses.add(new Address()); } - Resources
addressResources = new Resources
(addresses); + CollectionModel
addressResources = new CollectionModel
(addresses); addressResources.add(new Link("http://example.com/addresses", "self")); SirenEntity entity = new SirenEntity(); sirenUtils.toSirenEntity(entity, addressResources); @@ -256,7 +256,7 @@ public void testPagedResources() { } - PagedResources
addressResources = new PagedResources
(addresses, + PagedModel
addressResources = new PagedModel
(addresses, new PageMetadata(2, 0, addresses.size())); addressResources.add(new Link("http://example.com/addresses", "self")); SirenEntity entity = new SirenEntity(); @@ -422,7 +422,7 @@ public void testListOfBean() { public void testMapContainingResource() { Map map = new LinkedHashMap(); map.put("name", "Joe"); - Resource
addressResource = new Resource
(new Address()); + EntityModel
addressResource = new EntityModel
(new Address()); addressResource.add(new Link("http://example.com/addresses/1", "self")); map.put("address", addressResource); @@ -443,14 +443,14 @@ class Customer { private final String customerId = "pj123"; private final String name = "Peter Joseph"; - private Resources
addresses; + private CollectionModel
addresses; Customer() { List
content = new ArrayList
(); for (int i = 0; i < 4; i++) { content.add(new Address()); } - addresses = new Resources
(content); + addresses = new CollectionModel
(content); } public String getCustomerId() { @@ -461,7 +461,7 @@ public String getName() { return name; } - public Resources
getAddresses() { + public CollectionModel
getAddresses() { return addresses; } } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/AbstractUberNodeTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/AbstractUberNodeTest.java index a618f622..5c1292e6 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/AbstractUberNodeTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/AbstractUberNodeTest.java @@ -15,7 +15,9 @@ import org.junit.Before; import org.junit.Test; +import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkRelation; import java.util.Arrays; @@ -29,8 +31,8 @@ public class AbstractUberNodeTest { private UberNode foo = new UberNode(); private UberNode bar = new UberNode(); private UberNode baz = new UberNode(); - private Link linkPrevious = new Link(URL_PREVIOUS, Link.REL_PREVIOUS); - private Link linkNext = new Link(URL_NEXT, Link.REL_NEXT); + private Link linkPrevious = new Link(URL_PREVIOUS, IanaLinkRelations.PREVIOUS); + private Link linkNext = new Link(URL_NEXT, IanaLinkRelations.NEXT); class DummyUberNode extends AbstractUberNode { @@ -118,7 +120,7 @@ public void getsFirstNodeByRel() throws Exception { dummyUberNode.addData(bar); dummyUberNode.addLink(linkPrevious); - assertNotNull("rel previous not found", dummyUberNode.getFirstByRel(Link.REL_PREVIOUS)); + assertNotNull("rel previous not found", dummyUberNode.getFirstByRel(IanaLinkRelations.PREVIOUS.value())); } @Test @@ -135,10 +137,8 @@ public void getsFirstNodeByName() throws Exception { @Test public void findsAddedLinks() throws Exception { dummyUberNode.addLinks(Arrays.asList(linkNext, linkPrevious)); - assertEquals(URL_NEXT, dummyUberNode.getFirstByRel(Link.REL_NEXT) - .getUrl()); - assertEquals(URL_PREVIOUS, dummyUberNode.getFirstByRel(Link.REL_PREVIOUS) - .getUrl()); + assertEquals(URL_NEXT, dummyUberNode.getFirstByRel(IanaLinkRelations.NEXT.value()).getUrl()); + assertEquals(URL_PREVIOUS, dummyUberNode.getFirstByRel(IanaLinkRelations.PREVIOUS.value()).getUrl()); assertNull(dummyUberNode.getFirstByRel("noSuchRel")); } } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/UberUtilsTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/UberUtilsTest.java index 7fa4916d..7f467bb4 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/UberUtilsTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/uber/UberUtilsTest.java @@ -19,10 +19,11 @@ import org.hamcrest.Matchers; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.web.bind.annotation.RequestMethod; import java.util.*; @@ -42,8 +43,8 @@ public class UberUtilsTest { @Test public void linkGetToUberNode() throws Exception { UberNode linkNode = UberUtils.toUberLink("/foo", new SpringActionDescriptor("get", RequestMethod.GET.name()), - Link.REL_SELF); - assertEquals(Arrays.asList(Link.REL_SELF), linkNode.getRel()); + IanaLinkRelations.SELF.value()); + assertEquals(Arrays.asList(IanaLinkRelations.SELF.value()), linkNode.getRel()); assertEquals("/foo", linkNode.getUrl()); assertNull(linkNode.getModel()); assertNull(linkNode.getAction()); @@ -82,8 +83,8 @@ public void linkPostToUberNode() throws Exception { actionDescriptor.setRequestBody( new SpringActionInputParameter(new MethodParameter(this.getClass() .getMethod("requestBody", FooRequestBody.class), 0), null)); - UberNode linkNode = UberUtils.toUberLink("/foo", actionDescriptor, Link.REL_SELF); - assertEquals(Arrays.asList(Link.REL_SELF), linkNode.getRel()); + UberNode linkNode = UberUtils.toUberLink("/foo", actionDescriptor, IanaLinkRelations.SELF.value()); + assertEquals(Arrays.asList(IanaLinkRelations.SELF.value()), linkNode.getRel()); assertEquals("/foo", linkNode.getUrl()); assertThat(linkNode.getModel(), Matchers.containsString("foo={foo}")); @@ -140,7 +141,7 @@ public String getBar() { } - class BeanResource extends ResourceSupport { + class BeanResource extends RepresentationModel { public String getFoo() { @@ -154,7 +155,7 @@ public String getBar() { @Test public void resourceToUberNode() throws Exception { - Resource beanResource = new Resource(new Bean()); + EntityModel beanResource = new EntityModel(new Bean()); beanResource.add(LINK_HOME); UberNode node = new UberNode(); @@ -193,7 +194,7 @@ public void beansToUberNode() throws Exception { @Test public void resourcesToUberNode() throws Exception { List beans = Arrays.asList(new Bean(), new Bean("fooValue2", "barValue2")); - Resources beanResources = new Resources(beans); + CollectionModel beanResources = new CollectionModel(beans); beanResources.add(LINK_HOME); UberNode node = new UberNode(); @@ -222,11 +223,11 @@ public void resourcesToUberNode() throws Exception { public void identifiableToUberNode() throws Exception { BeanResource bean = new BeanResource(); String canonicalUrl = "http://www.example.com/bean/1"; - bean.add(new Link(canonicalUrl, Link.REL_SELF)); + bean.add(new Link(canonicalUrl, IanaLinkRelations.SELF.value())); UberNode node = new UberNode(); UberUtils.toUberData(node, bean); System.out.println(new ObjectMapper().writeValueAsString(node)); - UberNode selfRel = node.getFirstByRel(Link.REL_SELF); + UberNode selfRel = node.getFirstByRel(IanaLinkRelations.SELF.value()); assertEquals(canonicalUrl, selfRel.getUrl()); } diff --git a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriterTest.java b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriterTest.java index e48d8ae2..cf91c059 100644 --- a/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriterTest.java +++ b/spring-hateoas-ext/src/test/java/de/escalon/hypermedia/spring/xhtml/XhtmlWriterTest.java @@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.Link; +import org.springframework.hateoas.Links; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -75,7 +76,7 @@ public ResponseEntity putMultiplePossibleValues(@RequestBody Event event) .EVENT_SCHEDULED))) .withSelfRel(); - xhtml.writeLinks(Arrays.asList(affordance)); + xhtml.writeLinks(Links.of(affordance)); String xml = writer.toString(); System.out.println(xml); @@ -110,7 +111,7 @@ public ResponseEntity postMultiplePossibleValues(@RequestBody Event event) .EVENT_SCHEDULED))) .withSelfRel(); - xhtml.writeLinks(Arrays.asList(affordance)); + xhtml.writeLinks(Links.of(affordance)); String xml = writer.toString(); System.out.println(xml); @@ -147,7 +148,7 @@ public ResponseEntity postEventStatusOnly( .EVENT_SCHEDULED))) .withSelfRel(); - xhtml.writeLinks(Arrays.asList(affordance)); + xhtml.writeLinks(Links.of(affordance)); String xml = writer.toString(); System.out.println(xml); @@ -182,7 +183,7 @@ public ResponseEntity postEventStatusOnly( .EVENT_SCHEDULED))) .withSelfRel(); - xhtml.writeLinks(Arrays.asList(affordance)); + xhtml.writeLinks(Links.of(affordance)); String xml = writer.toString(); System.out.println(xml); @@ -213,7 +214,7 @@ public ResponseEntity postEventStatusOnly( .EVENT_SCHEDULED))) .withSelfRel(); - xhtml.writeLinks(Arrays.asList(affordance)); + xhtml.writeLinks(Links.of(affordance)); String xml = writer.toString(); System.out.println(xml); From e1a2515d510be42f75de652d08aa340918cf5c34 Mon Sep 17 00:00:00 2001 From: "hendra.saputra" Date: Wed, 28 Oct 2020 21:52:21 +0000 Subject: [PATCH 2/2] Update example Spring Web MVC project --- hydra-sample/service/pom.xml | 3 - .../de/escalon/hypermedia/sample/Config.java | 88 +++++++------- .../hypermedia/sample/beans/event/Event.java | 14 +-- .../hypermedia/sample/beans/store/Offer.java | 6 +- .../hypermedia/sample/beans/store/Order.java | 8 +- .../sample/beans/store/OrderedItem.java | 4 +- .../sample/beans/store/Product.java | 33 ++++-- .../hypermedia/sample/beans/store/Store.java | 4 +- .../sample/event/EventController.java | 20 ++-- .../sample/event/EventResourceAssembler.java | 6 +- .../sample/event/ReviewController.java | 12 +- .../sample/model/store/OrderStatus.java | 1 + .../sample/model/store/ProductModel.java | 4 + .../sample/store/OrderAssembler.java | 27 ++--- .../hypermedia/sample/store/OrderBackend.java | 18 ++- .../sample/store/OrderController.java | 112 +++++++++++------- .../sample/store/OrderedItemAssembler.java | 14 +-- .../sample/store/OrderedItemController.java | 2 +- .../sample/store/PaymentController.java | 18 ++- .../sample/store/ProductAssembler.java | 10 +- .../sample/store/ProductController.java | 10 +- .../sample/store/StoreController.java | 8 +- 22 files changed, 245 insertions(+), 177 deletions(-) diff --git a/hydra-sample/service/pom.xml b/hydra-sample/service/pom.xml index aea7980c..6da03981 100644 --- a/hydra-sample/service/pom.xml +++ b/hydra-sample/service/pom.xml @@ -25,18 +25,15 @@ junit junit - 4.12 test org.springframework spring-webmvc - org.springframework.plugin spring-plugin-core - javax.servlet diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/Config.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/Config.java index 19744a13..847c3c73 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/Config.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/Config.java @@ -1,27 +1,32 @@ package de.escalon.hypermedia.sample; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; import de.escalon.hypermedia.spring.HypermediaTypes; import de.escalon.hypermedia.spring.hydra.HydraMessageConverter; import de.escalon.hypermedia.spring.hydra.JsonLdDocumentationProvider; import de.escalon.hypermedia.spring.siren.SirenMessageConverter; import de.escalon.hypermedia.spring.uber.UberJackson2HttpMessageConverter; import de.escalon.hypermedia.spring.xhtml.XhtmlResourceMessageConverter; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSourceResolvable; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.RelProvider; import org.springframework.hateoas.UriTemplate; -import org.springframework.hateoas.core.AnnotationRelProvider; -import org.springframework.hateoas.core.DefaultRelProvider; -import org.springframework.hateoas.core.DelegatingRelProvider; -import org.springframework.hateoas.core.EvoInflectorRelProvider; -import org.springframework.hateoas.hal.CurieProvider; -import org.springframework.hateoas.hal.DefaultCurieProvider; -import org.springframework.hateoas.hal.Jackson2HalModule; +import org.springframework.hateoas.mediatype.MessageResolver; +import org.springframework.hateoas.mediatype.hal.CurieProvider; +import org.springframework.hateoas.mediatype.hal.DefaultCurieProvider; +import org.springframework.hateoas.mediatype.hal.Jackson2HalModule; +import org.springframework.hateoas.server.LinkRelationProvider; +import org.springframework.hateoas.server.core.AnnotationLinkRelationProvider; +import org.springframework.hateoas.server.core.DefaultLinkRelationProvider; +import org.springframework.hateoas.server.core.DelegatingLinkRelationProvider; +import org.springframework.hateoas.server.core.EvoInflectorLinkRelationProvider; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; @@ -30,33 +35,32 @@ import org.springframework.util.ClassUtils; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; /** * Sample configuration. Created by dschulten on 28.12.2014. */ @Configuration @EnableWebMvc -@EnablePluginRegistries(RelProvider.class) +@EnablePluginRegistries(LinkRelationProvider.class) @ComponentScan({"de.escalon.hypermedia.sample.event", "de.escalon.hypermedia.sample.store"}) -public class Config extends WebMvcConfigurerAdapter { +public class Config implements WebMvcConfigurer { private static final boolean EVO_PRESENT = ClassUtils.isPresent("org.atteo.evo.inflector.English", null); @Autowired - private PluginRegistry> relProviderRegistry; + private PluginRegistry relProviderRegistry; @Override public void configureMessageConverters(List> converters) { converters.add(hydraMessageConverter()); converters.add(sirenMessageConverter()); - converters.add(halConverter()); +// converters.add(halConverter()); converters.add(uberConverter()); converters.add(xhtmlMessageConverter()); converters.add(jsonConverter()); @@ -73,9 +77,9 @@ public HttpMessageConverter uberConverter() { private HttpMessageConverter xhtmlMessageConverter() { XhtmlResourceMessageConverter xhtmlResourceMessageConverter = new XhtmlResourceMessageConverter(); xhtmlResourceMessageConverter.setStylesheets( - Arrays.asList( - "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" - )); + Collections.singletonList( + "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" + )); xhtmlResourceMessageConverter.setDocumentationProvider(new JsonLdDocumentationProvider()); return xhtmlResourceMessageConverter; } @@ -96,7 +100,7 @@ public HydraMessageConverter hydraMessageConverter() { @Bean public SirenMessageConverter sirenMessageConverter() { SirenMessageConverter sirenMessageConverter = new SirenMessageConverter(); - sirenMessageConverter.setRelProvider(new DelegatingRelProvider(relProviderRegistry)); + sirenMessageConverter.setRelProvider(new DelegatingLinkRelationProvider(relProviderRegistry)); sirenMessageConverter.setDocumentationProvider(new JsonLdDocumentationProvider()); sirenMessageConverter.setSupportedMediaTypes(Collections.singletonList(HypermediaTypes.SIREN_JSON)); return sirenMessageConverter; @@ -114,43 +118,41 @@ public ObjectMapper jacksonObjectMapper() { public MappingJackson2HttpMessageConverter jsonConverter() { MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); - jacksonConverter.setSupportedMediaTypes(Arrays.asList(MediaType.valueOf("application/json"))); + jacksonConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("application/json"))); jacksonConverter.setObjectMapper(jacksonObjectMapper()); return jacksonConverter; } @Bean public CurieProvider curieProvider() { - return new DefaultCurieProvider("ex", new UriTemplate("http://localhost:8080/webapp/hypermedia-api/rels/{rels}")); + return new DefaultCurieProvider("ex", UriTemplate.of("http://localhost:8080/webapp/hypermedia-api/rels/{rels}")); } @Bean public MappingJackson2HttpMessageConverter halConverter() { - CurieProvider curieProvider = curieProvider(); - - RelProvider relProvider = new DelegatingRelProvider(relProviderRegistry); - ObjectMapper halObjectMapper = new ObjectMapper(); - - halObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); - - halObjectMapper.registerModule(new Jackson2HalModule()); - halObjectMapper.setHandlerInstantiator(new - Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider, null)); - - MappingJackson2HttpMessageConverter halConverter = new - MappingJackson2HttpMessageConverter(); - halConverter.setSupportedMediaTypes(Arrays.asList(MediaTypes.HAL_JSON)); - halConverter.setObjectMapper(halObjectMapper); +// CurieProvider curieProvider = curieProvider(); +// +// LinkRelationProvider relProvider = new DelegatingLinkRelationProvider(relProviderRegistry); +// ObjectMapper halObjectMapper = new ObjectMapper(); +// +// halObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); +// +// halObjectMapper.registerModule(new Jackson2HalModule()); +// halObjectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider, null)); + + MappingJackson2HttpMessageConverter halConverter = new MappingJackson2HttpMessageConverter(); + halConverter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON)); +// halConverter.setObjectMapper(halObjectMapper); return halConverter; } @Bean - RelProvider defaultRelProvider() { - return EVO_PRESENT ? new EvoInflectorRelProvider() : new DefaultRelProvider(); + LinkRelationProvider defaultRelProvider() { + return EVO_PRESENT ? new EvoInflectorLinkRelationProvider() : new DefaultLinkRelationProvider(); } @Bean - RelProvider annotationRelProvider() { - return new AnnotationRelProvider(); + LinkRelationProvider annotationRelProvider() { + return new AnnotationLinkRelationProvider(); } } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/event/Event.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/event/Event.java index ebac3fd3..7c55a93c 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/event/Event.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/event/Event.java @@ -5,18 +5,18 @@ import de.escalon.hypermedia.action.Select; import de.escalon.hypermedia.sample.model.event.CreativeWork; import de.escalon.hypermedia.sample.model.event.EventStatusType; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.RepresentationModel; /** - * Sample Event Resource, represents an Event with links. Created by dschulten on 11.09.2014. + * Sample Event EntityModel, represents an Event with links. Created by dschulten on 11.09.2014. */ -public class Event extends ResourceSupport { +public class Event extends RepresentationModel { public final int id; public final String performer; public final String location; private EventStatusType eventStatus; - public final Resource workPerformed; + public final EntityModel workPerformed; @JsonCreator public Event(@JsonProperty("performer") String performer, @@ -26,14 +26,14 @@ public Event(@JsonProperty("performer") String performer, this.id = 0; this.performer = performer; this.location = location; - this.workPerformed = new Resource(workPerformed); + this.workPerformed = new EntityModel(workPerformed); this.eventStatus = eventStatus; } public Event(int id, String performer, CreativeWork workPerformed, String location, EventStatusType eventStatus) { this.id = id; this.performer = performer; - this.workPerformed = new Resource(workPerformed); + this.workPerformed = new EntityModel(workPerformed); this.location = location; this.eventStatus = eventStatus; } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Offer.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Offer.java index 9b5b6a35..be8d9492 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Offer.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Offer.java @@ -2,8 +2,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.core.Relation; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.server.core.Relation; import java.math.BigDecimal; import java.util.ArrayList; @@ -15,7 +15,7 @@ */ @JsonPropertyOrder({"itemOffered", "price", "priceCurrency", "addOns"}) @Relation("offer") -public class Offer extends ResourceSupport { +public class Offer extends RepresentationModel { private Product itemOffered; private BigDecimal price; private List addOns = new ArrayList(); diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Order.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Order.java index 1b69a1a4..b92d3e66 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Order.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Order.java @@ -2,7 +2,7 @@ import de.escalon.hypermedia.hydra.mapping.Expose; import de.escalon.hypermedia.sample.model.store.OrderStatus; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.RepresentationModel; import java.util.ArrayList; import java.util.List; @@ -10,8 +10,8 @@ /** * Created by Dietrich on 17.02.2015. */ -public class Order extends ResourceSupport { - private List items = new ArrayList(); +public class Order extends RepresentationModel { + private List items = new ArrayList<>(); private Offer acceptedOffer; private Store seller; private OrderStatus orderStatus; @@ -24,7 +24,6 @@ public Store getSeller() { return seller; } - public void addItem(Product orderedItem) { this.items.add(orderedItem); } @@ -34,7 +33,6 @@ public List getItems() { return items; } - public void setOrderStatus(OrderStatus orderStatus) { this.orderStatus = orderStatus; } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/OrderedItem.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/OrderedItem.java index 4c4bf7ac..12f44a68 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/OrderedItem.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/OrderedItem.java @@ -1,11 +1,11 @@ package de.escalon.hypermedia.sample.beans.store; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.RepresentationModel; /** * Created by Dietrich on 02.11.2015. */ -public class OrderedItem extends ResourceSupport { +public class OrderedItem extends RepresentationModel { private String orderItemNumber; private Product orderedItem; diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Product.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Product.java index ec66abde..d1ee8e90 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Product.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Product.java @@ -3,8 +3,8 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import de.escalon.hypermedia.hydra.mapping.Term; -import org.springframework.hateoas.ResourceSupport; -import org.springframework.hateoas.core.Relation; +import org.springframework.hateoas.RepresentationModel; +import org.springframework.hateoas.server.core.Relation; import java.util.ArrayList; import java.util.List; @@ -14,11 +14,11 @@ */ @Term(define = "accessories", as = "isAccessoryOrSparePartFor", reverse = true) @Relation("product") -public class Product extends ResourceSupport { +public class Product extends RepresentationModel { public final String name; public final String productID; private Offer offer; - public List accessories = new ArrayList(); + public List accessories = new ArrayList<>(); public Offer getOffers() { return offer; @@ -35,14 +35,31 @@ public void addOffer(Offer offer) { } public boolean hasExtra(String accessoryId) { - boolean ret = false; for (Product accessory : accessories) { if (accessory.productID.equals(accessoryId)) { - ret = true; - break; + return true; } } - return ret; + return false; + } + + public Product getExtra(String accessoryId) { + for (Product accessory : accessories) { + if (accessory.productID.equals(accessoryId)) { + return accessory; + } + } + return null; + } + + public int getExtraId(String accessoryId) { + int index = 0; + for (Product accessory : accessories) { + if (accessory.productID.equals(accessoryId)) { + return index; + } + } + return -1; } public void addAccessory(Product product) { diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Store.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Store.java index c78654a1..154748a2 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Store.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/beans/store/Store.java @@ -1,7 +1,7 @@ package de.escalon.hypermedia.sample.beans.store; import de.escalon.hypermedia.hydra.mapping.Expose; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.RepresentationModel; import java.util.ArrayList; import java.util.List; @@ -10,7 +10,7 @@ * Created by Dietrich on 17.02.2015. */ @Expose("CafeOrCoffeeShop") -public class Store extends ResourceSupport { +public class Store extends RepresentationModel { public String name = "Kaffeehaus Hagen"; diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventController.java index f827c2fc..f30c0831 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventController.java @@ -8,7 +8,7 @@ import de.escalon.hypermedia.sample.model.event.EventStatusType; import de.escalon.hypermedia.spring.AffordanceBuilder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -33,31 +33,31 @@ public class EventController { // @RequestMapping(method = RequestMethod.GET) // @ResponseBody -// public ResponseEntity> getEvents() { +// public ResponseEntity> getEvents() { // List events = assembler.toResources(eventBackend.getEvents()); // for (Event event : events) { // addAffordances(event); // } -// Resources eventResources = new Resources(events); +// CollectionModel eventResources = new CollectionModel(events); // // eventResources.add(AffordanceBuilder.linkTo(AffordanceBuilder.methodOn(EventController.class).addEvent(null)) // .withSelfRel()); // -// return new ResponseEntity>(eventResources, HttpStatus.OK); +// return new ResponseEntity>(eventResources, HttpStatus.OK); // } @RequestMapping(method = RequestMethod.GET) @ResponseBody - public ResponseEntity> findEvents(@RequestParam(required = false) String name) { - List events = assembler.toResources(eventBackend.getEvents()); - List matches = new ArrayList(); + public ResponseEntity> findEvents(@RequestParam(required = false) String name) { + CollectionModel events = assembler.toCollectionModel(eventBackend.getEvents()); + List matches = new ArrayList<>(); for (Event event : events) { if (name == null || event.workPerformed.getContent().name.equals(name)) { addAffordances(event); matches.add(event); } } - Resources eventResources = new Resources(matches); + CollectionModel eventResources = CollectionModel.of(matches); eventResources.add(AffordanceBuilder.linkTo(AffordanceBuilder.methodOn(EventController.class) .addEvent(new Event(null, new CreativeWork(null), null, EventStatusType.EVENT_SCHEDULED))) @@ -67,13 +67,13 @@ public ResponseEntity> findEvents(@RequestParam(required = fals .findEvents(null)) .withRel("hydra:search")); - return new ResponseEntity>(eventResources, HttpStatus.OK); + return new ResponseEntity>(eventResources, HttpStatus.OK); } @RequestMapping(value = "/{eventId}", method = RequestMethod.GET) public ResponseEntity getEvent(@PathVariable Integer eventId) { - Event event = assembler.toResource(eventBackend.getEvent(eventId)); + Event event = assembler.toModel(eventBackend.getEvent(eventId)); addAffordances(event); diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventResourceAssembler.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventResourceAssembler.java index bf039cdd..ea9f41f9 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventResourceAssembler.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/EventResourceAssembler.java @@ -2,21 +2,21 @@ import de.escalon.hypermedia.sample.beans.event.Event; import de.escalon.hypermedia.sample.model.event.EventModel; -import org.springframework.hateoas.mvc.ResourceAssemblerSupport; +import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; import org.springframework.stereotype.Component; /** * Created by dschulten on 28.12.2014. */ @Component -public class EventResourceAssembler extends ResourceAssemblerSupport { +public class EventResourceAssembler extends RepresentationModelAssemblerSupport { public EventResourceAssembler() { super(EventController.class, Event.class); } @Override - public Event toResource(EventModel eventModel) { + public Event toModel(EventModel eventModel) { return new Event(eventModel.id, eventModel.performer, eventModel.workPerformed, eventModel.location, eventModel.eventStatus); } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/ReviewController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/ReviewController.java index d7fa4a11..ca52545b 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/ReviewController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/event/ReviewController.java @@ -17,7 +17,7 @@ import de.escalon.hypermedia.sample.beans.event.Review; import de.escalon.hypermedia.spring.AffordanceBuilder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -40,13 +40,13 @@ public class ReviewController { @RequestMapping(value = "/events/{eventId}", method = RequestMethod.GET) @ResponseBody - public ResponseEntity> getReviews(@PathVariable int eventId) { + public ResponseEntity> getReviews(@PathVariable int eventId) { List reviews = eventBackend.getReviews() .get(eventId); - ResponseEntity> ret; + ResponseEntity> ret; if (reviews != null) { - final Resources reviewResources = new Resources(reviews); + final CollectionModel reviewResources = new CollectionModel(reviews); reviewResources.add(AffordanceBuilder.linkTo(AffordanceBuilder.methodOn(EventController.class) .getEvent(eventId)) // passing null requires that method takes Integer, not int @@ -55,9 +55,9 @@ public ResponseEntity> getReviews(@PathVariable int eventId) { .addReview (eventId, null)) .withSelfRel()); - ret = new ResponseEntity>(reviewResources, HttpStatus.OK); + ret = new ResponseEntity>(reviewResources, HttpStatus.OK); } else { - ret = new ResponseEntity>(HttpStatus.NOT_FOUND); + ret = new ResponseEntity>(HttpStatus.NOT_FOUND); } return ret; } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/OrderStatus.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/OrderStatus.java index e7a086a9..2faa2c4f 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/OrderStatus.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/OrderStatus.java @@ -6,6 +6,7 @@ public enum OrderStatus { ORDER_CANCELLED, ORDER_PROCESSING, + ORDER_PAID, ORDER_DELIVERED, ORDER_PAYMENT_DUE, ORDER_PICKUP_AVAILABLE, diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/ProductModel.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/ProductModel.java index 215be7f6..ebbacbbd 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/ProductModel.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/model/store/ProductModel.java @@ -19,4 +19,8 @@ public ProductModel(String name, String productId) { public void addAccessory(ProductModel accessory) { accessories.add(accessory); } + + public void removeAccessory(final int accessoryId) { + accessories.remove(accessoryId); + } } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderAssembler.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderAssembler.java index d2896905..c2578790 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderAssembler.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderAssembler.java @@ -1,23 +1,23 @@ package de.escalon.hypermedia.sample.store; - import de.escalon.hypermedia.sample.beans.store.Order; import de.escalon.hypermedia.sample.beans.store.Product; import de.escalon.hypermedia.sample.model.store.OrderModel; import de.escalon.hypermedia.sample.model.store.OrderedItemModel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.mvc.ResourceAssemblerSupport; -import org.springframework.stereotype.Component; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import java.util.List; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; +import org.springframework.stereotype.Component; /** * Created by Dietrich on 17.02.2015. */ @Component -public class OrderAssembler extends ResourceAssemblerSupport { +public class OrderAssembler extends RepresentationModelAssemblerSupport { @Autowired private ProductAssembler itemAssembler; @@ -27,21 +27,20 @@ public OrderAssembler() { } @Override - public Order toResource(OrderModel entity) { - return createResourceWithId(entity.getId(), entity); + public Order toModel(OrderModel entity) { + return createModelWithId(entity.getId(), entity); } @Override - protected Order instantiateResource(OrderModel entity) { - Order order = super.instantiateResource(entity); + protected Order instantiateModel(OrderModel entity) { + Order order = super.instantiateModel(entity); order.setOrderStatus(entity.getOrderStatus()); List orderedItems = entity.getOrderedItems(); for (OrderedItemModel orderedItemModel : orderedItems) { - Product product = itemAssembler.instantiateResource(orderedItemModel.orderedItem); - Object parameters; + Product product = itemAssembler.instantiateModel(orderedItemModel.orderedItem); product.add(linkTo(OrderedItemController.class, entity.getId()) - .slash(orderedItemModel.orderedItemId) - .withSelfRel()); + .slash(orderedItemModel.orderedItemId) + .withSelfRel()); order.addItem(product); } return order; diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderBackend.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderBackend.java index 17276cbf..2038d820 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderBackend.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderBackend.java @@ -16,7 +16,7 @@ public class OrderBackend { public static int orderCounter; public static int orderedItemCounter; - public List orderModels = new ArrayList(); + public List orderModels = new ArrayList<>(); public OrderModel createOrder() { OrderModel orderModel = new OrderModel(); @@ -60,7 +60,19 @@ public List getOrdersByStatus(OrderStatus orderStatus) { public void deleteOrderedItem(int orderId, int orderedItemId) { OrderModel order = getOrder(orderId); - order.getOrderedItems() - .remove(orderedItemId); + order.getOrderedItems().remove(orderedItemId); + } + + public void payOrder(int orderId) { + OrderModel order = getOrder(orderId); + order.setOrderStatus(OrderStatus.ORDER_PAID); + } + + public OrderModel removeAccessoryForOrderedItem(final int orderId, final int orderedItemId, final int accessoryId) { + OrderModel orderModel = orderModels.get(orderId); + List products = orderModel.getOrderedItems(); + OrderedItemModel orderedItem = products.get(orderedItemId); + orderedItem.orderedItem.removeAccessory(accessoryId); + return orderModel; } } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderController.java index b32b6955..f2a5e428 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderController.java @@ -12,23 +12,28 @@ import de.escalon.hypermedia.sample.model.store.OrderStatus; import de.escalon.hypermedia.sample.model.store.ProductModel; import de.escalon.hypermedia.spring.AffordanceBuilder; +import sun.reflect.generics.reflectiveObjects.NotImplementedException; +import static de.escalon.hypermedia.spring.AffordanceBuilder.linkTo; +import static de.escalon.hypermedia.spring.AffordanceBuilder.methodOn; + +import java.math.BigDecimal; +import java.util.Currency; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.ExposesResourceFor; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.IanaLinkRelations; +import org.springframework.hateoas.server.ExposesResourceFor; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import java.math.BigDecimal; -import java.util.Currency; -import java.util.List; - -import static de.escalon.hypermedia.spring.AffordanceBuilder.linkTo; -import static de.escalon.hypermedia.spring.AffordanceBuilder.methodOn; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; /** * Created by Dietrich on 17.02.2015. @@ -54,37 +59,45 @@ public class OrderController { @ResourceHandler(Cardinality.COLLECTION) @RequestMapping(method = RequestMethod.POST) public ResponseEntity makeOrder(@Input(readOnly = {"productID"}) @RequestBody Product product) { - OrderModel orderModel = orderBackend.createOrder(); Product resolvedProduct = productController.getProduct(product.productID); orderModel = orderBackend.addOrderedItem(orderModel.getId(), new ProductModel(resolvedProduct.name, resolvedProduct.productID)); return redirectToUpdatedOrder(orderModel.getId()); - } @RequestMapping("/{orderId}") public ResponseEntity getOrder(@PathVariable int orderId) { OrderModel orderModel = orderBackend.getOrder(orderId); - Order order = orderAssembler.toResource(orderModel); + Order order = orderAssembler.toModel(orderModel); //TODO need to add additional action for delete to self rel // offer extras for each product List items = order.getItems(); - for (int i = 0; i < items.size(); i++) { - Product product = items.get(i); + for (int orderItemId = 0; orderItemId < items.size(); orderItemId++) { + Product product = items.get(orderItemId); Offer offer = new Offer(); - if (!product - .hasExtra("9052006")) { - Offer shot = createAddOnOffer(product, "9052006", 0.2, orderId, i); + + if (!product.hasExtra("9052006")) { + Offer shot = createAddOnOffer(product, "9052006", 0.2, orderId, orderItemId); offer.addOn(shot); } + else { + final String productId = "9052006"; + deleteOrderAccessory(orderId, orderItemId, product, productId); + } + if (!product.hasExtra("9052007")) { - Offer briocheCrema = createAddOnOffer(product, "9052007", 0.8, orderId, i); + Offer briocheCrema = createAddOnOffer(product, "9052007", 0.8, orderId, orderItemId); offer.addOn(briocheCrema); } - if (!offer.getAddOns() - .isEmpty()) { + else { + final String productId = "9052007"; + deleteOrderAccessory(orderId, orderItemId, product, productId); + } + + if (!offer.getAddOns().isEmpty()) { + offer.add(linkTo(methodOn(this.getClass()).deleteOrderedItem(orderId, orderItemId)).withRel("removeOffer")); product.addOffer(offer); } } @@ -94,7 +107,17 @@ public ResponseEntity getOrder(@PathVariable int orderId) { order.setSeller(store); order.add(linkTo(methodOn(PaymentController.class).makePayment(orderId)).withRel("paymentUrl")); - return new ResponseEntity(order, HttpStatus.OK); + return new ResponseEntity<>(order, HttpStatus.OK); + } + + private void deleteOrderAccessory(final int orderId, final int orderItemId, final Product product, final String productId) { + Product accessory = productController.getProduct(productId); + String accessorySelfRel = accessory.getLink(IanaLinkRelations.SELF).get().getHref(); + final int extraId = product.getExtraId(productId); + product.getExtra(productId).add(linkTo(methodOn(OrderController.class).removeAccessory(orderId, orderItemId, + extraId)) + .reverseRel("isAccessoryOrSparePartFor", "extras", new TypedResource("Product", accessorySelfRel)) + .build()); } @RequestMapping(value = "/{orderId}/items/{orderedItemId}/accessories", method = RequestMethod.POST) @@ -102,8 +125,14 @@ public ResponseEntity orderAccessory(@PathVariable int orderId, @PathVaria @RequestBody @Input(readOnly = "productID") Product product) { // TODO should write a productBackend to avoid this resolution nonsense: Product resolvedProduct = productController.getProduct(product.productID); - orderBackend.orderAccessoryForOrderedItem(orderId, orderedItemId, new ProductModel(resolvedProduct.name, - resolvedProduct.productID)); + orderBackend.orderAccessoryForOrderedItem(orderId, orderedItemId, + new ProductModel(resolvedProduct.name, resolvedProduct.productID)); + return redirectToUpdatedOrder(orderId); + } + + @RequestMapping(value = "/{orderId}/items/{orderedItemId}/accessories/{accessoryId}", method = RequestMethod.DELETE) + public ResponseEntity removeAccessory(@PathVariable int orderId, @PathVariable int orderedItemId, @PathVariable int accessoryId) { + orderBackend.removeAccessoryForOrderedItem(orderId, orderedItemId, accessoryId); return redirectToUpdatedOrder(orderId); } @@ -111,15 +140,14 @@ private ResponseEntity redirectToUpdatedOrder(int orderId) { AffordanceBuilder location = linkTo(methodOn(this.getClass()).getOrder(orderId)); HttpHeaders headers = new HttpHeaders(); headers.setLocation(location.toUri()); - return new ResponseEntity(headers, HttpStatus.SEE_OTHER); + return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER); } @RequestMapping(value = "/{orderId}/items", method = RequestMethod.POST) public ResponseEntity orderAdditionalItem( @PathVariable int orderId, @RequestBody @Input(readOnly = "productID") Product product) { - Product resolvedProduct = productController.getProduct(product.productID); - OrderModel orderModel = orderBackend.addOrderedItem(orderId, + orderBackend.addOrderedItem(orderId, new ProductModel(resolvedProduct.name, resolvedProduct.productID)); return redirectToUpdatedOrder(orderId); } @@ -130,17 +158,20 @@ public ResponseEntity deleteOrderedItem(@PathVariable int orderId, @PathVa return redirectToUpdatedOrder(orderId); } - private Offer createAddOnOffer(Product product, String addOnProductID, double price, int orderId, int - orderedItemId) { + private Offer createOffer(final double price) { Offer addOnOffer = new Offer(); addOnOffer.setPriceCurrency(Currency.getInstance("EUR")); addOnOffer.setPrice(BigDecimal.valueOf(price)); + return addOnOffer; + } + + private Offer createAddOnOffer(Product product, String addOnProductID, double price, int orderId, int orderedItemId) { + Offer addOnOffer = createOffer(price); Product addOnProduct = productController.getProduct(addOnProductID); addOnOffer.setItemOffered(addOnProduct); - String productSelfRel = product.getLink(Link.REL_SELF) - .getHref(); + String productSelfRel = product.getLink(IanaLinkRelations.SELF).get().getHref(); addOnProduct.add(linkTo(methodOn(OrderController.class).orderAccessory(orderId, orderedItemId, addOnProduct)) .reverseRel("isAccessoryOrSparePartFor", "extras", new TypedResource("Product", productSelfRel)) .build()); @@ -149,25 +180,22 @@ private Offer createAddOnOffer(Product product, String addOnProductID, double pr } @RequestMapping(method = RequestMethod.GET) - public ResponseEntity> getOrders(@RequestParam(required = false) OrderStatus orderStatus) { + public ResponseEntity> getOrders(@RequestParam(required = false) OrderStatus orderStatus) { List orders; if (orderStatus == null) { orders = orderBackend.getOrders(); } else { - orders = orderBackend - .getOrdersByStatus(orderStatus); + orders = orderBackend.getOrdersByStatus(orderStatus); } - Resources orderResources = new Resources( - orderAssembler.toResources(orders)); - return new ResponseEntity>(orderResources, HttpStatus.OK); + CollectionModel orderResources = orderAssembler.toCollectionModel(orders); + return new ResponseEntity<>(orderResources, HttpStatus.OK); } @RequestMapping("/{orderId}/offers") - public HttpEntity> getOffersForOrder(@PathVariable int orderId) { - HttpEntity> offers = storeController.getOffers(); - for (Offer offer : offers.getBody() - .getContent()) { + public HttpEntity> getOffersForOrder(@PathVariable int orderId) { + HttpEntity> offers = storeController.getOffers(); + for (Offer offer : offers.getBody().getContent()) { Product itemOffered = offer.getItemOffered(); // we can determine the subject URI of the order diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemAssembler.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemAssembler.java index e54b1c30..39b7cda5 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemAssembler.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemAssembler.java @@ -3,7 +3,7 @@ import de.escalon.hypermedia.sample.beans.store.OrderedItem; import de.escalon.hypermedia.sample.model.store.OrderedItemModel; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.mvc.ResourceAssemblerSupport; +import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; import org.springframework.stereotype.Component; /** @@ -12,7 +12,7 @@ * Created by Dietrich on 02.11.2015. */ @Component -public class OrderedItemAssembler extends ResourceAssemblerSupport { +public class OrderedItemAssembler extends RepresentationModelAssemblerSupport { @Autowired @@ -23,14 +23,14 @@ public OrderedItemAssembler() { } @Override - public OrderedItem toResource(OrderedItemModel entity) { - return createResourceWithId(entity.orderedItemId, entity); + public OrderedItem toModel(OrderedItemModel entity) { + return createModelWithId(entity.orderedItemId, entity); } @Override - protected OrderedItem instantiateResource(OrderedItemModel entity) { - OrderedItem orderedItem = super.instantiateResource(entity); - orderedItem.setOrderedItem(productAssembler.toResource(entity.orderedItem)); + protected OrderedItem instantiateModel(OrderedItemModel entity) { + OrderedItem orderedItem = super.instantiateModel(entity); + orderedItem.setOrderedItem(productAssembler.toModel(entity.orderedItem)); orderedItem.setOrderItemNumber(Integer.toString(entity.orderedItemId)); return orderedItem; } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemController.java index 519f18c6..04b0fc53 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/OrderedItemController.java @@ -41,7 +41,7 @@ public ResponseEntity getOrderedItem(@PathVariable int orderId, @PathVa } Product product = null; if (found != null) { - product = productAssembler.instantiateResource(found.orderedItem); + product = productAssembler.instantiateModel(found.orderedItem); product.add(linkTo(methodOn(this.getClass()) .getOrderedItem(orderId, orderedItemId)) .withSelfRel()); diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/PaymentController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/PaymentController.java index 577e6426..cb48cfee 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/PaymentController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/PaymentController.java @@ -1,7 +1,12 @@ package de.escalon.hypermedia.sample.store; +import de.escalon.hypermedia.sample.beans.store.Order; import de.escalon.hypermedia.sample.beans.store.Payment; +import de.escalon.hypermedia.sample.model.store.OrderModel; +import de.escalon.hypermedia.sample.model.store.OrderStatus; import de.escalon.hypermedia.spring.AffordanceBuilder; + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -17,11 +22,17 @@ @Controller public class PaymentController { + @Autowired + private OrderBackend orderBackend; + + @Autowired + private OrderAssembler orderAssembler; + @RequestMapping("/{id}/payment") - public ResponseEntity makePayment(@PathVariable int id) { + public ResponseEntity makePayment(@PathVariable int orderId) { + orderBackend.payOrder(orderId); HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setLocation(linkTo(AffordanceBuilder.methodOn(this.getClass()) - .getPayment()).toUri()); + httpHeaders.setLocation(linkTo(AffordanceBuilder.methodOn(this.getClass()).getPayment()).toUri()); return new ResponseEntity(httpHeaders, HttpStatus.CREATED); } @@ -29,5 +40,4 @@ public Payment getPayment() { return null; } - } diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductAssembler.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductAssembler.java index 97d83eaa..94a1a53d 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductAssembler.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductAssembler.java @@ -2,26 +2,26 @@ import de.escalon.hypermedia.sample.beans.store.Product; import de.escalon.hypermedia.sample.model.store.ProductModel; -import org.springframework.hateoas.mvc.ResourceAssemblerSupport; +import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; import org.springframework.stereotype.Component; /** * Created by Dietrich on 17.02.2015. */ @Component -public class ProductAssembler extends ResourceAssemblerSupport { +public class ProductAssembler extends RepresentationModelAssemblerSupport { public ProductAssembler() { super(ProductController.class, Product.class); } @Override - public Product toResource(ProductModel entity) { - return createResourceWithId(entity.productId, entity); + public Product toModel(ProductModel entity) { + return createModelWithId(entity.productId, entity); } @Override - protected Product instantiateResource(ProductModel entity) { + protected Product instantiateModel(ProductModel entity) { Product product = new Product(entity.name, entity.productId); for (ProductModel accessory : entity.accessories) { product.addAccessory(new Product(accessory.name, accessory.productId)); diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductController.java index 3672b686..71eb5a81 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/ProductController.java @@ -2,7 +2,7 @@ import de.escalon.hypermedia.sample.beans.store.Product; import de.escalon.hypermedia.sample.model.store.ProductModel; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -35,13 +35,13 @@ public class ProductController { @RequestMapping public @ResponseBody - Resources getProducts() { + CollectionModel getProducts() { List resources = new ArrayList(); for (ProductModel productModel : productModels) { - Product product = assembler.toResource(productModel); + Product product = assembler.toModel(productModel); resources.add(product); } - return new Resources(resources); + return new CollectionModel(resources); } @@ -51,7 +51,7 @@ Resources getProducts() { Product getProduct(@PathVariable String productID) { for (ProductModel productModel : productModels) { if (productID.equals(productModel.productId)) { - return assembler.toResource(productModel); + return assembler.toModel(productModel); } } return null; diff --git a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/StoreController.java b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/StoreController.java index b2d27b08..01fe60a2 100644 --- a/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/StoreController.java +++ b/hydra-sample/service/src/main/java/de/escalon/hypermedia/sample/store/StoreController.java @@ -6,7 +6,7 @@ import de.escalon.hypermedia.sample.beans.store.Store; import de.escalon.hypermedia.spring.AffordanceBuilder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.Resources; +import org.springframework.hateoas.CollectionModel; import org.springframework.http.HttpEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -49,10 +49,10 @@ Store getStoreWithOffers() { return store; } - public HttpEntity> getOffers() { - Resources offers = new Resources( + public HttpEntity> getOffers() { + CollectionModel offers = new CollectionModel( mockOffers()); - return new HttpEntity>(offers); + return new HttpEntity>(offers); } private List mockOffers() {