use of org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata 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.addon.jpa.addon.entity.JpaEntityMetadata in project spring-roo by spring-projects.
the class ServiceMetadataProviderImpl method getMetadata.
@Override
protected ItdTypeDetailsProvidingMetadataItem getMetadata(final String metadataIdentificationString, final JavaType aspectName, final PhysicalTypeMetadata governorPhysicalTypeMetadata, final String itdFilename) {
final ServiceAnnotationValues annotationValues = new ServiceAnnotationValues(governorPhysicalTypeMetadata);
// Getting entity
JavaType entity = annotationValues.getEntity();
Validate.notNull(entity, "ERROR: You should specify a valid entity on @RooService annotation");
final JavaType identifierType = getPersistenceMemberLocator().getIdentifierType(entity);
Validate.notNull(identifierType, "ERROR: You should specify a valid entity on @RooService annotation");
final JpaEntityMetadata entityMetadata = getEntityMetadata(entity);
if (entityMetadata == null) {
return null;
}
registerDependency(entityMetadata.getId(), metadataIdentificationString);
// Getting associated repository
ClassOrInterfaceTypeDetails repositoryDetails = getRepositoryJpaLocator().getRepository(entity);
// Check if we have a valid repository
Validate.notNull(repositoryDetails, String.format("ERROR: You must generate some @RooJpaRepository for entity '%s' to be able to generate services", entity.getSimpleTypeName()));
// Get repository metadata
final String repositoryMetadataKey = RepositoryJpaMetadata.createIdentifier(repositoryDetails);
registerDependency(repositoryMetadataKey, metadataIdentificationString);
final RepositoryJpaMetadata repositoryMetadata = getMetadataService().get(repositoryMetadataKey);
List<MethodMetadata> finders = new ArrayList<MethodMetadata>();
List<MethodMetadata> countMethods = new ArrayList<MethodMetadata>();
if (repositoryMetadata == null) {
// Can't generate metadata yet
return null;
}
// Add dependencies between modules
for (MethodMetadata finder : repositoryMetadata.getFindersGenerated()) {
// Add to service finders list
finders.add(finder);
registerDependencyModulesOfFinder(governorPhysicalTypeMetadata, finder);
}
// Get count methods
countMethods.addAll(repositoryMetadata.getCountMethods());
// Get finders and its associated count method from repository metadata
Map<JavaSymbolName, MethodMetadata> repositoryFindersAndCounts = repositoryMetadata.getFinderMethodsAndCounts();
// Getting methods declared on related RepositoryJpaCustomMetadata
final JavaType customRepository = repositoryMetadata.getCustomRepository();
final ClassOrInterfaceTypeDetails customRepositoryDetails = getTypeLocationService().getTypeDetails(customRepository);
final String customRepositoryMetadataKey = RepositoryJpaCustomMetadata.createIdentifier(customRepositoryDetails);
final RepositoryJpaCustomMetadata repositoryCustomMetadata = getMetadataService().get(customRepositoryMetadataKey);
// Return null if repository dependency is not satisfied
if (repositoryCustomMetadata == null) {
return null;
}
// Get finders and its associated count method from custom repository metadata
Map<JavaSymbolName, MethodMetadata> repositoryCustomFindersAndCounts = repositoryCustomMetadata.getFinderMethodsAndCounts();
// Check if we have a valid custom repository
Validate.notNull(repositoryCustomMetadata, String.format("ERROR: Can't found a class @RooJpaRepositoryCustom for entity '%s' to be able to generate services", entity.getSimpleTypeName()));
registerDependency(customRepositoryMetadataKey, metadataIdentificationString);
final Map<FieldMetadata, MethodMetadata> countByReferencedFieldMethods = new HashMap<FieldMetadata, MethodMetadata>(repositoryMetadata.getCountMethodByReferencedFields());
// Add custom finders to finders list and add dependencies between modules
for (Pair<MethodMetadata, PartTree> finderInfo : repositoryCustomMetadata.getCustomFinderMethods()) {
// Add to service finders list
finders.add(finderInfo.getKey());
registerDependencyModulesOfFinder(governorPhysicalTypeMetadata, finderInfo.getKey());
}
// Add custom count methods to count method list
for (Pair<MethodMetadata, PartTree> countInfo : repositoryCustomMetadata.getCustomCountMethods()) {
countMethods.add(countInfo.getKey());
}
// Get related entities metadata
final Map<JavaType, JpaEntityMetadata> relatedEntities = new HashMap<JavaType, JpaEntityMetadata>();
// As parent
JavaType childEntity;
JpaEntityMetadata childEntityMetadata;
List<RelationInfo> relatedInfosWithServiceLayer = new ArrayList<RelationInfo>();
for (RelationInfo info : entityMetadata.getRelationInfos().values()) {
childEntity = info.fieldMetadata.getFieldType().getBaseType();
if (relatedEntities.containsKey(childEntity)) {
continue;
}
// No need to add relation methods if related entity has not service
ClassOrInterfaceTypeDetails childService = getServiceLocator().getFirstService(childEntity);
if (childService != null) {
relatedInfosWithServiceLayer.add(info);
childEntityMetadata = getEntityMetadata(childEntity);
if (childEntityMetadata == null) {
// We need child metadata. Return null waiting next metadata iteration
return null;
}
registerDependency(childEntityMetadata.getId(), metadataIdentificationString);
relatedEntities.put(childEntity, childEntityMetadata);
}
}
// As child
JavaType parentEntity;
JpaEntityMetadata parentEntityMetadata;
for (FieldMetadata fieldAsChild : entityMetadata.getRelationsAsChild().values()) {
parentEntity = fieldAsChild.getFieldType().getBaseType();
if (relatedEntities.containsKey(parentEntity)) {
continue;
}
parentEntityMetadata = getEntityMetadata(parentEntity);
if (parentEntityMetadata == null) {
// We need parent metadata. Return null waiting next metadata iteration
return null;
}
registerDependency(parentEntityMetadata.getId(), metadataIdentificationString);
relatedEntities.put(parentEntity, parentEntityMetadata);
}
return new ServiceMetadata(metadataIdentificationString, aspectName, governorPhysicalTypeMetadata, entity, identifierType, entityMetadata, repositoryMetadata, finders, repositoryCustomMetadata.getCurrentFindAllGlobalSearchMethod(), repositoryCustomMetadata.getCurrentFindAllByIdsInGlobalSearchMethod(), repositoryCustomMetadata.getReferencedFieldsFindAllMethods(), countByReferencedFieldMethods, countMethods, relatedEntities, repositoryFindersAndCounts, repositoryCustomFindersAndCounts, relatedInfosWithServiceLayer);
}
use of org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata in project spring-roo by spring-projects.
the class ControllerOperationsImpl method createOrUpdateControllerForEntity.
@Override
public void createOrUpdateControllerForEntity(JavaType entity, ControllerMVCResponseService responseType, JavaPackage controllerPackage, String pathPrefix) {
// Getting entity details to obtain information about it
ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService().getTypeDetails(entity);
AnnotationMetadata entityAnnotation = entityDetails.getAnnotation(RooJavaType.ROO_JPA_ENTITY);
if (entityAnnotation == null) {
LOGGER.log(Level.INFO, String.format("ERROR: The provided class %s is not a valid entity. It should be annotated with @RooEntity", entity.getSimpleTypeName()));
return;
}
JpaEntityMetadata entityMetadata = getMetadataService().get(JpaEntityMetadata.createIdentifier(entityDetails));
if (entityMetadata.isCompositionChild()) {
// Don't generate Controller for composition Child entities
LOGGER.log(Level.INFO, String.format("INFO: The provided class %s is composition child part of a relationship. No controller is needed as it's managed form parent controller", entity.getSimpleTypeName()));
return;
}
// Getting related service
JavaType service = null;
ClassOrInterfaceTypeDetails serviceDetails = getServiceLocator().getService(entity);
if (serviceDetails == null) {
// Is necessary at least one service to generate controller
LOGGER.log(Level.INFO, String.format("ERROR: You must generate a service to '%s' entity before to generate a new controller.", entity.getFullyQualifiedTypeName()));
return;
}
service = serviceDetails.getName();
Collection<ClassOrInterfaceTypeDetails> controllers = getControllerLocator().getControllers(entity);
// Check controllersPackage value
if (controllerPackage == null) {
controllerPackage = getDefaultControllerPackage();
if (controllerPackage == null) {
return;
}
}
ControllerAnnotationValues values;
for (ClassOrInterfaceTypeDetails existingController : controllers) {
values = new ControllerAnnotationValues(existingController);
if ((values.getType() == ControllerType.COLLECTION || values.getType() == ControllerType.ITEM)) {
if (StringUtils.equals(values.getPathPrefix(), pathPrefix) && existingController.getAnnotation(responseType.getAnnotation()) != null) {
LOGGER.log(Level.INFO, String.format("ERROR: Already exists a controller associated to entity '%s' with the " + "pathPrefix '%s' for this responseType. Specify different one " + "using --pathPrefix or --responseType parameter.", entity.getSimpleTypeName(), pathPrefix));
return;
}
}
}
// Generate Collection controller JavaType
String entityPluralCapitalized = StringUtils.capitalize(getPluralService().getPlural(entity));
JavaType collectionController = new JavaType(String.format("%s.%sCollection%sController", controllerPackage.getFullyQualifiedPackageName(), entityPluralCapitalized, responseType.getControllerNameModifier()), controllerPackage.getModule());
ClassOrInterfaceTypeDetails collectionControllerDetails = getTypeLocationService().getTypeDetails(collectionController);
if (collectionControllerDetails == null) {
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(getRooControllerAnnotation(entity, pathPrefix, ControllerType.COLLECTION));
// Add responseType annotation. Don't use responseTypeService
// annotate to
// prevent multiple
// updates of the .java file. Annotate operation will be used during
// controller update.
annotations.add(new AnnotationMetadataBuilder(responseType.getAnnotation()));
final LogicalPath controllerPath = getPathResolver().getPath(collectionController.getModule(), Path.SRC_MAIN_JAVA);
final String resourceIdentifier = getTypeLocationService().getPhysicalTypeCanonicalPath(collectionController, controllerPath);
final String declaredByMetadataId = PhysicalTypeIdentifier.createIdentifier(collectionController, getPathResolver().getPath(resourceIdentifier));
ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(declaredByMetadataId, Modifier.PUBLIC, collectionController, PhysicalTypeCategory.CLASS);
cidBuilder.setAnnotations(annotations);
getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build());
// Create LinkFactory class
if (responseType.getName().equals("THYMELEAF")) {
createLinkFactoryClass(cidBuilder.getName());
}
} else {
LOGGER.log(Level.INFO, String.format("ERROR: The controller %s already exists.", collectionController.getFullyQualifiedTypeName()));
return;
}
// Same operation to itemController
// Generate Item Controller JavaType
JavaType itemController = new JavaType(String.format("%s.%sItem%sController", controllerPackage.getFullyQualifiedPackageName(), entityPluralCapitalized, responseType.getControllerNameModifier()), controllerPackage.getModule());
ClassOrInterfaceTypeDetails itemControllerDetails = getTypeLocationService().getTypeDetails(itemController);
if (itemControllerDetails == null) {
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(getRooControllerAnnotation(entity, pathPrefix, ControllerType.ITEM));
// Add responseType annotation. Don't use responseTypeService
// annotate to
// prevent multiple
// updates of the .java file. Annotate operation will be used during
// controller update.
annotations.add(new AnnotationMetadataBuilder(responseType.getAnnotation()));
final LogicalPath controllerPathItem = getPathResolver().getPath(itemController.getModule(), Path.SRC_MAIN_JAVA);
final String resourceIdentifierItem = getTypeLocationService().getPhysicalTypeCanonicalPath(itemController, controllerPathItem);
final String declaredByMetadataIdItem = PhysicalTypeIdentifier.createIdentifier(itemController, getPathResolver().getPath(resourceIdentifierItem));
ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(declaredByMetadataIdItem, Modifier.PUBLIC, itemController, PhysicalTypeCategory.CLASS);
cidBuilder.setAnnotations(annotations);
getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build());
// Create LinkFactory class
if (responseType.getName().equals("THYMELEAF")) {
createLinkFactoryClass(cidBuilder.getName());
}
} else {
LOGGER.log(Level.INFO, String.format("ERROR: The controller %s already exists.", collectionController.getFullyQualifiedTypeName()));
return;
}
// Check if requires Deserializer
if (responseType.requiresJsonDeserializer()) {
createJsonDeserializersIfDontExists(entity, itemController.getModule(), controllerPackage);
}
if (responseType.requiresJsonMixin()) {
createJsonMixinIfDontExists(entity, entityMetadata, itemController.getModule(), controllerPackage);
}
// Check multimodule project
if (getProjectOperations().isMultimoduleProject()) {
getProjectOperations().addModuleDependency(collectionController.getModule(), service.getModule());
getProjectOperations().addModuleDependency(itemController.getModule(), service.getModule());
}
}
use of org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata in project spring-roo by spring-projects.
the class ControllerOperationsImpl method checkRelationField.
/**
* Find recursively if relation field is valid. Check that the fields are
* Set or List and check that the parents controllers exists
*/
private List<RelationInfo> checkRelationField(JpaEntityMetadata entityMetadata, String[] relationField, int level, ControllerMVCResponseService responseType, JavaPackage controllerPackage, String pathPrefix, JavaType masterEntity) {
List<RelationInfo> infos = new ArrayList<RelationInfo>();
RelationInfo info = entityMetadata.getRelationInfos().get(relationField[level]);
if (info == null) {
return null;
}
if (info.cardinality != Cardinality.ONE_TO_MANY && info.cardinality != Cardinality.MANY_TO_MANY) {
return null;
}
infos.add(info);
if (relationField.length > level + 1) {
List<String> currentPathList = new ArrayList<String>(level + 1);
for (int i = 0; i < relationField.length; i++) {
currentPathList.add(relationField[i]);
}
String currentPath = StringUtils.join(currentPathList, '.');
// try to find it
if (checkDetailControllerExists(masterEntity, responseType, controllerPackage, pathPrefix, currentPath)) {
JpaEntityMetadata childEntity = getMetadataService().get(JpaEntityMetadata.createIdentifier(getTypeLocationService().getTypeDetails(info.childType)));
List<RelationInfo> subPath = checkRelationField(childEntity, relationField, level + 1, responseType, controllerPackage, pathPrefix, masterEntity);
if (subPath == null) {
return null;
}
infos.addAll(subPath);
} else {
LOGGER.info(String.format("Details controller is required for %s befor can create %s", currentPath, StringUtils.join(Arrays.asList(relationField), ',')));
return null;
}
}
return infos;
}
use of org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata in project spring-roo by spring-projects.
the class ControllerOperationsImpl method createOrUpdateDetailControllerForEntity.
@Override
public void createOrUpdateDetailControllerForEntity(JavaType entity, String relationField, ControllerMVCResponseService responseType, JavaPackage controllerPackage, String viewsList) {
// Getting entity details to obtain information about it
ClassOrInterfaceTypeDetails entityDetails = getTypeLocationService().getTypeDetails(entity);
AnnotationMetadata entityAnnotation = entityDetails.getAnnotation(RooJavaType.ROO_JPA_ENTITY);
if (entityAnnotation == null) {
LOGGER.log(Level.INFO, String.format("ERROR: The provided class %s is not a valid entity. It should be annotated with @RooJpaEntity", entity.getSimpleTypeName()));
return;
}
// Check controllersPackage value
if (controllerPackage == null) {
controllerPackage = getDefaultControllerPackage();
if (controllerPackage == null) {
return;
}
}
boolean existsBasicControllers = false;
String pathPrefixController = "";
Collection<ClassOrInterfaceTypeDetails> itemControllers = getControllerLocator().getControllers(entity, ControllerType.ITEM);
for (ClassOrInterfaceTypeDetails existingController : itemControllers) {
if (existingController.getType().getPackage().equals(controllerPackage)) {
ControllerAnnotationValues values = new ControllerAnnotationValues(existingController);
AnnotationMetadata responseTypeAnnotation = existingController.getAnnotation(responseType.getAnnotation());
if (responseTypeAnnotation != null) {
pathPrefixController = values.getPathPrefix();
existsBasicControllers = true;
break;
}
}
}
if (!existsBasicControllers) {
LOGGER.log(Level.INFO, String.format("INFO: Doesn't exist parent controller in the package %s with the response type %s for the entity %s. Please, use 'web mvc controller' command to create them.", controllerPackage, responseType.getName(), entity.getSimpleTypeName()));
return;
}
JpaEntityMetadata entityMetadata = getMetadataService().get(JpaEntityMetadata.createIdentifier(entityDetails));
List<Pair<String, List<RelationInfoExtended>>> relationsToAdd = new ArrayList<Pair<String, List<RelationInfoExtended>>>();
if (StringUtils.isNotBlank(relationField)) {
// Check field received as parameter
List<RelationInfoExtended> infos = getRelationInfoFor(entityMetadata, relationField);
// TODO support multilevel detail (TO BE ANALIZED)
if (infos.size() > 1) {
LOGGER.log(Level.INFO, "ERROR: multi-level details not supported.");
return;
}
StringBuilder sbuilder = new StringBuilder();
for (int i = 0; i < infos.size(); i++) {
RelationInfoExtended info = infos.get(i);
sbuilder.append(info.fieldName);
if (!(info.cardinality == Cardinality.ONE_TO_MANY || info.cardinality == Cardinality.MANY_TO_MANY)) {
LOGGER.log(Level.INFO, String.format("ERROR: %s.%s is not a one-to-many or many-to-many relationships.", info.entityType.getFullyQualifiedTypeName(), info.fieldName));
return;
}
// Check than previous level details has been created before
if (i < infos.size() - 2) {
if (!checkDetailControllerExists(entity, responseType, controllerPackage, pathPrefixController, sbuilder.toString())) {
LOGGER.log(Level.INFO, String.format("ERROR: Detail controller for entity %s and detail field %s must be created before generate %s controller.", entity, sbuilder.toString(), relationField));
return;
}
}
}
relationsToAdd.add(Pair.of(relationField, infos));
} else {
for (RelationInfo info : entityMetadata.getRelationInfos().values()) {
if (info.cardinality == Cardinality.ONE_TO_MANY || info.cardinality == Cardinality.MANY_TO_MANY) {
// Check that is not already generated controller
if (!checkDetailControllerExists(entity, responseType, controllerPackage, pathPrefixController, info.fieldName)) {
relationsToAdd.add(Pair.of(info.fieldName, getRelationInfoFor(entityMetadata, info.fieldName)));
}
}
}
}
if (relationsToAdd.isEmpty()) {
LOGGER.log(Level.INFO, String.format("INFO: none relation found to generate detail controllers for entity '%s'.", entity.getSimpleTypeName()));
return;
}
for (Pair<String, List<RelationInfoExtended>> relation : relationsToAdd) {
boolean generated = createDetailClass(relation.getLeft(), entity, responseType, controllerPackage, pathPrefixController, viewsList);
RelationInfo lastRelation = relation.getRight().get(relation.getRight().size() - 1);
if (generated && lastRelation.type == JpaRelationType.COMPOSITION) {
createDetailsItemClass(relation.getLeft(), entity, responseType, controllerPackage, pathPrefixController, viewsList);
}
}
}
Aggregations