diff --git a/src/main/java/org/springframework/hateoas/Link.java b/src/main/java/org/springframework/hateoas/Link.java index 4a3273c1..7435dedf 100755 --- a/src/main/java/org/springframework/hateoas/Link.java +++ b/src/main/java/org/springframework/hateoas/Link.java @@ -26,6 +26,7 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -88,7 +89,7 @@ public class Link implements Serializable { private String deprecation; private String profile; private String name; - private @JsonIgnore UriTemplate template; + private @JsonIgnore @Nullable UriTemplate template; private @JsonIgnore List affordances; /** @@ -112,7 +113,7 @@ public class Link implements Serializable { */ @Deprecated public Link(String href, String rel) { - this(UriTemplate.of(href), LinkRelation.of(rel)); + this(href, LinkRelation.of(rel)); } /** @@ -124,7 +125,7 @@ public class Link implements Serializable { */ @Deprecated public Link(String href, LinkRelation rel) { - this(UriTemplate.of(href), rel); + this(href, templateOrNull(href), rel, Collections.emptyList()); } /** @@ -169,8 +170,20 @@ public class Link implements Serializable { this.affordances = affordances; } + private Link(String href, @Nullable UriTemplate template, LinkRelation rel, List affordances) { + + Assert.hasText(href, "Href must not be null or empty!"); + Assert.notNull(rel, "LinkRelation must not be null!"); + Assert.notNull(affordances, "Affordances must not be null!"); + + this.href = href; + this.template = template; + this.rel = rel; + this.affordances = affordances; + } + private Link(LinkRelation rel, String href, String hreflang, String media, String title, String type, - String deprecation, String profile, String name, UriTemplate template, List affordances) { + String deprecation, String profile, String name, @Nullable UriTemplate template, List affordances) { this.rel = rel; this.href = href; @@ -320,7 +333,7 @@ public class Link implements Serializable { */ @JsonIgnore public List getVariableNames() { - return template.getVariableNames(); + return template == null ? Collections.emptyList() : template.getVariableNames(); } /** @@ -330,7 +343,7 @@ public class Link implements Serializable { */ @JsonIgnore public List getVariables() { - return template.getVariables(); + return template == null ? Collections.emptyList() : template.getVariables(); } /** @@ -339,7 +352,7 @@ public class Link implements Serializable { * @return */ public boolean isTemplated() { - return !template.getVariables().isEmpty(); + return template == null ? false : !template.getVariables().isEmpty(); } /** @@ -349,7 +362,7 @@ public class Link implements Serializable { * @return */ public Link expand(Object... arguments) { - return of(template.expand(arguments).toString(), getRel()); + return template == null ? this : of(template.expand(arguments).toString(), getRel()); } /** @@ -359,7 +372,7 @@ public class Link implements Serializable { * @return */ public Link expand(Map arguments) { - return of(template.expand(arguments).toString(), getRel()); + return template == null ? this : of(template.expand(arguments).toString(), getRel()); } /** @@ -663,16 +676,22 @@ public class Link implements Serializable { @JsonProperty public UriTemplate getTemplate() { - return this.template; + return template == null ? UriTemplate.of(href) : this.template; } + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } Link link = (Link) o; return Objects.equals(this.rel, link.rel) && Objects.equals(this.href, link.href) && Objects.equals(this.hreflang, link.hreflang) && Objects.equals(this.media, link.media) @@ -681,6 +700,10 @@ public class Link implements Serializable { && Objects.equals(this.name, link.name) && Objects.equals(this.affordances, link.affordances); } + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { @@ -727,4 +750,12 @@ public class Link implements Serializable { return linkString; } + + @Nullable + private static UriTemplate templateOrNull(String href) { + + Assert.notNull(href, "Href must not be null!"); + + return href.contains("{") ? UriTemplate.of(href) : null; + } } diff --git a/src/main/java/org/springframework/hateoas/UriTemplate.java b/src/main/java/org/springframework/hateoas/UriTemplate.java index 71a485e9..f9daae6d 100644 --- a/src/main/java/org/springframework/hateoas/UriTemplate.java +++ b/src/main/java/org/springframework/hateoas/UriTemplate.java @@ -32,7 +32,6 @@ import java.util.stream.Collectors; import org.springframework.hateoas.TemplateVariable.VariableType; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.StringUtils; import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode; @@ -55,8 +54,6 @@ public class UriTemplate implements Iterable, Serializable { private static final Pattern VARIABLE_REGEX = Pattern.compile("\\{([\\?\\&#/]?)([\\w\\,*]+)\\}"); private static final long serialVersionUID = -1007874653930162262L; - private static final Map CACHE = new ConcurrentReferenceHashMap<>(); - private final TemplateVariables variables; private String baseUri; private transient UriBuilderFactory factory; @@ -134,7 +131,7 @@ public class UriTemplate implements Iterable, Serializable { Assert.hasText(template, "Template must not be null or empty!"); - return CACHE.computeIfAbsent(template, UriTemplate::new); + return new UriTemplate(template); } /** @@ -147,7 +144,7 @@ public class UriTemplate implements Iterable, Serializable { Assert.hasText(template, "Template must not be null or empty!"); - return CACHE.computeIfAbsent(template, UriTemplate::new).with(variables); + return new UriTemplate(template).with(variables); } /**