use of com.datastax.oss.driver.api.mapper.annotations.Select in project java-driver by datastax.
the class DaoSelectMethodGenerator method generate.
@Override
public Optional<MethodSpec> generate() {
// Validate the return type:
DaoReturnType returnType = parseAndValidateReturnType(getSupportedReturnTypes(), Select.class.getSimpleName());
if (returnType == null) {
return Optional.empty();
}
TypeElement entityElement = returnType.getEntityElement();
EntityDefinition entityDefinition = context.getEntityFactory().getDefinition(entityElement);
// Validate the parameters:
// - if there is a custom clause, they are free-form (they'll be used as bind variables)
// - otherwise, we accept the primary key components or a subset thereof (possibly empty to
// select all rows), followed by free-form parameters bound to the secondary clauses (such as
// LIMIT).
// In either case, a Function<BoundStatementBuilder, BoundStatementBuilder> can be added in last
// position.
List<? extends VariableElement> parameters = methodElement.getParameters();
VariableElement boundStatementFunction = findBoundStatementFunction(methodElement);
if (boundStatementFunction != null) {
parameters = parameters.subList(0, parameters.size() - 1);
}
final List<? extends VariableElement> primaryKeyParameters;
final List<? extends VariableElement> freeFormParameters;
Select selectAnnotation = methodElement.getAnnotation(Select.class);
// otherwise we wouldn't have gotten into this class
assert selectAnnotation != null;
String customClause = selectAnnotation.customWhereClause();
if (parameters.isEmpty()) {
primaryKeyParameters = freeFormParameters = Collections.emptyList();
} else if (customClause.isEmpty()) {
// If we have a partial primary key *and* free-form parameters, things get ambiguous because
// we don't know where the primary key ends. By convention, we require the first free-form
// parameter to be annotated with @CqlName in those cases.
// So the boundary is either when we have enough parameters for a full primary key, or when we
// encounter the first annotated parameter.
int firstNamedParameter = parameters.size();
for (int i = 0; i < parameters.size(); i++) {
if (parameters.get(i).getAnnotation(CqlName.class) != null) {
firstNamedParameter = i;
break;
}
}
int primaryKeyEnd = Math.min(firstNamedParameter, entityDefinition.getPrimaryKey().size());
if (primaryKeyEnd >= parameters.size()) {
primaryKeyParameters = parameters;
freeFormParameters = Collections.emptyList();
} else {
primaryKeyParameters = parameters.subList(0, primaryKeyEnd);
freeFormParameters = parameters.subList(primaryKeyEnd, parameters.size());
}
} else {
primaryKeyParameters = Collections.emptyList();
freeFormParameters = parameters;
}
// If we have parameters for some primary key components, validate that the types match:
if (!primaryKeyParameters.isEmpty() && !EntityUtils.areParametersValid(entityElement, entityDefinition, primaryKeyParameters, Select.class, context, methodElement, processedType, "don't use a custom clause")) {
return Optional.empty();
}
// Generate the method:
String helperFieldName = enclosingClass.addEntityHelperField(ClassName.get(entityElement));
String statementName = enclosingClass.addPreparedStatement(methodElement, (methodBuilder, requestName) -> generateSelectRequest(methodBuilder, requestName, helperFieldName, primaryKeyParameters.size()));
CodeBlock.Builder createStatementBlock = CodeBlock.builder();
createStatementBlock.addStatement("$T boundStatementBuilder = $L.boundStatementBuilder()", BoundStatementBuilder.class, statementName);
populateBuilderWithStatementAttributes(createStatementBlock, methodElement);
populateBuilderWithFunction(createStatementBlock, boundStatementFunction);
if (!primaryKeyParameters.isEmpty()) {
List<CodeBlock> primaryKeyNames = entityDefinition.getPrimaryKey().stream().map(PropertyDefinition::getCqlName).collect(Collectors.toList()).subList(0, primaryKeyParameters.size());
GeneratedCodePatterns.bindParameters(primaryKeyParameters, primaryKeyNames, createStatementBlock, enclosingClass, context, false);
}
if (!freeFormParameters.isEmpty()) {
if (validateCqlNamesPresent(freeFormParameters)) {
GeneratedCodePatterns.bindParameters(freeFormParameters, createStatementBlock, enclosingClass, context, false);
} else {
return Optional.empty();
}
}
createStatementBlock.addStatement("$T boundStatement = boundStatementBuilder.build()", BoundStatement.class);
return crudMethod(createStatementBlock, returnType, helperFieldName);
}
use of com.datastax.oss.driver.api.mapper.annotations.Select in project java-driver by datastax.
the class DaoSelectMethodGenerator method generateSelectRequest.
private void generateSelectRequest(MethodSpec.Builder methodBuilder, String requestName, String helperFieldName, int numberOfPrimaryKeyPartsInWhereClause) {
Select annotation = methodElement.getAnnotation(Select.class);
String customWhereClause = annotation.customWhereClause();
if (customWhereClause.isEmpty()) {
methodBuilder.addCode("$[$T $L = $L.selectByPrimaryKeyParts($L)", SimpleStatement.class, requestName, helperFieldName, numberOfPrimaryKeyPartsInWhereClause);
} else {
methodBuilder.addCode("$[$T $L = $L.selectStart().whereRaw($S)", SimpleStatement.class, requestName, helperFieldName, customWhereClause);
}
maybeAddSimpleClause(annotation.limit(), Integer::parseInt, "limit", "limit", methodBuilder);
maybeAddSimpleClause(annotation.perPartitionLimit(), Integer::parseInt, "perPartitionLimit", "perPartitionLimit", methodBuilder);
for (String orderingSpec : annotation.orderBy()) {
addOrdering(orderingSpec, methodBuilder);
}
for (String groupByColumn : annotation.groupBy()) {
methodBuilder.addCode(".groupBy($S)", groupByColumn);
}
if (annotation.allowFiltering()) {
methodBuilder.addCode(".allowFiltering()");
}
methodBuilder.addCode(".build();$]\n");
}
Aggregations