package org.springframework.roo.addon.dbre.addon;
import static org.springframework.roo.addon.dbre.addon.model.DbreModelService.DBRE_XML;
import static org.springframework.roo.model.JavaType.OBJECT;
import static org.springframework.roo.model.RooJavaType.ROO_DB_MANAGED;
import static org.springframework.roo.model.RooJavaType.ROO_IDENTIFIER;
import static org.springframework.roo.model.RooJavaType.ROO_JAVA_BEAN;
import static org.springframework.roo.model.RooJavaType.ROO_JPA_ENTITY;
import static org.springframework.roo.model.RooJavaType.ROO_TO_STRING;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.springframework.roo.addon.dbre.addon.model.Column;
import org.springframework.roo.addon.dbre.addon.model.Database;
import org.springframework.roo.addon.dbre.addon.model.DbreModelService;
import org.springframework.roo.addon.dbre.addon.model.Table;
import org.springframework.roo.addon.jpa.addon.identifier.Identifier;
import org.springframework.roo.addon.jpa.addon.identifier.IdentifierService;
import org.springframework.roo.addon.layers.repository.jpa.addon.RepositoryJpaOperations;
import org.springframework.roo.addon.layers.service.addon.ServiceOperations;
import org.springframework.roo.addon.test.addon.integration.IntegrationTestOperations;
import org.springframework.roo.classpath.PhysicalTypeCategory;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.TypeManagementService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.file.monitor.event.FileEvent;
import org.springframework.roo.file.monitor.event.FileEventListener;
import org.springframework.roo.file.monitor.event.FileOperation;
import org.springframework.roo.metadata.AbstractHashCodeTrackingMetadataNotifier;
import org.springframework.roo.metadata.MetadataItem;
import org.springframework.roo.model.JavaPackage;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.JdkJavaType;
import org.springframework.roo.process.manager.FileManager;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.shell.Shell;
import org.springframework.roo.support.util.CollectionUtils;
/**
* Implementation of {@link DbreDatabaseListener}.
*
* @author Alan Stewart
* @author Juan Carlos GarcĂa
* @since 1.1
*/
@Component
@Service
public class DbreDatabaseListenerImpl extends AbstractHashCodeTrackingMetadataNotifier implements
IdentifierService, FileEventListener {
private static final JavaSymbolName DB_MANAGED = new JavaSymbolName("dbManaged");
private static final String IDENTIFIER_TYPE = "identifierType";
private static final String PRIMARY_KEY_SUFFIX = "PK";
private static final String SEQUENCE_NAME_FIELD = "sequenceName";
private static final String VERSION = "version";
private static final String VERSION_FIELD = "versionField";
private DbreModelService dbreModelService;
private FileManager fileManager;
private IntegrationTestOperations integrationTestOperations;
private ProjectOperations projectOperations;
private RepositoryJpaOperations repositoryJpaOperations;
private ServiceOperations serviceOperations;
private Shell shell;
private TypeLocationService typeLocationService;
private TypeManagementService typeManagementService;
private Map<JavaType, List<Identifier>> identifierResults;
private void createIdentifierClass(final JavaType identifierType) {
final List<AnnotationMetadataBuilder> identifierAnnotations =
new ArrayList<AnnotationMetadataBuilder>();
final AnnotationMetadataBuilder identifierBuilder =
new AnnotationMetadataBuilder(ROO_IDENTIFIER);
identifierBuilder.addBooleanAttribute(DB_MANAGED.getSymbolName(), true);
identifierAnnotations.add(identifierBuilder);
// Produce identifier itself
final String declaredByMetadataId =
PhysicalTypeIdentifier.createIdentifier(identifierType, getProjectOperations()
.getPathResolver().getFocusedPath(Path.SRC_MAIN_JAVA));
final ClassOrInterfaceTypeDetailsBuilder cidBuilder =
new ClassOrInterfaceTypeDetailsBuilder(declaredByMetadataId, Modifier.PUBLIC
| Modifier.FINAL, identifierType, PhysicalTypeCategory.CLASS);
cidBuilder.setAnnotations(identifierAnnotations);
getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build());
getShell().flash(Level.FINE, "Created " + identifierType.getFullyQualifiedTypeName(),
DbreDatabaseListenerImpl.class.getName());
getShell().flash(Level.FINE, "", DbreDatabaseListenerImpl.class.getName());
}
/**
* Creates a new DBRE-managed entity from the given table
*
* @param javaType the name of the entity to be created (required)
* @param table the table from which to create the entity (required)
* @return the newly created entity
*/
private ClassOrInterfaceTypeDetails createNewManagedEntityFromTable(final JavaType javaType,
final Table table) {
// Create type annotations for new entity
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(ROO_JAVA_BEAN));
annotations.add(new AnnotationMetadataBuilder(ROO_TO_STRING));
// Find primary key from db metadata and add identifier attributes to
// @RooJpaEntity
final AnnotationMetadataBuilder jpaAnnotationBuilder =
new AnnotationMetadataBuilder(ROO_JPA_ENTITY);
manageIdentifier(javaType, jpaAnnotationBuilder, new HashSet<JavaSymbolName>(), table);
if (!hasVersionField(table)) {
jpaAnnotationBuilder.addStringAttribute(VERSION_FIELD, "");
}
if (table.isDisableGeneratedIdentifiers()) {
jpaAnnotationBuilder.addStringAttribute(SEQUENCE_NAME_FIELD, "");
}
jpaAnnotationBuilder.addStringAttribute("table", table.getName());
if (!DbreModelService.NO_SCHEMA_REQUIRED.equals(table.getSchema().getName())) {
jpaAnnotationBuilder.addStringAttribute("schema", table.getSchema().getName());
}
annotations.add(jpaAnnotationBuilder);
// Add @RooDbManaged
annotations.add(getRooDbManagedAnnotation());
final JavaType superclass = OBJECT;
final List<JavaType> extendsTypes = new ArrayList<JavaType>();
extendsTypes.add(superclass);
// Create entity class
final String declaredByMetadataId =
PhysicalTypeIdentifier.createIdentifier(javaType, getProjectOperations().getPathResolver()
.getFocusedPath(Path.SRC_MAIN_JAVA));
final ClassOrInterfaceTypeDetailsBuilder cidBuilder =
new ClassOrInterfaceTypeDetailsBuilder(declaredByMetadataId, Modifier.PUBLIC, javaType,
PhysicalTypeCategory.CLASS);
cidBuilder.setExtendsTypes(extendsTypes);
cidBuilder.setAnnotations(annotations);
final ClassOrInterfaceTypeDetails entity = cidBuilder.build();
getTypeManagementService().createOrUpdateTypeOnDisk(entity);
getShell().flash(Level.FINE, "Created " + javaType.getFullyQualifiedTypeName(),
DbreDatabaseListenerImpl.class.getName());
getShell().flash(Level.FINE, "", DbreDatabaseListenerImpl.class.getName());
return entity;
}
/**
* Deletes the given {@link JavaType} for the given reason
*
* @param javaType the type to be deleted (required)
* @param reason the reason for deletion (can be blank)
*/
private void deleteJavaType(final JavaType javaType, final String reason) {
final PhysicalTypeMetadata governorPhysicalTypeMetadata = getPhysicalTypeMetadata(javaType);
if (governorPhysicalTypeMetadata != null) {
final String filePath = governorPhysicalTypeMetadata.getPhysicalLocationCanonicalPath();
if (getFileManager().exists(filePath)) {
getFileManager().delete(filePath, reason);
getShell().flash(Level.FINE, "Deleted " + javaType.getFullyQualifiedTypeName(),
DbreDatabaseListenerImpl.class.getName());
}
getShell().flash(Level.FINE, "", DbreDatabaseListenerImpl.class.getName());
}
}
private void deleteManagedType(final ClassOrInterfaceTypeDetails managedEntity,
final String reason) {
if (!isEntityDeletable(managedEntity)) {
return;
}
deleteJavaType(managedEntity.getName(), reason);
final JavaType identifierType = getIdentifierType(managedEntity.getName());
for (final ClassOrInterfaceTypeDetails managedIdentifier : getManagedIdentifiers()) {
if (managedIdentifier.getName().equals(identifierType)) {
deleteJavaType(identifierType,
"managed identifier of deleted type " + managedEntity.getName());
break;
}
}
}
private void deserializeDatabase() {
final Database database = getDbreModelService().getDatabase(true);
if (database != null) {
identifierResults = new LinkedHashMap<JavaType, List<Identifier>>();
reverseEngineer(database);
}
}
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 = getProjectOperations().getFocusedTopLevelPackage();
}
return destinationPackage;
}
public List<Identifier> getIdentifiers(final JavaType pkType) {
if (identifierResults == null) {
// Need to populate the identifier results before returning from
// this method
deserializeDatabase();
}
if (identifierResults == null) {
// It's still null, so maybe the DBRE XML file isn't available at
// this time or similar
return null;
}
return identifierResults.get(pkType);
}
private List<Identifier> getIdentifiers(final Table table, final boolean usePrimaryKeys) {
final List<Identifier> result = new ArrayList<Identifier>();
// Add fields to the identifier class
final Set<Column> columns = usePrimaryKeys ? table.getPrimaryKeys() : table.getColumns();
for (final Column column : columns) {
final String columnName = column.getName();
JavaSymbolName fieldName;
try {
fieldName = new JavaSymbolName(DbreTypeUtils.suggestFieldName(columnName));
} catch (final RuntimeException e) {
throw new IllegalArgumentException("Failed to create field name for column '" + columnName
+ "' in table '" + table.getName() + "': " + e.getMessage());
}
final JavaType fieldType = column.getJavaType();
final String columnDefinition =
table.isIncludeNonPortableAttributes() ? column.getTypeName() : "";
result.add(new Identifier(fieldName, fieldType, columnName, column.getColumnSize(), column
.getScale(), columnDefinition));
}
return result;
}
private List<Identifier> getIdentifiersFromColumns(final Table table) {
return getIdentifiers(table, false);
}
private List<Identifier> getIdentifiersFromPrimaryKeys(final Table table) {
return getIdentifiers(table, true);
}
/**
* Returns the type of ID that DBRE should use for the given entity
*
* @param entity the entity for which to get the ID type (required)
* @return a non-<code>null</code> ID type
*/
private JavaType getIdentifierType(final JavaType entity) {
final PhysicalTypeMetadata governorPhysicalTypeMetadata = getPhysicalTypeMetadata(entity);
if (governorPhysicalTypeMetadata != null) {
final ClassOrInterfaceTypeDetails governorTypeDetails =
governorPhysicalTypeMetadata.getMemberHoldingTypeDetails();
final AnnotationMetadata jpaAnnotation = getJpaAnnotation(governorTypeDetails);
if (jpaAnnotation != null) {
final AnnotationAttributeValue<?> identifierTypeAttribute =
jpaAnnotation.getAttribute(new JavaSymbolName(IDENTIFIER_TYPE));
if (identifierTypeAttribute != null) {
// The identifierType attribute exists, so get its value
final JavaType identifierType = (JavaType) identifierTypeAttribute.getValue();
if (identifierType != null && !JdkJavaType.isPartOfJavaLang(identifierType)) {
return identifierType;
}
}
}
}
// The JPA annotation's "identifierType" attribute does not exist or is
// not a simple type, so return a default
return new JavaType(entity.getFullyQualifiedTypeName() + PRIMARY_KEY_SUFFIX);
}
/**
* Returns the JPA-related annotation on the given managed entity
*
* @param managedEntity an existing DBRE-managed entity (required)
* @return <code>null</code> if there isn't one
*/
private AnnotationMetadata getJpaAnnotation(final ClassOrInterfaceTypeDetails managedEntity) {
// The @RooJpaEntity annotation takes precedence if present
final AnnotationMetadata rooJpaEntity = managedEntity.getAnnotation(ROO_JPA_ENTITY);
return rooJpaEntity;
}
private Set<ClassOrInterfaceTypeDetails> getManagedIdentifiers() {
final Set<ClassOrInterfaceTypeDetails> managedIdentifierTypes =
new LinkedHashSet<ClassOrInterfaceTypeDetails>();
final Set<ClassOrInterfaceTypeDetails> identifierTypes =
getTypeLocationService().findClassesOrInterfaceDetailsWithAnnotation(ROO_IDENTIFIER);
for (final ClassOrInterfaceTypeDetails managedIdentifierType : identifierTypes) {
final AnnotationMetadata identifierAnnotation =
managedIdentifierType.getTypeAnnotation(ROO_IDENTIFIER);
final AnnotationAttributeValue<?> attrValue = identifierAnnotation.getAttribute(DB_MANAGED);
if (attrValue != null && (Boolean) attrValue.getValue()) {
managedIdentifierTypes.add(managedIdentifierType);
}
}
return managedIdentifierTypes;
}
private PhysicalTypeMetadata getPhysicalTypeMetadata(final JavaType javaType) {
final String declaredByMetadataId =
getTypeLocationService().getPhysicalTypeIdentifier(javaType);
if (StringUtils.isBlank(declaredByMetadataId)) {
return null;
}
return (PhysicalTypeMetadata) getMetadataService().get(declaredByMetadataId);
}
private AnnotationMetadataBuilder getRooDbManagedAnnotation() {
final AnnotationMetadataBuilder rooDbManagedBuilder =
new AnnotationMetadataBuilder(ROO_DB_MANAGED);
rooDbManagedBuilder.addBooleanAttribute("automaticallyDelete", true);
return rooDbManagedBuilder;
}
/**
* Indicates whether the given entity has the standard annotations applied
* by Roo, and no others.
*
* @param entity the entity to check (required)
* @return <code>false</code> if any of the standard ones are missing or any
* extra ones have been added
*/
private boolean hasStandardEntityAnnotations(final ClassOrInterfaceTypeDetails entity) {
final List<? extends AnnotationMetadata> typeAnnotations = entity.getAnnotations();
// We expect four: RooDbManaged, RooJavaBean, RooToString, and either
// RooEntity or RooJpaEntity
if (typeAnnotations.size() != 4) {
return false;
}
// There are exactly four - check for any non-standard ones
for (final AnnotationMetadata annotation : typeAnnotations) {
final JavaType annotationType = annotation.getAnnotationType();
final boolean entityAnnotation = ROO_JPA_ENTITY.equals(annotationType);
if (!entityAnnotation && !ROO_DB_MANAGED.equals(annotationType)
&& !ROO_JAVA_BEAN.equals(annotationType) && !ROO_TO_STRING.equals(annotationType)) {
return false;
}
}
return true;
}
private boolean hasVersionField(final Table table) {
if (!table.isDisableVersionFields()) {
for (final Column column : table.getColumns()) {
if (VERSION.equalsIgnoreCase(column.getName())) {
return true;
}
}
}
return false;
}
private boolean isEntityDeletable(final ClassOrInterfaceTypeDetails managedEntity) {
final String declaredByMetadataId =
DbreMetadata.createIdentifier(managedEntity.getName(),
PhysicalTypeIdentifier.getPath(managedEntity.getDeclaredByMetadataId()));
final DbreMetadata dbreMetadata = (DbreMetadata) getMetadataService().get(declaredByMetadataId);
if (dbreMetadata == null || !dbreMetadata.isAutomaticallyDelete()) {
return false;
}
// Check whether the type's annotations have been customised
if (!hasStandardEntityAnnotations(managedEntity)) {
return false;
}
// Finally, check for added constructors, fields and methods
return managedEntity.getDeclaredConstructors().isEmpty()
&& managedEntity.getDeclaredFields().isEmpty()
&& managedEntity.getDeclaredMethods().isEmpty();
}
private boolean isIdentifierDeletable(final JavaType identifierType) {
final PhysicalTypeMetadata governorPhysicalTypeMetadata =
getPhysicalTypeMetadata(identifierType);
if (governorPhysicalTypeMetadata == null) {
return false;
}
// Check for added constructors, fields and methods
final ClassOrInterfaceTypeDetails managedIdentifier =
governorPhysicalTypeMetadata.getMemberHoldingTypeDetails();
return managedIdentifier.getDeclaredConstructors().isEmpty()
&& managedIdentifier.getDeclaredFields().isEmpty()
&& managedIdentifier.getDeclaredMethods().isEmpty();
}
private void manageIdentifier(final JavaType javaType,
final AnnotationMetadataBuilder jpaAnnotationBuilder,
final Set<JavaSymbolName> attributesToDeleteIfPresent, final Table table) {
final JavaType identifierType = getIdentifierType(javaType);
final PhysicalTypeMetadata identifierPhysicalTypeMetadata =
getPhysicalTypeMetadata(identifierType);
// Process primary keys and add 'identifierType' attribute
final int pkCount = table.getPrimaryKeyCount();
if (pkCount == 1) {
// Table has one primary key
// Check for redundant, managed identifier class and delete if found
if (isIdentifierDeletable(identifierType)) {
deleteJavaType(identifierType, "the " + table.getName() + " table has only one primary key");
}
attributesToDeleteIfPresent.add(new JavaSymbolName(IDENTIFIER_TYPE));
// We don't need a PK class
final List<Identifier> identifiers = getIdentifiersFromPrimaryKeys(table);
identifierResults.put(javaType, identifiers);
} else if (pkCount == 0 || pkCount > 1) {
// Table has either no primary keys or more than one primary key so
// create a composite key
// Check if identifier class already exists and if not, create it
if (identifierPhysicalTypeMetadata == null || !identifierPhysicalTypeMetadata.isValid()
|| identifierPhysicalTypeMetadata.getMemberHoldingTypeDetails() == null) {
createIdentifierClass(identifierType);
}
jpaAnnotationBuilder.addClassAttribute(IDENTIFIER_TYPE, identifierType);
// We need a PK class, so we tell the IdentifierMetadataProvider via
// IdentifierService the various column names, field types and field
// names to use
// For tables with no primary keys, create a composite key using all
// the table's columns
final List<Identifier> identifiers =
pkCount == 0 ? getIdentifiersFromColumns(table) : getIdentifiersFromPrimaryKeys(table);
identifierResults.put(identifierType, identifiers);
}
}
private void notify(final List<ClassOrInterfaceTypeDetails> entities) {
for (final ClassOrInterfaceTypeDetails managedIdentifierType : getManagedIdentifiers()) {
final MetadataItem metadataItem =
getMetadataService().evictAndGet(managedIdentifierType.getDeclaredByMetadataId());
if (metadataItem != null) {
notifyIfRequired(metadataItem);
}
}
for (final ClassOrInterfaceTypeDetails entity : entities) {
final MetadataItem metadataItem =
getMetadataService().evictAndGet(entity.getDeclaredByMetadataId());
if (metadataItem != null) {
notifyIfRequired(metadataItem);
}
}
}
public void onFileEvent(final FileEvent fileEvent) {
if (fileEvent.getFileDetails().getCanonicalPath().endsWith(DBRE_XML)) {
final FileOperation operation = fileEvent.getOperation();
if (operation == FileOperation.UPDATED || operation == FileOperation.CREATED) {
deserializeDatabase();
}
}
}
private void reverseEngineer(final Database database) {
final Set<ClassOrInterfaceTypeDetails> managedEntities =
getTypeLocationService().findClassesOrInterfaceDetailsWithAnnotation(ROO_DB_MANAGED);
// 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);
if (getTypeLocationService().getTypeDetails(javaType) == null) {
table.setIncludeNonPortableAttributes(database.isIncludeNonPortableAttributes());
table.setDisableVersionFields(database.isDisableVersionFields());
table.setDisableGeneratedIdentifiers(database.isDisableGeneratedIdentifiers());
newEntities.add(createNewManagedEntityFromTable(javaType, table));
}
}
}
// Create repositories if required
if (database.isRepository()) {
for (final ClassOrInterfaceTypeDetails entity : newEntities) {
final JavaType type = entity.getType();
getRepositoryJpaOperations().addRepository(
new JavaType(type.getFullyQualifiedTypeName() + "Repository"), type, null);
}
}
// Create services if required
if (database.isService()) {
for (final ClassOrInterfaceTypeDetails entity : newEntities) {
final JavaType type = entity.getType();
final String typeName = type.getFullyQualifiedTypeName();
getServiceOperations().addService(type, new JavaType(typeName + "Service"), null);
}
}
// Create integration tests if required
if (database.isTestAutomatically()) {
for (final ClassOrInterfaceTypeDetails entity : newEntities) {
getIntegrationTestOperations().newIntegrationTest(entity.getType());
}
}
// Notify
final List<ClassOrInterfaceTypeDetails> allEntities =
new ArrayList<ClassOrInterfaceTypeDetails>();
allEntities.addAll(newEntities);
allEntities.addAll(managedEntities);
notify(allEntities);
}
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, "@%s not found on existing DBRE-managed entity %s",
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 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);
getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build());
return table;
}
/**
* Method to get DbreModelService Service implementation
*
* @return
*/
public DbreModelService getDbreModelService() {
if (dbreModelService == null) {
// Get all Services implement DbreModelService interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(DbreModelService.class.getName(), null);
for (ServiceReference<?> ref : references) {
dbreModelService = (DbreModelService) context.getService(ref);
return dbreModelService;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load DbreModelService on DbreDatabaseListenerImpl.");
return null;
}
} else {
return dbreModelService;
}
}
/**
* Method to get FileManager Service implementation
*
* @return
*/
public FileManager getFileManager() {
if (fileManager == null) {
// Get all Services implement FileManager interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(FileManager.class.getName(), null);
for (ServiceReference<?> ref : references) {
fileManager = (FileManager) context.getService(ref);
return fileManager;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load FileManager on DbreDatabaseListenerImpl.");
return null;
}
} else {
return fileManager;
}
}
/**
* Method to get IntegrationTestOperations Service implementation
*
* @return
*/
public IntegrationTestOperations getIntegrationTestOperations() {
if (integrationTestOperations == null) {
// Get all Services implement IntegrationTestOperations interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(IntegrationTestOperations.class.getName(), null);
for (ServiceReference<?> ref : references) {
integrationTestOperations = (IntegrationTestOperations) context.getService(ref);
return integrationTestOperations;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load IntegrationTestOperations on DbreDatabaseListenerImpl.");
return null;
}
} else {
return integrationTestOperations;
}
}
/**
* Method to get ProjectOperations Service implementation
*
* @return
*/
public ProjectOperations getProjectOperations() {
if (projectOperations == null) {
// Get all Services implement ProjectOperations interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(ProjectOperations.class.getName(), null);
for (ServiceReference<?> ref : references) {
projectOperations = (ProjectOperations) context.getService(ref);
return projectOperations;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load ProjectOperations on DbreDatabaseListenerImpl.");
return null;
}
} else {
return projectOperations;
}
}
/**
* Method to get RepositoryJpaOperations Service implementation
*
* @return
*/
public RepositoryJpaOperations getRepositoryJpaOperations() {
if (repositoryJpaOperations == null) {
// Get all Services implement RepositoryJpaOperations interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(RepositoryJpaOperations.class.getName(), null);
for (ServiceReference<?> ref : references) {
repositoryJpaOperations = (RepositoryJpaOperations) context.getService(ref);
return repositoryJpaOperations;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load RepositoryJpaOperations on DbreDatabaseListenerImpl.");
return null;
}
} else {
return repositoryJpaOperations;
}
}
/**
* Method to get ServiceOperations Service implementation
*
* @return
*/
public ServiceOperations getServiceOperations() {
if (serviceOperations == null) {
// Get all Services implement ServiceOperations interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(ServiceOperations.class.getName(), null);
for (ServiceReference<?> ref : references) {
serviceOperations = (ServiceOperations) context.getService(ref);
return serviceOperations;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load ServiceOperations on DbreDatabaseListenerImpl.");
return null;
}
} else {
return serviceOperations;
}
}
/**
* Method to get Shell Service implementation
*
* @return
*/
public Shell getShell() {
if (shell == null) {
// Get all Services implement Shell interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(Shell.class.getName(), null);
for (ServiceReference<?> ref : references) {
shell = (Shell) context.getService(ref);
return shell;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load Shell on DbreDatabaseListenerImpl.");
return null;
}
} else {
return shell;
}
}
/**
* Method to get TypeLocationService Service implementation
*
* @return
*/
public TypeLocationService getTypeLocationService() {
if (typeLocationService == null) {
// Get all Services implement TypeLocationService interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(TypeLocationService.class.getName(), null);
for (ServiceReference<?> ref : references) {
typeLocationService = (TypeLocationService) context.getService(ref);
return typeLocationService;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load TypeLocationService on DbreDatabaseListenerImpl.");
return null;
}
} else {
return typeLocationService;
}
}
/**
* Method to get TypeManagementService Service implementation
*
* @return
*/
public TypeManagementService getTypeManagementService() {
if (typeManagementService == null) {
// Get all Services implement TypeManagementService interface
try {
ServiceReference<?>[] references =
context.getAllServiceReferences(TypeManagementService.class.getName(), null);
for (ServiceReference<?> ref : references) {
typeManagementService = (TypeManagementService) context.getService(ref);
return typeManagementService;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load TypeManagementService on DbreDatabaseListenerImpl.");
return null;
}
} else {
return typeManagementService;
}
}
}