/* * Copyright 2014 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.rest.webmvc.mapping; import java.util.ArrayList; import java.util.List; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.SimpleAssociationHandler; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.rest.core.Path; import org.springframework.hateoas.Link; import org.springframework.hateoas.Links; import org.springframework.util.Assert; /** * {@link SimpleAssociationHandler} that will collect {@link Link}s for all linkable associations. * * @author Oliver Gierke * @since 2.1 */ public class LinkCollectingAssociationHandler implements SimpleAssociationHandler { private static final String AMBIGUOUS_ASSOCIATIONS = "Detected multiple association links with same relation type! Disambiguate association %s using @RestResource!"; private final PersistentEntities entities; private final Associations associations; private final Path basePath; private final boolean nested; private final List<Link> links; /** * Creates a new {@link LinkCollectingAssociationHandler} for the given {@link PersistentEntities}, {@link Path} and * {@link Associations}. * * @param entities must not be {@literal null}. * @param path must not be {@literal null}. * @param associations must not be {@literal null}. */ public LinkCollectingAssociationHandler(PersistentEntities entities, Path path, Associations associations) { this(entities, path, associations, false); } private LinkCollectingAssociationHandler(PersistentEntities entities, Path path, Associations associations, boolean nested) { Assert.notNull(entities, "PersistentEntities must not be null!"); Assert.notNull(path, "Path must not be null!"); Assert.notNull(associations, "AssociationLinks must not be null!"); this.entities = entities; this.associations = associations; this.basePath = path; this.links = new ArrayList<Link>(); this.nested = nested; } public LinkCollectingAssociationHandler nested() { return nested ? this : new LinkCollectingAssociationHandler(entities, basePath, associations, true); } /** * Returns the links collected after the {@link Association} has been traversed. * * @return the links */ public List<Link> getLinks() { return links; } /* * (non-Javadoc) * @see org.springframework.data.mapping.SimpleAssociationHandler#doWithAssociation(org.springframework.data.mapping.Association) */ @Override public void doWithAssociation(final Association<? extends PersistentProperty<?>> association) { PersistentProperty<?> property = association.getInverse(); if (associations.isLinkableAssociation(property)) { Links existingLinks = new Links(links); for (Link link : associations.getLinksFor(association, basePath)) { if (existingLinks.hasLink(link.getRel())) { throw new MappingException(String.format(AMBIGUOUS_ASSOCIATIONS, property.toString())); } else { links.add(link); } } } } }