ElementHandle.Type bindingValue = (ElementHandle.Type)binding.get("value");
ElementHandle.Type bindingImplementation = (ElementHandle.Type)binding.get("implementation");
String scope = (String)binding.get("scope");
//
JSON bindingJSON = new JSON().set("value", bindingValue.getName().toString());
//
TypeElement valueElt = env.get(bindingValue);
TypeMirror valueTM = valueElt.asType();
//
if (bindingImplementation != null) {
TypeElement implementationElt = env.get(bindingImplementation);
DeclaredType implementationTM = (DeclaredType)implementationElt.asType();
// Check class
if (implementationElt.getKind() != ElementKind.CLASS) {
throw IMPLEMENTATION_INVALID_TYPE.failure(env.get(key.getElement()), providerElt.getQualifiedName());
}
//
Set<Modifier> modifiers = implementationElt.getModifiers();
// Check not abstract
if (modifiers.contains(Modifier.ABSTRACT)) {
throw IMPLEMENTATION_NOT_ABSTRACT.failure(env.get(key.getElement()), implementationElt.getQualifiedName());
}
//
if (env.isAssignable(implementationTM, providerFactoryTM)) {
// Check public
if (!modifiers.contains(Modifier.PUBLIC)) {
throw PROVIDER_FACTORY_NOT_PUBLIC.failure(env.get(key.getElement()), implementationElt.getQualifiedName());
}
// Find zero arg constructor
ExecutableElement emptyCtor = null;
for (ExecutableElement ctorElt : ElementFilter.constructorsIn(env.getAllMembers(implementationElt))) {
if (ctorElt.getParameters().isEmpty()) {
emptyCtor = ctorElt;
break;
}
}
// Validate constructor
if (emptyCtor == null) {
throw PROVIDER_FACTORY_NO_ZERO_ARG_CTOR.failure(env.get(key.getElement()), implementationElt.getQualifiedName());
}
if (!emptyCtor.getModifiers().contains(Modifier.PUBLIC)) {
throw PROVIDER_FACTORY_NO_PUBLIC_CTOR.failure(env.get(key.getElement()), implementationElt.getQualifiedName());
}
}
else if (env.isAssignable(implementationTM, rawProviderTM)) {
TypeVariable T = (TypeVariable)providerTM.getTypeArguments().get(0);
TypeMirror resolved = env.asMemberOf(implementationTM, T.asElement());
if (env.isAssignable(resolved, valueTM)) {
// OK
}
else {
throw PROVIDER_NOT_ASSIGNABLE.failure(
env.get(key.getElement()),
implementationElt.getQualifiedName(),
resolved,
valueElt.getQualifiedName());
}
}
else if (env.isAssignable(implementationTM, valueTM)) {
// OK
}
else {
throw IMPLEMENTATION_NOT_ASSIGNABLE.failure(
env.get(key.getElement()),
implementationElt.getQualifiedName(),
valueElt.getQualifiedName());
}
//
bindingJSON.set("implementation", bindingImplementation.getName().toString());
}
// Add the declared scope if any
if (scope != null) {
bindingJSON.set("scope", scope);
}
//
list.add(bindingJSON);
}
}
//
state.put(metaModel.getHandle(), new JSON().set("bindings", list));
}