/* * gvNIX is an open source tool for rapid application development (RAD). * Copyright (C) 2010 Generalitat Valenciana * * This program 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 (at your option) any later * version. * * This program 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 * this program. If not, see <http://www.gnu.org/licenses/>. */ package org.gvnix.service.roo.addon.addon; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.gvnix.service.roo.addon.addon.ws.export.WSExportWsdlConfigService.GvNIXAnnotationType; import org.gvnix.service.roo.addon.annotations.GvNIXWebMethod; import org.springframework.roo.classpath.PhysicalTypeCategory; import org.springframework.roo.classpath.PhysicalTypeDetails; import org.springframework.roo.classpath.PhysicalTypeIdentifier; import org.springframework.roo.classpath.PhysicalTypeMetadata; import org.springframework.roo.classpath.TypeLocationService; import org.springframework.roo.classpath.TypeManagementService; import org.springframework.roo.classpath.TypeParsingService; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder; import org.springframework.roo.classpath.details.ConstructorMetadata; import org.springframework.roo.classpath.details.FieldMetadata; import org.springframework.roo.classpath.details.IdentifiableAnnotatedJavaStructure; import org.springframework.roo.classpath.details.MemberHoldingTypeDetails; 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.AnnotationAttributeValue; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder; import org.springframework.roo.classpath.scanner.MemberDetails; import org.springframework.roo.classpath.scanner.MemberDetailsScanner; import org.springframework.roo.metadata.MetadataService; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.process.manager.FileManager; import org.springframework.roo.project.LogicalPath; import org.springframework.roo.project.Path; import org.springframework.roo.project.ProjectOperations; /** * @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a * href="http://www.dgti.gva.es">General Directorate for Information * Technologies (DGTI)</a> */ @Component @Service public class JavaParserServiceImpl implements JavaParserService { @Reference private MetadataService metadataService; @Reference private TypeManagementService typeManagementService; @Reference private FileManager fileManager; @Reference private ProjectOperations projectOperations; @Reference private TypeLocationService typeLocationService; @Reference protected MemberDetailsScanner memberDetailsScanner; @Reference protected TypeParsingService typeParsingService; /** * {@inheritDoc} * <p> * Adds @org.springframework.stereotype.Service annotation to the class. * </p> */ public void createServiceClass(JavaType serviceClass) { // Service class String declaredByMetadataId = PhysicalTypeIdentifier.createIdentifier( serviceClass, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")); // Service annotations List<AnnotationMetadata> serviceAnnotations = new ArrayList<AnnotationMetadata>(); serviceAnnotations.add(new AnnotationMetadataBuilder(new JavaType( "org.springframework.stereotype.Service"), new ArrayList<AnnotationAttributeValue<?>>()).build()); ClassOrInterfaceTypeDetailsBuilder serviceDetails = new ClassOrInterfaceTypeDetailsBuilder( declaredByMetadataId, Modifier.PUBLIC, serviceClass, PhysicalTypeCategory.CLASS); for (AnnotationMetadata annotationMetadata : serviceAnnotations) { serviceDetails.addAnnotation(annotationMetadata); } typeManagementService.createOrUpdateTypeOnDisk(serviceDetails.build()); } /** * {@inheritDoc} * <p> * Only creates the class if not exists in project. * </p> */ public void createGvNixWebServiceClass(JavaType type, List<AnnotationMetadata> annots, GvNIXAnnotationType gvNixAnnot, List<FieldMetadata> fields, List<MethodMetadata> methods, List<ConstructorMetadata> constrs, List<JavaType> exts, PhysicalTypeCategory physicalType, List<JavaSymbolName> enumConsts) { // Metadata Id. String id = PhysicalTypeIdentifier.createIdentifier(type, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")); // Determine the canonical filename String physicalPath = typeLocationService .getPhysicalTypeCanonicalPath(id); // Check the file doesn't already exist if (!fileManager.exists(physicalPath)) { if (!physicalType.equals(PhysicalTypeCategory.ENUMERATION)) { enumConsts = null; } // Create class ClassOrInterfaceTypeDetailsBuilder typeDetails = new ClassOrInterfaceTypeDetailsBuilder( id, Modifier.PUBLIC, type, physicalType); for (AnnotationMetadata annotationMetadata : annots) { typeDetails.addAnnotation(annotationMetadata); } for (FieldMetadata field : fields) { typeDetails.addField(field); } for (ConstructorMetadata constr : constrs) { typeDetails.addConstructor(constr); } for (MethodMetadata method : methods) { typeDetails.addMethod(method); } for (JavaType ext : exts) { typeDetails.addExtendsTypes(ext); } if (enumConsts != null) { for (JavaSymbolName enumConst : enumConsts) { typeDetails.addEnumConstant(enumConst); } } typeManagementService.createOrUpdateTypeOnDisk(typeDetails.build()); } } /** * {@inheritDoc} * <p> * Updates the class with the new method created with selected attributes. * </p> */ public void createMethod(JavaSymbolName methodName, JavaType returnType, JavaType targetType, int modifier, List<JavaType> throwsTypes, List<AnnotationMetadata> annotationList, List<AnnotatedJavaType> paramTypes, List<JavaSymbolName> paramNames, String body) { Validate.notNull(paramTypes, "Param type mustn't be null"); Validate.notNull(paramNames, "Param name mustn't be null"); // MetadataID String targetId = PhysicalTypeIdentifier.createIdentifier(targetType, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")); // Obtain the physical type and itd mutable details PhysicalTypeMetadata ptm = (PhysicalTypeMetadata) metadataService .get(targetId); Validate.notNull(ptm, "Java source class doesn't exists."); PhysicalTypeDetails ptd = ptm.getMemberHoldingTypeDetails(); Validate.notNull(ptd, "Java source code details unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(targetId)); Validate.isInstanceOf(ClassOrInterfaceTypeDetails.class, ptd, "Java source code is immutable for type " + PhysicalTypeIdentifier.getFriendlyName(targetId)); ClassOrInterfaceTypeDetails mutableTypeDetails = (ClassOrInterfaceTypeDetails) ptd; // create method InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine(body); MethodMetadataBuilder operationMetadata = new MethodMetadataBuilder( targetId, modifier, methodName, (returnType == null ? JavaType.VOID_PRIMITIVE : returnType), paramTypes, paramNames, bodyBuilder); for (AnnotationMetadata annotationMetadata : annotationList) { operationMetadata.addAnnotation(annotationMetadata); } for (JavaType javaType : throwsTypes) { operationMetadata.addThrowsType(javaType); } ClassOrInterfaceTypeDetailsBuilder mutableTypeDetailsBuilder = new ClassOrInterfaceTypeDetailsBuilder( mutableTypeDetails); mutableTypeDetailsBuilder.addMethod(operationMetadata.build()); typeManagementService .createOrUpdateTypeOnDisk(mutableTypeDetailsBuilder.build()); } /** * {@inheritDoc} * <p> * Adds Web Service annotation to selected method. * </p> */ public void updateMethodAnnotations(JavaType className, JavaSymbolName method, List<AnnotationMetadata> annotationMetadataUpdateList, List<AnnotatedJavaType> annotationWebParamMetadataList) { // MetadataID String targetId = PhysicalTypeIdentifier.createIdentifier(className, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")); // Obtain the physical type and itd mutable details PhysicalTypeMetadata ptm = (PhysicalTypeMetadata) metadataService .get(targetId); PhysicalTypeDetails ptd = ptm.getMemberHoldingTypeDetails(); Validate.notNull(ptd, "Java source code details unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(targetId)); Validate.isInstanceOf(ClassOrInterfaceTypeDetails.class, ptd, "Java source code is immutable for type " + PhysicalTypeIdentifier.getFriendlyName(targetId)); ClassOrInterfaceTypeDetails mutableTypeDetails = (ClassOrInterfaceTypeDetails) ptd; List<MethodMetadata> updatedMethodList = new ArrayList<MethodMetadata>(); // Add to list required method and all methods in Java // Search one method in all (Java and AspectJ) updatedMethodList.addAll(searchMethodInAll(className, method, annotationMetadataUpdateList, annotationWebParamMetadataList, targetId)); // Search methods in Java, excepts one method updatedMethodList.addAll(searchMethodsInJava(method, targetId, mutableTypeDetails)); ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetails = createTypeDetails( mutableTypeDetails, updatedMethodList); // Add old class imports into new class to avoid undefined imports // Example: Not included HashSet import when exporting method in // petclinic Owner classOrInterfaceTypeDetails.setRegisteredImports(mutableTypeDetails .getRegisteredImports()); // Updates the class in file system. updateClass(classOrInterfaceTypeDetails.build()); } /** * Create a class or interface from java parser and add methods. * * @param mutableTypeDetails * @param updatedMethodList * @return */ protected ClassOrInterfaceTypeDetailsBuilder createTypeDetails( ClassOrInterfaceTypeDetails mutableTypeDetails, List<MethodMetadata> updatedMethodList) { List<ConstructorMetadata> contructorList = new ArrayList<ConstructorMetadata>(); contructorList.addAll(mutableTypeDetails.getDeclaredConstructors()); List<FieldMetadata> fieldMetadataList = new ArrayList<FieldMetadata>(); fieldMetadataList.addAll(mutableTypeDetails.getDeclaredFields()); List<AnnotationMetadata> annotationMetadataList = new ArrayList<AnnotationMetadata>(); annotationMetadataList.addAll(mutableTypeDetails.getAnnotations()); // Replicates the values from the original class ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetails = new ClassOrInterfaceTypeDetailsBuilder( mutableTypeDetails.getDeclaredByMetadataId(), mutableTypeDetails.getModifier(), mutableTypeDetails.getName(), mutableTypeDetails.getPhysicalTypeCategory()); for (AnnotationMetadata annotationMetadata : annotationMetadataList) { classOrInterfaceTypeDetails.addAnnotation(annotationMetadata); } for (FieldMetadata fieldMetadata : fieldMetadataList) { classOrInterfaceTypeDetails.addField(fieldMetadata); } for (ConstructorMetadata constructorMetadata : contructorList) { classOrInterfaceTypeDetails.addConstructor(constructorMetadata); } for (MethodMetadata methodMetadata : updatedMethodList) { classOrInterfaceTypeDetails.addMethod(methodMetadata); } for (JavaType declaredClass : mutableTypeDetails.getExtendsTypes()) { classOrInterfaceTypeDetails.addExtendsTypes(declaredClass); } for (JavaType declaredClass : mutableTypeDetails.getImplementsTypes()) { classOrInterfaceTypeDetails.addImplementsType(declaredClass); } if (mutableTypeDetails.getPhysicalTypeCategory() == PhysicalTypeCategory.ENUMERATION) { for (JavaSymbolName enumConstant : mutableTypeDetails .getEnumConstants()) { classOrInterfaceTypeDetails.addEnumConstant(enumConstant); } } return classOrInterfaceTypeDetails; } /** * Search method in Java. * * @param methodName Method name to search * @param targetId New method destination identifier * @param mutableTypeDetails Type to search methods in * @return Methods list */ protected List<MethodMetadata> searchMethodsInJava( JavaSymbolName methodName, String targetId, ClassOrInterfaceTypeDetails mutableTypeDetails) { List<MethodMetadata> methods = new ArrayList<MethodMetadata>(); for (MethodMetadata method : mutableTypeDetails.getDeclaredMethods()) { if (method.getMethodName().toString() .compareTo(methodName.toString()) != 0) { InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder.appendFormalLine(method.getBody()); MethodMetadataBuilder methodMetadataBuilder = new MethodMetadataBuilder( targetId, method.getModifier(), method.getMethodName(), method.getReturnType(), method.getParameterTypes(), method.getParameterNames(), bodyBuilder); for (AnnotationMetadata annotationMetadata : method .getAnnotations()) { methodMetadataBuilder.addAnnotation(annotationMetadata); } for (JavaType javaType : method.getThrowsTypes()) { methodMetadataBuilder.addThrowsType(javaType); } MethodMetadata operationMetadata = methodMetadataBuilder .build(); methods.add(operationMetadata); } } return methods; } /** * Search method in all (Java and AspectJ). * <p> * Add into method and into method params required web service annotations. * </p> * * @param className Class name to seach * @param method Method name to search * @param annotationMetadataUpdateList Method annotation list * @param annotationWebParamMetadataList Method params annotation list * @param targetId New method destination identifier * @return Methods list */ protected List<MethodMetadata> searchMethodInAll(JavaType className, JavaSymbolName method, List<AnnotationMetadata> annotationMetadataUpdateList, List<AnnotatedJavaType> annotationWebParamMetadataList, String targetId) { List<MethodMetadata> methods = new ArrayList<MethodMetadata>(); List<AnnotationMetadata> methodAnnotationList = new ArrayList<AnnotationMetadata>(); MethodMetadata javaParserMethodMetadata; MethodMetadata operationMetadata; List<? extends MethodMetadata> allMethodsList = getMethodsInAll(className); for (MethodMetadata methodMetadata : allMethodsList) { javaParserMethodMetadata = methodMetadata; // Only export methods in this entity: no parent class methods check // Example: Duplicated method when export toString in Owner boolean equal = isMetadataId(targetId, methodMetadata); if (methodMetadata.getMethodName().toString() .compareTo(method.toString()) == 0 && equal) { Validate.isTrue( !isAnnotationIntroducedInMethod( GvNIXWebMethod.class.getName(), methodMetadata), "The method '" + method.toString() + "' has been annotated with '@" + GvNIXWebMethod.class.getName() + "' before."); methodAnnotationList.addAll(javaParserMethodMetadata .getAnnotations()); methodAnnotationList.addAll(annotationMetadataUpdateList); InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder .appendFormalLine(javaParserMethodMetadata.getBody()); MethodMetadataBuilder methodMetadataBuilder = new MethodMetadataBuilder( targetId, javaParserMethodMetadata.getModifier(), javaParserMethodMetadata.getMethodName(), javaParserMethodMetadata.getReturnType(), annotationWebParamMetadataList, javaParserMethodMetadata.getParameterNames(), bodyBuilder); for (AnnotationMetadata annotationMetadata : methodAnnotationList) { methodMetadataBuilder.addAnnotation(annotationMetadata); } for (JavaType javaType : javaParserMethodMetadata .getThrowsTypes()) { methodMetadataBuilder.addThrowsType(javaType); } operationMetadata = methodMetadataBuilder.build(); methods.add(operationMetadata); } } return methods; } /** * {@inheritDoc} **/ public boolean isMetadataId(String id, IdentifiableAnnotatedJavaStructure metadata) { return metadata .getDeclaredByMetadataId() .substring( metadata.getDeclaredByMetadataId().lastIndexOf("?") + 1) .equals(id.substring(id.lastIndexOf("?") + 1)); } /** * {@inheritDoc} * <p> * </p> */ @Deprecated public void updateMethodParameters(JavaType className, JavaSymbolName method, String paramName, JavaType paramType) { // TODO: Probar 'MethodDeclaration' ya que permite la creación con // javadoc. // MetadataID String targetId = PhysicalTypeIdentifier.createIdentifier(className, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")); // Obtain the physical type and itd mutable details PhysicalTypeMetadata ptm = (PhysicalTypeMetadata) metadataService .get(targetId); PhysicalTypeDetails ptd = ptm.getMemberHoldingTypeDetails(); Validate.notNull(ptd, "Java source code details unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(targetId)); Validate.isInstanceOf(ClassOrInterfaceTypeDetails.class, ptd, "Java source code is immutable for type " + PhysicalTypeIdentifier.getFriendlyName(targetId)); ClassOrInterfaceTypeDetails mutableTypeDetails = (ClassOrInterfaceTypeDetails) ptd; // Update method List<? extends MethodMetadata> methodsList = mutableTypeDetails .getDeclaredMethods(); // Create param type. AnnotatedJavaType annotatedJavaType = new AnnotatedJavaType(paramType, new ArrayList<AnnotationMetadata>()); // Create param name. JavaSymbolName parameterName = new JavaSymbolName(paramName); MethodMetadata javaParserMethodMetadata; List<MethodMetadata> updatedMethodList = new ArrayList<MethodMetadata>(); List<AnnotatedJavaType> parameterTypelist = new ArrayList<AnnotatedJavaType>(); List<JavaSymbolName> parameterNamelist = new ArrayList<JavaSymbolName>(); MethodMetadata operationMetadata; for (MethodMetadata methodMetadata : methodsList) { javaParserMethodMetadata = (MethodMetadata) methodMetadata; if (methodMetadata.getMethodName().toString() .compareTo(method.toString()) == 0) { Validate.isTrue(!javaParserMethodMetadata.getParameterNames() .contains(parameterName), "There couldn't be two parameters with same name: '" + parameterName + "' in the method " + methodMetadata.getMethodName()); for (JavaSymbolName tmpParameterName : javaParserMethodMetadata .getParameterNames()) { parameterNamelist.add(tmpParameterName); } parameterNamelist.add(parameterName); for (AnnotatedJavaType tmpParameterType : javaParserMethodMetadata .getParameterTypes()) { parameterTypelist.add(tmpParameterType); } parameterTypelist.add(annotatedJavaType); InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder .appendFormalLine(javaParserMethodMetadata.getBody()); MethodMetadataBuilder methodMetadataBuilder = new MethodMetadataBuilder( targetId, javaParserMethodMetadata.getModifier(), javaParserMethodMetadata.getMethodName(), javaParserMethodMetadata.getReturnType(), parameterTypelist, parameterNamelist, bodyBuilder); for (AnnotationMetadata annotationMetadata : javaParserMethodMetadata .getAnnotations()) { methodMetadataBuilder.addAnnotation(annotationMetadata); } for (JavaType javaType : javaParserMethodMetadata .getThrowsTypes()) { methodMetadataBuilder.addThrowsType(javaType); } operationMetadata = methodMetadataBuilder.build(); } else { InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); bodyBuilder .appendFormalLine(javaParserMethodMetadata.getBody()); MethodMetadataBuilder methodMetadataBuilder = new MethodMetadataBuilder( targetId, javaParserMethodMetadata.getModifier(), javaParserMethodMetadata.getMethodName(), javaParserMethodMetadata.getReturnType(), javaParserMethodMetadata.getParameterTypes(), javaParserMethodMetadata.getParameterNames(), bodyBuilder); for (AnnotationMetadata annotationMetadata : javaParserMethodMetadata .getAnnotations()) { methodMetadataBuilder.addAnnotation(annotationMetadata); } for (JavaType javaType : javaParserMethodMetadata .getThrowsTypes()) { methodMetadataBuilder.addThrowsType(javaType); } operationMetadata = methodMetadataBuilder.build(); } updatedMethodList.add(operationMetadata); } ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetails = createTypeDetails( mutableTypeDetails, updatedMethodList); classOrInterfaceTypeDetails .addInnerType(new ClassOrInterfaceTypeDetailsBuilder( mutableTypeDetails.getSuperclass())); // Updates the class in file system. updateClass(classOrInterfaceTypeDetails.build()); } /** * {@inheritDoc} * <p> * return true if exists an annotation with the same name in method. * </p> */ public boolean isAnnotationIntroducedInMethod(String annotation, MethodMetadata methodMetadata) { List<AnnotationMetadata> annotationMethodList = methodMetadata .getAnnotations(); for (AnnotationMetadata annotationMetadata : annotationMethodList) { if (annotationMetadata.getAnnotationType() .getFullyQualifiedTypeName().compareTo(annotation) == 0) { return true; } } return false; } /** * {@inheritDoc} * <p> * Checks if annotation is defined in as DeclaredType. * </p> */ public boolean isAnnotationIntroduced(String annotation, ClassOrInterfaceTypeDetails governorTypeDetails) { JavaType javaType = new JavaType(annotation); boolean isDefined = false; for (AnnotationMetadata annotationMetadata : governorTypeDetails .getAnnotations()) { isDefined = annotationMetadata.getAnnotationType().equals(javaType); if (isDefined) { return isDefined; } } return isDefined; } public AnnotationMetadata getAnnotation(String annotation, ClassOrInterfaceTypeDetails governorTypeDetails) { JavaType javaType = new JavaType(annotation); for (AnnotationMetadata annotationMetadata : governorTypeDetails .getAnnotations()) { if (annotationMetadata.getAnnotationType().equals(javaType)) { return annotationMetadata; } } return null; } /** * {@inheritDoc} * <p> * Search the method by name in class. * </p> */ public MethodMetadata getMethodByNameInClass(JavaType serviceClass, JavaSymbolName methodName) { // Load class details. If class not found an exception will be raised. ClassOrInterfaceTypeDetails tmpServiceDetails = typeLocationService .getTypeDetails(serviceClass); // Checks if it's mutable Validate.isInstanceOf(ClassOrInterfaceTypeDetails.class, tmpServiceDetails, "Can't modify " + tmpServiceDetails.getName()); ClassOrInterfaceTypeDetails serviceDetails = (ClassOrInterfaceTypeDetails) tmpServiceDetails; List<? extends MethodMetadata> methodList = serviceDetails .getDeclaredMethods(); for (MethodMetadata methodMetadata : methodList) { if (methodMetadata.getMethodName().equals(methodName)) { return methodMetadata; } } return null; } /** * {@inheritDoc} * <p> * Search the method by name in class and related AJs. * </p> */ public MethodMetadata getMethodByNameInAll(JavaType serviceClass, JavaSymbolName methodName) { MethodMetadata method = null; Iterator<MemberHoldingTypeDetails> members = getMemberDetails( serviceClass).iterator(); while (method == null && members.hasNext()) { @SuppressWarnings("unchecked") List<MethodMetadata> methods = (List<MethodMetadata>) members .next().getDeclaredMethods(); Iterator<MethodMetadata> methodsIter = methods.iterator(); while (method == null && methodsIter.hasNext()) { MethodMetadata tmpMethod = methodsIter.next(); if (tmpMethod.getMethodName().getSymbolName() .equals(methodName.getSymbolName())) { method = tmpMethod; } } } return method; } /** * {@inheritDoc} * <p> * Search all methods in class and related AJs. * </p> */ public List<MethodMetadata> getMethodsInAll(JavaType name) { List<MethodMetadata> methods = new ArrayList<MethodMetadata>(); for (MemberHoldingTypeDetails member : getMemberDetails(name)) { methods.addAll(member.getDeclaredMethods()); } return methods; } /** * {@inheritDoc} * <p> * Search all fields in class and related AJs. * </p> */ public List<FieldMetadata> getFieldsInAll(JavaType name) { List<FieldMetadata> methods = new ArrayList<FieldMetadata>(); for (MemberHoldingTypeDetails member : getMemberDetails(name)) { methods.addAll(member.getDeclaredFields()); } return methods; } /** * {@inheritDoc} */ public FieldMetadata getFieldByNameInAll(JavaType type, JavaSymbolName name) { FieldMetadata field = null; Iterator<MemberHoldingTypeDetails> members = getMemberDetails(type) .iterator(); while (field == null && members.hasNext()) { @SuppressWarnings("unchecked") List<FieldMetadata> fields = (List<FieldMetadata>) members.next() .getDeclaredFields(); Iterator<FieldMetadata> fieldsIter = fields.iterator(); while (field == null && fieldsIter.hasNext()) { FieldMetadata tmpField = fieldsIter.next(); if (tmpField.getFieldName().getSymbolName() .equals(name.getSymbolName())) { field = tmpField; } } } return field; } /** * Get the list of type details (Java and AJs) from a Java type. * * @param name Java type to get details * @return List of type details */ protected List<MemberHoldingTypeDetails> getMemberDetails(JavaType name) { String identifier = PhysicalTypeIdentifier.createIdentifier(name, LogicalPath.getInstance(Path.SRC_MAIN_JAVA, "")); PhysicalTypeMetadata physicalType = (PhysicalTypeMetadata) metadataService .get(identifier); String className = getClass().getName(); ClassOrInterfaceTypeDetails typeDetails = (ClassOrInterfaceTypeDetails) physicalType .getMemberHoldingTypeDetails(); MemberDetails member = memberDetailsScanner.getMemberDetails(className, typeDetails); return member.getDetails(); } /** * {@inheritDoc} * <p> * First, deletes the old class using its Id and then creates the new one * with the updated values in file system. * </p> */ public void updateClass( ClassOrInterfaceTypeDetails classOrInterfaceTypeDetails) { // TODO: Comprobar si ha variado el contenido para no hacer operaciones // innecesarias. // TODO: 'ClassOrInterfaceDeclaration' mantiene el javaDoc. String javaIdentifier = typeLocationService .getPhysicalTypeIdentifier(classOrInterfaceTypeDetails .getName()); javaIdentifier = javaIdentifier.substring( javaIdentifier.indexOf("?") + 1).replaceAll("\\.", "/"); fileManager.delete(projectOperations.getPathResolver().getIdentifier( LogicalPath.getInstance(Path.SRC_MAIN_JAVA, ""), javaIdentifier.concat(".java"))); typeManagementService .createOrUpdateTypeOnDisk(classOrInterfaceTypeDetails); } }