Пример #1
0
  private CodeBlock buildPopulateValuesIntoCursor() {
    CodeBlock.Builder builder = CodeBlock.builder();

    List<ColumnDefinition> columns = schema.getColumns();
    for (int i = 0; i < columns.size(); i++) {
      ColumnDefinition c = columns.get(i);
      RelationDefinition r = c.getRelation();
      TypeName type = c.getUnboxType();
      if (r == null) {
        CodeBlock.Builder getCursorExpr = CodeBlock.builder();

        if (Types.needsTypeAdapter(type)) {
          getCursorExpr.add(
              "conn.getTypeAdapterRegistry().$L($T.$L.type, $L)",
              c.nullable ? "deserializeNullable" : "deserialize",
              schema.getSchemaClassName(),
              c.name,
              cursorGetter(c, i));
        } else {
          getCursorExpr.add("$L", cursorGetter(c, i));
        }

        if (c.setter != null) {
          builder.addStatement("model.$L($L)", c.setter.getSimpleName(), getCursorExpr.build());

        } else {
          builder.addStatement("model.$L = $L", c.name, getCursorExpr.build());
        }
      } else { // SingleRelation
        if (c.setter != null) {
          builder.addStatement(
              "model.$L(new $T<>(conn, OrmaDatabase.schema$T, cursor.getLong($L)))",
              c.setter.getSimpleName(),
              r.relationType,
              r.modelType,
              i);

        } else {
          builder.addStatement(
              "model.$L = new $T<>(conn, OrmaDatabase.schema$T, cursor.getLong($L))",
              c.name,
              r.relationType,
              r.modelType,
              i);
        }
      }
    }
    return builder.build();
  }
Пример #2
0
  private TypeSpec buildModule(ModuleSpec spec) {
    CodeBlock.Builder blockBuilder =
        CodeBlock.builder().add("return new $T(", spec.getPresenterTypeName());
    int i = 0;
    for (ParameterSpec parameterSpec : spec.getPresenterArgs()) {
      blockBuilder.add(parameterSpec.name);

      if (i++ < spec.getPresenterArgs().size() - 1) {
        blockBuilder.add(", ");
      }
    }
    blockBuilder.add(");\n");

    MethodSpec.Builder methodSpecBuilder =
        MethodSpec.methodBuilder("providesPresenter")
            .addModifiers(Modifier.PUBLIC)
            .returns(spec.getPresenterTypeName())
            .addAnnotation(Provides.class)
            .addParameters(spec.getProvideParameters())
            .addCode(blockBuilder.build());

    if (spec.getScopeAnnotationSpec() != null) {
      methodSpecBuilder.addAnnotation(spec.getScopeAnnotationSpec());
    }

    return TypeSpec.classBuilder(spec.getClassName().simpleName())
        .addModifiers(Modifier.PUBLIC)
        .addAnnotation(Module.class)
        .addMethod(methodSpecBuilder.build())
        .build();
  }
Пример #3
0
 private CodeBlock buildCreateModelFromCursor() {
   CodeBlock.Builder builder = CodeBlock.builder();
   builder.addStatement(
       "$T model = new $T()", schema.getModelClassName(), schema.getModelClassName()); // FIXME
   builder.add(buildPopulateValuesIntoCursor());
   builder.addStatement("return model");
   return builder.build();
 }
Пример #4
0
  // http://developer.android.com/intl/ja/reference/android/database/sqlite/SQLiteStatement.html
  private CodeBlock buildBindArgs() {
    CodeBlock.Builder builder = CodeBlock.builder();

    List<ColumnDefinition> columns = schema.getColumnsWithoutAutoId();
    for (int i = 0; i < columns.size(); i++) {
      int n = i + 1; // bind index starts 1
      ColumnDefinition c = columns.get(i);
      TypeName type = c.getUnboxType();
      RelationDefinition r = c.getRelation();
      boolean nullable = !type.isPrimitive() && c.nullable;

      if (nullable) {
        builder.beginControlFlow("if (model.$L != null)", c.name);
      }

      if (type.equals(TypeName.BOOLEAN)) {
        builder.addStatement(
            "statement.bindLong($L, model.$L ? 1 : 0)", n, c.getColumnGetterExpr());
      } else if (Types.looksLikeIntegerType(type)) {
        builder.addStatement("statement.bindLong($L, model.$L)", n, c.getColumnGetterExpr());
      } else if (Types.looksLikeFloatType(type)) {
        builder.addStatement("statement.bindDouble($L, model.$L)", n, c.getColumnGetterExpr());
      } else if (type.equals(Types.ByteArray)) {
        builder.addStatement("statement.bindBlob($L, model.$L)", n, c.getColumnGetterExpr());
      } else if (type.equals(Types.String)) {
        builder.addStatement("statement.bindString($L, model.$L)", n, c.getColumnGetterExpr());
      } else if (r != null && r.relationType.equals(Types.SingleRelation)) {
        builder.addStatement(
            "statement.bindLong($L, model.$L.getId())", n, c.getColumnGetterExpr());
      } else {
        builder.addStatement(
            "statement.bindString($L, conn.getTypeAdapterRegistry().serialize($T.$L.type, model.$L))",
            n,
            schema.getSchemaClassName(),
            c.name,
            c.getColumnGetterExpr());
      }

      if (nullable) {
        builder.endControlFlow();
        builder.beginControlFlow("else");
        builder.addStatement("statement.bindNull($L)", n);
        builder.endControlFlow();
      }
    }

    return builder.build();
  }
Пример #5
0
  public CodeBlock buildColumnsInitializer(List<FieldSpec> columns) {
    CodeBlock.Builder builder = CodeBlock.builder();

    builder.add("$T.<$T>asList(\n", Types.Arrays, Types.WildcardColumnDef).indent();

    for (int i = 0; i < columns.size(); i++) {
      builder.add("$N", columns.get(i));
      if ((i + 1) != columns.size()) {
        builder.add(",\n");
      } else {
        builder.add("\n");
      }
    }

    builder.unindent().add(")");

    return builder.build();
  }
Пример #6
0
  public CodeBlock buildEscapedColumnNamesInitializer() {
    CodeBlock.Builder builder = CodeBlock.builder();

    builder.add("{\n").indent();

    List<ColumnDefinition> columns = schema.getColumns();

    for (int i = 0; i < columns.size(); i++) {
      builder.add("$S", '"' + columns.get(i).columnName + '"');
      if ((i + 1) != columns.size()) {
        builder.add(",\n");
      } else {
        builder.add("\n");
      }
    }

    builder.unindent().add("}");

    return builder.build();
  }
  @Override
  public void onWriteDefinition(TypeSpec.Builder typeBuilder) {

    typeBuilder.addField(
        FieldSpec.builder(
                ClassName.get(String.class),
                AUTHORITY,
                Modifier.PRIVATE,
                Modifier.STATIC,
                Modifier.FINAL)
            .initializer("$S", authority)
            .build());

    int code = 0;
    for (TableEndpointDefinition endpointDefinition : endpointDefinitions) {
      for (ContentUriDefinition contentUriDefinition : endpointDefinition.contentUriDefinitions) {
        typeBuilder.addField(
            FieldSpec.builder(
                    TypeName.INT,
                    contentUriDefinition.name,
                    Modifier.PRIVATE,
                    Modifier.STATIC,
                    Modifier.FINAL)
                .initializer(String.valueOf(code))
                .build());
        code++;
      }
    }

    FieldSpec.Builder uriField =
        FieldSpec.builder(
            ClassNames.URI_MATCHER, URI_MATCHER, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);

    CodeBlock.Builder initializer =
        CodeBlock.builder()
            .addStatement("new $T($T.NO_MATCH)", ClassNames.URI_MATCHER, ClassNames.URI_MATCHER)
            .add("static {\n");

    for (TableEndpointDefinition endpointDefinition : endpointDefinitions) {
      for (ContentUriDefinition contentUriDefinition : endpointDefinition.contentUriDefinitions) {
        String path;
        if (contentUriDefinition.path != null) {
          path = "\"" + contentUriDefinition.path + "\"";
        } else {
          path =
              CodeBlock.builder()
                  .add(
                      "$L.$L.getPath()",
                      contentUriDefinition.elementClassName,
                      contentUriDefinition.name)
                  .build()
                  .toString();
        }
        initializer.addStatement(
            "$L.addURI($L, $L, $L)", URI_MATCHER, AUTHORITY, path, contentUriDefinition.name);
      }
    }
    initializer.add("}\n");
    typeBuilder.addField(uriField.initializer(initializer.build()).build());

    typeBuilder.addMethod(
        MethodSpec.methodBuilder("getDatabaseName")
            .addAnnotation(Override.class)
            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
            .addStatement("return $S", databaseNameString)
            .returns(ClassName.get(String.class))
            .build());

    MethodSpec.Builder getTypeBuilder =
        MethodSpec.methodBuilder("getType")
            .addAnnotation(Override.class)
            .addParameter(ClassNames.URI, "uri")
            .returns(ClassName.get(String.class))
            .addModifiers(Modifier.PUBLIC, Modifier.FINAL);

    CodeBlock.Builder getTypeCode =
        CodeBlock.builder()
            .addStatement("$T type = null", ClassName.get(String.class))
            .beginControlFlow("switch($L.match(uri))", URI_MATCHER);

    for (TableEndpointDefinition tableEndpointDefinition : endpointDefinitions) {
      for (ContentUriDefinition uriDefinition : tableEndpointDefinition.contentUriDefinitions) {
        getTypeCode
            .beginControlFlow("case $L:", uriDefinition.name)
            .addStatement("type = $S", uriDefinition.type)
            .addStatement("break")
            .endControlFlow();
      }
    }
    getTypeCode
        .beginControlFlow("default:")
        .addStatement(
            "throw new $T($S + $L)",
            ClassName.get(IllegalArgumentException.class),
            "Unknown URI",
            "uri")
        .endControlFlow();
    getTypeCode.endControlFlow();
    getTypeCode.addStatement("return type");

    getTypeBuilder.addCode(getTypeCode.build());
    typeBuilder.addMethod(getTypeBuilder.build());

    for (MethodDefinition method : methods) {
      MethodSpec methodSpec = method.getMethodSpec();
      if (methodSpec != null) {
        typeBuilder.addMethod(methodSpec);
      }
    }
  }
Пример #8
0
  @Override
  Optional<TypeSpec.Builder> write(ClassName generatedTypeName, ProvisionBinding binding) {
    // We don't want to write out resolved bindings -- we want to write out the generic version.
    checkState(!binding.unresolved().isPresent());

    TypeMirror keyType =
        binding.contributionType().equals(ContributionType.MAP)
            ? MapType.from(binding.key().type()).unwrappedValueType(Provider.class)
            : binding.key().type();
    TypeName providedTypeName = TypeName.get(keyType);
    ParameterizedTypeName parameterizedFactoryName = factoryOf(providedTypeName);
    Optional<ParameterizedTypeName> factoryOfRawTypeName = Optional.absent();
    TypeSpec.Builder factoryBuilder;
    Optional<MethodSpec.Builder> constructorBuilder = Optional.absent();
    ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding);
    ImmutableMap<BindingKey, FrameworkField> fields =
        generateBindingFieldsForDependencies(dependencyRequestMapper, binding);
    switch (binding.factoryCreationStrategy()) {
      case ENUM_INSTANCE:
        factoryBuilder = enumBuilder(generatedTypeName.simpleName()).addEnumConstant("INSTANCE");
        // If we have type parameters, then remove the parameters from our providedTypeName,
        // since we'll be implementing an erased version of it.
        if (!typeParameters.isEmpty()) {
          factoryBuilder.addAnnotation(SUPPRESS_WARNINGS_RAWTYPES);
          // TODO(ronshapiro): instead of reassigning, introduce an optional/second parameter
          providedTypeName = ((ParameterizedTypeName) providedTypeName).rawType;
          factoryOfRawTypeName = Optional.of(factoryOf(providedTypeName));
        }
        break;
      case CLASS_CONSTRUCTOR:
        factoryBuilder =
            classBuilder(generatedTypeName.simpleName())
                .addTypeVariables(typeParameters)
                .addModifiers(FINAL);
        constructorBuilder = Optional.of(constructorBuilder().addModifiers(PUBLIC));
        if (binding.bindingKind().equals(PROVISION)
            && !binding.bindingElement().getModifiers().contains(STATIC)) {
          addConstructorParameterAndTypeField(
              TypeName.get(binding.bindingTypeElement().asType()),
              "module",
              factoryBuilder,
              constructorBuilder.get());
        }
        for (FrameworkField bindingField : fields.values()) {
          addConstructorParameterAndTypeField(
              bindingField.javapoetFrameworkType(),
              bindingField.name(),
              factoryBuilder,
              constructorBuilder.get());
        }
        break;
      default:
        throw new AssertionError();
    }

    factoryBuilder
        .addModifiers(PUBLIC)
        .addSuperinterface(factoryOfRawTypeName.or(parameterizedFactoryName));

    // If constructing a factory for @Inject or @Provides bindings, we use a static create method
    // so that generated components can avoid having to refer to the generic types
    // of the factory.  (Otherwise they may have visibility problems referring to the types.)
    Optional<MethodSpec> createMethod;
    switch (binding.bindingKind()) {
      case INJECTION:
      case PROVISION:
        // The return type is usually the same as the implementing type, except in the case
        // of enums with type variables (where we cast).
        MethodSpec.Builder createMethodBuilder =
            methodBuilder("create")
                .addModifiers(PUBLIC, STATIC)
                .addTypeVariables(typeParameters)
                .returns(parameterizedFactoryName);
        List<ParameterSpec> params =
            constructorBuilder.isPresent()
                ? constructorBuilder.get().build().parameters
                : ImmutableList.<ParameterSpec>of();
        createMethodBuilder.addParameters(params);
        switch (binding.factoryCreationStrategy()) {
          case ENUM_INSTANCE:
            if (typeParameters.isEmpty()) {
              createMethodBuilder.addStatement("return INSTANCE");
            } else {
              // We use an unsafe cast here because the types are different.
              // It's safe because the type is never referenced anywhere.
              createMethodBuilder.addStatement("return ($T) INSTANCE", TypeNames.FACTORY);
              createMethodBuilder.addAnnotation(SUPPRESS_WARNINGS_UNCHECKED);
            }
            break;

          case CLASS_CONSTRUCTOR:
            createMethodBuilder.addStatement(
                "return new $T($L)",
                javapoetParameterizedGeneratedTypeNameForBinding(binding),
                makeParametersCodeBlock(Lists.transform(params, CodeBlocks.PARAMETER_NAME)));
            break;
          default:
            throw new AssertionError();
        }
        createMethod = Optional.of(createMethodBuilder.build());
        break;
      default:
        createMethod = Optional.absent();
    }

    if (constructorBuilder.isPresent()) {
      factoryBuilder.addMethod(constructorBuilder.get().build());
    }

    List<CodeBlock> parameters = Lists.newArrayList();
    for (DependencyRequest dependency : binding.dependencies()) {
      parameters.add(
          frameworkTypeUsageStatement(
              CodeBlocks.format("$L", fields.get(dependency.bindingKey()).name()),
              dependency.kind()));
    }
    CodeBlock parametersCodeBlock = makeParametersCodeBlock(parameters);

    MethodSpec.Builder getMethodBuilder =
        methodBuilder("get")
            .returns(providedTypeName)
            .addAnnotation(Override.class)
            .addModifiers(PUBLIC);

    if (binding.bindingKind().equals(PROVISION)) {
      CodeBlock.Builder providesMethodInvocationBuilder = CodeBlock.builder();
      if (binding.bindingElement().getModifiers().contains(STATIC)) {
        providesMethodInvocationBuilder.add("$T", ClassName.get(binding.bindingTypeElement()));
      } else {
        providesMethodInvocationBuilder.add("module");
      }
      providesMethodInvocationBuilder.add(
          ".$L($L)", binding.bindingElement().getSimpleName(), parametersCodeBlock);
      CodeBlock providesMethodInvocation = providesMethodInvocationBuilder.build();

      if (binding.provisionType().equals(SET)) {
        TypeName paramTypeName =
            TypeName.get(MoreTypes.asDeclared(keyType).getTypeArguments().get(0));
        // TODO(cgruber): only be explicit with the parameter if paramType contains wildcards.
        getMethodBuilder.addStatement(
            "return $T.<$T>singleton($L)",
            Collections.class,
            paramTypeName,
            providesMethodInvocation);
      } else if (binding.nullableType().isPresent()
          || nullableValidationType.equals(Diagnostic.Kind.WARNING)) {
        if (binding.nullableType().isPresent()) {
          getMethodBuilder.addAnnotation((ClassName) TypeName.get(binding.nullableType().get()));
        }
        getMethodBuilder.addStatement("return $L", providesMethodInvocation);
      } else {
        String failMsg = CANNOT_RETURN_NULL_FROM_NON_NULLABLE_PROVIDES_METHOD;
        getMethodBuilder
            .addStatement(
                "$T provided = $L", getMethodBuilder.build().returnType, providesMethodInvocation)
            .addCode("if (provided == null) { ")
            .addStatement("throw new $T($S)", NullPointerException.class, failMsg)
            .addCode("}")
            .addStatement("return provided");
      }
    } else if (binding.membersInjectionRequest().isPresent()) {
      getMethodBuilder.addStatement(
          "$1T instance = new $1T($2L)", providedTypeName, parametersCodeBlock);
      getMethodBuilder.addStatement(
          "$L.injectMembers(instance)",
          fields.get(binding.membersInjectionRequest().get().bindingKey()).name());
      getMethodBuilder.addStatement("return instance");
    } else {
      getMethodBuilder.addStatement("return new $T($L)", providedTypeName, parametersCodeBlock);
    }

    factoryBuilder.addMethod(getMethodBuilder.build());
    if (createMethod.isPresent()) {
      factoryBuilder.addMethod(createMethod.get());
    }

    // TODO(gak): write a sensible toString
    return Optional.of(factoryBuilder);
  }