in mapper-processor/src/main/java/com/datastax/oss/driver/internal/mapper/processor/mapper/MapperDaoFactoryMethodGenerator.java [64:197]
public Optional<MethodSpec> generate() {
// Validate the return type, which tells us what DAO to build, and whether the method should be
// async.
ClassName daoImplementationName = null;
boolean isAsync = false;
TypeMirror returnTypeMirror = methodElement.getReturnType();
if (returnTypeMirror.getKind() == TypeKind.DECLARED) {
DeclaredType declaredReturnType = (DeclaredType) returnTypeMirror;
if (declaredReturnType.getTypeArguments().isEmpty()) {
Element returnTypeElement = declaredReturnType.asElement();
if (returnTypeElement.getAnnotation(Dao.class) != null) {
daoImplementationName =
GeneratedNames.daoImplementation(((TypeElement) returnTypeElement));
}
} else if (context.getClassUtils().isFuture(declaredReturnType)) {
TypeMirror typeArgument = declaredReturnType.getTypeArguments().get(0);
if (typeArgument.getKind() == TypeKind.DECLARED) {
Element typeArgumentElement = ((DeclaredType) typeArgument).asElement();
if (typeArgumentElement.getAnnotation(Dao.class) != null) {
daoImplementationName =
GeneratedNames.daoImplementation(((TypeElement) typeArgumentElement));
isAsync = true;
}
}
}
}
if (daoImplementationName == null) {
context
.getMessager()
.error(
methodElement,
"Invalid return type: %s methods must return a %s-annotated interface, "
+ "or future thereof",
DaoFactory.class.getSimpleName(),
Dao.class.getSimpleName());
return Optional.empty();
}
// Validate the arguments
String keyspaceArgumentName = null;
String tableArgumentName = null;
String profileArgumentName = null;
boolean profileIsClass = false;
for (VariableElement parameterElement : methodElement.getParameters()) {
if (parameterElement.getAnnotation(DaoKeyspace.class) != null) {
keyspaceArgumentName =
validateKeyspaceOrTableParameter(
parameterElement, keyspaceArgumentName, DaoKeyspace.class, context);
if (keyspaceArgumentName == null) {
return Optional.empty();
}
} else if (parameterElement.getAnnotation(DaoTable.class) != null) {
tableArgumentName =
validateKeyspaceOrTableParameter(
parameterElement, tableArgumentName, DaoTable.class, context);
if (tableArgumentName == null) {
return Optional.empty();
}
} else if (parameterElement.getAnnotation(DaoProfile.class) != null) {
profileArgumentName =
validateExecutionProfile(parameterElement, profileArgumentName, context);
profileIsClass =
context.getClassUtils().isSame(parameterElement.asType(), DriverExecutionProfile.class);
if (profileArgumentName == null) {
return Optional.empty();
}
} else {
context
.getMessager()
.error(
methodElement,
"Invalid parameter annotations: "
+ "%s method parameters must be annotated with @%s, @%s or @%s",
DaoFactory.class.getSimpleName(),
DaoKeyspace.class.getSimpleName(),
DaoTable.class.getSimpleName(),
DaoProfile.class.getSimpleName());
return Optional.empty();
}
}
boolean isCachedByMethodArguments =
(keyspaceArgumentName != null || tableArgumentName != null || profileArgumentName != null);
TypeName returnTypeName = ClassName.get(methodElement.getReturnType());
String suggestedFieldName = methodElement.getSimpleName() + "Cache";
String fieldName =
isCachedByMethodArguments
? enclosingClass.addDaoMapField(suggestedFieldName, returnTypeName)
: enclosingClass.addDaoSimpleField(
suggestedFieldName, returnTypeName, daoImplementationName, isAsync);
MethodSpec.Builder overridingMethodBuilder = GeneratedCodePatterns.override(methodElement);
if (isCachedByMethodArguments) {
// DaoCacheKey key = new DaoCacheKey(<ks>, <table>, <profileName>, <profile>)
// where <ks>, <table> is either the name of the parameter or "(CqlIdentifier)null"
overridingMethodBuilder.addCode("$1T key = new $1T(", DaoCacheKey.class);
if (keyspaceArgumentName == null) {
overridingMethodBuilder.addCode("($T)null", CqlIdentifier.class);
} else {
overridingMethodBuilder.addCode("$L", keyspaceArgumentName);
}
overridingMethodBuilder.addCode(", ");
if (tableArgumentName == null) {
overridingMethodBuilder.addCode("($T)null", CqlIdentifier.class);
} else {
overridingMethodBuilder.addCode("$L", tableArgumentName);
}
overridingMethodBuilder.addCode(", ");
if (profileArgumentName == null) {
overridingMethodBuilder.addCode("null, null);\n");
} else {
if (profileIsClass) {
overridingMethodBuilder.addCode("null, $L);\n", profileArgumentName);
} else {
overridingMethodBuilder.addCode("$L, null);\n", profileArgumentName);
}
}
overridingMethodBuilder.addStatement(
"return $L.computeIfAbsent(key, "
+ "k -> $T.$L(context.withDaoParameters(k.getKeyspaceId(), k.getTableId(), "
+ "k.getExecutionProfileName(), k.getExecutionProfile())))",
fieldName,
daoImplementationName,
isAsync ? "initAsync" : "init");
} else {
overridingMethodBuilder.addStatement("return $L.get()", fieldName);
}
return Optional.of(overridingMethodBuilder.build());
}