Search in sources :

Example 1 with Select

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);
}
Also used : EntityDefinition(com.datastax.oss.driver.internal.mapper.processor.entity.EntityDefinition) TypeElement(javax.lang.model.element.TypeElement) Select(com.datastax.oss.driver.api.mapper.annotations.Select) CodeBlock(com.squareup.javapoet.CodeBlock) VariableElement(javax.lang.model.element.VariableElement) PropertyDefinition(com.datastax.oss.driver.internal.mapper.processor.entity.PropertyDefinition)

Example 2 with Select

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");
}
Also used : Select(com.datastax.oss.driver.api.mapper.annotations.Select)

Aggregations

Select (com.datastax.oss.driver.api.mapper.annotations.Select)2 EntityDefinition (com.datastax.oss.driver.internal.mapper.processor.entity.EntityDefinition)1 PropertyDefinition (com.datastax.oss.driver.internal.mapper.processor.entity.PropertyDefinition)1 CodeBlock (com.squareup.javapoet.CodeBlock)1 TypeElement (javax.lang.model.element.TypeElement)1 VariableElement (javax.lang.model.element.VariableElement)1