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 extends Event> eventType, SubscriptionOptions options) {
events.put(eventType, options);
}
};
// Set up declarative subscriptions
new DeclarativeSubscriptionSource(subscriptions).configureSubscriptions(ctx);
// Invoke each SubscriptionSource
for (Class extends SubscriptionSource> clazz : subscriptions.sources()) {
injector.getInstance(clazz).configureSubscriptions(ctx);
}
// Perform actual registration
for (Map.Entry, SubscriptionOptions> entry : events.entrySet()) {
Class extends Event> 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 extends Event> 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