package org.openflow.util;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
/**
* The following implement a producer/consumer design pattern in which both
* producers and consumers explicitly employ a centralized registration
* mechanism, and java Interfaces are used as contracts.<br>
*/
public class ProducerConsumer {
/*
* Class variables
*/
protected static ProducerConsumer singleton;
/*
* Default constructor
*/
protected ProducerConsumer() {
producerMap = new Hashtable<Class<?>, Set<IProducer>>();
}
/*
* Instance variables
*/
// Interface/IProducer map
protected Map<Class<?>, Set<IProducer>> producerMap;
/*
* Protected methods
*/
protected void _registerConsumer(Object consumer, Class<?>[] interfaces,
Set<Class<?>> iSet,
Set<Class<?>> iUniqueSet) {
// *...Process all interfaces...*/
for (Class<?> iface : interfaces) {
// *...Protect against repeated interfaces...*/
if (!iUniqueSet.contains(iface)) {
iUniqueSet.add(iface);
Set<IProducer> producers = producerMap.get(iface);
if (producers != null) {
for (IProducer producer : producers)
producer.registerConsumer(iface, consumer);
iSet.add(iface);
}
// *...Recurse...*/
_registerConsumer(consumer, iface.getInterfaces(), iSet,
iUniqueSet);
}
}
}
protected void _registerConsumer(Object consumer, Class<?> clazz,
Set<Class<?>> iSet,
Set<Class<?>> iUniqueSet) {
if (clazz != null) {
// *...Process all interfaces...*/
_registerConsumer(consumer, clazz.getInterfaces(), iSet,
iUniqueSet);
// *...Recurse the class hierarchy...*/
_registerConsumer(consumer, clazz.getSuperclass(), iSet,
iUniqueSet);
}
}
protected int _deregisterConsumer(Object consumer,
Class<?>[] interfaces,
Set<Class<?>> iUniqueSet) {
int count = 0;
// *...Process all interfaces...*/
for (Class<?> iface : interfaces) {
// *...Protect against repeated interfaces...*/
if (!iUniqueSet.contains(iface)) {
iUniqueSet.add(iface);
Set<IProducer> producers = producerMap.get(iface);
if (producers != null) {
for (IProducer producer : producers)
producer.deregisterConsumer(iface, consumer);
count++;
}
// *...Recurse...*/
count += _deregisterConsumer(consumer,
iface.getInterfaces(),
iUniqueSet);
}
}
return count;
}
protected int _deregisterConsumer(Object consumer, Class<?> clazz,
Set<Class<?>> iUniqueSet) {
int count = 0;
if (clazz != null) {
// *...Process all interfaces...*/
count += _deregisterConsumer(consumer, clazz.getInterfaces(),
iUniqueSet);
// *...Recurse the class hierarchy...*/
count += _deregisterConsumer(consumer, clazz.getSuperclass(),
iUniqueSet);
}
return count;
}
/*
* Singleton API
*/
/**
* @return singleton ProducerConsumer
*/
public static synchronized ProducerConsumer getSingleton() {
if (singleton == null) singleton = new ProducerConsumer();
return singleton;
}
/*
* Producer APIs
*/
/**
* Producer registration
*
* @param producer
* object that implements IProducer
* @param iface
* interface supported by the producer
* @return whether there was a previously registered producer, or true if
* one or more the arguments were invalid
*/
public boolean registerProducer(IProducer producer, Class<?> iface) {
if (producer != null && iface != null && iface.isInterface()) {
Set<IProducer> producers = producerMap.get(iface);
if (producers == null) {
producers = new HashSet<IProducer>();
producerMap.put(iface, producers);
}
return producers.add(producer);
} else
return true;
}
/**
* Producer deregistration
*
* @param producer
* object that implements IProducer
* @param iface
* interface supported by the producer
* @return whether the interface/producer pair was removed, or false if one
* or more the arguments were invalid
*/
public boolean deregisterProducer(IProducer producer, Class<?> iface) {
if (producer != null && iface != null && iface.isInterface()) {
Set<IProducer> producers = producerMap.get(iface);
if (producers != null) return producers.remove(producer);
}
return false;
}
/*
* Consumer APIs
*/
/**
* Consumer registration
*
* @param consumer
* object that implements producer-specific interfaces
* @return set of supported interfaces
*/
public Set<Class<?>> registerConsumer(Object consumer) {
Set<Class<?>> iSet = new HashSet<Class<?>>();
if (consumer != null)
_registerConsumer(consumer,
consumer.getClass(), iSet,
new HashSet<Class<?>>());
return iSet;
}
/**
* Consumer deregistration
*
* @param consumer
* object to deregister
* @return number of unregistered interfaces
*/
public int deregisterConsumer(Object consumer) {
if (consumer != null)
return _deregisterConsumer(consumer, consumer.getClass(),
new HashSet<Class<?>>());
else
return 0;
}
}