@Override
  public void systemService(
      final JavaType type,
      JavaSymbolName fieldName,
      final SystemService service,
      final boolean addPermissions) {

    final ClassOrInterfaceTypeDetails typeDetails = typeLocationService.getTypeDetails(type);
    Validate.notNull(typeDetails, "The type specified, '" + type + "' doesn't exist");

    if (fieldName == null) {
      fieldName =
          new JavaSymbolName(
              StringUtils.uncapitalize(service.getServiceType().getSimpleTypeName()));
    }

    final String physicalTypeIdentifier = typeDetails.getDeclaredByMetadataId();

    final List<AnnotationMetadataBuilder> annotations =
        Arrays.asList(new AnnotationMetadataBuilder(ROO_SYSTEM_SERVICE));

    final FieldMetadataBuilder fieldBuilder =
        new FieldMetadataBuilder(
            physicalTypeIdentifier, 0, annotations, fieldName, service.getServiceType());
    typeManagementService.addField(fieldBuilder.build());

    if (addPermissions) {
      final String moduleName = projectOperations.getFocusedModuleName();
      for (Permission permission : service.getPermissions()) {
        androidTypeService.addPermission(moduleName, permission.permissionName());
      }
    }
  }
Example #2
0
  public void injectEmailTemplate(
      final JavaType targetType, final JavaSymbolName fieldName, final boolean async) {
    Assert.notNull(targetType, "Java type required");
    Assert.notNull(fieldName, "Field name required");

    final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
    annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));

    // Obtain the physical type and its mutable class details
    final String declaredByMetadataId = PhysicalTypeIdentifier.createIdentifier(targetType);
    ClassOrInterfaceTypeDetails existing = typeLocationService.findClassOrInterface(targetType);
    if (existing == null) {
      log.warning(
          "Aborting: Unable to find metadata for target type '"
              + targetType.getFullyQualifiedTypeName()
              + "'");
      return;
    }
    final ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetailsBuilder =
        new ClassOrInterfaceTypeDetailsBuilder(existing);

    // Add the MailSender field
    final FieldMetadataBuilder mailSenderFieldBuilder =
        new FieldMetadataBuilder(
            declaredByMetadataId, PRIVATE_TRANSIENT, annotations, fieldName, MAIL_SENDER);
    classOrInterfaceTypeDetailsBuilder.addField(mailSenderFieldBuilder.build());

    // Add the "sendMessage" method
    classOrInterfaceTypeDetailsBuilder.addMethod(
        getSendMethod(fieldName, async, declaredByMetadataId, classOrInterfaceTypeDetailsBuilder));
    typeManagementService.createOrUpdateTypeOnDisk(classOrInterfaceTypeDetailsBuilder.build());
  }
  @Test
  public void testSimpleClassAddField() throws Exception {

    // Set up
    final File file = getResource(SIMPLE_CLASS_FILE_PATH);
    final String fileContents = getResourceContents(file);

    final ClassOrInterfaceTypeDetails simpleInterfaceDetails =
        typeParsingService.getTypeFromString(
            fileContents, SIMPLE_CLASS_DECLARED_BY_MID, SIMPLE_CLASS_TYPE);

    final FieldMetadataBuilder fieldBuilder =
        new FieldMetadataBuilder(
            SIMPLE_CLASS_DECLARED_BY_MID,
            Modifier.PRIVATE,
            new JavaSymbolName("newFieldAddedByCode"),
            new JavaType(String.class),
            "\"Create by code\"");
    final ClassOrInterfaceTypeDetails newSimpleInterfaceDetails =
        addField(simpleInterfaceDetails, fieldBuilder.build());

    // Invoke
    final String result =
        typeParsingService.updateAndGetCompilationUnitContents(
            file.getCanonicalPath(), newSimpleInterfaceDetails);

    saveResult(file, result, "-addedField");

    checkSimpleClass(result);

    assertTrue(result.contains("private String newFieldAddedByCode = \"Create by code\";"));
  }
  /**
   * Locates the entity manager field that should be used.
   *
   * <p>If a parent is defined, it must provide the field.
   *
   * <p>We generally expect the field to be named "entityManager" and be of type
   * javax.persistence.EntityManager. We also require it to be public or protected, and annotated
   * with @PersistenceContext. If there is an existing field which doesn't meet these latter
   * requirements, we add an underscore prefix to the "entityManager" name and try again, until such
   * time as we come up with a unique name that either meets the requirements or the name is not
   * used and we will create it.
   *
   * @return the entity manager field (never returns null)
   */
  public FieldMetadata getEntityManagerField() {
    if (parent != null) {
      // The parent is required to guarantee this is available
      return parent.getEntityManagerField();
    }

    // Need to locate it ourself
    int index = -1;
    while (true) {
      // Compute the required field name
      index++;
      final JavaSymbolName fieldSymbolName =
          new JavaSymbolName(StringUtils.repeat("_", index) + "entityManager");
      final FieldMetadata candidate = governorTypeDetails.getField(fieldSymbolName);
      if (candidate != null) {
        // Verify if candidate is suitable

        if (!Modifier.isPublic(candidate.getModifier())
            && !Modifier.isProtected(candidate.getModifier())
            && (Modifier.TRANSIENT != candidate.getModifier())) {
          // Candidate is not public and not protected and not simply a transient field (in which
          // case subclasses
          // will see the inherited field), so any subsequent subclasses won't be able to see it.
          // Give up!
          continue;
        }

        if (!candidate.getFieldType().equals(ENTITY_MANAGER)) {
          // Candidate isn't an EntityManager, so give up
          continue;
        }

        if (MemberFindingUtils.getAnnotationOfType(candidate.getAnnotations(), PERSISTENCE_CONTEXT)
            == null) {
          // Candidate doesn't have a PersistenceContext annotation, so give up
          continue;
        }

        // If we got this far, we found a valid candidate
        return candidate;
      }

      // Candidate not found, so let's create one
      final List<AnnotationMetadataBuilder> annotations =
          new ArrayList<AnnotationMetadataBuilder>();
      final AnnotationMetadataBuilder annotationBuilder =
          new AnnotationMetadataBuilder(PERSISTENCE_CONTEXT);
      if (StringUtils.hasText(crudAnnotationValues.getPersistenceUnit())) {
        annotationBuilder.addStringAttribute("unitName", crudAnnotationValues.getPersistenceUnit());
      }
      annotations.add(annotationBuilder);

      final FieldMetadataBuilder fieldBuilder =
          new FieldMetadataBuilder(
              getId(), Modifier.TRANSIENT, annotations, fieldSymbolName, ENTITY_MANAGER);
      return fieldBuilder.build();
    }
  }
  /**
   * Create metadata for a field definition.
   *
   * @return a FieldMetadata object
   */
  private FieldMetadata getSampleField() {
    // Note private fields are private to the ITD, not the target type, this is undesirable if a
    // dependent method is pushed in to the target type
    int modifier = 0;

    // Using the FieldMetadataBuilder to create the field definition.
    final FieldMetadataBuilder fieldBuilder =
        new FieldMetadataBuilder(
            getId(), // Metadata ID provided by supertype
            modifier, // Using package protection rather than private
            new ArrayList<AnnotationMetadataBuilder>(), // No annotations for this field
            new JavaSymbolName("sampleField"), // Field name
            JavaType.STRING); // Field type

    return fieldBuilder.build(); // Build and return a FieldMetadata instance
  }
  @Override
  public void resourceString(
      final JavaType type, final String name, final JavaSymbolName fieldName, final String value) {

    final ClassOrInterfaceTypeDetails typeDetails = typeLocationService.getTypeDetails(type);
    Validate.notNull(typeDetails, "The type specified, '" + type + "' doesn't exist");

    final DocumentBuilder builder = newDocumentBuilder();
    final String valuesPath =
        pathResolver.getFocusedIdentifier(Path.ROOT, VALUES_PATH + SEP + STRINGS + XML_EXTENSION);

    InputStream inputStream = null;
    Document document = null;
    try {
      inputStream = fileManager.getInputStream(valuesPath);
      document = builder.parse(inputStream);
    } catch (final Exception e) {
      LOGGER.severe("Error reading resource XML: " + e.getMessage());
    } finally {
      IOUtils.closeQuietly(inputStream);
    }

    if (document != null) {
      final Element root = document.getDocumentElement();

      final Element stringElem = XmlUtils.createTextElement(document, "string", value);
      final String id = StringUtils.isEmpty(name) ? fieldName.getSymbolName() : name;
      stringElem.setAttribute("name", id);
      root.appendChild(stringElem);

      fileManager.createOrUpdateTextFileIfRequired(
          valuesPath, XmlUtils.nodeToString(document), true);
    }

    final String physicalTypeIdentifier = typeDetails.getDeclaredByMetadataId();

    final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
    final AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder(ROO_STRING);
    if (!StringUtils.isEmpty(name)) {
      annotationBuilder.addStringAttribute("value", name);
    }
    annotations.add(annotationBuilder);

    final FieldMetadataBuilder fieldBuilder =
        new FieldMetadataBuilder(physicalTypeIdentifier, 0, annotations, fieldName, STRING);
    typeManagementService.addField(fieldBuilder.build());
  }
  public void insertField(
      final FieldDetails fieldDetails,
      final boolean permitReservedWords,
      final boolean transientModifier) {

    String module = null;
    if (!permitReservedWords) {
      ReservedWords.verifyReservedWordsNotPresent(fieldDetails.getFieldName());
      if (fieldDetails.getColumn() != null) {
        ReservedWords.verifyReservedWordsNotPresent(fieldDetails.getColumn());
      }
    }

    final List<AnnotationMetadataBuilder> annotations = fieldDetails.getInitedAnnotations();
    fieldDetails.decorateAnnotationsList(annotations);
    fieldDetails.setAnnotations(annotations);

    if (fieldDetails.getFieldType() != null) {
      module = fieldDetails.getFieldType().getModule();
    }

    fieldDetails.setModifiers(Modifier.PRIVATE);

    String initializer = null;
    if (fieldDetails instanceof CollectionField) {
      final CollectionField collectionField = (CollectionField) fieldDetails;
      module = collectionField.getGenericParameterTypeName().getModule();
      initializer = "new " + collectionField.getInitializer() + "()";
    } else if (fieldDetails instanceof DateField
        && fieldDetails.getFieldName().getSymbolName().equals("created")) {
      initializer = "new Date()";
    }

    // Format the passed-in comment (if given)
    formatFieldComment(fieldDetails);

    final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(fieldDetails);
    fieldBuilder.setFieldInitializer(initializer);
    typeManagementService.addField(fieldBuilder.build());

    if (module != null) {
      projectOperations.addModuleDependency(module);
    }
  }
Example #8
0
  /**
   * Generates the "send email" method to be added to the domain type
   *
   * @param mailSenderName the name of the MailSender field (required)
   * @param async whether to send the email asynchronously
   * @param targetClassMID the MID of the class to receive the method
   * @param mutableTypeDetails the type to which the method is being added (required)
   * @return a non-<code>null</code> method
   */
  private MethodMetadata getSendMethod(
      final JavaSymbolName mailSenderName,
      final boolean async,
      final String targetClassMID,
      final ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetailsBuilder) {
    final String contextPath = getApplicationContextPath();
    final Document document = XmlUtils.readXml(fileManager.getInputStream(contextPath));
    final Element root = document.getDocumentElement();

    // Make a builder for the created method's body
    final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();

    // Collect the types and names of the created method's parameters
    final PairList<AnnotatedJavaType, JavaSymbolName> parameters =
        new PairList<AnnotatedJavaType, JavaSymbolName>();

    if (getSimpleMailMessageBean(root) == null) {
      // There's no SimpleMailMessage bean; use a local variable
      bodyBuilder.appendFormalLine(
          "org.springframework.mail.SimpleMailMessage "
              + LOCAL_MESSAGE_VARIABLE
              + " = new org.springframework.mail.SimpleMailMessage();");
      // Set the from address
      parameters.add(STRING, new JavaSymbolName("mailFrom"));
      bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setFrom(mailFrom);");
      // Set the subject
      parameters.add(STRING, new JavaSymbolName("subject"));
      bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setSubject(subject);");
    } else {
      // A SimpleMailMessage bean exists; auto-wire it into the entity and use it as a template
      final List<AnnotationMetadataBuilder> smmAnnotations =
          Arrays.asList(new AnnotationMetadataBuilder(AUTOWIRED));
      final FieldMetadataBuilder smmFieldBuilder =
          new FieldMetadataBuilder(
              targetClassMID,
              PRIVATE_TRANSIENT,
              smmAnnotations,
              new JavaSymbolName(TEMPLATE_MESSAGE_FIELD),
              SIMPLE_MAIL_MESSAGE);
      classOrInterfaceTypeDetailsBuilder.addField(smmFieldBuilder.build());
      // Use the injected bean as a template (for thread safety)
      bodyBuilder.appendFormalLine(
          "org.springframework.mail.SimpleMailMessage "
              + LOCAL_MESSAGE_VARIABLE
              + " = new org.springframework.mail.SimpleMailMessage("
              + TEMPLATE_MESSAGE_FIELD
              + ");");
    }

    // Set the to address
    parameters.add(STRING, new JavaSymbolName("mailTo"));
    bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setTo(mailTo);");

    // Set the message body
    parameters.add(STRING, new JavaSymbolName("message"));
    bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setText(message);");

    bodyBuilder.newLine();
    bodyBuilder.appendFormalLine(mailSenderName + ".send(" + LOCAL_MESSAGE_VARIABLE + ");");

    final MethodMetadataBuilder methodBuilder =
        new MethodMetadataBuilder(
            targetClassMID,
            Modifier.PUBLIC,
            new JavaSymbolName("sendMessage"),
            JavaType.VOID_PRIMITIVE,
            parameters.getKeys(),
            parameters.getValues(),
            bodyBuilder);

    if (async) {
      if (DomUtils.findFirstElementByName("task:annotation-driven", root) == null) {
        // Add asynchronous email support to the application
        if (!StringUtils.hasText(root.getAttribute("xmlns:task"))) {
          // Add the "task" namespace to the Spring config file
          root.setAttribute("xmlns:task", SPRING_TASK_NS);
          root.setAttribute(
              "xsi:schemaLocation",
              root.getAttribute("xsi:schemaLocation")
                  + "  "
                  + SPRING_TASK_NS
                  + " "
                  + SPRING_TASK_XSD);
        }
        root.appendChild(
            new XmlElementBuilder("task:annotation-driven", document)
                .addAttribute("executor", "asyncExecutor")
                .addAttribute("mode", "aspectj")
                .build());
        root.appendChild(
            new XmlElementBuilder("task:executor", document)
                .addAttribute("id", "asyncExecutor")
                .addAttribute("pool-size", "${executor.poolSize}")
                .build());
        // Write out the new Spring config file
        fileManager.createOrUpdateTextFileIfRequired(
            contextPath, XmlUtils.nodeToString(document), false);
        // Update the email properties file
        propFileOperations.addPropertyIfNotExists(
            Path.SPRING_CONFIG_ROOT, "email.properties", "executor.poolSize", "10", true);
      }
      methodBuilder.addAnnotation(new AnnotationMetadataBuilder(ASYNC));
    }
    return methodBuilder.build();
  }
  @Override
  public void view(
      final JavaType type,
      final String viewName,
      final String identifier,
      final JavaSymbolName fieldName,
      final Dimension height,
      final Dimension width) {

    final ClassOrInterfaceTypeDetails typeDetails = typeLocationService.getTypeDetails(type);
    Validate.notNull(typeDetails, "The type specified, '" + type + "'doesn't exist");

    final JavaType viewType =
        new JavaType(viewName.contains(".") ? viewName : WIDGET_PACKAGE + "." + viewName);

    final String layout =
        RequestFactoryUtils.getStringAnnotationValue(typeDetails, ROO_ACTIVITY, "value", "");
    if (!StringUtils.isEmpty(layout)) {
      final DocumentBuilder builder = newDocumentBuilder();
      final String layoutPath =
          pathResolver.getFocusedIdentifier(Path.ROOT, LAYOUT_PATH + SEP + layout + XML_EXTENSION);

      InputStream inputStream = null;
      Document document = null;
      try {
        inputStream = fileManager.getInputStream(layoutPath);
        document = builder.parse(inputStream);
      } catch (final Exception e) {
        LOGGER.severe("Error reading layout XML: " + e.getMessage());
      } finally {
        IOUtils.closeQuietly(inputStream);
      }

      if (document != null) {
        final Element root = document.getDocumentElement();

        final Element viewElem = document.createElement(viewType.getSimpleTypeName());
        final String id = StringUtils.isEmpty(identifier) ? fieldName.getSymbolName() : identifier;
        viewElem.setAttribute("android:id", ID_PREFIX + id);
        viewElem.setAttribute("android:layout_height", height.value());
        viewElem.setAttribute("android:layout_width", width.value());
        root.appendChild(viewElem);

        fileManager.createOrUpdateTextFileIfRequired(
            layoutPath, XmlUtils.nodeToString(document), true);
      }
    }

    final String physicalTypeIdentifier = typeDetails.getDeclaredByMetadataId();

    final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
    final AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder(ROO_VIEW);
    if (!StringUtils.isEmpty(identifier)) {
      annotationBuilder.addStringAttribute("value", identifier);
    }
    annotations.add(annotationBuilder);

    final FieldMetadataBuilder fieldBuilder =
        new FieldMetadataBuilder(physicalTypeIdentifier, 0, annotations, fieldName, viewType);
    typeManagementService.addField(fieldBuilder.build());
  }