use of org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaMetadata in project spring-roo by spring-projects.
the class FinderCommands method installFinders.
@CliCommand(value = "finder add", help = "Installs a finder in the given target (must be an entity). This command needs an existing " + "repository for the target entity, you can create it with `repository jpa` command. The " + "finder will be added to targeted entity associated repository and associated service if " + "exists or when it will be created.")
public void installFinders(@CliOption(key = "entity", mandatory = true, unspecifiedDefaultValue = "*", optionContext = PROJECT, help = "The entity for which the finders are generated. When working on a mono module project, " + "simply specify the name of the entity. If you consider it necessary, you can also " + "specify the package. Ex.: `--class ~.domain.MyEntity` (where `~` is the base package). " + "When working with multiple modules, you should specify the name of the class and the " + "module where it is. Ex.: `--class model:~.domain.MyEntity`. If the module is not " + "specified, it is assumed that the entity is in the module which has the focus.") final JavaType entity, @CliOption(key = "name", mandatory = true, help = "The finder string defined as a Spring Data query. Use Spring Data JPA nomenclature. " + "Possible values are: any finder name following Spring Data nomenclature. " + "This option will not be available until `--entity` is specified.") final JavaSymbolName finderName, @CliOption(key = "formBean", mandatory = true, help = "The finder's search parameter. Should be a DTO and it must have at least same fields " + "(name and type) as those included in the finder `--name`, which can be target entity" + " fields or related entity fields. " + "Possible values are: any of the DTO's in the project. " + "This option is mandatory if `--returnType` is specified and its a projection. " + "This option is not available if `--entity` parameter has not been specified before or " + "if it does not exist any DTO in generated project. " + "Default if option not present: the entity specified in `--entity` option.") final JavaType formBean, @CliOption(key = "returnType", mandatory = false, optionContext = PROJECT, help = "The finder's results return type. " + "Possible values are: Projection classes annotated with `@RooEntityProjection` and " + "related to the entity specified in `--entity` option (use `entity projection` command), " + "or the same entity. " + "This option is not available if `--entity` parameter has not been specified before or " + "if it does not exist any Projection class associated to the targeted entity. " + "Default if not present: the default return type of the repository related to the entity, " + "which can be specified with `--defaultReturnType` parameter in `repository jpa` command.") JavaType returnType) {
// Check if specified finderName follows Spring Data nomenclature
PartTree partTree = new PartTree(finderName.getSymbolName(), getEntityDetails(entity), this);
// If generated partTree is not valid, shows an exception
Validate.isTrue(partTree.isValid(), "--name parameter must follow Spring Data nomenclature. Please, write a valid value using autocomplete feature (TAB or CTRL + Space)");
// related repository
if (returnType == null) {
// Obtain the related repository metadata
RepositoryJpaMetadata repositoryMetadata = getRepositoryJpaLocator().getFirstRepositoryMetadata(entity);
Validate.notNull(repositoryMetadata, "ERROR: You must create a repository related with this entity before to generate a finder");
// Use the repository metadata to obtain the default return type
returnType = repositoryMetadata.getDefaultReturnType();
}
Validate.notNull(returnType, "ERROR: The new finder must define a returnType");
// Check if the returnType is an entity. If is is not an entity validate
// that the formBean is not null
ClassOrInterfaceTypeDetails type = getTypeLocationService().getTypeDetails(returnType);
if (type.getAnnotation(RooJavaType.ROO_JPA_ENTITY) == null) {
Validate.notNull(formBean, "--formBean is requied when --returnType parameter is a projection.");
}
finderOperations.installFinder(entity, finderName, formBean, returnType);
}
use of org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaMetadata 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.layers.repository.jpa.addon.RepositoryJpaMetadata in project spring-roo by spring-projects.
the class WebFinderOperationsImpl method createOrUpdateSearchControllerForEntity.
@Override
public void createOrUpdateSearchControllerForEntity(JavaType entity, List<String> queryMethods, ControllerMVCResponseService responseType, JavaPackage controllerPackage, String pathPrefix) {
Validate.notNull(entity, "Entity type required");
Validate.notNull(responseType, "Response type required");
Validate.notNull(controllerPackage, "Package required");
Validate.notNull(typeLocationService.getTypeDetails(entity).getAnnotation(RooJavaType.ROO_JPA_ENTITY), "The provided JavaType %s must be annotated with @RooJpaEntity", entity.getSimpleTypeName());
// Check if module has an application class
controllerPackage = checkAndUseApplicationModule(controllerPackage);
// Check if entity has any associated repository
final ClassOrInterfaceTypeDetails relatedRepositoryDetails = repositoryJpaLocator.getRepository(entity);
Validate.notNull(relatedRepositoryDetails, "Entity %s doesn't have an associated repository. You " + "need at least an associated repository with finders to publish them to the web layer." + "Please, create one associated repository with 'repository jpa' command.", entity);
// Get repository finder methods
RepositoryJpaMetadata repositoryMetadata = repositoryJpaLocator.getRepositoryMetadata(entity);
// Get finders in @RooRepositoryJpa
// List<String> entityFinders = repositoryMetadata.getDeclaredFinderNames();
List<String> entityFinders = getFindersWhichCanBePublish(repositoryMetadata, responseType);
// Check if specified finder methods exists in associated repository
for (String finder : queryMethods) {
if (!entityFinders.contains(finder)) {
LOGGER.log(Level.INFO, String.format("ERROR: Provided finder '%s' doesn't exists on the repository '%s' " + "related to entity '%s'", finder, relatedRepositoryDetails.getType().getSimpleTypeName(), entity.getSimpleTypeName()));
return;
}
}
// Check if entity has any associated service
JavaType relatedService = null;
ClassOrInterfaceTypeDetails service = serviceLocator.getService(entity);
if (service == null) {
LOGGER.log(Level.INFO, String.format("Entity %s doesn't have associated services, " + "necessary to create controllers. Please, create one associated service with " + "'service' command before publish finders to web layer.", entity.getSimpleTypeName()));
return;
}
relatedService = service.getType();
// Seek for search type controllers related to entity
Collection<ClassOrInterfaceTypeDetails> entitySearchControllers = controllerLocator.getControllers(entity, ControllerType.SEARCH, responseType.getAnnotation());
// Check if any of the search controllers have the same pathPrefix.
// If so, and controllerPackage is as well the same, update the controller.
ClassOrInterfaceTypeDetails controllerToUpdateOrCreate = null;
for (ClassOrInterfaceTypeDetails entitySearchController : entitySearchControllers) {
ControllerAnnotationValues controllerValues = new ControllerAnnotationValues(entitySearchController);
if (StringUtils.equals(pathPrefix, controllerValues.getPathPrefix())) {
if (controllerPackage.equals(entitySearchController.getType().getPackage())) {
// The controller exists, so choose it for updating.
controllerToUpdateOrCreate = entitySearchController;
break;
} else {
// A related controller already exists for the same entity, with the same 'pathPrefix',
// but in a different package.
LOGGER.log(Level.INFO, String.format("ERROR: Already exists a controller associated " + "to entity '%s' with the pathPrefix '%s', in a different package. Specify " + "a different pathPrefix to create a new one, or the same 'package' and " + "'pathPrefix' to update the existing controller.", entity.getSimpleTypeName(), pathPrefix));
return;
}
} else if (entitySearchController.getType().getPackage().equals(controllerPackage)) {
// A related controller already exists for the same entity, in the same package
LOGGER.log(Level.INFO, String.format("ERROR: Already exists a controller associated to entity '%s' in the " + "same package '%s', with different 'pathPrefix'. Specify a different 'pathPrefix' " + "and a different package that the existing one to create a new one, or the same " + "'package' and 'pathPrefix' to update the existing controller.", entity.getSimpleTypeName(), controllerPackage.getFullyQualifiedPackageName()));
return;
}
}
// Update or create the search controller
ClassOrInterfaceTypeDetailsBuilder controllerBuilder = null;
if (controllerToUpdateOrCreate == null) {
// Create controller builder for a new file
controllerBuilder = buildNewSearchController(entity, queryMethods, responseType, controllerPackage, pathPrefix);
} else {
// Controller already exists, so create builder with it
controllerBuilder = new ClassOrInterfaceTypeDetailsBuilder(controllerToUpdateOrCreate);
// Update existing controller
boolean findersAdded = updateExistingSearchController(queryMethods, controllerToUpdateOrCreate, controllerBuilder);
// Check if response type is already added
AnnotationMetadata responseTypeAnnotation = controllerToUpdateOrCreate.getAnnotation(responseType.getAnnotation());
if (responseTypeAnnotation != null) {
if (!findersAdded) {
// Controller already had same response type annotation and same finders added
LOGGER.log(Level.WARNING, String.format("Controller %s already has specified finders and specified response type.", controllerToUpdateOrCreate.getType().getFullyQualifiedTypeName()));
return;
}
} else {
// Add annotation for the new response type
controllerBuilder.addAnnotation(new AnnotationMetadataBuilder(responseType.getAnnotation()));
}
}
// Add dependencies between modules if required
addModuleDependencies(entity, relatedRepositoryDetails, relatedService, controllerBuilder.build());
// Write changes to disk
typeManagementService.createOrUpdateTypeOnDisk(controllerBuilder.build());
// Create LinkFactory class for the search controler
controllerOperations.createLinkFactoryClass(controllerBuilder.getName());
}
use of org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaMetadata in project spring-roo by spring-projects.
the class WebFinderOperationsImpl method createOrUpdateSearchControllerForAllEntities.
@Override
public void createOrUpdateSearchControllerForAllEntities(ControllerMVCResponseService responseType, JavaPackage controllerPackage, String pathPrefix) {
Validate.notNull(responseType, "responseType required");
Validate.notNull(controllerPackage, "package required");
Validate.notNull(pathPrefix, "pathPrefix required");
// Check if module has an application class
controllerPackage = checkAndUseApplicationModule(controllerPackage);
// Search all entities with associated repository
for (ClassOrInterfaceTypeDetails entityDetails : typeLocationService.findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_JPA_ENTITY)) {
JavaType entity = entityDetails.getType();
// Ignore abstract classes
if (entityDetails.isAbstract()) {
continue;
}
// Seek the repositories of each entity
RepositoryJpaMetadata repositoryMetadata = repositoryJpaLocator.getRepositoryMetadata(entity);
if (repositoryMetadata == null) {
LOGGER.log(Level.INFO, String.format("Entity %s hasn't any repository associated. Web " + "finder generation won't have effects. Use 'repository jpa' command to create repositories.", entity.getSimpleTypeName()));
}
List<String> entityFinders = getFindersWhichCanBePublish(repositoryMetadata, responseType);
if (!entityFinders.isEmpty()) {
this.createOrUpdateSearchControllerForEntity(entity, entityFinders, responseType, controllerPackage, pathPrefix);
}
}
}
use of org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaMetadata in project spring-roo by spring-projects.
the class AbstractViewGenerationService method createDetailEntityItem.
/**
* Create a new instance of {@link DetailEntityItem}. Implementation can
* override this method to include it own information or extend defaults.
*
* @param detailController
* @param detailSuffix
* @param ctx
* @param string
* @param entityMetadata
* @param entity
* @return
*/
protected DetailEntityItem createDetailEntityItem(T detailController, MemberDetails entityMembers, JpaEntityMetadata entityMetadata, String entityName, ViewContext<T> ctx, String detailSuffix, EntityItem rootEntity) {
ControllerMetadata controllerMetadata = detailController.getControllerMetadata();
RelationInfoExtended last = controllerMetadata.getLastDetailsInfo();
ClassOrInterfaceTypeDetails childEntityDetails = getTypeLocationService().getTypeDetails(last.childType);
JpaEntityMetadata childEntityMetadata = last.childEntityMetadata;
String controllerPath = getControllerOperations().getBasePathForController(controllerMetadata.getDestination());
DetailEntityItem detailItem = new DetailEntityItem(childEntityMetadata, controllerMetadata, controllerPath, detailSuffix, rootEntity);
// Saving necessary configuration
detailItem.addConfigurationElement("referencedFieldType", last.childType.getSimpleTypeName());
// Getting identifier field
detailItem.addConfigurationElement("identifierField", childEntityMetadata.getCurrentIndentifierField().getFieldName().getSymbolName());
// Getting referencedfield label plural
detailItem.addConfigurationElement("referencedFieldLabel", FieldItem.buildLabel(entityName, last.fieldName));
// Getting all referenced fields
List<FieldMetadata> referencedFields = null;
// Get the repository related with the child entity to check the default return type
RepositoryJpaMetadata repository = getRepositoryJpaLocator().getFirstRepositoryMetadata(childEntityMetadata.getAnnotatedEntity());
// All views should have a repository
Validate.notNull(repository, "ERROR: The provided child entity should have an associated repository to be able " + "to generate the list view.");
// Obtain the defaultReturnType
JavaType defaultReturnType = repository.getDefaultReturnType();
// The defaultReturnType must not be null. If it's not an entity projection,
// it must be an entity
Validate.notNull(defaultReturnType, "ERROR: The repository associated to the provided entity should define a defaultReturnType");
// Obtain details of the provided defaultReturnType. If not exists as type, show an error
ClassOrInterfaceTypeDetails defaultReturnTypeCid = getTypeLocationService().getTypeDetails(defaultReturnType);
Validate.notNull(defaultReturnTypeCid, "ERROR: The provided defaultReturnType is not a valid type");
MemberDetails defaultReturnTypeDetails = getMemberDetailsScanner().getMemberDetails(getClass().toString(), defaultReturnTypeCid);
Validate.notNull(defaultReturnTypeDetails, "ERROR: Is not possible to obtain any detail from the " + "provided defaultReturnType.");
List<FieldMetadata> defaultReturnTypeFields = defaultReturnTypeDetails.getFields();
if (defaultReturnTypeFields.isEmpty()) {
referencedFields = getEditableFields(getMemberDetailsScanner().getMemberDetails(getClass().toString(), childEntityDetails).getFields());
} else {
referencedFields = getEditableFields(defaultReturnTypeFields);
}
detailItem.addConfigurationElement("referenceFieldFields", getFieldViewItems(childEntityMetadata, referencedFields, entityName + "." + last.fieldName, true, ctx, StringUtils.EMPTY));
detailItem.addConfigurationElement("fields", getFieldViewItems(childEntityMetadata, referencedFields, detailItem.getEntityName(), true, ctx, StringUtils.EMPTY));
return detailItem;
}
Aggregations