quickfix.ApplicationFunctionalAdapter Maven / Gradle / Ivy
package quickfix;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* This is an adapter implementation of Application interface that transforms the usage into more functional style.
* It breaks down each interface method into a number of single-method interfaces, which can be supplied with lambda
* expressions. Each single-method interface has its own add and remove listener method.
*
*
* - Support multiple listeners of the same operation, e.g. onLogon. The method of the listeners will be invoked
* in the same order of when add method was invoked, i.e. FIFO
* - Support type-safe listeners to be registered. However, FIFO order is maintained separated for type-safe and
* generic Message listeners
* - Support fail fast exception propagation for fromAdmin, toApp, and fromApp. The exception will be thrown for
* the first encountered exception.
* - Provides a thread-safe way to delegate to, add and remove listeners, by the means of concurrent and immutable
* collections, under the assumption that adding and removing listeners are rare.
*
*/
public class ApplicationFunctionalAdapter implements Application {
private final List> onCreateListeners = new CopyOnWriteArrayList<>();
private final List> onLogonListeners = new CopyOnWriteArrayList<>();
private final List> onLogoutListeners = new CopyOnWriteArrayList<>();
private final List> toAdminListeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap> toAdminTypeSafeListeners = new ConcurrentHashMap<>();
private final List> fromAdminListeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap> fromAdminTypeSafeListeners = new ConcurrentHashMap<>();
private final List> toAppListeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap> toAppTypeSafeListeners = new ConcurrentHashMap<>();
private final List> fromAppListeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap> fromAppTypeSafeListeners = new ConcurrentHashMap<>();
/**
* Add a Consumer of SessionID to listen to onCreate operation.
*
* @param onCreateListener the Consumer of Session for onCreate operation.
*/
public void addOnCreateListener(Consumer onCreateListener) {
onCreateListeners.add(onCreateListener);
}
/**
* Remove a Consumer of SessionID from onCreate operation.
*
* @param onCreateListener the Consumer of Session for onCreate operation.
*/
public void removeOnCreateListener(Consumer onCreateListener) {
onCreateListeners.remove(onCreateListener);
}
/**
* Add a Consumer of SessionID to listen to onLogon operation.
*
* @param onLogonListener the Consumer of Session for onLogon operation.
*/
public void addOnLogonListener(Consumer onLogonListener) {
onLogonListeners.add(onLogonListener);
}
/**
* Remove a Consumer of SessionID from onLogon operation.
*
* @param onLogonListener the Consumer of Session for onLogon operation.
*/
public void removeOnLogonListener(Consumer onLogonListener) {
onLogonListeners.remove(onLogonListener);
}
/**
* Add a Consumer of SessionID to listen to onLogout operation.
*
* @param onLogoutListener the Consumer of Session for onLogout operation.
*/
public void addOnLogoutListener(Consumer onLogoutListener) {
onLogoutListeners.add(onLogoutListener);
}
/**
* Remove a Consumer of SessionID from onLogout operation.
*
* @param onLogoutListener the Consumer of Session for onLogout operation.
*/
public void removeOnLogoutListener(Consumer onLogoutListener) {
onLogoutListeners.remove(onLogoutListener);
}
/**
* Add a BiConsumer of SessionID to listen to toAdmin operation.
*
* @param toAdminListener the BiConsumer of Session for toAdmin operation.
*/
public void addToAdminListener(BiConsumer toAdminListener) {
toAdminListeners.add(toAdminListener);
}
/**
* Add a type-safe BiConsumer of SessionID to listen to toAdmin operation.
*
* @param clazz the specific Message class the listener expects
* @param toAdminListener the BiConsumer of Session for toAdmin operation.
*/
public void addToAdminListener(Class clazz, BiConsumer toAdminListener) {
getList(toAdminTypeSafeListeners, clazz)
.add(toAdminListener);
}
/**
* Remove a BiConsumer of SessionID from toAdmin operation.
*
* @param toAdminListener the BiConsumer of Session for toAdmin operation.
*/
public void removeToAdminListener(BiConsumer toAdminListener) {
toAdminListeners.remove(toAdminListener);
toAdminTypeSafeListeners
.values()
.forEach(list -> list.remove(toAdminListener));
}
/**
* Add a listener of fromAdmin operation.
*
* @param fromAdminListener the listener of fromAdmin operation.
*/
public void addFromAdminListener(FromAdminListener fromAdminListener) {
fromAdminListeners.add(fromAdminListener);
}
/**
* Add a listener of fromAdmin operation.
*
* @param clazz the specific Message class the listener expects
* @param fromAdminListener the listener of fromAdmin operation.
*/
public void addFromAdminListener(Class clazz, FromAdminListener fromAdminListener) {
getList(fromAdminTypeSafeListeners, clazz)
.add(fromAdminListener);
}
/**
* Remove a listener of fromAdmin operation.
*
* @param fromAdminListener the listener of fromAdmin operation.
*/
public void removeFromAdminListener(FromAdminListener fromAdminListener) {
fromAdminListeners.remove(fromAdminListener);
fromAdminTypeSafeListeners
.values()
.forEach(list -> list.remove(fromAdminListener));
}
/**
* Add a listener of toApp operation.
*
* @param toAppListener the listener of fromAdmin operation.
*/
public void addToAppListener(ToAppListener toAppListener) {
toAppListeners.add(toAppListener);
}
/**
* Add a listener of toApp operation.
*
* @param clazz the specific Message class the listener expects
* @param toAppListener the listener of fromAdmin operation.
*/
public void addToAppListener(Class clazz, ToAppListener toAppListener) {
getList(toAppTypeSafeListeners, clazz)
.add(toAppListener);
}
/**
* Remove a listener of toApp operation.
*
* @param toAppListener the listener of toApp operation.
*/
public void removeToAppListener(ToAppListener toAppListener) {
toAppListeners.remove(toAppListener);
toAppTypeSafeListeners
.values()
.forEach(list -> list.remove(toAppListener));
}
/**
* Add a listener of fromApp operation.
*
* @param fromAppListener the listener of fromApp operation.
*/
public void addFromAppListener(FromAppListener fromAppListener) {
fromAppListeners.add(fromAppListener);
}
/**
* Add a listener of fromApp operation.
*
* @param clazz the specific Message class the listener expects
* @param fromAppListener the listener of fromApp operation.
*/
public void addFromAppListener(Class clazz, FromAppListener fromAppListener) {
getList(fromAppTypeSafeListeners, clazz)
.add(fromAppListener);
}
/**
* Remove a listener of fromApp operation.
*
* @param fromAppListener the listener of fromApp operation.
*/
public void removeFromAppListener(FromAppListener fromAppListener) {
fromAppListeners.remove(fromAppListener);
fromAppTypeSafeListeners
.values()
.forEach(list -> list.remove(fromAppListener));
}
@Override
public void onCreate(SessionID sessionId) {
onCreateListeners.forEach(c -> c.accept(sessionId));
}
@Override
public void onLogon(SessionID sessionId) {
onLogonListeners.forEach(c -> c.accept(sessionId));
}
@Override
public void onLogout(SessionID sessionId) {
onLogoutListeners.forEach(c -> c.accept(sessionId));
}
@Override
public void toAdmin(Message message, SessionID sessionId) {
toAdminListeners.forEach(c -> c.accept(message, sessionId));
getList(toAdminTypeSafeListeners, message.getClass())
.forEach(c -> c.accept(message, sessionId));
}
@Override
public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon {
for (FromAdminListener listener : fromAdminListeners) {
listener.accept(message, sessionId);
}
for (FromAdminListener listener : getList(fromAdminTypeSafeListeners, message.getClass())) {
listener.accept(message, sessionId);
}
}
@Override
public void toApp(Message message, SessionID sessionId) throws DoNotSend {
for (ToAppListener listener : toAppListeners) {
listener.accept(message, sessionId);
}
for (ToAppListener listener : getList(toAppTypeSafeListeners, message.getClass())) {
listener.accept(message, sessionId);
}
}
@Override
public void fromApp(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
for (FromAppListener listener : fromAppListeners) {
listener.accept(message, sessionId);
}
for (FromAppListener listener : getList(fromAppTypeSafeListeners, message.getClass())) {
listener.accept(message, sessionId);
}
}
private List getList(ConcurrentMap> multimap, Class clazz) {
return multimap.computeIfAbsent(clazz, k -> new CopyOnWriteArrayList<>());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy