private JavaPackage getDestinationPackage( final Database database, final Set<ClassOrInterfaceTypeDetails> managedEntities) { JavaPackage destinationPackage = database.getDestinationPackage(); if (destinationPackage == null) { if (!managedEntities.isEmpty() && !database.hasMultipleSchemas()) { // Take the package of the first one destinationPackage = managedEntities.iterator().next().getName().getPackage(); } } // Fall back to project's top level package if (destinationPackage == null) { destinationPackage = projectOperations.getFocusedTopLevelPackage(); } return destinationPackage; }
/** * Indicates whether active record CRUD methods should be generated for the given entities (this * being an all or nothing decision) * * @param database the database being reverse-engineered (required) * @param managedEntities any existing DB-managed entities in the user project (can be <code>null * </code> or empty) * @return see above */ private boolean isActiveRecord( final Database database, final Collection<ClassOrInterfaceTypeDetails> managedEntities) { if (CollectionUtils.isEmpty(managedEntities)) { // There are no existing entities; use the given setting return database.isActiveRecord(); } /* * There are one or more existing entities; preserve the existing * decision, based on the first such entity. This saves the user from * having to enter the same value for the "activeRecord" option each * time they run the database reverse engineer command. */ return managedEntities.iterator().next().getAnnotation(ROO_JPA_ACTIVE_RECORD) != null; }
private Table updateOrDeleteManagedEntity( final ClassOrInterfaceTypeDetails managedEntity, final Database database) { // Update the attributes of the existing JPA-related annotation final AnnotationMetadata jpaAnnotation = getJpaAnnotation(managedEntity); Validate.validState( jpaAnnotation != null, "Neither @%s nor @%s found on existing DBRE-managed entity %s", ROO_JPA_ACTIVE_RECORD.getSimpleTypeName(), ROO_JPA_ENTITY.getSimpleTypeName(), managedEntity.getName().getFullyQualifiedTypeName()); // Find table in database using 'table' and 'schema' attributes from the // JPA annotation final AnnotationAttributeValue<?> tableAttribute = jpaAnnotation.getAttribute(new JavaSymbolName("table")); final String errMsg = "Unable to maintain database-managed entity " + managedEntity.getName().getFullyQualifiedTypeName() + " because its associated table could not be found"; Validate.notNull(tableAttribute, errMsg); final String tableName = (String) tableAttribute.getValue(); Validate.notBlank(tableName, errMsg); final AnnotationAttributeValue<?> schemaAttribute = jpaAnnotation.getAttribute(new JavaSymbolName("schema")); final String schemaName = schemaAttribute != null ? (String) schemaAttribute.getValue() : null; final Table table = database.getTable(tableName, schemaName); if (table == null) { // Table is missing and probably has been dropped so delete managed // type and its identifier if applicable deleteManagedType(managedEntity, "no database table called '" + tableName + "'"); return null; } table.setIncludeNonPortableAttributes(database.isIncludeNonPortableAttributes()); table.setDisableVersionFields(database.isDisableVersionFields()); table.setDisableGeneratedIdentifiers(database.isDisableGeneratedIdentifiers()); // Update the @RooJpaEntity/@RooJpaActiveRecord attributes final AnnotationMetadataBuilder jpaAnnotationBuilder = new AnnotationMetadataBuilder(jpaAnnotation); final Set<JavaSymbolName> attributesToDeleteIfPresent = new LinkedHashSet<JavaSymbolName>(); manageIdentifier( managedEntity.getName(), jpaAnnotationBuilder, attributesToDeleteIfPresent, table); // Manage versionField attribute final AnnotationAttributeValue<?> versionFieldAttribute = jpaAnnotation.getAttribute(new JavaSymbolName(VERSION_FIELD)); if (versionFieldAttribute == null) { if (hasVersionField(table)) { attributesToDeleteIfPresent.add(new JavaSymbolName(VERSION_FIELD)); } else { jpaAnnotationBuilder.addStringAttribute(VERSION_FIELD, ""); } } else { final String versionFieldValue = (String) versionFieldAttribute.getValue(); if (hasVersionField(table) && (StringUtils.isBlank(versionFieldValue) || VERSION.equals(versionFieldValue))) { attributesToDeleteIfPresent.add(new JavaSymbolName(VERSION_FIELD)); } } final AnnotationAttributeValue<?> sequenceNameFieldAttribute = jpaAnnotation.getAttribute(new JavaSymbolName(SEQUENCE_NAME_FIELD)); if (sequenceNameFieldAttribute == null) { if (!table.isDisableGeneratedIdentifiers()) { attributesToDeleteIfPresent.add(new JavaSymbolName(SEQUENCE_NAME_FIELD)); } else { jpaAnnotationBuilder.addStringAttribute(SEQUENCE_NAME_FIELD, ""); } } else { final String sequenceNameFieldValue = (String) sequenceNameFieldAttribute.getValue(); if (!table.isDisableGeneratedIdentifiers() && ("".equals(sequenceNameFieldValue))) { attributesToDeleteIfPresent.add(new JavaSymbolName(SEQUENCE_NAME_FIELD)); } } // Update the annotation on disk final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(managedEntity); cidBuilder.updateTypeAnnotation(jpaAnnotationBuilder.build(), attributesToDeleteIfPresent); typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build()); return table; }
private void reverseEngineer(final Database database) { final Set<ClassOrInterfaceTypeDetails> managedEntities = typeLocationService.findClassesOrInterfaceDetailsWithAnnotation(ROO_DB_MANAGED); // Determine whether to create "active record" CRUD methods database.setActiveRecord(isActiveRecord(database, managedEntities)); // Lookup the relevant destination package if not explicitly given final JavaPackage destinationPackage = getDestinationPackage(database, managedEntities); // Set the destination package in the database database.setDestinationPackage(destinationPackage); // Get tables from database final Set<Table> tables = new LinkedHashSet<Table>(database.getTables()); // Manage existing entities with @RooDbManaged annotation for (final ClassOrInterfaceTypeDetails managedEntity : managedEntities) { // Remove table from set as each managed entity is processed. // The tables that remain in the set will be used for creation of // new entities later final Table table = updateOrDeleteManagedEntity(managedEntity, database); if (table != null) { tables.remove(table); } } // Create new entities from tables final List<ClassOrInterfaceTypeDetails> newEntities = new ArrayList<ClassOrInterfaceTypeDetails>(); for (final Table table : tables) { // Don't create types from join tables in many-to-many associations if (!table.isJoinTable()) { JavaPackage schemaPackage = destinationPackage; if (database.hasMultipleSchemas()) { schemaPackage = new JavaPackage( destinationPackage.getFullyQualifiedPackageName() + "." + DbreTypeUtils.suggestPackageName(table.getSchema().getName())); } final JavaType javaType = DbreTypeUtils.suggestTypeNameForNewTable(table.getName(), schemaPackage); final boolean activeRecord = database.isActiveRecord() && !database.isRepository(); if (typeLocationService.getTypeDetails(javaType) == null) { table.setIncludeNonPortableAttributes(database.isIncludeNonPortableAttributes()); table.setDisableVersionFields(database.isDisableVersionFields()); table.setDisableGeneratedIdentifiers(database.isDisableGeneratedIdentifiers()); newEntities.add(createNewManagedEntityFromTable(javaType, table, activeRecord)); } } } // Create repositories if required if (database.isRepository()) { for (final ClassOrInterfaceTypeDetails entity : newEntities) { final JavaType type = entity.getType(); repositoryJpaOperations.setupRepository( new JavaType(type.getFullyQualifiedTypeName() + "Repository"), type); } } // Create services if required if (database.isService()) { for (final ClassOrInterfaceTypeDetails entity : newEntities) { final JavaType type = entity.getType(); final String typeName = type.getFullyQualifiedTypeName(); serviceOperations.setupService( new JavaType(typeName + "Service"), new JavaType(typeName + "ServiceImpl"), type, false, "", false, false); } } // Create integration tests if required if (database.isTestAutomatically()) { for (final ClassOrInterfaceTypeDetails entity : newEntities) { integrationTestOperations.newIntegrationTest(entity.getType()); } } // Notify final List<ClassOrInterfaceTypeDetails> allEntities = new ArrayList<ClassOrInterfaceTypeDetails>(); allEntities.addAll(newEntities); allEntities.addAll(managedEntities); notify(allEntities); }