/** {@inheritDoc} */
  public void annotateType(final JavaType type, final JavaPackage javaPackage) {
    // TODO check for existing controller

    // Use Roo's Assert type for null checks
    Validate.notNull(type, "Java type required");
    Validate.notNull(javaPackage, "Java package required, web mvc all command package required");

    // Obtain ClassOrInterfaceTypeDetails for this java type
    ClassOrInterfaceTypeDetails entityDetails = typeLocationService.getTypeDetails(type);

    // Test if the annotation already exists on the target type
    if (entityDetails != null
        && MemberFindingUtils.getAnnotationOfType(
                entityDetails.getAnnotations(), new JavaType(RooEnvers.class.getName()))
            == null) {
      ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetailsBuilder =
          new ClassOrInterfaceTypeDetailsBuilder(entityDetails);

      // Create JavaType instance for the add-ons trigger annotation
      JavaType rooEnvers = new JavaType(RooEnvers.class.getName());

      // Create Annotation metadata
      AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder(rooEnvers);

      // Add annotation to target type
      classOrInterfaceTypeDetailsBuilder.addAnnotation(annotationBuilder.build());

      // Save changes to disk
      typeManagementService.createOrUpdateTypeOnDisk(classOrInterfaceTypeDetailsBuilder.build());
    }

    // Get details for existing controller
    JavaType typeController =
        new JavaType(
            javaPackage.getFullyQualifiedPackageName()
                + "."
                + type.getSimpleTypeName()
                + "Controller");
    ClassOrInterfaceTypeDetails typeControllerDetails =
        typeLocationService.getTypeDetails(typeController);

    // Add annotation @RooEnversController to existing controller
    ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetailsBuilder =
        new ClassOrInterfaceTypeDetailsBuilder(typeControllerDetails);
    JavaType rooEnversController =
        new JavaType("de.eightbitboy.roo.envers.controller.RooEnversController");

    final List<AnnotationAttributeValue<?>> rooEnversControllerAttributes =
        new ArrayList<AnnotationAttributeValue<?>>();
    rooEnversControllerAttributes.add(new ClassAttributeValue(new JavaSymbolName("type"), type));

    AnnotationMetadataBuilder annotationBuilder =
        new AnnotationMetadataBuilder(rooEnversController, rooEnversControllerAttributes);
    classOrInterfaceTypeDetailsBuilder.addAnnotation(annotationBuilder.build());

    typeManagementService.createOrUpdateTypeOnDisk(classOrInterfaceTypeDetailsBuilder.build());
  }
 public void createModule(
     final JavaPackage topLevelPackage,
     final String name,
     final GAV parent,
     final PackagingType packagingType) {
   Assert.isTrue(isCreateModuleAvailable(), "Cannot create modules at this time");
   final String moduleName = StringUtils.defaultIfEmpty(name, topLevelPackage.getLastElement());
   final GAV module =
       new GAV(topLevelPackage.getFullyQualifiedPackageName(), moduleName, parent.getVersion());
   final ProjectMetadata project = getProjectMetadata();
   // TODO create or update "modules" element of parent module's POM
   // Create the new module's directory, named by its artifactId (Maven standard practice)
   fileManager.createDirectory(moduleName);
   // Focus the new module so that artifacts created below go to the correct path(s)
   focus(module);
   packagingType.createArtifacts(topLevelPackage, name, "${java.version}", parent);
 }
  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);
  }