@Override
  public void writeFieldReadStatement(
      VariableElement field,
      Collection<ExecutableElement> postCreateChildMethods,
      JavaWriter writer)
      throws IOException {
    DeclaredType type = (DeclaredType) field.asType();
    TypeMirror itemType = type.getTypeArguments().get(0);
    TypeMirror itemTypeErasure = processingEnv.getTypeUtils().erasure(itemType);

    String collectionInitializer;
    try {
      collectionInitializer = initializers.findCollectionInitializer(type);
    } catch (InvalidTypeException e) {
      processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage(), field);
      collectionInitializer = "null";
    }
    writer.beginControlFlow("if (bundle.containsKey(\"%s\"))", field.getSimpleName());
    writer.emitStatement("object.%s = %s", field.getSimpleName(), collectionInitializer);
    writer.emitStatement(
        "%1$s.readCollectionFromBundle(object.%2$s, bundle, %3$s.class, \"%2$s\")",
        CollectionBundler.class.getCanonicalName(), field.getSimpleName(), itemTypeErasure);

    writePostCreateChildMethodCalls(field, itemType, postCreateChildMethods, writer);
    writer.endControlFlow();
  }
Example #2
0
  private void createHeader(
      Set<? extends Element> annotatedElements, String packageName, JavaWriter writer)
      throws IOException {
    writer.emitPackage(packageName);

    Map<String, Element> nonRepeatedImports = new HashMap<>();

    for (Element element : annotatedElements) {
      TypeMirror elementType = element.asType();

      if (isSubtypeOfType(elementType, "android.view.View")) {
        nonRepeatedImports.put(element.asType().toString(), element);
      } else {
        processingEnv
            .getMessager()
            .printMessage(
                Diagnostic.Kind.ERROR,
                String.format(
                    "Variable: %s, is not of a type that subclasses android.view.View. @%s can only be used with Views",
                    element.getSimpleName().toString(), InjectView.class.getSimpleName()));
      }
    }
    for (String importString : nonRepeatedImports.keySet()) {
      writer.emitImports(importString);
    }
  }
  public String getJavaTypeName(final Type type, final boolean sequence, final JavaWriter writer) {
    final String typeName;
    if (type instanceof Message) {
      if (sequence) {
        typeName = writer.compressType(getSequenceTypeName(type.getCanonicalName()));
      } else {
        typeName = type.getCanonicalName();
      }
    } else if (type.isPrimitive()) {

      if (isEnumDeclaration(type)) {
        return Names.capitalize(type.getCanonicalName());
      }

      Class<?> clazz = getJavaClass(type);
      if (sequence) {
        String itemClassName = getSequenceItemClassName(clazz);
        typeName = writer.compressType(getSequenceTypeName(itemClassName));
      } else {
        typeName = writer.compressType(clazz.getCanonicalName());
      }
    } else {
      throw new UnsupportedOperationException(
          "Cannot resolve Java type for " + type + ", sequence: " + sequence);
    }
    return typeName;
  }
  @Override
  public void writeFieldWriteStatement(VariableElement field, JavaWriter writer)
      throws IOException {
    DeclaredType type = (DeclaredType) field.asType();
    TypeMirror itemType = type.getTypeArguments().get(0);
    TypeMirror itemTypeErasure = processingEnv.getTypeUtils().erasure(itemType);

    writer.beginControlFlow("if (object.%s != null)", field.getSimpleName());
    writer.emitStatement(
        "%1$s.writeCollectionToBundle(object.%2$s, bundle, %3$s.class, \"%2$s\")",
        CollectionBundler.class.getCanonicalName(), field.getSimpleName(), itemTypeErasure);
    writer.endControlFlow();
  }
Example #5
0
  @Override
  public void handle(ProcessorManager processorManager, RoundEnvironment roundEnvironment) {
    for (BaseContainerHandler containerHandler : handlers) {
      containerHandler.handle(processorManager, roundEnvironment);
    }

    ContentProviderValidator validator = new ContentProviderValidator();
    Collection<ContentProviderDefinition> contentProviderDefinitions = providerMap.values();
    for (ContentProviderDefinition contentProviderDefinition : contentProviderDefinitions) {
      if (validator.validate(processorManager, contentProviderDefinition)) {
        WriterUtils.writeBaseDefinition(contentProviderDefinition, processorManager);
      }
    }
    List<DatabaseWriter> databaseWriters = getManagerWriters();
    for (DatabaseWriter databaseWriter : databaseWriters) {
      try {
        JavaWriter javaWriter =
            new JavaWriter(
                processorManager
                    .getProcessingEnvironment()
                    .getFiler()
                    .createSourceFile(databaseWriter.getSourceFileName())
                    .openWriter());
        databaseWriter.write(javaWriter);
        javaWriter.close();
      } catch (IOException e) {
        processorManager.getMessager().printMessage(Diagnostic.Kind.WARNING, e.getMessage());
      }
    }

    if (roundEnvironment.processingOver()) {
      try {
        JavaWriter staticFlowManager =
            new JavaWriter(
                processorManager
                    .getProcessingEnvironment()
                    .getFiler()
                    .createSourceFile(
                        Classes.FLOW_MANAGER_PACKAGE
                            + "."
                            + Classes.DATABASE_HOLDER_STATIC_CLASS_NAME)
                    .openWriter());
        new FlowManagerHolderWriter(processorManager).write(staticFlowManager);

        staticFlowManager.close();
      } catch (IOException e) {
        processorManager.getMessager().printMessage(Diagnostic.Kind.WARNING, e.getMessage());
      }
    }
  }
  private void writePostCreateChildMethodCalls(
      VariableElement field,
      TypeMirror itemType,
      Collection<ExecutableElement> postCreateChildMethods,
      JavaWriter writer)
      throws IOException {

    if (!postCreateChildMethods.isEmpty() && metaTypes.isSubtype(itemType, Names.PARCELABLE)) {
      writer.beginControlFlow("for (Object child : object.%s)", field.getSimpleName());
      for (ExecutableElement method : postCreateChildMethods) {
        writer.emitStatement("object.%s(child)", method.getSimpleName());
      }
      writer.endControlFlow();
    }
  }
  public static void emitPreferenceCommitAction(
      JavaWriter writer, PreferenceEditorCommitStyle commitStyle, StringBuilder statementPattern)
      throws IOException {

    String statement = String.format(statementPattern.toString(), commitStyle.getStatementPart());
    writer.emitStatement(statement);
  }
Example #8
0
  public void write(final Type type, final EnumConstraint<String> constraint) throws IOException {
    JavaWriter jw = javaClassWriter.getOutput();
    jw.emitPackage(options.getPackageName());
    javaClassWriter.writeImports(Collections.<String>emptySet());

    if (type.getDescription() != null) {
      jw.emitJavadoc(type.getDescription());
    }

    String enumName = Names.capitalize(type.getCanonicalName());
    jw.beginType(enumName, "enum", EnumSet.of(PUBLIC));

    Iterator<String> valuesIterator = constraint.getValues().iterator();
    while (valuesIterator.hasNext()) {
      String value = valuesIterator.next();

      javaClassWriter.writeEnumValue(value, !valuesIterator.hasNext());
    }

    jw.endType();
  }
Example #9
0
 private void emitStatements(
     Set<? extends Element> annotatedElements, String hostActivityname, JavaWriter writer)
     throws IOException {
   for (Element element : annotatedElements) {
     writer.emitStatement(
         "(("
             + hostActivityname
             + ")target)."
             + element.getSimpleName().toString()
             + " = "
             + "("
             + element.asType().toString()
             + ")target.findViewById("
             + element.getAnnotation(InjectView.class).value()
             + ")");
   }
 }
  public void generate() throws IOException {
    String qualifiedGeneratedClassName =
        String.format("%s.%s", Constants.REALM_PACKAGE_NAME, Constants.DEFAULT_MODULE_CLASS_NAME);
    JavaFileObject sourceFile = env.getFiler().createSourceFile(qualifiedGeneratedClassName);
    JavaWriter writer = new JavaWriter(new BufferedWriter(sourceFile.openWriter()));
    writer.setIndent("    ");

    writer.emitPackage(Constants.REALM_PACKAGE_NAME);
    writer.emitEmptyLine();

    Map<String, Boolean> attributes = new HashMap<String, Boolean>();
    attributes.put("allClasses", Boolean.TRUE);
    writer.emitAnnotation(RealmModule.class, attributes);
    writer.beginType(
        qualifiedGeneratedClassName, // full qualified name of the item to generate
        "class", // the type of the item
        Collections.<Modifier>emptySet(), // modifiers to apply
        null); // class to extend
    writer.emitEmptyLine();

    writer.endType();
    writer.close();
  }
 public static void emitFillRealmObjectFromStream(
     String setter,
     String fieldName,
     String fieldTypeCanonicalName,
     String proxyClass,
     JavaWriter writer)
     throws IOException {
   writer
       .beginControlFlow("if (reader.peek() == JsonToken.NULL)")
       .emitStatement("reader.skipValue()")
       .emitStatement("obj.%s(null)", setter)
       .nextControlFlow("else")
       .emitStatement(
           "%s %sObj = %s.createUsingJsonStream(realm, reader)",
           fieldTypeCanonicalName, fieldName, proxyClass)
       .emitStatement("obj.%s(%sObj)", setter, fieldName)
       .endControlFlow();
 }
 public static void emitFillRealmObjectWithJsonValue(
     String setter,
     String fieldName,
     String qualifiedFieldType,
     String proxyClass,
     JavaWriter writer)
     throws IOException {
   writer
       .beginControlFlow("if (json.has(\"%s\"))", fieldName)
       .beginControlFlow("if (json.isNull(\"%s\"))", fieldName)
       .emitStatement("obj.%s(null)", setter)
       .nextControlFlow("else")
       .emitStatement(
           "%s %sObj = %s.createOrUpdateUsingJsonObject(realm, json.getJSONObject(\"%s\"), update)",
           qualifiedFieldType, fieldName, proxyClass, fieldName)
       .emitStatement("obj.%s(%sObj)", setter, fieldName)
       .endControlFlow()
       .endControlFlow();
 }
 @Override
 public void emitStreamTypeConversion(
     String setter, String fieldName, String fieldType, JavaWriter writer) throws IOException {
   String statementSetNullOrThrow;
   if (Utils.isPrimitiveType(fieldType)) {
     // Only throw exception for primitive types. For boxed types and String, exception will be
     // thrown in
     // the setter.
     statementSetNullOrThrow =
         String.format(Constants.STATEMENT_EXCEPTION_ILLEGAL_NULL_VALUE, fieldName);
   } else {
     statementSetNullOrThrow = String.format("obj.%s(null)", setter);
   }
   writer
       .beginControlFlow("if (reader.peek() == JsonToken.NULL)")
       .emitStatement("reader.skipValue()")
       .emitStatement(statementSetNullOrThrow)
       .nextControlFlow("else")
       .emitStatement("obj.%s((%s) reader.next%s())", setter, castType, jsonType)
       .endControlFlow();
 }
 public static void emitFillRealmListFromStream(
     String getter,
     String setter,
     String fieldTypeCanonicalName,
     String proxyClass,
     JavaWriter writer)
     throws IOException {
   writer
       .beginControlFlow("if (reader.peek() == JsonToken.NULL)")
       .emitStatement("reader.skipValue()")
       .emitStatement("obj.%s(null)", setter)
       .nextControlFlow("else")
       .emitStatement("reader.beginArray()")
       .beginControlFlow("while (reader.hasNext())")
       .emitStatement(
           "%s item = %s.createUsingJsonStream(realm, reader)", fieldTypeCanonicalName, proxyClass)
       .emitStatement("obj.%s().add(item)", getter)
       .endControlFlow()
       .emitStatement("reader.endArray()")
       .endControlFlow();
 }
 public static void emitFillRealmListWithJsonValue(
     String getter,
     String setter,
     String fieldName,
     String fieldTypeCanonicalName,
     String proxyClass,
     JavaWriter writer)
     throws IOException {
   writer
       .beginControlFlow("if (json.has(\"%s\"))", fieldName)
       .beginControlFlow("if (json.isNull(\"%s\"))", fieldName)
       .emitStatement("obj.%s(null)", setter)
       .nextControlFlow("else")
       .emitStatement("obj.%s().clear()", getter)
       .emitStatement("JSONArray array = json.getJSONArray(\"%s\")", fieldName)
       .beginControlFlow("for (int i = 0; i < array.length(); i++)")
       .emitStatement(
           "%s item = %s.createOrUpdateUsingJsonObject(realm, array.getJSONObject(i), update)",
           fieldTypeCanonicalName, proxyClass, fieldTypeCanonicalName)
       .emitStatement("obj.%s().add(item)", getter)
       .endControlFlow()
       .endControlFlow()
       .endControlFlow();
 }
Example #16
0
 private void beginType(String newSourceName, JavaWriter writer) throws IOException {
   writer.beginType(newSourceName, "class", EnumSet.of(Modifier.PUBLIC));
 }
Example #17
0
 private void beginMethod(String hostActivityname, JavaWriter writer) throws IOException {
   writer.beginMethod("void", "inject", EnumSet.of(Modifier.PUBLIC), hostActivityname, "target");
 }
Example #18
0
 private void emitClose(JavaWriter writer) throws IOException {
   writer.endMethod();
   writer.endType();
   writer.close();
 }
  @SuppressWarnings({"unchecked", "ConstantConditions"})
  private void manageType(TypeElement enclosingElement, Logger logger) {

    // Make sure we don't process twice the same type
    String simpleName = enclosingElement.getSimpleName().toString();
    String qualifiedName = enclosingElement.getQualifiedName().toString();
    String packageName = Utils.getElementPackageName(enclosingElement);
    if (managedTypes.contains(qualifiedName)) return;
    managedTypes.add(qualifiedName);

    // Prepare the output file
    try {
      JavaFileObject classFile =
          processingEnv.getFiler().createSourceFile(qualifiedName + INJECTOR_SUFFIX);
      logger.note("Writing " + classFile.toUri().getRawPath());
      Writer out = classFile.openWriter();
      JavaWriter writer = new JavaWriter(out);

      writer.emitPackage(packageName);

      // Initial imports
      writer
          .emitImports(AsyncService.class, Injector.class, Message.class, Set.class, HashSet.class)
          .emitImports(
              "com.joanzapata.android.asyncservice.api.annotation.OnMessage.Priority",
              "android.os.Handler",
              "android.os.Looper")
          .emitStaticImports(
              "com.joanzapata.android.asyncservice.api.annotation.OnMessage.Priority.*");

      // Generates "public final class XXXInjector extends Injector<XXX>"
      writer
          .emitEmptyLine()
          .beginType(
              simpleName + INJECTOR_SUFFIX,
              "class",
              of(PUBLIC, FINAL),
              "Injector<" + simpleName + ">");

      // Generate a handler to execute runnables on the UI Thread
      writer
          .emitEmptyLine()
          .emitField(
              "Handler", "__handler", of(PRIVATE, FINAL), "new Handler(Looper.getMainLooper())");

      // Keep trace of when a method has received data which is not from cache
      writer
          .emitEmptyLine()
          .emitField(
              "Set<String>",
              "__receivedFinalResponses",
              of(PRIVATE, FINAL),
              "new HashSet<String>()");

      // Generates "protected void inject(XXX target) { ..."
      writer
          .emitEmptyLine()
          .emitAnnotation(Override.class)
          .beginMethod("void", "inject", of(PROTECTED), simpleName, "target");

      // Here, inject all services
      List<Element> elementsAnnotatedWith =
          findElementsAnnotatedWith(enclosingElement, InjectService.class);
      for (Element element : elementsAnnotatedWith) {
        if (isPublicOrPackagePrivate(element)) {
          writer.emitStatement(
              "target.%s = new %s(target)",
              element.getSimpleName(),
              element.asType().toString() + AsyncServiceAP.GENERATED_CLASS_SUFFIX);
        }
      }

      // End of inject()
      writer.endMethod().emitEmptyLine();

      // Generates "protected void dispatch(XXX target, Message event)"
      writer
          .emitAnnotation(Override.class)
          .beginMethod(
              "void",
              "dispatch",
              of(PROTECTED),
              "final " + simpleName,
              "target",
              "final " + Message.class.getSimpleName(),
              "event",
              Priority.class.getSimpleName(),
              "priority");

      // Once the user has received a "remote" result, make sure no cache is sent anymore
      writer
          .emitField(
              "boolean",
              "__hasBeenReceivedAlready",
              of(FINAL),
              "event.getQuery() != null && __receivedFinalResponses.contains(event.getQuery())")
          .emitStatement("if (event.isCached() && __hasBeenReceivedAlready) return")
          .emitStatement(
              "if (!__hasBeenReceivedAlready && !event.isCached() && priority == LAST) __receivedFinalResponses.add(event.getQuery())");

      // Here, dispatch events to methods
      List<Element> responseReceivers =
          findElementsAnnotatedWith(enclosingElement, OnMessage.class);
      for (Element responseReceiver : responseReceivers) {
        ExecutableElement annotatedMethod = (ExecutableElement) responseReceiver;
        AnnotationMirror annotationMirror = getAnnotation(annotatedMethod, OnMessage.class);
        List<? extends VariableElement> parameters = annotatedMethod.getParameters();

        if (parameters.size() > 1)
          logger.error(
              responseReceiver, "@OnMessage annotated methods can't have more than 1 argument");

        // Define event type given parameter or @InjectResponse value
        List<String> eventTypes;
        boolean hasArg = parameters.size() == 1;
        if (hasArg) {
          TypeMirror typeMirror = parameters.get(0).asType();
          eventTypes = asList(typeMirror.toString());
          if (hasTypeParameters(processingEnv, typeMirror))
            logger.error(
                parameters.get(0),
                "You can't receive typed parameters in @OnMessage annotated methods");

        } else {
          List<AnnotationValue> parameterTypeClasses =
              getAnnotationValue(annotationMirror, "value");

          // Validate each parameter type given in the annotation
          eventTypes = new ArrayList<String>();
          for (AnnotationValue value : parameterTypeClasses) {
            DeclaredType parameterTypeClass = (DeclaredType) value.getValue();
            if (parameterTypeClass == null)
              logger.error(
                  annotatedMethod, "Either declare an argument or give @OnMessage a value.");
            if (hasTypeParameters(processingEnv, parameterTypeClass))
              logger.error(
                  annotatedMethod,
                  annotationMirror,
                  "value",
                  "You can't receive typed parameters in @OnMessage method");
            eventTypes.add(parameterTypeClass.toString());
          }
        }

        // Define whether we should check emitter or not dependeing on the annotation value
        VariableElement from = getAnnotationValue(annotationMirror, "from");
        boolean checkEmitter = !ALL.toString().equals("" + from);

        // Check the priority of the method
        VariableElement priorityValue = getAnnotationValue(annotationMirror, "priority");
        Priority priority = !LAST.toString().equals("" + priorityValue) ? FIRST : LAST;
        writer.beginControlFlow("if (priority == %s)", priority);

        // Write the code to call the user method
        if (checkEmitter) writer.beginControlFlow("if (event.getEmitter() == getTarget())");

        // Create a new inner class for the Runnable to run on UI thread
        StringWriter buffer = new StringWriter();
        JavaWriter inner = new JavaWriter(buffer);
        inner
            .emitPackage("")
            .beginType("Runnable()", "new")
            .emitAnnotation("Override")
            .beginMethod("void", "run", of(PUBLIC));
        if (hasArg)
          inner.emitStatement(
              "target.%s((%s) event.getPayload())",
              annotatedMethod.getSimpleName(), eventTypes.get(0));
        else inner.emitStatement("target.%s()", annotatedMethod.getSimpleName());
        inner.endMethod().endType();

        // For each type (can be multiple)
        for (int i = 0; i < eventTypes.size(); i++) {
          String eventType = eventTypes.get(i);
          writer
              .beginControlFlow(
                  "%sif (event.getPayload() instanceof %s)", i != 0 ? "else " : "", eventType)
              .emitStatement("__handler.post(%s)", buffer.toString())
              .endControlFlow();
        }

        if (checkEmitter) writer.endControlFlow();
        writer.endControlFlow();
      }

      // End of inject();
      writer.endMethod().emitEmptyLine();

      // End of file
      writer.endType();
      out.flush();
      out.close();
    } catch (IOException e) {
      throw new IllegalStateException("Error while create the injector for " + qualifiedName, e);
    }
  }