/*
* 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 com.teradata.tempto.internal;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static java.util.Collections.unmodifiableSet;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import static org.reflections.util.ClasspathHelper.forPackage;
public final class ReflectionHelper
{
private static final String PACKAGES_PREFIX = "com";
private static final LoadingCache<Class<? extends Annotation>, Set<Field>> FIELDS_ANNOTATED_WITH = CacheBuilder.newBuilder()
.build(new CacheLoader<Class<? extends Annotation>, Set<Field>>()
{
@Override
public Set<Field> load(Class<? extends Annotation> key)
throws Exception
{
Reflections reflections = new Reflections(forPackage(PACKAGES_PREFIX),
new FieldAnnotationsScanner(), ReflectionHelper.class.getClassLoader());
return unmodifiableSet(reflections.getFieldsAnnotatedWith(key));
}
});
private static final LoadingCache<Class, Set<Class>> SUBTYPES_OF = CacheBuilder.newBuilder()
.build(new CacheLoader<Class, Set<Class>>()
{
@Override
@SuppressWarnings("unchecked")
public Set<Class> load(Class key)
throws Exception
{
Reflections reflections = new Reflections(PACKAGES_PREFIX);
return reflections.getSubTypesOf(key);
}
});
public static <T> T getStaticFieldValue(Field field)
{
try {
return (T) field.get(null);
}
catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public static Set<Field> getFieldsAnnotatedWith(Class<? extends Annotation> annotation)
{
return FIELDS_ANNOTATED_WITH.getUnchecked(annotation);
}
@SuppressWarnings("unchecked")
public static <T> Set<Class<? extends T>> getAnnotatedSubTypesOf(Class<T> clazz, Class<? extends Annotation> annotation)
{
Set<Class<? extends T>> subtypesOf = (Set) SUBTYPES_OF.getUnchecked(clazz);
return subtypesOf.stream()
.filter(c -> c.getAnnotation(annotation) != null)
.collect(toSet());
}
public static <T> List<? extends T> instantiate(Collection<Class<? extends T>> classes)
{
return classes
.stream()
.map(ReflectionHelper::instantiate)
.collect(toList());
}
public static <T> T instantiate(String className)
{
try {
return instantiate((Class<T>) Class.forName(className));
}
catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to find specified class: " + className, e);
}
}
private static <T> T instantiate(Class<? extends T> clazz)
{
try {
return clazz.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private ReflectionHelper()
{
}
}