/*
* Copyright 2012-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.lightadmin.core.util;
import org.lightadmin.api.config.AdministrationConfiguration;
import org.lightadmin.api.config.annotation.Administration;
import org.lightadmin.core.config.domain.unit.ConfigurationUnit;
import org.lightadmin.core.config.domain.unit.ConfigurationUnitBuilder;
import org.lightadmin.core.config.domain.unit.DomainConfigurationUnitType;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import static org.springframework.beans.BeanUtils.instantiateClass;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.util.ClassUtils.getConstructorIfAvailable;
import static org.springframework.util.ClassUtils.getMethodIfAvailable;
import static org.springframework.util.ReflectionUtils.invokeMethod;
public abstract class DomainConfigurationUtils {
public static Class<?> configurationDomainType(Class clazz) {
if (isAnnotationBasedConfigurationCandidate(clazz)) {
final Administration annotation = findAnnotation(clazz, Administration.class);
return annotation == null ? null : annotation.value();
}
if (isSuperClassBasedConfigurationCandidate(clazz)) {
final ParameterizedType genericSuperclass = (ParameterizedType) clazz.getGenericSuperclass();
return (Class<?>) genericSuperclass.getActualTypeArguments()[0];
}
throw new RuntimeException("Unknown configuration candidate");
}
public static boolean isAnnotationBasedConfigurationCandidate(Class clazz) {
return hasAdministrationAnnotation(clazz);
}
public static boolean isSuperClassBasedConfigurationCandidate(Class clazz) {
return ClassUtils.isAssignable(AdministrationConfiguration.class, clazz);
}
private static boolean hasAdministrationAnnotation(Class clazz) {
return findAnnotation(clazz, Administration.class) != null;
}
@SuppressWarnings({"unchecked"})
public static <T extends ConfigurationUnit> T initializeConfigurationUnitWithBuilder(final AdministrationConfiguration configurationInstance, DomainConfigurationUnitType configurationUnitType, Class<? extends ConfigurationUnitBuilder<T>> builderInterface, Class<? extends ConfigurationUnitBuilder<T>> concreteBuilderClass) {
final Class<? extends AdministrationConfiguration> configurationClass = configurationInstance.getClass();
final Class<?> domainType = configurationDomainType(configurationClass);
final Method method = getMethodIfAvailable(configurationClass, configurationUnitType.getName(), builderInterface);
final ConfigurationUnitBuilder<T> builder = instantiateBuilder(concreteBuilderClass, domainType, configurationUnitType);
try {
return (T) invokeMethod(method, configurationInstance, builder);
} catch (Exception ex) {
return instantiateBuilder(concreteBuilderClass, domainType, configurationUnitType).build();
}
}
@SuppressWarnings({"unchecked"})
public static <T extends ConfigurationUnit> T initializeConfigurationUnitWithBuilder(final Class<?> configurationClass, DomainConfigurationUnitType configurationUnitType, Class<? extends ConfigurationUnitBuilder<T>> builderInterface, Class<? extends ConfigurationUnitBuilder<T>> concreteBuilderClass) {
final Class<?> domainType = configurationDomainType(configurationClass);
final Method method = getMethodIfAvailable(configurationClass, configurationUnitType.getName(), builderInterface);
final ConfigurationUnitBuilder<T> builder = instantiateBuilder(concreteBuilderClass, domainType, configurationUnitType);
if (method != null) {
try {
return (T) invokeMethod(method, null, builder);
} catch (Exception ex) {
return instantiateBuilder(concreteBuilderClass, domainType, configurationUnitType).build();
}
}
return builder.build();
}
private static <T extends ConfigurationUnit> ConfigurationUnitBuilder<T> instantiateBuilder(final Class<? extends ConfigurationUnitBuilder<T>> concreteBuilderClass, final Class domainType, DomainConfigurationUnitType configurationUnitType) {
Constructor<? extends ConfigurationUnitBuilder<T>> extendedConstructor = getConstructorIfAvailable(concreteBuilderClass, Class.class, DomainConfigurationUnitType.class);
if (extendedConstructor != null) {
return instantiateClass(extendedConstructor, domainType, configurationUnitType);
}
Constructor<? extends ConfigurationUnitBuilder<T>> constructor = getConstructorIfAvailable(concreteBuilderClass, Class.class);
if (constructor != null) {
return instantiateClass(constructor, domainType);
}
return instantiateClass(concreteBuilderClass);
}
}