Java tutorial
/* * Copyright 2012 jccastrejon * * This file is part of Model2Roo. * * Model2Roo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Model2Roo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with Model2Roo. If not, see <http://www.gnu.org/licenses/>. */ package fr.imag.model2roo.addon.polyglot; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.builder.ToStringBuilder; import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils; import org.springframework.roo.classpath.PhysicalTypeMetadata; import org.springframework.roo.classpath.details.FieldMetadata; import org.springframework.roo.classpath.details.FieldMetadataBuilder; import org.springframework.roo.classpath.details.MethodMetadata; import org.springframework.roo.classpath.details.MethodMetadataBuilder; import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem; import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder; import org.springframework.roo.metadata.MetadataIdentificationUtils; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.project.LogicalPath; /** * This type produces metadata for a new ITD. It uses an {@link ItdTypeDetailsBuilder} provided by * {@link AbstractItdTypeDetailsProvidingMetadataItem} to register a field in the ITD and a new method. * * @since 1.1.0 */ public class PolyglotMetadata extends AbstractItdTypeDetailsProvidingMetadataItem { // Constants private static final String PROVIDES_TYPE_STRING = PolyglotMetadata.class.getName(); private static final String PROVIDES_TYPE = MetadataIdentificationUtils.create(PROVIDES_TYPE_STRING); public static final String getMetadataIdentiferType() { return PROVIDES_TYPE; } public static final String createIdentifier(JavaType javaType, LogicalPath path) { return PhysicalTypeIdentifierNamingUtils.createIdentifier(PROVIDES_TYPE_STRING, javaType, path); } public static final JavaType getJavaType(String metadataIdentificationString) { return PhysicalTypeIdentifierNamingUtils.getJavaType(PROVIDES_TYPE_STRING, metadataIdentificationString); } public static final LogicalPath getPath(String metadataIdentificationString) { return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING, metadataIdentificationString); } public static boolean isValid(String metadataIdentificationString) { return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING, metadataIdentificationString); } public PolyglotMetadata(String identifier, JavaType aspectName, PhysicalTypeMetadata governorPhysicalTypeMetadata) { super(identifier, aspectName, governorPhysicalTypeMetadata); Validate.isTrue(isValid(identifier), "Metadata identification string '" + identifier + "' does not appear to be a valid"); // Adding a new sample field definition builder.addField(getSampleField()); // Adding a new sample method definition builder.addMethod(getSampleMethod()); // Create a representation of the desired output ITD itdTypeDetails = builder.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 } private MethodMetadata getSampleMethod() { // Specify the desired method name JavaSymbolName methodName = new JavaSymbolName("sampleMethod"); // Check if a method with the same signature already exists in the target type final MethodMetadata method = methodExists(methodName, new ArrayList<AnnotatedJavaType>()); if (method != null) { // If it already exists, just return the method and omit its generation via the ITD return method; } // Define method annotations (none in this case) List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(); // Define method throws types (none in this case) List<JavaType> throwsTypes = new ArrayList<JavaType>(); // Define method parameter types (none in this case) List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>(); // Define method parameter names (none in this case) List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>(); // Create the method body InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine("System.out.println(\"Hello World\");"); // Use the MethodMetadataBuilder for easy creation of MethodMetadata MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE, parameterTypes, parameterNames, bodyBuilder); methodBuilder.setAnnotations(annotations); methodBuilder.setThrowsTypes(throwsTypes); return methodBuilder.build(); // Build and return a MethodMetadata instance } private MethodMetadata methodExists(JavaSymbolName methodName, List<AnnotatedJavaType> paramTypes) { // We have no access to method parameter information, so we scan by name alone and treat any match as authoritative // We do not scan the superclass, as the caller is expected to know we'll only scan the current class for (MethodMetadata method : governorTypeDetails.getDeclaredMethods()) { if (method.getMethodName().equals(methodName) && method.getParameterTypes().equals(paramTypes)) { // Found a method of the expected name; we won't check method parameters though return method; } } return null; } // Typically, no changes are required beyond this point public String toString() { final ToStringBuilder builder = new ToStringBuilder(this); builder.append("identifier", getId()); builder.append("valid", valid); builder.append("aspectName", aspectName); builder.append("destinationType", destination); builder.append("governor", governorPhysicalTypeMetadata.getId()); builder.append("itdTypeDetails", itdTypeDetails); return builder.toString(); } }