package com.lexicalscope.fluentreflection;
import static ch.lambdaj.Lambda.*;
import java.util.List;
import org.hamcrest.Matcher;
import com.google.inject.TypeLiteral;
final class ReflectedMembersImpl<T> implements ReflectedMembers<T> {
private final ReflectedSuperclassesAndInterfaces<T> superclassesAndInterfaces;
private final ReflectedMethods<T> methods;
private final ReflectedConstructors<T> constructors;
private final ReflectedFields<T> fields;
private final Class<T> klass;
private ReflectedMembersImpl(
final ReflectedSuperclassesAndInterfaces<T> superclassesAndInterfaces,
final ReflectedMethods<T> methods,
final ReflectedConstructors<T> constructors,
final ReflectedFields<T> fields,
final Class<T> klass) {
this.superclassesAndInterfaces = superclassesAndInterfaces;
this.methods = methods;
this.constructors = constructors;
this.fields = fields;
this.klass = klass;
}
@Override public List<FluentConstructor<T>> constructors() {
return constructors.constructors();
}
@Override public List<FluentMethod> methods() {
return methods.methods();
}
@Override public List<FluentMethod> declaredMethods() {
return methods.declaredMethods();
}
@Override public List<FluentClass<?>> superclassesAndInterfaces() {
return superclassesAndInterfaces.superclassesAndInterfaces();
}
@Override public List<FluentMethod> methods(final Matcher<? super FluentMethod> methodMatcher) {
return select(methods(), methodMatcher);
}
@Override public FluentMethod method(final Matcher<? super FluentMethod> methodMatcher) {
final FluentMethod selectedMethod = selectFirstMethod(methodMatcher);
if (selectedMethod == null) {
throw new MethodNotFoundException(klass, methodMatcher);
}
return selectedMethod;
}
private FluentMethod selectFirstMethod(final Matcher<? super FluentMethod> methodMatcher) {
return selectFirst(methods(), methodMatcher);
}
@Override public List<FluentConstructor<T>> constructors(
final Matcher<? super FluentConstructor<?>> constructorMatcher) {
return select(constructors(), constructorMatcher);
}
@Override public FluentConstructor<T> constructor(
final Matcher<? super FluentConstructor<?>> constructorMatcher) {
return selectFirst(constructors(), constructorMatcher);
}
@Override public List<FluentClass<?>> superclassesAndInterfaces(
final Matcher<? super FluentClass<?>> supertypeMatcher) {
return select(superclassesAndInterfaces(), supertypeMatcher);
}
@Override public List<FluentField> declaredFields() {
return fields.declaredFields();
}
@Override public List<FluentField> fields() {
return fields.fields();
}
@Override public List<FluentField> fields(final Matcher<? super FluentField> fieldMatcher) {
return select(fields(), fieldMatcher);
}
@Override public FluentField field(final Matcher<? super FluentField> fieldMatcher) {
final FluentField selectedMethod = selectFirstField(fieldMatcher);
if (selectedMethod == null) {
throw new FieldNotFoundException(klass, fieldMatcher);
}
return selectedMethod;
}
private FluentField selectFirstField(final Matcher<? super FluentField> fieldMatcher) {
return selectFirst(fields(), fieldMatcher);
}
@Override public FluentMember member(final Matcher<? super FluentMember> memberMatcher) {
final FluentMethod method = selectFirstMethod(memberMatcher);
if(method == null) {
final FluentField field = selectFirstField(memberMatcher);
if(field == null) {
throw new MemberNotFoundException(klass, memberMatcher);
}
return field;
}
return method;
}
@SuppressWarnings("unchecked") public static <T> ReflectedMembersImpl<T> createReflectedMembers(
final ReflectedTypeFactory reflectedTypeFactory,
final TypeLiteral<T> typeLiteral) {
final ReflectedSuperclassesAndInterfacesImpl<T> superclassesAndInterfaces
= new ReflectedSuperclassesAndInterfacesImpl<T>(reflectedTypeFactory, typeLiteral);
return new ReflectedMembersImpl<T>(
superclassesAndInterfaces,
new ReflectedMethodsImpl<T>(reflectedTypeFactory, typeLiteral, superclassesAndInterfaces),
new ReflectedConstructorsImpl<T>(reflectedTypeFactory, typeLiteral),
new ReflectedFieldsImpl<T>(reflectedTypeFactory, typeLiteral, superclassesAndInterfaces),
(Class<T>) typeLiteral.getRawType());
}
@SuppressWarnings("unchecked") public static <T> ReflectedMembersImpl<T> createBoundReflectedMembers(
final ReflectedTypeFactory reflectedTypeFactory,
final TypeLiteral<T> typeLiteral,
final T instance) {
final ReflectedSuperclassesAndInterfacesImpl<T> superclassesAndInterfaces
= new ReflectedSuperclassesAndInterfacesImpl<T>(reflectedTypeFactory, typeLiteral);
return new ReflectedMembersImpl<T>(
superclassesAndInterfaces,
new ReflectedMethodsBinder<T>(new ReflectedMethodsImpl<T>(reflectedTypeFactory, typeLiteral, superclassesAndInterfaces), instance),
new ReflectedConstructorsImpl<T>(reflectedTypeFactory, typeLiteral),
new ReflectedFieldsBinder<T>(new ReflectedFieldsImpl<T>(reflectedTypeFactory, typeLiteral, superclassesAndInterfaces), instance),
(Class<T>) typeLiteral.getRawType());
}
}