/** * Returns whether the given relation type is defined by the IANA. * * @param rel the relation type to check * @return * @deprecated Migrate to {@link IanaLinkRelation#isIanaRel(String)}. */ @Deprecated public static boolean isIanaRel(String rel) { return IanaLinkRelation.isIanaRel(rel); } }
/** * Creates a new link to the given URI with the self rel. * * @see IanaLinkRelation#SELF * @param href must not be {@literal null} or empty. */ public Link(String href) { this(href, IanaLinkRelation.SELF.value()); }
/** * Is this relation an IANA standard? * * Per RFC8288, parsing of link relations is case insensitive. * * @param rel * @return boolean */ public static boolean isIanaRel(String rel) { return rel != null && LINK_RELATIONS.stream().anyMatch(linkRelation -> linkRelation.value().equalsIgnoreCase(rel)); }
@Override public String getNamespacedRelFor(String rel) { boolean prefixingNeeded = defaultCurie != null && !IanaLinkRelation.isIanaRel(rel) && !rel.contains(":"); return prefixingNeeded ? String.format("%s:%s", defaultCurie, rel) : rel; }
/** * Convert a string-based link relation to a {@link IanaLinkRelation}. * * Per RFC8288, parsing of link relations is case insensitive. * * @param rel as a string * @return rel as a {@link IanaLinkRelation} */ public static IanaLinkRelation parse(String rel) { return LINK_RELATIONS.stream() .filter(linkRelation -> linkRelation.value().equalsIgnoreCase(rel)) .findFirst() .orElseThrow(() -> new IllegalArgumentException(rel + " is not a valid IANA link relation!")); } }
/** * Returns the {@link Link} with a rel of {@link IanaLinkRelation#SELF}. */ @JsonIgnore public Optional<Link> getId() { return getLink(IanaLinkRelation.SELF.value()); }
private static List<Link> withoutSelfLink(List<Link> links) { return links.stream() .filter(link -> !link.getRel().equals(IanaLinkRelation.SELF.value())) .collect(Collectors.toList()); }
/** * Returns a {@link Link} pointing to the same URI but with the {@code self} relation. * * @return */ public Link withSelfRel() { return withRel(IanaLinkRelation.SELF.value()); }
/** * Returns the Link pointing to the next page (if set). * * @return */ @JsonIgnore public Optional<Link> getNextLink() { return getLink(IanaLinkRelation.NEXT.value()); }
/** * Returns the Link pointing to the previous page (if set). * * @return */ @JsonIgnore public Optional<Link> getPreviousLink() { return getLink(IanaLinkRelation.PREV.value()); }
public Link withSelfRel() { return withRel(IanaLinkRelation.SELF.value()); }
private Link findSelfLink(String representation) { return this.selfLinkDiscoverer.findLinkWithRel(IanaLinkRelation.SELF.value(), representation); }
private Link findSelfLink(InputStream representation) { return this.selfLinkDiscoverer.findLinkWithRel(IanaLinkRelation.SELF.value(), representation); }
@Override public Link findLinkWithRel(String rel, String representation) { if (rel.equals(IanaLinkRelation.SELF.value())) { return findSelfLink(representation); } else { return super.findLinkWithRel(rel, representation); } }
@Override public Link findLinkWithRel(String rel, InputStream representation) { if (rel.equals(IanaLinkRelation.SELF.value())) { return findSelfLink(representation); } else { return super.findLinkWithRel(rel, representation); } }
/** * Return a list of {@link Link}s that includes a "self" link. * * @param links - base set of {@link Link}s. * @param href - the URI of the "self" link * @return */ private static List<Link> potentiallyAddSelfLink(List<Link> links, String href) { if (links == null) { if (href == null) { return Collections.emptyList(); } return Collections.singletonList(new Link(href)); } if (href == null || links.stream().map(Link::getRel).anyMatch(s -> s.equals(IanaLinkRelation.SELF.value()))) { return links; } // Clone and add the self link List<Link> newLinks = new ArrayList<>(); newLinks.add(new Link(href)); newLinks.addAll(links); return newLinks; }
@Override public List<Link> findLinksWithRel(String rel, String representation) { if (rel.equals(IanaLinkRelation.SELF.value())) { return addSelfLink(super.findLinksWithRel(rel, representation), representation); } else { return super.findLinksWithRel(rel, representation); } }
@Override public List<Link> findLinksWithRel(String rel, InputStream representation) { if (rel.equals(IanaLinkRelation.SELF.value())) { return addSelfLink(super.findLinksWithRel(rel, representation), representation); } else { return super.findLinksWithRel(rel, representation); } }
/** * Verify that the resource's self link and the affordance's URI have the same relative path. * * @param resource * @param model */ private static void validate(ResourceSupport resource, HalFormsAffordanceModel model) { String affordanceUri = model.getURI(); String selfLinkUri = resource.getRequiredLink(IanaLinkRelation.SELF.value()).expand().getHref(); if (!affordanceUri.equals(selfLinkUri)) { throw new IllegalStateException("Affordance's URI " + affordanceUri + " doesn't match self link " + selfLinkUri + " as expected in HAL-FORMS"); } } }
/** * Scan through the {@link Affordance}s and * @param resource * @return */ private static CollectionJsonTemplate findTemplate(ResourceSupport resource) { List<CollectionJsonTemplate> templates = new ArrayList<>(); if (resource.hasLink(IanaLinkRelation.SELF.value())) { resource.getRequiredLink(IanaLinkRelation.SELF.value()).getAffordances().forEach(affordance -> { CollectionJsonAffordanceModel model = affordance.getAffordanceModel(MediaTypes.COLLECTION_JSON); /** * For Collection+JSON, "templates" are made of any non-GET affordances. */ if (!(model.getHttpMethod() == HttpMethod.GET)) { CollectionJsonTemplate template = new CollectionJsonTemplate() // .withData(model.getInputProperties()); templates.add(template); } }); } /** * Collection+JSON can only have one template, so grab the first one. */ return templates.stream() .findFirst() .orElse(null); }