use of org.springframework.roo.classpath.scanner.MemberDetails in project spring-roo by spring-projects.
the class FinderOperationsImpl method installFinder.
public void installFinder(final JavaType entity, final JavaSymbolName finderName, JavaType formBean, JavaType returnType) {
Validate.notNull(entity, "ERROR: Entity type required to generate finder.");
Validate.notNull(finderName, "ERROR: Finder name required to generate finder.");
final String id = getTypeLocationService().getPhysicalTypeIdentifier(entity);
if (id == null) {
LOGGER.warning("Cannot locate source for '" + entity.getFullyQualifiedTypeName() + "'");
return;
}
// Check if provided entity is annotated with @RooJpaEntity
ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService().getTypeDetails(entity);
AnnotationMetadata entityAnnotation = entityDetails.getAnnotation(RooJavaType.ROO_JPA_ENTITY);
Validate.notNull(entityAnnotation, "ERROR: Provided entity must be annotated with @RooJpaEntity");
// Getting repository that manages current entity
ClassOrInterfaceTypeDetails repository = getRepositoryJpaLocator().getRepository(entity);
// Entity must have a repository that manages it, if not, shows an error
Validate.notNull(repository, "ERROR: You must generate a repository to the provided entity before to add new finder. You could use 'repository jpa' commands.");
// Check if provided formBean contains the field names and types indicated as finder params
if (formBean != null) {
MemberDetails entityMemberDetails = getMemberDetailsScanner().getMemberDetails(this.getClass().getName(), getTypeLocationService().getTypeDetails(entity));
PartTree finderPartTree = new PartTree(finderName.getSymbolName(), entityMemberDetails);
checkDtoFieldsForFinder(getTypeLocationService().getTypeDetails(formBean), finderPartTree, repository.getType());
}
// Get repository annotation
AnnotationMetadata repositoryAnnotation = repository.getAnnotation(RooJavaType.ROO_REPOSITORY_JPA);
AnnotationMetadataBuilder repositoryAnnotationBuilder = new AnnotationMetadataBuilder(repositoryAnnotation);
// Create list that will include finders to add
List<AnnotationAttributeValue<?>> finders = new ArrayList<AnnotationAttributeValue<?>>();
// Check if new finder name to be included already exists in @RooRepositoryJpa annotation
AnnotationAttributeValue<?> currentFinders = repositoryAnnotation.getAttribute("finders");
if (currentFinders != null) {
List<?> values = (List<?>) currentFinders.getValue();
Iterator<?> it = values.iterator();
while (it.hasNext()) {
NestedAnnotationAttributeValue finder = (NestedAnnotationAttributeValue) it.next();
if (finder.getValue() != null && finder.getValue().getAttribute("value") != null) {
if (finder.getValue().getAttribute("value").getValue().equals(finderName.getSymbolName())) {
LOGGER.log(Level.WARNING, String.format("ERROR: Finder '%s' already exists on entity '%s'", finderName.getSymbolName(), entity.getSimpleTypeName()));
return;
}
finders.add(finder);
}
}
}
// Create @RooFinder
AnnotationMetadataBuilder singleFinderAnnotation = new AnnotationMetadataBuilder(RooJavaType.ROO_FINDER);
// Add finder attribute
singleFinderAnnotation.addStringAttribute("value", finderName.getSymbolName());
// Add returnType attribute
singleFinderAnnotation.addClassAttribute("returnType", returnType);
// Prevent errors validating if the return type contains a valid module
if (returnType.getModule() != null) {
getProjectOperations().addModuleDependency(repository.getName().getModule(), returnType.getModule());
}
// Add formBean attribute
if (formBean != null) {
singleFinderAnnotation.addClassAttribute("formBean", formBean);
getProjectOperations().addModuleDependency(repository.getName().getModule(), formBean.getModule());
}
NestedAnnotationAttributeValue newFinder = new NestedAnnotationAttributeValue(new JavaSymbolName("value"), singleFinderAnnotation.build());
// If not exists current finder, include it
finders.add(newFinder);
// Add finder list to currentFinders
ArrayAttributeValue<AnnotationAttributeValue<?>> newFinders = new ArrayAttributeValue<AnnotationAttributeValue<?>>(new JavaSymbolName("finders"), finders);
// Include finder name to finders attribute
repositoryAnnotationBuilder.addAttribute(newFinders);
// Update @RooRepositoryJpa annotation
final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(repository);
// Update annotation
cidBuilder.updateTypeAnnotation(repositoryAnnotationBuilder);
// Save changes on disk
getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build());
}
use of org.springframework.roo.classpath.scanner.MemberDetails in project spring-roo by spring-projects.
the class FinderOperationsImpl method buildFormBeanFieldNamesMap.
/**
* Build a Map<String, String> with form bean type field names and "path" field names
* and adds it to the typesFieldMaps, typeFieldMetadataMap and finderParametersMap.
*
* @param entity the entity containing the FieldMetadata used as finder parameters.
* The fields can be fields from other related entity
* @param formBeanType the bean class containing the values for which to look up.
* @param typesFieldMaps the map with field names and "path" field names mappings.
* Can be null.
* @param typeFieldMetadataMap the map with field names and FieldMetadata mappings.
* Can be null.
* @param finderName the name of the finder to build mappings.
* @param finderParametersList the list of FinderParameters for each finder name.
*/
public void buildFormBeanFieldNamesMap(JavaType entity, JavaType formBeanType, Map<JavaType, Map<String, String>> typesFieldMaps, Map<JavaType, Map<String, FieldMetadata>> typeFieldMetadataMap, JavaSymbolName finderName, Map<JavaSymbolName, List<FinderParameter>> finderParametersMap) {
// Get all entity fields
ClassOrInterfaceTypeDetails entityCid = getTypeLocationService().getTypeDetails(entity);
MemberDetails entityMemberDetails = getMemberDetailsScanner().getMemberDetails(this.getClass().getName(), entityCid);
List<FieldMetadata> allEntityFields = entityMemberDetails.getFields();
// Create inner Maps
Map<String, String> fieldNamesMap = null;
if (typesFieldMaps != null) {
if (typesFieldMaps.get(formBeanType) == null) {
fieldNamesMap = new HashMap<String, String>();
} else {
fieldNamesMap = typesFieldMaps.get(formBeanType);
}
}
Map<String, FieldMetadata> fieldMetadataMap = null;
if (typeFieldMetadataMap != null) {
if (typeFieldMetadataMap.get(formBeanType) == null) {
fieldMetadataMap = new HashMap<String, FieldMetadata>();
} else {
fieldMetadataMap = typeFieldMetadataMap.get(formBeanType);
}
}
// Get finder fields
PartTree partTree = new PartTree(finderName.getSymbolName(), entityMemberDetails);
List<FinderParameter> finderParameters = partTree.getParameters();
// Create list of parameters for this finder
List<FinderParameter> finderParametersList = new ArrayList<FinderParameter>();
// Get all DTO fields if form bean is a DTO or entity fields if not
List<FieldMetadata> allFormBeanFields = new ArrayList<FieldMetadata>();
if (getTypeLocationService().getTypeDetails(formBeanType) != null && getTypeLocationService().getTypeDetails(formBeanType).getAnnotation(RooJavaType.ROO_DTO) != null) {
allFormBeanFields = getMemberDetailsScanner().getMemberDetails(this.getClass().getName(), getTypeLocationService().getTypeDetails(formBeanType)).getFields();
}
// Iterate over all specified fields
for (FinderParameter finderParameter : finderParameters) {
JavaSymbolName fieldName = finderParameter.getName();
JavaType fieldType = finderParameter.getType();
boolean found = false;
// Iterate over all entity fields
for (FieldMetadata field : allEntityFields) {
if (field.getFieldName().equals(fieldName) && field.getFieldType().equals(fieldType)) {
// Field found, build field "path" name and add it to map
// Path name for DTO's should be the path to entity's fields
String fieldPathName = String.format("%s.%s", StringUtils.uncapitalize(entity.getSimpleTypeName()), field.getFieldName());
if (typesFieldMaps != null) {
fieldNamesMap.put(fieldName.getSymbolName(), fieldPathName);
}
// Add FieldMetadata from DTO to fieldMetadataMap
if (!allFormBeanFields.isEmpty()) {
boolean fieldFoundInDto = false;
for (FieldMetadata dtoField : allFormBeanFields) {
if (dtoField.getFieldName().equals(fieldName) && dtoField.getFieldType().equals(fieldType)) {
if (typeFieldMetadataMap != null) {
fieldMetadataMap.put(fieldName.getSymbolName(), dtoField);
}
fieldFoundInDto = true;
}
}
Validate.isTrue(fieldFoundInDto, "Couldn't find a field with same name and type that %s on DTO %s", fieldName.getSymbolName(), formBeanType.getSimpleTypeName());
} else {
fieldMetadataMap.put(fieldName.getSymbolName(), field);
}
found = true;
break;
}
}
if (!found) {
// The field isn't in the entity, should be in one of its relations
for (FieldMetadata field : allEntityFields) {
found = findDtoFieldRecursivelyAndAddToMappings(entity, fieldNamesMap, fieldMetadataMap, found, field, fieldName, fieldType, allFormBeanFields, formBeanType.getSimpleTypeName());
}
}
if (!found) {
// Field not found in its
throw new IllegalArgumentException(String.format("Field %s couldn't be located in DTO %s. Please, be sure that it is well " + "written and exists in %s or its related entities.", fieldName, formBeanType.getSimpleTypeName(), entity.getSimpleTypeName()));
}
finderParametersList.add(finderParameter);
}
// Add dto mappings to domain type mappings
if (typesFieldMaps != null) {
typesFieldMaps.put(formBeanType, fieldNamesMap);
}
if (typeFieldMetadataMap != null) {
typeFieldMetadataMap.put(formBeanType, fieldMetadataMap);
}
// Add finder params to Map
finderParametersMap.put(finderName, finderParametersList);
}
use of org.springframework.roo.classpath.scanner.MemberDetails in project spring-roo by spring-projects.
the class RepositoryJpaMetadataProviderImpl method getMetadata.
@Override
protected ItdTypeDetailsProvidingMetadataItem getMetadata(final String metadataIdentificationString, final JavaType aspectName, final PhysicalTypeMetadata governorPhysicalTypeMetadata, final String itdFilename) {
final RepositoryJpaAnnotationValues annotationValues = new RepositoryJpaAnnotationValues(governorPhysicalTypeMetadata);
final JavaType domainType = annotationValues.getEntity();
// XXX clear entitiesDetails by security
entitiesDetails.clear();
// Remember that this entity JavaType matches up with this metadata
// identification string
// Start by clearing any previous association
final JavaType oldEntity = repositoryMidToDomainTypeMap.get(metadataIdentificationString);
if (oldEntity != null) {
domainTypeToRepositoryMidMap.remove(oldEntity);
}
domainTypeToRepositoryMidMap.put(domainType, metadataIdentificationString);
repositoryMidToDomainTypeMap.put(metadataIdentificationString, domainType);
// Getting associated entity
JavaType entity = annotationValues.getEntity();
ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService().getTypeDetails(entity);
MemberDetails entityMemberDetails = getMemberDetailsScanner().getMemberDetails(this.getClass().getName(), entityDetails);
final String entityMetadataId = JpaEntityMetadata.createIdentifier(entityDetails);
final JpaEntityMetadata entityMetadata = getMetadataService().get(entityMetadataId);
if (entityMetadata == null) {
return null;
}
// Getting java bean metadata
final String javaBeanMetadataKey = JavaBeanMetadata.createIdentifier(entityDetails);
// Register dependency between repositoryMetadata and jpaEntityMetadata
registerDependency(entityMetadataId, metadataIdentificationString);
// Create dependency between repository and java bean annotation
registerDependency(javaBeanMetadataKey, metadataIdentificationString);
// Check if related entity is setted as readOnly
JavaType readOnlyRepository = null;
if (entityMetadata.isReadOnly()) {
// Getting ReadOnlyRepository interface annotated with
// @RooReadOnlyRepository
Set<ClassOrInterfaceTypeDetails> readOnlyRepositories = getTypeLocationService().findClassesOrInterfaceDetailsWithAnnotation(ROO_READ_ONLY_REPOSITORY);
Validate.notEmpty(readOnlyRepositories, "ERROR: You should define a ReadOnlyRepository interface annotated with @RooReadOnlyRepository to be able to generate repositories of readOnly entities.");
Iterator<ClassOrInterfaceTypeDetails> it = readOnlyRepositories.iterator();
while (it.hasNext()) {
ClassOrInterfaceTypeDetails readOnlyRepositoryDetails = it.next();
readOnlyRepository = readOnlyRepositoryDetails.getType();
break;
}
}
List<JavaType> repositoryCustomList = new ArrayList<JavaType>();
// Getting RepositoryCustom interface annotated with
// @RooJpaRepositoryCustom
Set<ClassOrInterfaceTypeDetails> customRepositories = getTypeLocationService().findClassesOrInterfaceDetailsWithAnnotation(ROO_REPOSITORY_JPA_CUSTOM);
Iterator<ClassOrInterfaceTypeDetails> customRepositoriesIt = customRepositories.iterator();
while (customRepositoriesIt.hasNext()) {
ClassOrInterfaceTypeDetails customRepository = customRepositoriesIt.next();
AnnotationMetadata annotation = customRepository.getAnnotation(ROO_REPOSITORY_JPA_CUSTOM);
if (annotation.getAttribute("entity").getValue().equals(entity)) {
repositoryCustomList.add(customRepository.getType());
}
}
Validate.notEmpty(repositoryCustomList, "Can't find any interface annotated with @%s(entity=%s)", ROO_REPOSITORY_JPA_CUSTOM.getSimpleTypeName(), entity.getSimpleTypeName());
Validate.isTrue(repositoryCustomList.size() == 1, "More than one interface annotated with @%s(entity=%s): %s", ROO_REPOSITORY_JPA_CUSTOM.getSimpleTypeName(), entity.getSimpleTypeName(), StringUtils.join(repositoryCustomList, ","));
JavaType defaultReturnType;
final JavaType annotationDefaultReturnType = annotationValues.getDefaultReturnType();
// Get and check defaultReturnType
if (annotationDefaultReturnType == null || annotationDefaultReturnType.equals(JavaType.CLASS) || annotationDefaultReturnType.equals(entity)) {
defaultReturnType = entity;
} else {
// Validate that defaultReturnValue is projection of current entity
ClassOrInterfaceTypeDetails returnTypeCid = getTypeLocationService().getTypeDetails(annotationDefaultReturnType);
AnnotationMetadata projectionAnnotation = returnTypeCid.getAnnotation(RooJavaType.ROO_ENTITY_PROJECTION);
Validate.notNull(projectionAnnotation, "ERROR: %s defined on %s.@%s.defaultReturnType must be annotated with @%s annotation", annotationDefaultReturnType, governorPhysicalTypeMetadata.getType(), RooJavaType.ROO_REPOSITORY_JPA, RooJavaType.ROO_ENTITY_PROJECTION);
Validate.isTrue(entity.equals(projectionAnnotation.getAttribute("entity").getValue()), "ERROR: %s defined on %s.@%s.defaultReturnType must be annotated with @%s annotation and match the 'entity' attribute value", annotationDefaultReturnType, governorPhysicalTypeMetadata.getType(), RooJavaType.ROO_REPOSITORY_JPA, RooJavaType.ROO_ENTITY_PROJECTION);
defaultReturnType = annotationDefaultReturnType;
}
// Get field which entity is field part
List<Pair<FieldMetadata, RelationInfo>> relationsAsChild = getJpaOperations().getFieldChildPartOfRelation(entityDetails);
// Get Annotation
ClassOrInterfaceTypeDetails cid = governorPhysicalTypeMetadata.getMemberHoldingTypeDetails();
AnnotationMetadata repositoryAnnotation = cid.getAnnotation(ROO_REPOSITORY_JPA);
// Create list of finder to add
List<FinderMethod> findersToAdd = new ArrayList<FinderMethod>();
// Create list of finder to add in RespositoryCustom
List<Pair<FinderMethod, PartTree>> findersToAddInCustom = new ArrayList<Pair<FinderMethod, PartTree>>();
Map<JavaType, ClassOrInterfaceTypeDetails> detailsCache = new HashMap<JavaType, ClassOrInterfaceTypeDetails>();
List<String> declaredFinderNames = new ArrayList<String>();
RooFinder[] findersAnnValue = annotationValues.getFinders();
// Get finders attributes
AnnotationAttributeValue<?> currentFinders = repositoryAnnotation.getAttribute("finders");
if (currentFinders != null) {
List<?> values = (List<?>) currentFinders.getValue();
Iterator<?> valuesIt = values.iterator();
while (valuesIt.hasNext()) {
NestedAnnotationAttributeValue finderAnnotation = (NestedAnnotationAttributeValue) valuesIt.next();
if (finderAnnotation.getValue() != null && finderAnnotation.getValue().getAttribute("value") != null) {
// Get finder name
String finderName = null;
if (finderAnnotation.getValue().getAttribute("value").getValue() instanceof String) {
finderName = (String) finderAnnotation.getValue().getAttribute("value").getValue();
}
Validate.notNull(finderName, "'finder' attribute in @RooFinder must be a String");
declaredFinderNames.add(finderName);
// Get finder return type
JavaType returnType = getNestedAttributeValue(finderAnnotation, "returnType");
JavaType finderReturnType;
if (returnType == null || JavaType.CLASS.equals(returnType)) {
finderReturnType = defaultReturnType;
returnType = null;
} else {
finderReturnType = returnType;
}
// Get finder return type
JavaType formBean = getNestedAttributeValue(finderAnnotation, "formBean");
boolean isDeclaredFormBean = false;
if (JavaType.CLASS.equals(formBean)) {
formBean = null;
}
// Create FinderMethods
PartTree finder = new PartTree(finderName, entityMemberDetails, this, finderReturnType);
Validate.notNull(finder, String.format("ERROR: '%s' is not a valid finder. Use autocomplete feature (TAB or CTRL + Space) to include finder that follows Spring Data nomenclature.", finderName));
FinderMethod finderMethod = new FinderMethod(finder);
// Add dependencies between modules
List<JavaType> types = new ArrayList<JavaType>();
types.add(finder.getReturnType());
types.addAll(finder.getReturnType().getParameters());
for (FinderParameter parameter : finder.getParameters()) {
types.add(parameter.getType());
types.addAll(parameter.getType().getParameters());
}
for (JavaType parameter : types) {
getTypeLocationService().addModuleDependency(governorPhysicalTypeMetadata.getType().getModule(), parameter);
}
if (formBean == null && (returnType == null || entity.equals(returnType))) {
// Add to finder methods list
findersToAdd.add(finderMethod);
} else {
// RepositoryCustom classes.
if (returnType != null && !returnType.equals(entity)) {
ClassOrInterfaceTypeDetails returnTypeDetails = getDetailsFor(returnType, detailsCache);
Validate.isTrue(returnTypeDetails != null && returnTypeDetails.getAnnotation(RooJavaType.ROO_ENTITY_PROJECTION) != null, "ERROR: finder '%s' declared 'returnType' (%s) is not annotated with @%s annotation", finderName, returnType.getSimpleTypeName(), RooJavaType.ROO_ENTITY_PROJECTION.getSimpleTypeName());
}
Validate.notNull(formBean, "ERROR: finder '%s' requires 'formBean' value if 'defaultReturnType' is defined", finderName);
ClassOrInterfaceTypeDetails formBeanDetails = getTypeLocationService().getTypeDetails(formBean);
Validate.isTrue(formBeanDetails != null && formBeanDetails.getAnnotation(RooJavaType.ROO_DTO) != null, "ERROR: finder '%s' declared 'formBean' (%s) is not annotated with @%s annotation", finderName, formBean.getSimpleTypeName(), RooJavaType.ROO_ENTITY_PROJECTION.getSimpleTypeName());
checkDtoFieldsForFinder(formBeanDetails, finder, governorPhysicalTypeMetadata.getType());
if (returnType == null) {
returnType = entity;
}
finderMethod = new FinderMethod(returnType, new JavaSymbolName(finderName), Arrays.asList(new FinderParameter(formBean, new JavaSymbolName(StringUtils.uncapitalize(formBean.getSimpleTypeName())))));
findersToAddInCustom.add(Pair.of(finderMethod, finder));
}
}
}
}
return new RepositoryJpaMetadata(metadataIdentificationString, aspectName, governorPhysicalTypeMetadata, annotationValues, entityMetadata, readOnlyRepository, repositoryCustomList.get(0), defaultReturnType, relationsAsChild, findersToAdd, findersToAddInCustom, declaredFinderNames);
}
use of org.springframework.roo.classpath.scanner.MemberDetails in project spring-roo by spring-projects.
the class FinderCommands method isNameVisible.
@CliOptionVisibilityIndicator(command = "finder add", params = { "name" }, help = "You must define --entity to be able to define --name parameter.")
public boolean isNameVisible(ShellContext shellContext) {
// Getting all defined parameters on autocompleted command
Map<String, String> params = shellContext.getParameters();
// If mandatory parameter entity is not defined, name parameter should not
// be visible
String entity = params.get("entity");
if (StringUtils.isBlank(entity)) {
return false;
}
// Get current entity member details to check if is a valid Spring Roo entity
MemberDetails entityDetails = getEntityDetails(entity);
// If not entity details, is not a valid entity, so --name parameter is not visible
if (entityDetails == null) {
return false;
}
return true;
}
use of org.springframework.roo.classpath.scanner.MemberDetails in project spring-roo by spring-projects.
the class FinderCommands method getClassPossibleResults.
@CliOptionAutocompleteIndicator(command = "finder add", includeSpaceOnFinish = false, param = "entity", help = "--entity option should be an entity.")
public List<String> getClassPossibleResults(ShellContext shellContext) {
// ROO-3763: Clear current cache during --entity autocompletion.
// With that, Spring Roo will maintain cache during --name autocompletion
// but if --entity is autocomplete, cache should be refreshed to obtain
// last changes on entities
entitiesDetails = new HashMap<JavaType, MemberDetails>();
// Get current value of entity
String currentText = shellContext.getParameters().get("entity");
List<String> allPossibleValues = new ArrayList<String>();
Set<ClassOrInterfaceTypeDetails> entities = getTypeLocationService().findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_JPA_ENTITY);
for (ClassOrInterfaceTypeDetails entity : entities) {
String name = replaceTopLevelPackageString(entity, currentText);
if (!allPossibleValues.contains(name)) {
allPossibleValues.add(name);
}
}
return allPossibleValues;
}
Aggregations