diff --git a/src/main/java/org/springframework/hateoas/hal/DefaultCurieProvider.java b/src/main/java/org/springframework/hateoas/hal/DefaultCurieProvider.java index ee6be505..63ee94dc 100644 --- a/src/main/java/org/springframework/hateoas/hal/DefaultCurieProvider.java +++ b/src/main/java/org/springframework/hateoas/hal/DefaultCurieProvider.java @@ -17,12 +17,16 @@ package org.springframework.hateoas.hal; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; import org.springframework.hateoas.IanaRels; import org.springframework.hateoas.Link; import org.springframework.hateoas.Links; import org.springframework.hateoas.UriTemplate; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Default implementation of {@link CurieProvider} rendering a single configurable {@link UriTemplate} based curie. @@ -33,22 +37,63 @@ import org.springframework.util.Assert; */ public class DefaultCurieProvider implements CurieProvider { - private final Curie curie; + private final Map curies; + private final Curie defaultCurie; /** - * Creates a new {@link DefaultCurieProvider} for the given name and {@link UriTemplate}. + * Creates a new {@link DefaultCurieProvider} for the given name and {@link UriTemplate}. The curie will be used to + * expand previously unprefixed, non-IANA link relations. * * @param name must not be {@literal null} or empty. * @param uriTemplate must not be {@literal null} and contain exactly one template variable. */ public DefaultCurieProvider(String name, UriTemplate uriTemplate) { + this(Collections.singletonMap(name, uriTemplate)); + } - Assert.hasText(name, "Name must not be null or empty!"); - Assert.notNull(uriTemplate, "UriTemplate must not be null!"); - Assert.isTrue(uriTemplate.getVariableNames().size() == 1, - String.format("Expected a single template variable in the UriTemplate %s!", uriTemplate.toString())); + /** + * Creates a new {@link DefaultCurieProvider} for the given curies. If more than one curie is given, no default curie + * will be registered. Use {@link #DefaultCurieProvider(Map, String)} to define which of the provided curies shall be + * used as the default one. + * + * @param curies must not be {@literal null}. + * @see #DefaultCurieProvider(String, UriTemplate) + * @since 0.19 + */ + public DefaultCurieProvider(Map curies) { + this(curies, null); + } - this.curie = new Curie(name, uriTemplate.toString()); + /** + * Creates a new {@link DefaultCurieProvider} for the given curies using the one with the given name as default, which + * means to expand unprefixed, non-IANA link relations. + * + * @param curies must not be {@literal null}. + * @param defaultCurieName can be {@literal null}. + * @since 0.19 + */ + public DefaultCurieProvider(Map curies, String defaultCurieName) { + + Assert.notNull(curies, "Curies must not be null!"); + + Map map = new HashMap(curies.size()); + + for (Entry entry : curies.entrySet()) { + + String name = entry.getKey(); + UriTemplate template = entry.getValue(); + + Assert.hasText(name, "Curie name must not be null or empty!"); + Assert.notNull(template, "UriTemplate must not be null!"); + Assert.isTrue(template.getVariableNames().size() == 1, + String.format("Expected a single template variable in the UriTemplate %s!", template.toString())); + + map.put(name, new Curie(name, template.toString())); + } + + this.defaultCurie = StringUtils.hasText(defaultCurieName) ? map.get(defaultCurieName) + : map.size() == 1 ? map.values().iterator().next() : null; + this.curies = Collections.unmodifiableMap(map); } /* @@ -57,7 +102,7 @@ public class DefaultCurieProvider implements CurieProvider { */ @Override public Collection getCurieInformation(Links links) { - return Collections.singleton(curie); + return Collections.unmodifiableCollection(curies.values()); } /* @@ -76,8 +121,8 @@ public class DefaultCurieProvider implements CurieProvider { @Override public String getNamespacedRelFor(String rel) { - boolean prefixingNeeded = !IanaRels.isIanaRel(rel) && !rel.contains(":"); - return prefixingNeeded ? String.format("%s:%s", curie.name, rel) : rel; + boolean prefixingNeeded = defaultCurie != null && !IanaRels.isIanaRel(rel) && !rel.contains(":"); + return prefixingNeeded ? String.format("%s:%s", defaultCurie.name, rel) : rel; } /** diff --git a/src/test/java/org/springframework/hateoas/hal/DefaultCurieProviderUnitTest.java b/src/test/java/org/springframework/hateoas/hal/DefaultCurieProviderUnitTest.java index d22ec15e..2c880beb 100644 --- a/src/test/java/org/springframework/hateoas/hal/DefaultCurieProviderUnitTest.java +++ b/src/test/java/org/springframework/hateoas/hal/DefaultCurieProviderUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,15 @@ */ package org.springframework.hateoas.hal; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; + import org.junit.Test; import org.springframework.hateoas.Link; +import org.springframework.hateoas.Links; import org.springframework.hateoas.UriTemplate; /** @@ -96,4 +100,37 @@ public class DefaultCurieProviderUnitTest { public void doesNotPrefixQualifiedRelsForRelAsString() { assertThat(provider.getNamespacedRelFor("custom:rel"), is("custom:rel")); } + + /** + * @see #363 + */ + @Test + public void configuresMultipleCuriesWithoutDefaultCorrectly() { + + DefaultCurieProvider provider = new DefaultCurieProvider(getCuries()); + + assertThat(provider.getCurieInformation(new Links()), hasSize(2)); + assertThat(provider.getNamespacedRelFor("some"), is("some")); + } + + /** + * @see #363 + */ + @Test + public void configuresMultipleCuriesWithDefaultCorrectly() { + + DefaultCurieProvider provider = new DefaultCurieProvider(getCuries(), "foo"); + + assertThat(provider.getCurieInformation(new Links()), hasSize(2)); + assertThat(provider.getNamespacedRelFor("some"), is("foo:some")); + } + + private static Map getCuries() { + + Map curies = new HashMap(2); + curies.put("foo", new UriTemplate("/foo/{rel}")); + curies.put("bar", new UriTemplate("/bar/{rel}")); + + return curies; + } }