private final Method resolveCallbackMethod(
     final CallbackHandler<?> callbackHandler, final CallbackType callbackType) {
   final Class<? extends CallbackType> callbackTypeClass = callbackType.getClass();
   {
     final Class<? extends Annotation> specificAnnotationClass;
     if (callbackTypeClass == CloudletCallbackType.class)
       specificAnnotationClass = CloudletCallbackM.class;
     else if (callbackTypeClass == QueueConsumerCallbackType.class)
       specificAnnotationClass = QueueConsumerCallbackM.class;
     else if (callbackTypeClass == QueuePublisherCallbackType.class)
       specificAnnotationClass = QueuePublisherCallbackM.class;
     else throw (new IllegalArgumentException());
     for (final Method method : callbackHandler.getClass().getMethods()) {
       final Annotation specificAnnotation = method.getAnnotation(specificAnnotationClass);
       if (specificAnnotation != null) {
         final CallbackType[] acceptedCallbackTypes;
         if (specificAnnotationClass == CloudletCallbackM.class)
           acceptedCallbackTypes = ((CloudletCallbackM) specificAnnotation).types();
         else if (specificAnnotationClass == QueueConsumerCallbackM.class)
           acceptedCallbackTypes = ((QueueConsumerCallbackM) specificAnnotation).types();
         else if (specificAnnotationClass == QueuePublisherCallbackM.class)
           acceptedCallbackTypes = ((QueuePublisherCallbackM) specificAnnotation).types();
         else acceptedCallbackTypes = null;
         if (acceptedCallbackTypes != null)
           for (final CallbackType acceptedCallbackType : acceptedCallbackTypes)
             if (acceptedCallbackType == callbackType) return (method);
       }
     }
   }
   {
     for (final Method method : callbackHandler.getClass().getMethods()) {
       final GenericCallbackM genericAnnotation = method.getAnnotation(GenericCallbackM.class);
       if (genericAnnotation != null)
         for (final Class<? extends CallbackType> acceptedCallbackTypeClass :
             genericAnnotation.types())
           if (acceptedCallbackTypeClass.isAssignableFrom(callbackTypeClass)) return (method);
     }
   }
   return (null);
 }
  private final void handleCallback(
      final Object cloudlet, final eu.mosaic_cloud.callbacks.core.Callback callback) {
    assert (cloudlet == this);

    synchronized (this) {
      final CallbackType callbackType = callback.getType();
      final CallbackArguments callbackArguments = callback.getArguments();
      final CallbackTag callbackTag = callback.getTag();

      Transcript.traceEvent(
          "dispatching cloudlet callback: `%s`@`%s`",
          callbackType.getClass().getName(), callbackType);

      if (callbackTag instanceof CallbackRecord) {

        final CallbackRecord callbackRecord = (CallbackRecord) callbackTag;
        final CallbackHandler<?> callbackHandler_ = callbackRecord.callbackHandler;
        final Object callbackState = callbackRecord.callbackState;

        if (callbackType instanceof CloudletCallbackType) {

          if (callbackType == CloudletCallbackType.Initialize)
            this.handleInitializeCallback((CloudletCallbackGenericArguments) callbackArguments);
          else if (callbackType == CloudletCallbackType.Destroy)
            this.handleDestroyCallback((CloudletCallbackGenericArguments) callbackArguments);
          else if (callbackHandler_ instanceof GenericCallback) {

            final GenericCallback<Object> callbackHandler =
                (GenericCallback<Object>) callbackHandler_;
            callbackHandler.callback(
                callbackState,
                BasicCallback.create(this.internals, callbackType, callbackArguments));

          } else if (callbackHandler_ instanceof CloudletCallback) {

            final CloudletCallback<Object> callbackHandler =
                (CloudletCallback<Object>) callbackHandler_;

            switch ((CloudletCallbackType) callbackType) {
              case InitializeSucceeded:
                callbackHandler.initializeSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (CloudletCallbackType) callbackType,
                        (CloudletCallbackGenericArguments) callbackArguments));
                break;
              case InitializeFailed:
                callbackHandler.initializeFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (CloudletCallbackType) callbackType,
                        (CloudletCallbackGenericArguments) callbackArguments));
                break;
              case DestroySucceeded:
                callbackHandler.destroySucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (CloudletCallbackType) callbackType,
                        (CloudletCallbackGenericArguments) callbackArguments));
                break;
              case DestroyFailed:
                callbackHandler.destroyFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (CloudletCallbackType) callbackType,
                        (CloudletCallbackGenericArguments) callbackArguments));
                break;
              default:
                throw (new UnsupportedOperationException(
                    String.format("unknown callback type: %s", callbackType)));
            }

          } else if (callbackHandler_ instanceof AnnotatedCallback) {

            final Method callbackMethod =
                this.resolveCallbackMethod(callbackHandler_, callbackType);
            if (callbackMethod != null)
              this.invokeCallbackMethod(
                  callbackMethod, callbackHandler_, callbackState, callbackType, callbackArguments);
            else
              throw (new UnsupportedOperationException(
                  String.format("unhandled callback type: %s", callbackType)));

          } else
            throw (new IllegalArgumentException(
                String.format("unknown callback class: %s", callback.getClass())));

        } else if (callbackType instanceof QueueConsumerCallbackType) {

          if (callbackHandler_ instanceof GenericCallback) {

            final GenericCallback<Object> callbackHandler =
                (GenericCallback<Object>) callbackHandler_;
            callbackHandler.callback(
                callbackState,
                BasicCallback.create(this.internals, callbackType, callbackArguments));

          } else if (callbackHandler_ instanceof QueueConsumerCallback) {

            final QueueConsumerCallback<Object> callbackHandler =
                (QueueConsumerCallback<Object>) callbackHandler_;

            switch ((QueueConsumerCallbackType) callbackType) {
              case InitializeSucceeded:
                callbackHandler.initializeSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case InitializeFailed:
                callbackHandler.initializeFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case DestroySucceeded:
                callbackHandler.destroySucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case DestroyFailed:
                callbackHandler.destroyFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case RegisterSucceeded:
                callbackHandler.registerSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case RegisterFailed:
                callbackHandler.registerFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case UnregisterSucceeded:
                callbackHandler.unregisterSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case UnregisterFailed:
                callbackHandler.unregisterFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackGenericArguments) callbackArguments));
                break;
              case Consume:
                callbackHandler.consume(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackConsumeArguments) callbackArguments));
                break;
              case AcknowledgeSucceeded:
                callbackHandler.acknowledgeSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackAcknowledgeArguments) callbackArguments));
                break;
              case AcknowledgeFailed:
                callbackHandler.acknowledgeFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueueConsumerCallbackType) callbackType,
                        (QueueConsumerCallbackAcknowledgeArguments) callbackArguments));
                break;
              default:
                throw (new UnsupportedOperationException(
                    String.format("unknown callback type: %s", callbackType)));
            }

          } else if (callbackHandler_ instanceof AnnotatedCallback) {

            final Method callbackMethod =
                this.resolveCallbackMethod(callbackHandler_, callbackType);
            if (callbackMethod != null)
              this.invokeCallbackMethod(
                  callbackMethod, callbackHandler_, callbackState, callbackType, callbackArguments);
            else
              throw (new UnsupportedOperationException(
                  String.format("unhandled callback type: %s", callbackType)));

          } else
            throw (new IllegalArgumentException(
                String.format("unknown callback class: %s", callback.getClass())));

        } else if (callbackType instanceof QueuePublisherCallbackType) {

          if (callbackHandler_ instanceof GenericCallback) {

            final GenericCallback<Object> callbackHandler =
                (GenericCallback<Object>) callbackHandler_;
            callbackHandler.callback(
                callbackState,
                BasicCallback.create(this.internals, callbackType, callbackArguments));

          } else if (callbackHandler_ instanceof QueuePublisherCallback) {

            final QueuePublisherCallback<Object> callbackHandler =
                (QueuePublisherCallback<Object>) callbackHandler_;

            switch ((QueuePublisherCallbackType) callbackType) {
              case InitializeSucceeded:
                callbackHandler.initializeSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case InitializeFailed:
                callbackHandler.initializeFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case DestroySucceeded:
                callbackHandler.destroySucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case DestroyFailed:
                callbackHandler.destroyFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case RegisterSucceeded:
                callbackHandler.registerSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case RegisterFailed:
                callbackHandler.registerFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case UnregisterSucceeded:
                callbackHandler.unregisterSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case UnregisterFailed:
                callbackHandler.unregisterFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackGenericArguments) callbackArguments));
                break;
              case PublishSucceeded:
                callbackHandler.publishSucceeded(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackPublishArguments) callbackArguments));
                break;
              case PublishFailed:
                callbackHandler.publishFailed(
                    callbackState,
                    BasicCallback.create(
                        this.internals,
                        (QueuePublisherCallbackType) callbackType,
                        (QueuePublisherCallbackPublishArguments) callbackArguments));
                break;
              default:
                throw (new UnsupportedOperationException(
                    String.format("unknown callback type: %s", callbackType)));
            }

          } else if (callbackHandler_ instanceof AnnotatedCallback) {

            final Method callbackMethod =
                this.resolveCallbackMethod(callbackHandler_, callbackType);
            if (callbackMethod != null)
              this.invokeCallbackMethod(
                  callbackMethod, callbackHandler_, callbackState, callbackType, callbackArguments);
            else
              throw (new UnsupportedOperationException(
                  String.format("unhandled callback type: %s", callbackType)));

          } else
            throw (new IllegalArgumentException(
                String.format("unknown callback class: %s", callback.getClass())));

        } else
          throw (new UnsupportedOperationException(
              String.format("unknown callback type: %s", callbackType)));
      } else
        throw (new IllegalArgumentException(
            String.format("invalid callback tag: %s", callbackTag)));
    }
  }