@Override
  protected void processAnnotations(DeploymentUnit deploymentUnit, CompositeIndex compositeIndex)
      throws DeploymentUnitProcessingException {
    if (MetadataCompleteMarker.isMetadataComplete(deploymentUnit)) {
      return;
    }

    processMessageBeans(
        deploymentUnit,
        compositeIndex.getAnnotations(MESSAGE_DRIVEN_ANNOTATION_NAME),
        compositeIndex);
  }
  /** Process annotations and merge any available metadata at the same time. */
  @Override
  protected void processAnnotations(
      final DeploymentUnit deploymentUnit, final CompositeIndex compositeIndex)
      throws DeploymentUnitProcessingException {

    if (MetadataCompleteMarker.isMetadataComplete(deploymentUnit)) {
      return;
    }

    // Find and process any @Stateless bean annotations
    final List<AnnotationInstance> slsbAnnotations =
        compositeIndex.getAnnotations(STATELESS_ANNOTATION);
    if (!slsbAnnotations.isEmpty()) {
      processSessionBeans(
          deploymentUnit,
          slsbAnnotations,
          SessionBeanComponentDescription.SessionBeanType.STATELESS);
    }

    // Find and process any @Stateful bean annotations
    final List<AnnotationInstance> sfsbAnnotations =
        compositeIndex.getAnnotations(STATEFUL_ANNOTATION);
    if (!sfsbAnnotations.isEmpty()) {
      processSessionBeans(
          deploymentUnit,
          sfsbAnnotations,
          SessionBeanComponentDescription.SessionBeanType.STATEFUL);
    }

    // Find and process any @Singleton bean annotations
    final List<AnnotationInstance> sbAnnotations =
        compositeIndex.getAnnotations(SINGLETON_ANNOTATION);
    if (!sbAnnotations.isEmpty()) {
      processSessionBeans(
          deploymentUnit, sbAnnotations, SessionBeanComponentDescription.SessionBeanType.SINGLETON);
    }
  }
  private void processComponentConfig(
      final DeploymentUnit deploymentUnit,
      final EEApplicationClasses applicationClasses,
      final Module module,
      final DeploymentReflectionIndex deploymentReflectionIndex,
      final SessionBeanComponentDescription description)
      throws DeploymentUnitProcessingException, ClassNotFoundException {
    String home = null;
    String localHome = null;

    // first check for annotations
    if (!MetadataCompleteMarker.isMetadataComplete(deploymentUnit)) {
      final EEModuleClassDescription clazz =
          applicationClasses.getClassByName(description.getComponentClassName());
      // we only care about annotations on the bean class itself
      if (clazz != null) {
        final ClassAnnotationInformation<LocalHome, String> localAnnotations =
            clazz.getAnnotationInformation(LocalHome.class);
        if (localAnnotations != null) {
          if (!localAnnotations.getClassLevelAnnotations().isEmpty()) {
            localHome = localAnnotations.getClassLevelAnnotations().get(0);

            if (description.getEjbLocalView() == null) {
              // If the local home is specified via annotation then the corresponding business
              // interface is implied
              // by the signature of the create method
              // See EJB 3.1 21.4.5
              final String localClassName =
                  this.inferLocalInterfaceFromLocalHome(
                      localHome, module, deploymentReflectionIndex, description);
              description.addEjbLocalObjectView(localClassName);
            }
          }
        }
        final ClassAnnotationInformation<RemoteHome, String> remoteAnnotations =
            clazz.getAnnotationInformation(RemoteHome.class);
        if (remoteAnnotations != null) {
          if (!remoteAnnotations.getClassLevelAnnotations().isEmpty()) {
            home = remoteAnnotations.getClassLevelAnnotations().get(0);
            if (description.getEjbRemoteView() == null) {
              // If the remote home is specified via annotation then the corresponding business
              // interface is implied
              // by the signature of the create method
              // See EJB 3.1 21.4.5
              final String remoteClassName =
                  this.inferRemoteInterfaceFromHome(
                      home, module, deploymentReflectionIndex, description);
              description.addEjbObjectView(remoteClassName);
            }
          }
        }
      }
    }
    // now allow the annotations to be overridden by the DD
    final SessionBeanMetaData descriptorData = description.getDescriptorData();
    if (descriptorData != null) {

      if (descriptorData.getHome() != null) {
        home = descriptorData.getHome();
      }
      if (descriptorData.getLocalHome() != null) {
        localHome = descriptorData.getLocalHome();
      }
    }
    if (localHome != null) {
      description.addLocalHome(localHome);
    }
    if (home != null) {
      description.addRemoteHome(home);
    }
    // finally see if we have to infer the remote or local interface from the home/local home views,
    // respectively
    if (description.getEjbHomeView() != null && description.getEjbRemoteView() == null) {
      final String remoteClassName =
          this.inferRemoteInterfaceFromHome(
              description.getEjbHomeView().getViewClassName(),
              module,
              deploymentReflectionIndex,
              description);
      description.addEjbObjectView(remoteClassName);
    }
    if (description.getEjbLocalHomeView() != null && description.getEjbLocalView() == null) {
      final String localClassName =
          this.inferLocalInterfaceFromLocalHome(
              description.getEjbLocalHomeView().getViewClassName(),
              module,
              deploymentReflectionIndex,
              description);
      description.addEjbLocalObjectView(localClassName);
    }
  }