/*
* Copyright 2012-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.
* 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.config;
import java.util.Map;
import org.springframework.core.MethodParameter;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.repository.support.RepositoryInvoker;
import org.springframework.data.repository.support.RepositoryInvokerFactory;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* {@link HandlerMethodArgumentResolver} to create {@link RootResourceInformation} for injection into Spring MVC
* controller methods.
*
* @author Jon Brisbin
* @author Oliver Gierke
*/
public class RootResourceInformationHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
private final Repositories repositories;
private final RepositoryInvokerFactory invokerFactory;
private final ResourceMetadataHandlerMethodArgumentResolver resourceMetadataResolver;
/**
* Creates a new {@link RootResourceInformationHandlerMethodArgumentResolver} using the given {@link Repositories},
* {@link RepositoryInvokerFactory} and {@link ResourceMetadataHandlerMethodArgumentResolver}.
*
* @param repositories must not be {@literal null}.
* @param invokerFactory must not be {@literal null}.
* @param resourceMetadataResolver must not be {@literal null}.
*/
public RootResourceInformationHandlerMethodArgumentResolver(Repositories repositories,
RepositoryInvokerFactory invokerFactory, ResourceMetadataHandlerMethodArgumentResolver resourceMetadataResolver) {
Assert.notNull(repositories, "Repositories must not be null!");
Assert.notNull(invokerFactory, "invokerFactory must not be null!");
Assert.notNull(resourceMetadataResolver, "ResourceMetadataHandlerMethodArgumentResolver must not be null!");
this.repositories = repositories;
this.invokerFactory = invokerFactory;
this.resourceMetadataResolver = resourceMetadataResolver;
}
/*
* (non-Javadoc)
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
return RootResourceInformation.class.isAssignableFrom(parameter.getParameterType());
}
/*
* (non-Javadoc)
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
*/
@Override
public RootResourceInformation resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
ResourceMetadata resourceMetadata = resourceMetadataResolver.resolveArgument(parameter, mavContainer, webRequest,
binderFactory);
Class<?> domainType = resourceMetadata.getDomainType();
RepositoryInvoker repositoryInvoker = invokerFactory.getInvokerFor(domainType);
PersistentEntity<?, ?> persistentEntity = repositories.getPersistentEntity(domainType);
// TODO reject if ResourceMetadata cannot be resolved
return new RootResourceInformation(resourceMetadata, persistentEntity,
postProcess(parameter, repositoryInvoker, domainType, webRequest.getParameterMap()));
}
/**
* Potentially customize the given {@link RepositoryInvoker} for the given domain type. Default implementations simply
* returns the given invoker as is.
*
* @param parameter must not be {@literal null}.
* @param invoker will never be {@literal null}.
* @param domainType will never be {@literal null}.
* @param parameters will never be {@literal null}.
* @return the post-processed {@link RepositoryInvoker}.
*/
protected RepositoryInvoker postProcess(MethodParameter parameter, RepositoryInvoker invoker, Class<?> domainType,
Map<String, String[]> parameters) {
return invoker;
}
}