GHads mind

developers thoughts & finds

Posts Tagged ‘Enumerations

MongoDB and Java enums

leave a comment »

Well, there is no way in MongoDB/BSON to de-/serialize Java enums. At least I found none but to implement the Interface DBObject. Having no default implementation I started experimenting with implementing the Interface directly at the enum which would be a massive overhead when using multiple enums. So I decided to create a simple Wrapper like DBRef which does the work for you:

/**
 *
 * Use for put into document: document.put(key, DBEmum.of(SomeEnum.VALUE));
 * Use for get from document: DBEnum.to(SomeEnum.class, document.get(key));
 *
 */
public class DBEnum<T extends Enum<T>>
		implements DBObject
{

	private static final String KEY = "_enum";

	public static <U extends Enum<U>> DBEnum<U> of(U value)
	{
		return new DBEnum<U>(value);
	}

	public static <U extends Enum<U>> U to(Class<U> c, Object o)
	{
		if (o instanceof DBObject)
		{
			Object value = ((DBObject) o).get(KEY);
			if (value == null)
			{
				return null;
			}
			return Enum.valueOf(c, value.toString());
		}
		return null;
	}

	private final T value;

	private DBEnum(T value)
	{
		this.value = value;
	}

	public void markAsPartialObject() { }

	public boolean isPartialObject() { return false; }

	public Object put(String s, Object o) { return null; }

	public void putAll(BSONObject bsonObject) { }

	public void putAll(Map map) { }

	public Object get(String s)
	{
		return value.name();
	}

	public Map toMap()
	{
		return Collections.singletonMap(KEY, value.name());
	}

	public Object removeField(String s) { return null; }

	public boolean containsKey(String s)
	{
		return KEY.equals(s);
	}

	public boolean containsField(String s)
	{
		return KEY.equals(s);
	}

	public Set<String> keySet()
	{
		return Collections.singleton(KEY);
	}

	public String toString()
	{
		return "{ \"" + KEY + "\" : \"" + value.name() + "\" }";
	}
}

Using it this way (example main)…

		Mongo mongo = new Mongo();
		DB db = mongo.getDB("test");
		DBCollection collection = db.getCollection("enum");

		DBObject next = new BasicDBObject("key", DBEnum.of(SomeEnum.VALUE_1));
		collection.insert(next);

		next = collection.findOne(new BasicDBObject("key", DBEnum.of(SomeEnum.VALUE_1)));
		System.out.println(next);

		SomeEnum enumValue = DBEnum.to(SomeEnum.class, next.get("key"));
		System.out.println(enumValue);

… prints the expected results and creates the document:

{
	"_id" : ObjectId("4da421708db0535ebbd175c3"),
	"key" : {
		"_enum" : "VALUE_1"
	}
}

Only real downer is the type must be used explictly. And maybe someone wants to implement this directly into the MongoDB Java driver (and others) so the key could turn to “$enum” and become ‘official’…

Greetings,
GHad

Written by ghads

April 12, 2011 at 2:15 pm

Java Event handling via Enumerations

leave a comment »

It’s been a while

but I’m still active. Just had no time posting updates, but today I’ll start over, hoping to get more updates done more frequently. I want to start with a series of Java related posts showing some API usage code for my personal API JBase I developed over the last year. I will not post implementation details as far as full code but I’ll highlight one part and will give you hints about how to get it coded by yourself.

To start I will show an Event raising and handling system via Enumerations. There is no 3rd party library involved, just pure Java 5+ code is involved. So why Events?

Well it turns out that unless you use Bindings, updating a UI from model values or listenting for user actions involes an eventing system that needs quite a lot of work when used like it is promoted by Swing (i.e. WindowListener):

– A class for each event type (WindowEvent)
– An interface for the Listener (WindowListener) with a method per event (windowsActivated, windowsClosed, …)
– An internal raise method (processWindowEvent)
– An add method/remove method per listener interface (addWindowListener, removeWindowListener)
– List handling for keeping the listeners references (windowListeners)
– Synchronizing for multi-threading (when accesing the list)
– Did I forget somthing?

So scaling is a mess especially as changing any part leads to massive editing because of a tight coupling. For adding a new event type for example one needs all of the above. For adding new events (adding a method to the interface) all implementing listeners classes must be changed! And so on…

So I tried to solve those issues by decoupling the events completly from the class by using an Enumeration for the event type and an enumeration variable per event.

Use it like this:


public class SimpleEvent_Example implements SimpleEvent.Listener {

 public static void main(String[] args) {
   SimpleEvent.addListener(new SimpleEvent_Example());

   System.out.println("Raise SOME...");
   SimpleEvent.SOME.raise("some id");

   System.out.println("Raise OTHER...");
   SimpleEvent.OTHER.raise("other id");
 }

 public void handle(SimpleEvent event, String id) {
   switch (event) {
   case SOME:
     System.out.printf("SimpleEvent_Example.handle SOME: id= %1$s", id);
     System.out.println();
     break;
   case OTHER:
     System.out.printf("SimpleEvent_Example.handle OTHER: id= %1$s", id);
     System.out.println();
   break;
   }
 }
}

Easy, hm?

Let’s look at this line by line. The class implements an interface and thus listens to SimpleEvent, which would normaly be the Event class (e.g. WindowEvent). The Enumeration contains a non-static inner interface called Listener which is implemented here. For listing to multiple Event this would just be ‘implements SimpleEvent.Listener, OtherEvent.Listener’ and so on. It’s clearly declared at which event types this class listens to, so it should not be that confusing but very obvious on a second thought.

In the main method we first create a new instance of the example class and add this instance as listener to the Enumeration/event type. It has static methods for adding and removing Listeners so this is straight forward.

Next the event SOME of the type SimpleEvent is raised. As the enumeration variable IS the event it has a raise method. So this is completly decoupled from any class actually raising the event. Here the raise method is public but you can still make it package protected for example if you like to limit which class is allowed to raise events. So the event SOME of the event type SimpleEvent is like the previously mentioned windowsActivated event of the event type WindowEvent.

The handle method is implememted as declared in the Listener interface. For acting upon an event, the raised event is provided as well as the argument id from raising the event. A simple switch on event makes reacting to multiple events inside one method possible instead of using a method per event like with WindowListener (windowsActivated, windowsClosed, …). Now when adding a new event, you do not NEED to edit all Listeners anymore, if you design your switch right (don’t forget about default).

What’s missing is the source. But as the Listeners interface and the raise method is up to the developer when creating the Enumeration for the event type, an additional source parameter can be added at will.

How is SimpleEvent implemented then? Simple of course:


public enum SimpleEvent {

 // 1. declare events as enum variables
 SOME, OTHER;

 // 2. add the non-static interface for listeners
 public interface Listener {

   public void handle(SimpleEvent event, String id);

 }

 // 3. create delegator for handling listeners and events
 private static JEvents<Listener, SimpleEvent> EVENTS = JEvents.<Listener, SimpleEvent> create();

 // 4. add raise method and delegate to event types raise method
 public void raise(String id) {
   EVENTS.raise(this, new Object[] { id });
 }

 // 5. create static delegates for adding and removing listeners
 public static boolean addListener(Listener listener) {
   return EVENTS.addListener(listener);
 }

 public static boolean removeListener(Listener listener) {
   return EVENTS.removeListener(listener);
 }
}

As you can see there is not much code involved but there is a static instance of JEvents doing all the hard stuff in the background. So let’s look a little deeper inside the enum first and then go into JEvents…

The first few lines of the Enumeration is just standard stuff: declaring the events as enum variables and defining the listeners interface. Here we have one constraint though: the first parameter of each liteners interface method must be the Enumeration itself and is called ‘event’ by convention. One can always add more listeners methods but this is usally not needed as the event is an enumeration variable so you can switch inside the method implemtation instead of implementing multiple methods.

The third step creates the background instance of the class JEvents. This create call is just another way of providing concrete type information to a generic static create method instead of passing the class types. The JEvents instance uses the type information to restrict the raise and listeners add and remove methods to the correct interface and Enumeration, giving you a little type-savety for free.

At step four the non-static raise method is added to make the raise calls from the usage example possible. As the event itself is known by then (the selected enumeration variable) ‘this’ can be used when calling JEvents. As you can see the second part of the raise call looks rather akward but is needed. Here you need to pass all the arguments matching the parameter signature of one of the listeners methods except the event itself. The reason why I used an Object[] instead of varargs are listeners methods with varargs or arrays. When using a String[] for example by passing it to the JEvents raise method it would be casted to Object[]. So when looking for the right listeners method to call, we have a wrong signature. Thus to reduce errors I decided for using an Object[] directly so the I do not need to think about when I need to create a new Object[] or when using varargs is enough. A little akward syntax is the only trade-off here for reducing errors. Note you can still use varargs at the listeners methods as they get erased to arrays at compile time and JEvents can find the right method to call.

There are multiple raise methods at JEvents. I can use veto events (returning true if one listener returns true or throws an exception), synchronious events (like here), asychronious events and repeated events. The developer decides on what event he/she wants to use when implementing the Enumerations raise methods delegation to JEvents.

Finally adding and removing listeners are just static delegates to the JEvents instance and your done. This is far less code and far less changes for scaling than the classic approach:

– Adding a new event type is creating a new Enumeration (<30 lines of code)
– Adding a new event is just adding a new enum variable and no/little listeners changes involved
– No additional raise methods are needed if the listeners method can handle all the parameters
– No list handling for listeners as adding/removing is just a delegation
– JEvent does all the synchronizing for you
– completly decoupled

So how does JEvent works?

The JEvents instance manages a list of listers for the interface and lets you add/remove listeners at any time via the Enumeration itself via delegation. When a raise method is called, JEvents knows the signature of the listeners method, looks up the corresponding method and calls it for every listener. It can handle types that are assignable from a paramters type and looks for primitve types while checking the signature. Basicly that’s all. The fine-print involves errorhandling, asynchroniuos/delayed/repeated events via scheduled executors that can be canceled, synchronizing via ReentrantLocks for multi-threaded usage and veto events as mentioned above. I’ll just show the part actually checking if a method is the listener method for the event and the arguments:


private boolean isListener(Method m, E event, Object[] args) throws Exception {
   if (args == null) {
     args = new Object[0];
   }
   Class<?>[] parameterTypes = m.getParameterTypes();
   if (parameterTypes.length == args.length + 1) {
     if (parameterTypes[0].equals(event.getClass())) {
       for (int i = 0, max = args.length; i < max; i++) {
         Class<?> argsType = args[i].getClass();
         Class<?> parameterType = parameterTypes[i + 1];
         if (!argsType.equals(parameterType) && !parameterType.isAssignableFrom(argsType)) {
           if (Reflection.isPrimitveOrWrapper(argsType)) {
             argsType = Reflection.getPrimitiveClass(argsType);
             if (!argsType.equals(parameterType)) {
               return false;
             }
           } else {
             return false;
           }
         }
       }
       return true;
     }
   }
   return false;
 }

Note that a class Reflection is used, which is also a part of JBase but needs no further explanation here. We first check if the length of the methods parameters is correct, then if the first parameter is the events type. After that we check for every other parameter if the the parameters class matches the arguments class or is assignable from it. If not we try it once more for primitives, as the Object array contains only the wrapper classes to the primitives.

That concludes todays journey to my JBase API. I hope you enjoyed the dive and I’d like to get some feedback from you if you don’t bother to comment.

Thank you and greetz,
GHad

Written by ghads

September 2, 2010 at 12:16 pm