Search in sources :

Example 26 with JpaEntityMetadata

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);
}
Also used : FinderParameter(org.springframework.roo.addon.layers.repository.jpa.addon.finder.parser.FinderParameter) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) AnnotationMetadata(org.springframework.roo.classpath.details.annotations.AnnotationMetadata) JavaSymbolName(org.springframework.roo.model.JavaSymbolName) List(java.util.List) ArrayList(java.util.ArrayList) JpaEntityMetadata(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata) NestedAnnotationAttributeValue(org.springframework.roo.classpath.details.annotations.NestedAnnotationAttributeValue) Pair(org.apache.commons.lang3.tuple.Pair) RooFinder(org.springframework.roo.addon.layers.repository.jpa.annotations.finder.RooFinder) RooJavaType(org.springframework.roo.model.RooJavaType) JavaType(org.springframework.roo.model.JavaType) FinderMethod(org.springframework.roo.addon.layers.repository.jpa.addon.finder.parser.FinderMethod) ClassOrInterfaceTypeDetails(org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails) MemberDetails(org.springframework.roo.classpath.scanner.MemberDetails) PartTree(org.springframework.roo.addon.layers.repository.jpa.addon.finder.parser.PartTree)

Example 27 with JpaEntityMetadata

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);
}
Also used : RepositoryJpaMetadata(org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaMetadata) FieldMetadata(org.springframework.roo.classpath.details.FieldMetadata) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) RepositoryJpaCustomMetadata(org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaCustomMetadata) AnnotatedJavaType(org.springframework.roo.classpath.details.annotations.AnnotatedJavaType) RooJavaType(org.springframework.roo.model.RooJavaType) JavaType(org.springframework.roo.model.JavaType) JavaSymbolName(org.springframework.roo.model.JavaSymbolName) RelationInfo(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata.RelationInfo) MethodMetadata(org.springframework.roo.classpath.details.MethodMetadata) JpaEntityMetadata(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata) ClassOrInterfaceTypeDetails(org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails) PartTree(org.springframework.roo.addon.layers.repository.jpa.addon.finder.parser.PartTree)

Example 28 with JpaEntityMetadata

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());
    }
}
Also used : ArrayList(java.util.ArrayList) LogicalPath(org.springframework.roo.project.LogicalPath) AnnotationMetadata(org.springframework.roo.classpath.details.annotations.AnnotationMetadata) AnnotatedJavaType(org.springframework.roo.classpath.details.annotations.AnnotatedJavaType) RooJavaType(org.springframework.roo.model.RooJavaType) SpringJavaType(org.springframework.roo.model.SpringJavaType) JpaJavaType(org.springframework.roo.model.JpaJavaType) JavaType(org.springframework.roo.model.JavaType) ClassOrInterfaceTypeDetailsBuilder(org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder) ClassOrInterfaceTypeDetails(org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails) JpaEntityMetadata(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata) AnnotationMetadataBuilder(org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder)

Example 29 with JpaEntityMetadata

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;
}
Also used : RelationInfo(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata.RelationInfo) ArrayList(java.util.ArrayList) JpaEntityMetadata(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata)

Example 30 with JpaEntityMetadata

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);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) AnnotationMetadata(org.springframework.roo.classpath.details.annotations.AnnotationMetadata) RelationInfo(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata.RelationInfo) List(java.util.List) ArrayList(java.util.ArrayList) ClassOrInterfaceTypeDetails(org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails) JpaEntityMetadata(org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata) Pair(org.apache.commons.lang3.tuple.Pair)

Aggregations

JpaEntityMetadata (org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata)35 ArrayList (java.util.ArrayList)26 ClassOrInterfaceTypeDetails (org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails)23 JavaType (org.springframework.roo.model.JavaType)22 RooJavaType (org.springframework.roo.model.RooJavaType)20 RelationInfo (org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata.RelationInfo)18 MethodMetadata (org.springframework.roo.classpath.details.MethodMetadata)13 AnnotatedJavaType (org.springframework.roo.classpath.details.annotations.AnnotatedJavaType)13 FieldMetadata (org.springframework.roo.classpath.details.FieldMetadata)11 JavaSymbolName (org.springframework.roo.model.JavaSymbolName)10 HashMap (java.util.HashMap)9 Pair (org.apache.commons.lang3.tuple.Pair)9 JpaJavaType (org.springframework.roo.model.JpaJavaType)9 LinkedHashMap (java.util.LinkedHashMap)8 AnnotationMetadata (org.springframework.roo.classpath.details.annotations.AnnotationMetadata)8 MethodMetadataBuilder (org.springframework.roo.classpath.details.MethodMetadataBuilder)7 SpringJavaType (org.springframework.roo.model.SpringJavaType)6 List (java.util.List)5 ServiceMetadata (org.springframework.roo.addon.layers.service.addon.ServiceMetadata)5 AnnotationMetadataBuilder (org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder)5