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()); }
@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()); } } }
@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(); } }
public void addDataToField(final FieldMetadata replacement, final CustomData customData) { // If the MIDs don't match then the proposed can't be a replacement if (!replacement.getDeclaredByMetadataId().equals(getDeclaredByMetadataId())) { return; } for (FieldMetadataBuilder existingField : getDeclaredFields()) { if (existingField.getFieldName().equals(replacement.getFieldName())) { for (Object key : customData.keySet()) { existingField.putCustomData(key, customData.get(key)); } break; } } }
/** * 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); } }
/** * 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()); }