Example #1
0
  public static JavaType lookupTargetType(
      final ClassOrInterfaceTypeDetails cid, final boolean proxy) {
    JavaType stringBasedAnnotation = SERVICE_NAME;
    JavaType classBasedAnnotation = SERVICE;
    if (proxy) {
      stringBasedAnnotation = PROXY_FOR_NAME;
      classBasedAnnotation = PROXY_FOR;
    }
    AnnotationMetadata serviceNameAnnotation =
        MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), stringBasedAnnotation);
    if (serviceNameAnnotation != null) {
      AnnotationAttributeValue<String> serviceNameAttributeValue =
          serviceNameAnnotation.getAttribute("value");
      if (serviceNameAttributeValue != null) {
        return new JavaType(serviceNameAttributeValue.getValue());
      }
    }

    serviceNameAnnotation =
        MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), classBasedAnnotation);
    if (serviceNameAnnotation != null) {
      AnnotationAttributeValue<JavaType> serviceAttributeValue =
          serviceNameAnnotation.getAttribute("value");
      if (serviceAttributeValue != null) {
        return serviceAttributeValue.getValue();
      }
    }

    return null;
  }
  private String getDateTimeFormat() {
    String format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT)";
    if (annotations == null || annotations.isEmpty()) {
      return format;
    }

    String style = "";
    AnnotationMetadata annotation =
        MemberFindingUtils.getAnnotationOfType(annotations, DATE_TIME_FORMAT);
    if (annotation != null) {
      AnnotationAttributeValue<?> attr = annotation.getAttribute(new JavaSymbolName("style"));
      if (attr != null) {
        style = (String) attr.getValue();
      }
    }
    if (StringUtils.hasText(style)) {
      if (style.equals("S")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_SHORT)";
      } else if (style.equals("M")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_MEDIUM)";
      } else if (style.equals("F")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_FULL)";
      } else if (style.equals("S-")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT)";
      } else if (style.equals("M-")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM)";
      } else if (style.equals("F-")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_FULL)";
      }
    }
    return format;
  }
  public boolean isEmbeddable() {
    if (ptmd != null) {
      List<AnnotationMetadata> annotations = ptmd.getAnnotations();
      for (AnnotationMetadata annotation : annotations) {
        if (annotation.getAnnotationType().equals(EMBEDDABLE)) {
          return true;
        }
      }
    }

    return false;
  }
  private Set<ClassOrInterfaceTypeDetails> getManagedIdentifiers() {
    final Set<ClassOrInterfaceTypeDetails> managedIdentifierTypes =
        new LinkedHashSet<ClassOrInterfaceTypeDetails>();

    final Set<ClassOrInterfaceTypeDetails> identifierTypes =
        typeLocationService.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;
  }
Example #5
0
 public static boolean getBooleanAnnotationValue(
     final ClassOrInterfaceTypeDetails target,
     final JavaType annotationType,
     final String attributeName,
     final boolean valueIfNull) {
   AnnotationMetadata annotation =
       MemberFindingUtils.getAnnotationOfType(target.getAnnotations(), annotationType);
   if (annotation == null) {
     return valueIfNull;
   }
   AnnotationAttributeValue<?> attributeValue = annotation.getAttribute(attributeName);
   if (attributeValue != null && attributeValue instanceof BooleanAttributeValue) {
     BooleanAttributeValue booleanAttributeValue = (BooleanAttributeValue) attributeValue;
     return booleanAttributeValue.getValue();
   }
   return valueIfNull;
 }
  public void addField(final FieldMetadata field) {
    Assert.notNull(field, "Field metadata not provided");

    // Obtain the physical type and ITD mutable details
    PhysicalTypeMetadata ptm =
        (PhysicalTypeMetadata) metadataService.get(field.getDeclaredByMetadataId());
    Assert.notNull(
        ptm,
        "Java source code unavailable for type "
            + PhysicalTypeIdentifier.getFriendlyName(field.getDeclaredByMetadataId()));
    PhysicalTypeDetails ptd = ptm.getMemberHoldingTypeDetails();
    Assert.notNull(
        ptd,
        "Java source code details unavailable for type "
            + PhysicalTypeIdentifier.getFriendlyName(field.getDeclaredByMetadataId()));
    ClassOrInterfaceTypeDetailsBuilder cidBuilder =
        new ClassOrInterfaceTypeDetailsBuilder((ClassOrInterfaceTypeDetails) ptd);

    // Automatically add JSR 303 (Bean Validation API) support if there is
    // no current JSR 303 support but a JSR 303 annotation is present
    boolean jsr303Required = false;
    for (AnnotationMetadata annotation : field.getAnnotations()) {
      if (annotation
          .getAnnotationType()
          .getFullyQualifiedTypeName()
          .startsWith("javax.validation")) {
        jsr303Required = true;
        break;
      }
    }

    LogicalPath path = PhysicalTypeIdentifier.getPath(cidBuilder.getDeclaredByMetadataId());

    if (jsr303Required) {
      // It's more likely the version below represents a later version
      // than any specified in the user's own dependency list
      projectOperations.addDependency(
          path.getModule(), "javax.validation", "validation-api", "1.0.0.GA");
    }
    cidBuilder.addField(field);
    createOrUpdateTypeOnDisk(cidBuilder.build());
  }
 /**
  * If the given type is a web MVC controller, returns the ID of the WebJsonMetadata for its form
  * backing type, to ensure that any required layer components are injected. This is a workaround
  * to AspectJ not handling multiple ITDs introducing the same field (in our case the layer
  * component) into one Java class.
  *
  * @param governorTypeDetails the type to check (required)
  */
 private String getWebJsonMidIfMvcController(
     final ClassOrInterfaceTypeDetails governorTypeDetails) {
   final AnnotationMetadata controllerAnnotation =
       governorTypeDetails.getAnnotation(ROO_WEB_SCAFFOLD);
   if (controllerAnnotation != null) {
     final JavaType formBackingType =
         (JavaType) controllerAnnotation.getAttribute("formBackingObject").getValue();
     final String webJsonMetadataId = managedEntityTypes.get(formBackingType);
     if (webJsonMetadataId != null) {
       /*
        * We've been notified of a change to an MVC controller for
        * whose backing object we produce WebJsonMetadata; refresh that
        * MD to ensure our ITD does or does not introduce any required
        * layer components, as appropriate.
        */
       metadataService.get(webJsonMetadataId);
     }
   }
   return null;
 }
 /**
  * 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_ACTIVE_RECORD.equals(annotationType) || 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;
 }
  public String getFormatter() {
    if (isCollectionOfProxy()) {
      return getCollectionRenderer() + ".render";
    } else if (isDate()) {
      return getDateTimeFormat() + ".format";
    } else if (type.equals(JavaType.INT_OBJECT)
        || type.equals(JavaType.FLOAT_OBJECT)
        || type.equals(JavaType.DOUBLE_OBJECT)
        || type.equals(BIG_INTEGER)
        || type.equals(BIG_DECIMAL)) {
      String formatter = "String.valueOf";
      if (annotations == null || annotations.isEmpty()) {
        return formatter;
      }

      AnnotationMetadata annotation =
          MemberFindingUtils.getAnnotationOfType(annotations, NUMBER_FORMAT);
      if (annotation != null) {
        AnnotationAttributeValue<?> attr = annotation.getAttribute(new JavaSymbolName("style"));
        if (attr != null) {
          String style = attr.getValue().toString();
          if ("org.springframework.format.annotation.NumberFormat.Style.CURRENCY".equals(style)) {
            formatter = "NumberFormat.getCurrencyFormat().format";
          } else if ("org.springframework.format.annotation.NumberFormat.Style.PERCENT"
              .equals(style)) {
            formatter = "NumberFormat.getPercentFormat().format";
          } else {
            formatter = "NumberFormat.getDecimalFormat().format";
          }
        } else {
          formatter = "NumberFormat.getDecimalFormat().format";
        }
      }
      return formatter;
    } else if (isProxy()) {
      return getProxyRendererType() + ".instance().render";
    } else {
      return "String.valueOf";
    }
  }
 public boolean isRequestingAnnotatedWith(
     final AnnotationMetadata annotationMetadata, final String requestingMid) {
   for (final MemberHoldingTypeDetails memberHoldingTypeDetails : details) {
     if (MemberFindingUtils.getAnnotationOfType(
             memberHoldingTypeDetails.getAnnotations(), annotationMetadata.getAnnotationType())
         != null) {
       if (memberHoldingTypeDetails.getDeclaredByMetadataId().equals(requestingMid)) {
         return true;
       }
     }
   }
   return false;
 }
  /**
   * 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);
  }
Example #12
0
 public static List<String> getAnnotationValues(
     final ClassOrInterfaceTypeDetails target,
     final JavaType annotationType,
     final String attributeName) {
   List<String> values = new ArrayList<String>();
   AnnotationMetadata annotation =
       MemberFindingUtils.getAnnotationOfType(target.getAnnotations(), annotationType);
   if (annotation == null) {
     return values;
   }
   AnnotationAttributeValue<?> attributeValue = annotation.getAttribute(attributeName);
   if (attributeValue != null && attributeValue instanceof ArrayAttributeValue) {
     @SuppressWarnings("unchecked")
     ArrayAttributeValue<StringAttributeValue> arrayAttributeValue =
         (ArrayAttributeValue<StringAttributeValue>) attributeValue;
     for (StringAttributeValue value : arrayAttributeValue.getValue()) {
       values.add(value.getValue());
     }
   } else if (attributeValue != null && attributeValue instanceof StringAttributeValue) {
     StringAttributeValue stringAttributeVale = (StringAttributeValue) attributeValue;
     values.add(stringAttributeVale.getValue());
   }
   return values;
 }
  public boolean updateTypeAnnotation(
      AnnotationMetadata annotation, Set<JavaSymbolName> attributesToDeleteIfPresent) {
    boolean hasChanged = false;

    // We are going to build a replacement AnnotationMetadata.
    // This variable tracks the new attribute values the replacement will hold.
    Map<JavaSymbolName, AnnotationAttributeValue<?>> replacementAttributeValues =
        new LinkedHashMap<JavaSymbolName, AnnotationAttributeValue<?>>();

    AnnotationMetadataBuilder existingBuilder =
        MemberFindingUtils.getDeclaredTypeAnnotation(this, annotation.getAnnotationType());

    if (existingBuilder == null) {
      // Not already present, so just go and add it
      for (JavaSymbolName incomingAttributeName : annotation.getAttributeNames()) {
        // Do not copy incoming attributes which exist in the attributesToDeleteIfPresent Set
        if (attributesToDeleteIfPresent == null
            || !attributesToDeleteIfPresent.contains(incomingAttributeName)) {
          AnnotationAttributeValue<?> incomingValue =
              annotation.getAttribute(incomingAttributeName);
          replacementAttributeValues.put(incomingAttributeName, incomingValue);
        }
      }

      AnnotationMetadataBuilder replacement =
          new AnnotationMetadataBuilder(
              annotation.getAnnotationType(),
              new ArrayList<AnnotationAttributeValue<?>>(replacementAttributeValues.values()));
      addAnnotation(replacement);
      return true;
    }

    AnnotationMetadata existing = existingBuilder.build();

    // Copy the existing attributes into the new attributes
    for (JavaSymbolName existingAttributeName : existing.getAttributeNames()) {
      if (attributesToDeleteIfPresent != null
          && attributesToDeleteIfPresent.contains(existingAttributeName)) {
        hasChanged = true;
      } else {
        AnnotationAttributeValue<?> existingValue = existing.getAttribute(existingAttributeName);
        replacementAttributeValues.put(existingAttributeName, existingValue);
      }
    }

    // Now we ensure every incoming attribute replaces the existing
    for (JavaSymbolName incomingAttributeName : annotation.getAttributeNames()) {
      AnnotationAttributeValue<?> incomingValue = annotation.getAttribute(incomingAttributeName);

      // Add this attribute to the end of the list if the attribute is not already present
      if (replacementAttributeValues.keySet().contains(incomingAttributeName)) {
        // There was already an attribute. Need to determine if this new attribute value is
        // materially different
        AnnotationAttributeValue<?> existingValue =
            replacementAttributeValues.get(incomingAttributeName);
        Assert.notNull(existingValue, "Existing value should have been provided by earlier loop");
        if (!existingValue.equals(incomingValue)) {
          replacementAttributeValues.put(incomingAttributeName, incomingValue);
          hasChanged = true;
        }
      } else if (attributesToDeleteIfPresent == null
          || !attributesToDeleteIfPresent.contains(incomingAttributeName)) {
        // This is a new attribute that does not already exist, so add it to the end of the
        // replacement attributes
        replacementAttributeValues.put(incomingAttributeName, incomingValue);
        hasChanged = true;
      }
    }
    // Were there any material changes?
    if (!hasChanged) {
      return false;
    }

    // Make a new AnnotationMetadata representing the replacement
    AnnotationMetadataBuilder replacement =
        new AnnotationMetadataBuilder(
            annotation.getAnnotationType(),
            new ArrayList<AnnotationAttributeValue<?>>(replacementAttributeValues.values()));
    annotations.remove(existingBuilder);
    addAnnotation(replacement);

    return true;
  }
  public MetadataItem get(String metadataIdentificationString) {
    ProjectMetadata projectMetadata = projectOperations.getProjectMetadata();
    if (projectMetadata == null) {
      return null;
    }

    ClassOrInterfaceTypeDetails proxy = getGovernor(metadataIdentificationString);
    if (proxy == null) {
      return null;
    }

    AnnotationMetadata proxyAnnotation =
        GwtUtils.getFirstAnnotation(proxy, GwtUtils.PROXY_ANNOTATIONS);
    if (proxyAnnotation == null) {
      return null;
    }

    String locatorType = GwtUtils.getStringValue(proxyAnnotation.getAttribute("locator"));
    if (!StringUtils.hasText(locatorType)) {
      return null;
    }

    ClassOrInterfaceTypeDetails entity = gwtTypeService.lookupEntityFromProxy(proxy);
    if (entity == null) {
      return null;
    }

    MethodMetadata idAccessor = persistenceMemberLocator.getIdentifierAccessor(entity.getName());
    MethodMetadata versionAccessor = persistenceMemberLocator.getVersionAccessor(entity.getName());
    if (idAccessor == null || versionAccessor == null) {
      return null;
    }

    final JavaType idType = GwtUtils.convertPrimitiveType(idAccessor.getReturnType(), true);
    String locatorIdentifier = PhysicalTypeIdentifier.createIdentifier(new JavaType(locatorType));
    ClassOrInterfaceTypeDetailsBuilder locatorBuilder =
        new ClassOrInterfaceTypeDetailsBuilder(locatorIdentifier);
    AnnotationMetadataBuilder annotationMetadataBuilder =
        new AnnotationMetadataBuilder(RooJavaType.ROO_GWT_LOCATOR);
    annotationMetadataBuilder.addStringAttribute(
        "value", entity.getName().getFullyQualifiedTypeName());
    locatorBuilder.addAnnotation(annotationMetadataBuilder);
    annotationMetadataBuilder = new AnnotationMetadataBuilder(SpringJavaType.COMPONENT);
    locatorBuilder.addAnnotation(annotationMetadataBuilder);
    locatorBuilder.setName(new JavaType(locatorType));
    locatorBuilder.setModifier(Modifier.PUBLIC);
    locatorBuilder.setPhysicalTypeCategory(PhysicalTypeCategory.CLASS);
    locatorBuilder.addExtendsTypes(
        new JavaType(
            GwtUtils.LOCATOR.getFullyQualifiedTypeName(),
            0,
            DataType.TYPE,
            null,
            Arrays.asList(entity.getName(), idType)));
    locatorBuilder.addMethod(getCreateMethod(locatorIdentifier, entity.getName()));
    locatorBuilder.addMethod(
        getFindMethod(locatorBuilder, locatorIdentifier, entity.getName(), idType));
    locatorBuilder.addMethod(getDomainTypeMethod(locatorIdentifier, entity.getName()));
    locatorBuilder.addMethod(getIdMethod(locatorIdentifier, entity.getName(), idAccessor));
    locatorBuilder.addMethod(getIdTypeMethod(locatorIdentifier, entity.getName(), idType));
    locatorBuilder.addMethod(
        getVersionMethod(locatorIdentifier, entity.getName(), versionAccessor));

    typeManagementService.createOrUpdateTypeOnDisk(locatorBuilder.build());
    return null;
  }
  public void notify(String upstreamDependency, String downstreamDependency) {
    ProjectMetadata projectMetadata = projectOperations.getProjectMetadata();
    if (projectMetadata == null) {
      return;
    }

    if (MetadataIdentificationUtils.isIdentifyingClass(downstreamDependency)) {
      Assert.isTrue(
          MetadataIdentificationUtils.getMetadataClass(upstreamDependency)
              .equals(
                  MetadataIdentificationUtils.getMetadataClass(
                      PhysicalTypeIdentifier.getMetadataIdentiferType())),
          "Expected class-level notifications only for PhysicalTypeIdentifier (not '"
              + upstreamDependency
              + "')");

      ClassOrInterfaceTypeDetails cid =
          typeLocationService.getTypeForIdentifier(upstreamDependency);
      boolean processed = false;
      if (MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), RooJavaType.ROO_GWT_REQUEST)
          != null) {
        ClassOrInterfaceTypeDetails proxy = gwtTypeService.lookupProxyFromRequest(cid);
        if (proxy != null) {
          JavaType typeName = PhysicalTypeIdentifier.getJavaType(proxy.getDeclaredByMetadataId());
          Path typePath = PhysicalTypeIdentifier.getPath(proxy.getDeclaredByMetadataId());
          downstreamDependency = GwtLocatorMetadata.createIdentifier(typeName, typePath);
          processed = true;
        }
      }
      if (!processed
          && MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), RooJavaType.ROO_GWT_PROXY)
              == null) {
        boolean found = false;
        for (ClassOrInterfaceTypeDetails classOrInterfaceTypeDetails :
            typeLocationService.findClassesOrInterfaceDetailsWithAnnotation(
                RooJavaType.ROO_GWT_PROXY)) {
          AnnotationMetadata annotationMetadata =
              GwtUtils.getFirstAnnotation(
                  classOrInterfaceTypeDetails, GwtUtils.ROO_PROXY_REQUEST_ANNOTATIONS);
          if (annotationMetadata != null) {
            AnnotationAttributeValue<?> attributeValue = annotationMetadata.getAttribute("value");
            if (attributeValue != null) {
              String mirrorName = GwtUtils.getStringValue(attributeValue);
              if (mirrorName != null
                  && cid.getName().getFullyQualifiedTypeName().equals(attributeValue.getValue())) {
                found = true;
                JavaType typeName =
                    PhysicalTypeIdentifier.getJavaType(
                        classOrInterfaceTypeDetails.getDeclaredByMetadataId());
                Path typePath =
                    PhysicalTypeIdentifier.getPath(
                        classOrInterfaceTypeDetails.getDeclaredByMetadataId());
                downstreamDependency = GwtLocatorMetadata.createIdentifier(typeName, typePath);
                break;
              }
            }
          }
        }
        if (!found) {
          return;
        }
      } else if (!processed) {
        // A physical Java type has changed, and determine what the corresponding local metadata
        // identification string would have been
        JavaType typeName = PhysicalTypeIdentifier.getJavaType(upstreamDependency);
        Path typePath = PhysicalTypeIdentifier.getPath(upstreamDependency);
        downstreamDependency = GwtLocatorMetadata.createIdentifier(typeName, typePath);
      }

      // We only need to proceed if the downstream dependency relationship is not already registered
      // (if it's already registered, the event will be delivered directly later on)
      if (metadataDependencyRegistry
          .getDownstream(upstreamDependency)
          .contains(downstreamDependency)) {
        return;
      }
    }

    // We should now have an instance-specific "downstream dependency" that can be processed by this
    // class
    Assert.isTrue(
        MetadataIdentificationUtils.getMetadataClass(downstreamDependency)
            .equals(MetadataIdentificationUtils.getMetadataClass(getProvidesType())),
        "Unexpected downstream notification for '"
            + downstreamDependency
            + "' to this provider (which uses '"
            + getProvidesType()
            + "'");

    metadataService.get(downstreamDependency, true);
  }
  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;
  }