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.graph; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; 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.BeanInfoUtils; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; 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.classpath.scanner.MemberDetails; import org.springframework.roo.metadata.MetadataIdentificationUtils; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.model.SpringJavaType; import org.springframework.roo.project.LogicalPath; /** * Creates metadata for domain entity ITDs (annotated with {@link NodeEntity}. * Based on * org.springframework.roo.addon.layers.repository.mongo.MongoEntityMetadata. * * @author jccastrejon * */ public class NodeEntityMetadata extends AbstractItdTypeDetailsProvidingMetadataItem { private static final String PROVIDES_TYPE_STRING = NodeEntityMetadata.class.getName(); private static final String PROVIDES_TYPE = MetadataIdentificationUtils.create(PROVIDES_TYPE_STRING); public static String createIdentifier(final JavaType javaType, final LogicalPath path) { return PhysicalTypeIdentifierNamingUtils.createIdentifier(PROVIDES_TYPE_STRING, javaType, path); } public static JavaType getJavaType(final String metadataIdentificationString) { return PhysicalTypeIdentifierNamingUtils.getJavaType(PROVIDES_TYPE_STRING, metadataIdentificationString); } public static String getMetadataIdentiferType() { return PROVIDES_TYPE; } public static LogicalPath getPath(final String metadataIdentificationString) { return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING, metadataIdentificationString); } public static boolean isValid(final String metadataIdentificationString) { return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING, metadataIdentificationString); } private MemberDetails memberDetails; private NodeEntityMetadata parent; private JavaType idType; private FieldMetadata idField; /** * Constructor * * @param identifier * the identifier for this item of metadata (required) * @param aspectName * the Java type of the ITD (required) * @param governorPhysicalTypeMetadata * the governor, which is expected to contain a * {@link ClassOrInterfaceTypeDetails} (required) * @param parent * @param idType * the type of the entity's identifier field (required) * @param governorMemberDetails * the member details of the entity */ public NodeEntityMetadata(final String identifier, final JavaType aspectName, final PhysicalTypeMetadata governorPhysicalTypeMetadata, NodeEntityMetadata parent, final JavaType idType, final MemberDetails memberDetails) { super(identifier, aspectName, governorPhysicalTypeMetadata); Validate.notNull(idType, "Id type required"); Validate.notNull(memberDetails, "Entity MemberDetails required"); if (!isValid()) { return; } this.memberDetails = memberDetails; this.parent = parent; this.idType = idType; builder.addAnnotation(getTypeAnnotation(SpringJavaType.PERSISTENT)); idField = getIdentifierField(); if (idField != null) { builder.addField(idField); builder.addMethod(getIdentifierAccessor()); builder.addMethod(getIdentifierMutator()); } // Build the ITD itdTypeDetails = builder.build(); } private MethodMetadataBuilder getIdentifierAccessor() { if (parent != null) { final MethodMetadataBuilder parentIdAccessor = parent.getIdentifierAccessor(); if (parentIdAccessor != null && parentIdAccessor.getReturnType().equals(idType)) { return parentIdAccessor; } } JavaSymbolName requiredAccessorName = BeanInfoUtils.getAccessorMethodName(idField); // See if the user provided the field if (!getId().equals(idField.getDeclaredByMetadataId())) { // Locate an existing accessor final MethodMetadata method = memberDetails.getMethod(requiredAccessorName, new ArrayList<JavaType>()); if (method != null) { if (Modifier.isPublic(method.getModifier())) { // Method exists and is public so return it return new MethodMetadataBuilder(method); } // Method is not public so make the required accessor name // unique requiredAccessorName = new JavaSymbolName(requiredAccessorName.getSymbolName() + "_"); } } // We declared the field in this ITD, so produce a public accessor for // it final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine("return this." + idField.getFieldName().getSymbolName() + ";"); return new MethodMetadataBuilder(getId(), Modifier.PUBLIC, requiredAccessorName, idField.getFieldType(), bodyBuilder); } private FieldMetadata getIdentifierField() { if (parent != null) { final FieldMetadata parentIdField = parent.getIdentifierField(); if (parentIdField.getFieldType().equals(idType)) { return parentIdField; } } // Try to locate an existing field with DATA_ID final List<FieldMetadata> idFields = governorTypeDetails.getFieldsWithAnnotation(SpringJavaType.DATA_ID); if (!idFields.isEmpty()) { return idFields.get(0); } final JavaSymbolName idFieldName = governorTypeDetails.getUniqueFieldName("id"); final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(getId(), Modifier.PRIVATE, idFieldName, idType, null); fieldBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.DATA_ID)); return fieldBuilder.build(); } private MethodMetadataBuilder getIdentifierMutator() { if (parent != null) { final MethodMetadataBuilder parentIdMutator = parent.getIdentifierMutator(); if (parentIdMutator != null && parentIdMutator.getParameterTypes().get(0).getJavaType().equals(idType)) { return parentIdMutator; } } JavaSymbolName requiredMutatorName = BeanInfoUtils.getMutatorMethodName(idField); final List<JavaType> parameterTypes = Arrays.asList(idField.getFieldType()); final List<JavaSymbolName> parameterNames = Arrays.asList(new JavaSymbolName("id")); // See if the user provided the field if (!getId().equals(idField.getDeclaredByMetadataId())) { // Locate an existing mutator final MethodMetadata method = memberDetails.getMethod(requiredMutatorName, parameterTypes); if (method != null) { if (Modifier.isPublic(method.getModifier())) { // Method exists and is public so return it return new MethodMetadataBuilder(method); } // Method is not public so make the required mutator name unique requiredMutatorName = new JavaSymbolName(requiredMutatorName.getSymbolName() + "_"); } } // We declared the field in this ITD, so produce a public mutator for it final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine("this." + idField.getFieldName().getSymbolName() + " = id;"); return new MethodMetadataBuilder(getId(), Modifier.PUBLIC, requiredMutatorName, JavaType.VOID_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterTypes), parameterNames, bodyBuilder); } @Override 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(); } }