/*
* Copyright 2011-2017 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.mapping.model;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PreferredConstructor;
/**
* Exception being thrown in case an entity could not be instantiated in the process of a to-object-mapping.
*
* @author Oliver Gierke
* @author Jon Brisbin
* @author Christoph Strobl
*/
public class MappingInstantiationException extends RuntimeException {
private static final long serialVersionUID = 822211065035487628L;
private static final String TEXT_TEMPLATE = "Failed to instantiate %s using constructor %s with arguments %s";
private final Class<?> entityType;
private final Constructor<?> constructor;
private final List<Object> constructorArguments;
/**
* Creates a new {@link MappingInstantiationException} for the given {@link PersistentEntity}, constructor arguments
* and the causing exception.
*
* @param entity
* @param arguments
* @param cause
*/
public MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
Exception cause) {
this(entity, arguments, null, cause);
}
private MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments, String message,
Exception cause) {
super(buildExceptionMessage(entity, arguments.stream(), message), cause);
this.entityType = entity.map(PersistentEntity::getType).orElse(null);
this.constructor = entity.flatMap(PersistentEntity::getPersistenceConstructor).map(PreferredConstructor::getConstructor).orElse(null);
this.constructorArguments = arguments;
}
private static String buildExceptionMessage(Optional<PersistentEntity<?, ?>> entity, Stream<Object> arguments,
String defaultMessage) {
return entity.map(it -> {
Optional<? extends PreferredConstructor<?, ?>> constructor = it.getPersistenceConstructor();
return String.format(TEXT_TEMPLATE, it.getType().getName(),
constructor.map(c -> c.getConstructor().toString()).orElse("NO_CONSTRUCTOR"),
String.join(",", arguments.map(Object::toString).collect(Collectors.toList())));
}).orElse(defaultMessage);
}
/**
* Returns the type of the entity that was attempted to instantiate.
*
* @return the entityType
*/
public Optional<Class<?>> getEntityType() {
return Optional.ofNullable(entityType);
}
/**
* The constructor used during the instantiation attempt.
*
* @return the constructor
*/
public Optional<Constructor<?>> getConstructor() {
return Optional.ofNullable(constructor);
}
/**
* The constructor arguments used to invoke the constructor.
*
* @return the constructorArguments
*/
public List<Object> getConstructorArguments() {
return constructorArguments;
}
}