All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.getperka.sea.jms.impl.SubscriptionObserver Maven / Gradle / Ivy

package com.getperka.sea.jms.impl;

/*
 * #%L
 * Simple Event Architecture - JMS Support
 * %%
 * Copyright (C) 2012 Perka Inc.
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.inject.Inject;
import javax.inject.Singleton;

import com.getperka.sea.Event;
import com.getperka.sea.ext.EventObserver;
import com.getperka.sea.jms.EventSubscriberException;
import com.getperka.sea.jms.RoutingMode;
import com.getperka.sea.jms.SubscriptionOptions;
import com.getperka.sea.jms.Subscriptions;
import com.getperka.sea.jms.ext.SubscriptionSource;
import com.google.inject.Injector;

/**
 * Intercepts events from the local EventDispatch and forwards them to the JMS subscription logic.
 */
@Singleton
public class SubscriptionObserver implements EventObserver {

  private Injector injector;
  private ConcurrentMap, Boolean> shouldSuppress =
      new ConcurrentHashMap, Boolean>();
  private EventSubscriber subscriber;

  protected SubscriptionObserver() {}

  @Override
  public void initialize(Subscriptions subscriptions) {
    final Map, SubscriptionOptions> events =
        new HashMap, SubscriptionOptions>();

    // A simple context implementation that drops subscriptions into the map
    SubscriptionSource.Context ctx = new SubscriptionSource.Context() {
      @Override
      public void subscribe(Class eventType, SubscriptionOptions options) {
        events.put(eventType, options);
      }
    };

    // Set up declarative subscriptions
    new DeclarativeSubscriptionSource(subscriptions).configureSubscriptions(ctx);

    // Invoke each SubscriptionSource
    for (Class clazz : subscriptions.sources()) {
      injector.getInstance(clazz).configureSubscriptions(ctx);
    }

    // Perform actual registration
    for (Map.Entry, SubscriptionOptions> entry : events.entrySet()) {
      Class eventType = entry.getKey();
      SubscriptionOptions options = entry.getValue();
      try {
        shouldSuppress.put(eventType, RoutingMode.REMOTE.equals(options.routingMode()));
        subscriber.subscribe(eventType, options);
      } catch (EventSubscriberException e) {
        throw new RuntimeException("Could not subscribe to event", e);
      }
    }
  }

  @Override
  public void observeEvent(Context context) {
    // Allow events being sent by a subscription to be dispatched normally
    if (context.getContext().getUserObject() instanceof EventSubscription) {
      return;
    }
    if (shouldSuppress(context.getEvent().getClass())) {
      context.suppressEvent();
    }
    subscriber.fire(context.getOriginalEvent(), context.getContext().getUserObject());
  }

  @Override
  public void shutdown() {
    subscriber.shutdown();
  }

  @Inject
  void inject(Injector injector, EventSubscriber subscriber) {
    this.injector = injector;
    this.subscriber = subscriber;
  }

  private boolean shouldSuppress(Class eventType) {
    Boolean suppress = shouldSuppress.get(eventType);
    if (Boolean.TRUE.equals(suppress)) {
      return true;
    }

    // Shouldn't be the usual case, but look for the first assignable type and copy that value
    for (Map.Entry, Boolean> entry : shouldSuppress.entrySet()) {
      if (entry.getKey().isAssignableFrom(eventType)) {
        suppress = entry.getValue();
        shouldSuppress.put(eventType, suppress);
        return suppress;
      }
    }

    // Memoize ignoring everything else
    shouldSuppress.put(eventType, false);
    return false;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy