Monday, May 29, 2006

Caught by an iPod Nano

Ok, it finally happened some days ago: I bought a black Apple iPod Nano.

I don't generally fall in love with all those fashionable things (mmmhhhh ... maybe sometimes ...), but this time Apple caught me with its iPod Nano, and I have to say it's worth one's while.

You may know I'm a proud Linux user, so here are some tools you may want to use for making your iPod talking with your good Penguin:

  • IPodSlave, an experimental KDE I/O slave for accessing your iPod from Konqueror and other applications supporting I/O slaves.

  • GTKPod, a GTK application for managing your iPod, stable and fully working, but a bit ugly.

  • amaroK, the best Linux media player, which in its latest 1.4 version comes with full iPod support, becoming a full replacement for Apple iTunes!


If you have a modern Linux distribution, I strongly suggest you to give a try to amaroK 1.4.

Happy listening!

Wednesday, May 24, 2006

Google Web Toolkit: The Next Big Hype

Let me say something about Google (I don't put links here because everyone knows).

I love Google Search Engine.
I love Google Mail.
I love Google Chat.
I think all those people at Google are great in creating advanced (and cool) applications.

This is what I think, and this is what a lot of people also think.

Now, too bad, thanks to this kind of leadership, everything Google produces gets acclaimed by the majority like the next big thing, without a small crumb of criticism.

This is the case of Google Web Toolkit (GWT).

GWT is the new born at Google: a framework for developing Ajax applications in Java.
Let me quote its web site:

Google Web Toolkit - Build AJAX apps in the Java language


Google Web Toolkit (GWT) is a Java software development framework that makes writing AJAX applications like Google Maps and Gmail easy for developers who don't speak browser quirks as a second language. Writing dynamic web applications today is a tedious and error-prone process; you spend 90% of your time working around subtle incompatabilities between web browsers and platforms, and JavaScript's lack of modularity makes sharing, testing, and reusing AJAX components difficult and fragile.
GWT lets you avoid many of these headaches while offering your users the same dynamic, standards-compliant experience. You write your front end in the Java programming language, and the GWT compiler converts your Java classes to browser-compliant JavaScript and HTML.


What is Google Web Toolkit?


Google Web Toolkit (GWT) is a Java development framework that lets you escape the matrix of technologies that make writing AJAX applications so difficult and error prone. With GWT, you can develop and debug AJAX applications in the Java language using the Java development tools of your choice. When you deploy your application to production, the GWT compiler to translates your Java application to browser-compliant JavaScript and HTML.
Here's the GWT development cycle:

  1. Use your favorite Java IDE to write and debug an application in the Java language, using as many (or as few) GWT libraries as you find useful.

  2. Use GWT's Java-to-JavaScript compiler to distill your application into a set of JavaScript and HTML files that you can serve with any web server.

  3. Confirm that your application works in each browser that you want to support, which usually takes no additional work.



GWT drove people literally crazy.
But before going to GWT web site and start playing with the new, acclaimed, next big thing, because everyone will do and you cannot be cut off, please think ...

Developers spend 90% of their time in developing and maintaining business components.
It is not true that you, as a developer, spend 90% of your time working around subtle incompatabilities between web browsers and platforms.
Developers should spend (and actually do) most of their time in developing the application domain model and all the business logic and components.
With GWT, developers will spend a lot of time in developing also the whole presentation layer. This is because ...

GWT makes Separation of Concerns absolutely unfeasible.
If Separation of Concerns is applied, developers can focus on business logic and only limited presentation logic, because talented web designers will do all the hard job with HTML and alike.
With GWT, developers must write every single web page like it was a SWING window, and if you think it will not be an hard job because you are a very talented Java developers, please consider ...

Writing SWING-like interfaces is a lot more difficult than writing HTML-like interfaces.
If you have ever developed a Java SWING application, you know what I'm talking about.
Moreover, consider a web application with dozens and dozens of web pages ... you'll end up with dozens and dozens of Java classes whose only job is constructing a web page.
Ooops.
Did I say that those Java classes construct your web pages?
I've been wrong: they are actually compiled into HTML+Javascript code, and it is that HTML+Javascript which makes up your web page.
Yes, because ...

GWT automatically generates HTML and Javascript code from your Java classes.
Just one thing: if the GWT compiler has one or more bugs, generating so wrong code, how difficult would be to debug and detect those bugs in the automatically generated JavaScript code?

Now, I'm not condemning GWT: it can be more than good for little to medium ui-centric web applications where developers can focus on presentation logic.
This is obviously my opinion: and I'm inviting you to be judgemental and have your opinion without taking as gold all Google gives to you.

Wednesday, May 17, 2006

Spring Hacks : Reflection Based Property Editors.

Property Editors are a J2SE feature used for editing JavaBeans properties from user interfaces, typically representing these properties as text values.

They are used in SpringMVC for similar purposes: representing and binding complex objects in web interfaces as they were simple, plain, properties.

A short example will clarify.
Say you have an Order owning a collection of Orders, each with its Product:


public class Order {

public String getOrderCode() { ... }

public List getLineItems() { ... }
}


public class LineItem {

public String getItemCode() { ... }

public Product getProduct() { ... }
}


public class Product {

public String getCode() { ... }

public String getName() { ... }
}



If you want to display Products in a web selection list, in order to assign a Product to a LineItem, you have to write in your JSP something like this:


<spring:bind path="command.product">
<select name="${status.expression}">
<c:forEach items="${products}" var="p">
<spring:transform value="${p}" var="pCode"/>
<option value="${pCode}">${p.name}</option>
</c:forEach>
</spring:bind>


For doing this, you have to write and configure a PropertyEditor for the Product object, in order to transform the Product object into a text value, specifically its code, and then directly bind the Product having its text representation.
The same applies if you want to bind a collection of LineItems to a Product:


<spring:bind path="command.lineItems">
<c:forEach items="${items}" var="item">
<input type="checkbox" name="${status.expression}" value="${item.itemCode}"/>
.....
</c:forEach>
</spring:bind>


You have to write a CustomCollectionEditor for the collection of LineItem objects, in order to convert the collection of line item codes to the corresponding collection of LineItems objects (take a look here for more info).

Writing PropertyEditors or CustomCollectionEditors is pretty simple: however, if you have to do a lot of bindings, each for a different object, you have to hand-write a lot of property editors, which is boring and error-prone.

Now, think a moment at how you usually transform objects to text values and vice-versa: you use an object property for obtaining a text representation (often an id), and use some kind of data access object for obtaining an object from a given text value (i.e., an object given its id).
So, let us write a generic property editor and a generic collection editor, using Java Reflection.
Here is the property editor:


public class ReflectivePropertyEditor extends PropertyEditorSupport {

private Object dataAccessObject;
private String dataAccessMethod;
private String propertyName;
private PropertyEditor stringConvertor;

public String getAsText() {
if (this.getValue() == null) {
return null;
}
else {
Method method = null;
String result = null;
try {
BeanWrapperImpl wrapper = new BeanWrapperImpl(this.getValue());
result = wrapper.getPropertyValue(this.propertyName).toString();
}
catch(Exception ex) {
throw new ReflectiveCollectionEditorException("An error occurred while using: " + this.propertyName, ex);
}
return result;
}
}

public void setAsText(String textValue) {
try {
if (this.stringConvertor == null) {
Method method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{String.class});
this.setValue(method.invoke(this.dataAccessObject, new Object[]{textValue}));
}
else {
this.stringConvertor.setAsText(textValue);
Object value = this.stringConvertor.getValue();
Method method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{value.getClass()});
this.setValue(method.invoke(this.dataAccessObject, new Object[]{value}));
}
}
catch(Exception ex) {
throw new ReflectiveCollectionEditorException("An error occurred while executing: " + this.dataAccessMethod, ex);
}
}

public String getPropertyName() {
return this.propertyName;
}

public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}

public Object getDataAccessObject() {
return this.dataAccessObject;
}

public void setDataAccessObject(Object dataAccessObject) {
this.dataAccessObject = dataAccessObject;
}

public String getDataAccessMethod() {
return this.dataAccessMethod;
}

public void setDataAccessMethod(String dataAccessMethod) {
this.dataAccessMethod = dataAccessMethod;
}

public PropertyEditor getStringConvertor() {
return this.stringConvertor;
}

public void setStringConvertor(PropertyEditor stringConvertor) {
this.stringConvertor = stringConvertor;
}
}


And here the collection editor:


public class ReflectiveCollectionEditor extends CustomCollectionEditor {

private Object dataAccessObject;
private String dataAccessMethod;
private PropertyEditor stringConvertor;

public ReflectiveCollectionEditor(Class collection) {
super(collection);
}

public ReflectiveCollectionEditor(Class collection, boolean nullAsEmptyCollection) {
super(collection, nullAsEmptyCollection);
}

protected Object convertElement(Object element) {
if (!(element instanceof String)) {
new IllegalArgumentException("The element to convert must be of type java.lang.String");
}
String textValue = (String) element;
Object result = null;
try {
if (this.stringConvertor == null) {
Method method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{String.class});
result = method.invoke(this.dataAccessObject, new Object[] {textValue});
}
else {
this.stringConvertor.setAsText(textValue);
Object value = this.stringConvertor.getValue();
Method method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{value.getClass()});
result = method.invoke(this.dataAccessObject, new Object[] {value});
}
}
catch(Exception ex) {
throw new ReflectiveCollectionEditorException("An error occurred while executing: " + this.dataAccessMethod, ex);
}

return result;
}

public Object getDataAccessObject() {
return this.dataAccessObject;
}

public void setDataAccessObject(Object dataAccessObject) {
this.dataAccessObject = dataAccessObject;
}

public String getDataAccessMethod() {
return this.dataAccessMethod;
}

public void setDataAccessMethod(String dataAccessMethod) {
this.dataAccessMethod = dataAccessMethod;
}

public PropertyEditor getStringConvertor() {
return this.stringConvertor;
}

public void setStringConvertor(PropertyEditor stringConvertor) {
this.stringConvertor = stringConvertor;
}
}


What they ask you to do is nothing more than configuring the following properties:

  • dataAccessObject : the object used for converting from a text value to the actual object; it could be a Factory, a DAO, or Repository.

  • dataAccessMethod : the method, on the dataAccessObject, to call for converting from text to object.

  • propertyName : the name of the property which will be used for the object text value (only in ReflectivePropertyEditor).

  • stringConvertor : a PropertyEditor to use for converting the string value that will be passed as argument to the dataAccessMethod (required only if it takes as argument an object that is not a String).


Then, Java Reflection will do all the boring job.

Moreover, those property editors are best configured in the Spring container:


<bean id="productEditor" class="org.acme.ReflectivePropertyEditor">
<property name="dataAccessObject"><ref bean="productDAO"/></property>
<property name="dataAccessMethod"><value>getProduct</value></property>
<property name="propertyName"><value>code</value></property>
</bean>

<bean id="lineItemsCollectionEditor" class="org.acme.ReflectiveCollectionEditor">
<constructor-arg index="0"><value>java.util.Set</value></constructor-arg>
<property name="dataAccessObject"><ref bean="productDAO"/></property>
<property name="dataAccessMethod"><value>getLineItem</value></property>
</bean>



Comments and suggestions are welcome.
Hope you'll find this useful!

Thursday, May 11, 2006

Enhancing Composite Specifications with Message Notifications

In this blog entry we'll enhance our previous Composite Specifications implementation, in order to sending message notifications at evaluation time.

We'll take back some ideas from A notification strategy for business errors and related comments by Johannes Brodwall.
We'll use the same concept of Notification object, but intended as a carrier of generic messages (not only errors).

So, let's start with some code.

First, we need a simple Message class.


public interface Message {

/**
* Set the message code.
* @param code The code to set.
*/
public void setCode(String code);

/**
* Get the message code.
* @return The message code.
*/
public String getCode();

/**
* Set the default message string of this message object.
* @param message The default message string.
*/
public void setDefaultMessage(String message);

/**
* Get the default message string of this message object.
* @return The default message string.
*/
public String getDefaultMessage();
}


It is very simple and contains just the message code (intended to be resolved using i18n), and a default message string.

We need also the Notification class, for carrying messages all around.


public interface Notification {

public enum Type { ERROR, WARNING, INFO };

/**
* Add a message.
* @param message The message to add.
* @param type The notification type of the message to add.
*/
public void addMessage(Message message, Notification.Type type);

/**
* Remove a message.
* @param message The message to remove.
* @param type The notification type of the message to remove.
* @return True if removed.
*/
public boolean removeMessage(Message message, Notification.Type type);

/**
* Get messages of the given type.
* @param type The type of messages to retrieve.
* @return An array of messages.
*/
public Message[] getMessages(Notification.Type type);

/**
* Check if this notification has messages of the given type.
* @param type The type of messages to look for.
* @return True if this notification has messages of the given type,
* false otherwise.
*/
public boolean hasMessages(Notification.Type type);

/**
* Get all messages contained in this notification.
* @return An array of messages.
*/
public Message[] getAllMessages();

/**
* Check if this notification has messages of whatever type.
* @return True if this notification has messages,
* false otherwise.
*/
public boolean hasMessages();

/**
* Add to this notification all the messages contained in the notification in argument.
* @param notification The notification whose messages must be added.
*/
public void addAllMessages(Notification notification);
}


The most important thing to note is that you can add generic messages and assign them a notification type: ERROR, WARNING or INFO.
This actually classify your messages and let clients do different actions based on the notification type.

How to integrate this with our CompositeSpecification?

First, let us modify the base Specification interface:


public interface Specification<O> {

/**
* Specification evaluation method.
*
* @param object The object to evaluate.
* @return True if satisfied, false otherwise.
*/
public boolean evaluate(O object);

/**
* Specification evaluation method, with a Notification object for collecting error messages.
*
* @param object The object to evaluate.
* @param notification A notification object where errors regarding specification evaluation will be put.<br>
* It can be left <code>null</code> if not used.
* @return True if satisfied, false otherwise.
*/
public boolean evaluate(O object, Notification notification);

/**
* Add a notification message to be notified by this specification.
*
* @param message The message to add.
* @param type The notification type of the message.
* @param whenSatisfied True if the message must be notified when the specification gets satisfied,
* false if notified when unsatisfied.
*/
public void addNotificationMessage(Message message, Notification.Type type, boolean whenSatisfied);

/**
* Remove a notification message.
*
* @param message The message to remove.
* @param type The notification type of the message.
* @param whenSatisfied True if the message was to be notified once satisfied,
* false otherwise.
* @return True if removed.
*/
public boolean removeNotificationMessage(Message message, Notification.Type type, boolean whenSatisfied);
}


Now you have:

  • The old evaluate(Object o) method, to be used when you're not interested in notifications.

  • A new evaluate(Object o, Notification n) method, where the Notification object in argument will collect message notifications fired by the specification.

  • Te addNotificationMessage(Message message, Notification.Type type, boolean whenSatisfied); method: it is used not only to add the message notifications the specification can fire, but also to define their notification type and when to fire them.
    Doing so, you can specify what (and what type of) message notifications to fire when the specification gets satisfied, and what to fire when not satisfied.


We've finally arrived to the new CompositeSpecification.
Here I'll show only the CompositeSpecification interface: I'm not going to show the complete code for managing Notifications because it would clutter all the blog entry.
All this stuff will be released soon as part of an Open Source project, so those interested will be able soon to take a look at the whole implementation.

Here is the refined CompositeSpecification interface:


public interface CompositeSpecification<S, O> extends Specification<O> {

/**
* Apply the logical <code>and</code> operator to this composite specification and another, supplied, composite specificaton.
* @param specification The other composite specification.
*/
public CompositeSpecification and(CompositeSpecification<S, O> specification);

/**
* Apply the logical <code>and</code> operator to this composite specification and the supplied one.
* @param specification The supplied specification to compose.
*/
public CompositeSpecification and(S specification);

/**
* Apply the logical, negated, <code>and</code> operator to this composite specification and another, supplied, composite specificaton.
* @param specification The other composite specification.
*/
public CompositeSpecification andNot(CompositeSpecification<S, O> specification);

/**
* Apply the logical, negated, <code>and</code> operator to this composite specification and the supplied one.
* @param specification The supplied specification to compose.
*/
public CompositeSpecification andNot(S specification);

/**
* Start composing the specification.<br>
* This is the first method to be called for composition.
*
* @param specification The actual specification to compose.
*/
public CompositeSpecification compose(S specification);

/**
* Add a notification message to the last composed specification.
* @param message The message to add.
* @param type The notification type of the message.
* @param whenSatisfied True if the message must be notified when the specification gets satisfied,
* false if notified when unsatisfied.
*/
public CompositeSpecification withMessage(Message message, Notification.Type type, boolean whenSatisfied);

/**
* Composite specification evaluation.
*
* @param object The object to evaluate.
*/
public boolean evaluate(O object);

/**
* Apply the logical <code>or</code> operator to this composite specification and another, supplied, composite specificaton.
* @param specification The other composite specification.
*/
public CompositeSpecification or(CompositeSpecification<S, O> specification);

/**
* Apply the logical <code>or</code> operator to this composite specification and the supplied one.
* @param specification The supplied specification to compose.
*/
public CompositeSpecification or(S specification);

/**
* Apply the logical, negated, <code>or</code> operator to this composite specification and another, supplied, composite specificaton.
* @param specification The other composite specification.
*/
public CompositeSpecification orNot(CompositeSpecification<S, O> specification);

/**
* Apply the logical, negated, <code>or</code> operator to this composite specification and the supplied one.
* @param specification The actual specification to compose.
*/
public CompositeSpecification orNot(S specification);
}


The most important things are:

  • The evaluate(Object o, Notification n) method, inherited by the previously described Specification interface, to be used for collecting message notifications
    from all the composed specifications.

  • The fluent-style CompositeSpecification withMessage(Message message, Notification.Type type, boolean whenSatisfied) method: it has to be used for defining a message notification fired by a composed specification (specifically, the last one added), its type and when it has to be fired.


So, considering our example classes (defined here), you can now write something like this:


CompositeSpecification<Example Specification> compositeSpecification = new CompositeSpecification<Specification>(ExampleSpecification.class, "isSatisfiedBy", IOffice.class);

OfficeIdSpecification spec1 = new OfficeIdSpecification();
FullOfficeSpecification spec2 = new FullOfficeSpecification();

IOffice office1 = new Office();
IEmployee emp1 = new Employee();
office1.setOfficeId("o1");
emp1.setMatriculationCode("1");
office1.addEmployee(emp1);

Notification notification = ...;

compositeSpecification.compose(spec1).withMessage(new Message(...), Notification.Type.ERROR, false)
.andNot(spec2).withMessage(new Message(...), Notification.Type.WARNING, true)
.evaluate(office1, notification);



Here is how you can read the composite specification declaration: compose the specification defining the office id structure, with an error message notification to be fired when not satisfied, and the specification defining when the office is full, with a warning message notification to be fired when satisfied.
After evaluation, you'll have your notification object filled with all message notifications fired by the composite specification (obviously, if any).

Suggestions and every type of feedback are welcome!

Monday, May 08, 2006

Implementing Composite Specifications

In my previous post, An idea for Composite Specifications, we took a look at how a composite specification could be structured and designed.
Now, we'll see how to concretely implement it, using (as always here in my blog, where not specified) the Java language.

Let us rewrite the composite specification interfaces:


public interface Specification<O> {

public boolean evaluate(O o);
}


public interface CompositeSpecification<S, O> extends Specification<O> {

public CompositeSpecification compose(S specification);

public CompositeSpecification and(CompositeSpecification<S, O> specification);

public CompositeSpecification and(S specification);

public CompositeSpecification andNot(CompositeSpecification<S, O> specification);

public CompositeSpecification andNot(S specification);

public CompositeSpecification or(CompositeSpecification<S, O> specification);

public CompositeSpecification or(S specification);

public CompositeSpecification orNot(CompositeSpecification<S, O> specification);

public CompositeSpecification orNot(S specification);

public boolean evaluate(O object);
}


Here are some main advantages of such an interface:

  • Composition using well known logical operators.

  • Composition of custom specification types, without requiring to implement any particular interface.

  • Highly declarative style of composition, thanks to a fluent interface.


The CompositeSpecification let you compose custom specification with other CompositeSpecification: the first thing you need is an adapter for adapting custom types to the Specification interface:


public class SpecificationGenericAdapter implements Specification {

private Object specification;
private Method specificationMethod;

public SpecificationGenericAdapter(Object specification, Method specificationMethod) {
this.specification = specification;
this.specificationMethod = specificationMethod;
}

public boolean evaluate(Object object) {
boolean result = false;

try {
Object tmp = this.specificationMethod.invoke(specification, object);
result = (Boolean) tmp;
}
catch(Exception ex) {
throw new SpecificationAdapterException("...", ex);
}

return result;
}
}


This adapter encapsulate the object to adapt and use Java reflection to call the method that will actually evaluate the specification.

You may note the possibility to compose with the inverse of a specification, using the andNot and orNot operators: this is accomplished simply applying the following decorator:


public class InverseSpecification implements Specification {

private Specification specification;

public InverseSpecification(Specification specification) {
this.specification = specification;
}

public boolean evaluate(Object o) {
return !this.specification.evaluate(o);
}
}


It simply inverts the decorated specification.

Now we need to implement the logical operators.
I've made a first implementation using Apache Commons Predicate: it worked well, was very straightforward, but it was rather inefficient in terms of memory usage.
Due to the Commons Predicates implementation, you have to create a different Predicate object for every operator you use: so, considering a simple CompositeSpecification with just one logical and operator, used in one thousand different instances of a business object, you'll have one thousand of AndPredicate just for implementing an and operator which makes always the same task!
So, here is a shared implementation of logical operators, which uses the flyweight pattern; these are the involved classes:


public interface BinaryOperator {

public boolean evaluate(Specification a, Specification b, Object o);

public boolean evaluate(Specification a, boolean b, Object o);
}


public class AndOperator implements BinaryOperator {

public boolean evaluate(Specification a, Specification b, Object o) {
return a.evaluate(o) && b.evaluate(o);
}

public boolean evaluate(Specification a, boolean b, Object o) {
return a.evaluate(o) && b;
}
}


public class OrOperator implements BinaryOperator {

public boolean evaluate(Specification a, Specification b, Object o) {
return a.evaluate(o) || b.evaluate(o);
}

public boolean evaluate(Specification a, boolean b, Object o) {
return a.evaluate(o) || b;
}
}


public class OperatorFactory {

private static final OperatorFactory factory = new OperatorFactory();

private BinaryOperator andOperator = new AndOperator();
private BinaryOperator orOperator = new OrOperator();

private OperatorFactory() {}

public static OperatorFactory getInstance() {
return factory;
}

public BinaryOperator getAndOperator() {
return this.andOperator;
}

public BinaryOperator getOrOperator() {
return this.orOperator;
}
}


You should note the following:

  • The BinaryOperator evaluate() method takes as arguments not only the object to evaluate, but also the two specifications to apply (or a specification and an already computed boolean value): this is the so called extrinsic state, that is, state that cannot be shared because context dependent.

  • The singleton OperatorFactory must be used in order to obtain shared operator instances: so, you don't have to directly construct operators.


Last, but not least, the CompositeSpecification implementation:


public class CompositeSpecificationImpl<S, O>
implements CompositeSpecification<S, O> {

private Class<S> specificationClass;
private Method specificationMethod;

private OperatorFactory operatorFactory = OperatorFactory.getInstance();
private List<Specification> specificationsList = new LinkedList<Specification>();
private List<BinaryOperator> operatorsList = new LinkedList<BinaryOperator>();

public CompositeSpecificationImpl(Class<S> specificationClass, String specificationMethod) {
this.specificationClass = specificationClass;

try {
Method[] methods = this.specificationClass.getDeclaredMethods();
for (Method m : methods) {
if (m.getName().equals(specificationMethod)) {
this.specificationMethod = m;
break;
}
}
if (this.specificationMethod == null) {
throw new SpecificationDescriptionException("...");
}
}
catch(SecurityException ex) {
throw new SpecificationDescriptionException("...");
}
}

public CompositeSpecification compose(S specification) {
this.specificationsList.clear();
this.operatorsList.clear();
this.specificationsList.add(this.adaptSpecification(specification));
return this;
}

public CompositeSpecification and(S specification) {
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getAndOperator());
this.specificationsList.add(this.adaptSpecification(specification));
return this;
}

public CompositeSpecification or(S specification) {
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getOrOperator());
this.specificationsList.add(this.adaptSpecification(specification));
return this;
}

public CompositeSpecification and(CompositeSpecification<S, O> specification) {
if (!specification.equals(this)) {
throw new IllegalArgumentException("...");
}
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getAndOperator());
this.specificationsList.add(specification);
return this;
}

public CompositeSpecification or(CompositeSpecification<S, O> specification) {
if (!specification.equals(this)) {
throw new IllegalArgumentException("...");
}
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getOrOperator());
this.specificationsList.add(specification);
return this;
}

public CompositeSpecification andNot(S specification) {
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getAndOperator());
this.specificationsList.add(new InverseSpecification(this.adaptSpecification(specification)));
return this;
}

public CompositeSpecification orNot(S specification) {
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getOrOperator());
this.specificationsList.add(new InverseSpecification(this.adaptSpecification(specification)));
return this;
}

public CompositeSpecification andNot(CompositeSpecification<S, O> specification) {
if (!specification.equals(this)) {
throw new IllegalArgumentException("...");
}
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getAndOperator());
this.specificationsList.add(new InverseSpecification(specification));
return this;
}

public CompositeSpecification orNot(CompositeSpecification<S, O> specification) {
if (!specification.equals(this)) {...");
}
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
this.operatorsList.add(this.operatorFactory.getOrOperator());
this.specificationsList.add(new InverseSpecification(specification));
return this;
}

public boolean evaluate(O object) {
if (this.specificationsList.isEmpty()) {
throw new SpecificationNotComposedException("...");
}
Iterator<Specification> specificationsIt = this.specificationsList.iterator();
boolean result = specificationsIt.next().evaluate(object);
for (BinaryOperator op : operatorsList) {
result = op.evaluate(specificationsIt.next(), result, object);
}
return result;
}

public boolean equals(Object obj) {
if (obj == null) return false;
if (! (obj instanceof CompositeSpecificationImpl)) {
return false;
}
else {
CompositeSpecificationImpl otherSpec = (CompositeSpecificationImpl) obj;
EqualsBuilder builder = new EqualsBuilder();
return builder.append(this.specificationClass,
otherSpec.specificationClass)
.append(this.specificationMethod,
otherSpec.specificationMethod)
.isEquals();
}
}

public int hashCode() {
HashCodeBuilder builder = new HashCodeBuilder();
return builder.append(this.specificationClass)
.append(this.specificationMethod)
.toHashCode();
}

private Specification adaptSpecification(S specification) {
return new SpecificationGenericAdapter(specification, this.specificationMethod);
}
}


The most important thing to note is how the composite specification is internally constructed and evaluated.
Each time a new specification is composed, the new specification and the operator used for composing are stored into two different lists acting as queues:


private List<Specification> specificationsList = new LinkedList<Specification>();
private List<BinaryOperator> operatorsList = new LinkedList<BinaryOperator>();


Then, when the evaluate() method gets called, each operator is applied to its corresponding specification, starting from the first one added:


Iterator<Specification> specificationsIt = this.specificationsList.iterator();
boolean result = specificationsIt.next().evaluate(object);
for (BinaryOperator op : operatorsList) {
result = op.evaluate(specificationsIt.next(), result, object);
}
return result;



Now, your CompositeSpecification is ready to be used:


compositeSpecification.compose(simpleSpecification1).and(simpleSpecification2).evaluate(objectToEvaluate);



Every feedback will be highly appreciated!

Updates:
09/05/2006 : Enhancements in explaining code snippets regarding logical operators.

Tuesday, May 02, 2006

An idea for Composite Specifications

Several days ago I've written some blog posts about how to work with and implement Specifications.

In particular, I've written one article about how to implement Specifications with Apache Commons Collections.
For a short recalling, we implemented Specifications using Commons Predicate as base interface, which let us combine those specifications using Commons PredicateUtils class.
This approach has two main disadvantages:

  • Force you to use the Commons Predicate interface which, for example, is not generics-enabled

  • Give you a flexibility limited by Commons PredicateUtils capabilities.


What about using a generic composite specification, capable of combining general specifications using logical operators, with a fluent-style interface?

Let us suddenly go with a simple example.

Take one office interface:


public interface IOffice {

void setOfficeId(String officeId);

String getOfficeId();

void addEmployee(IEmployee e);

Set getEmployees();
}


Take one employee interface:


public interface IEmployee extends Serializable {

void setMatriculationCode(String matriculationCode);

String getMatriculationCode();
}


You can create offices and add employees to them, but your boss said you have some business rules:

  • Every office id must begin with the "o" letter, and follow with numbers.

  • You cannot have an office with more than three employees.



Say you want to implement those rules as Specifications (remember, this is an oversimplified example).
Here are your specifications:


/**
* A generics-enabled specification interface.
*/
public interface Specification<T> {
public Boolean isSatisfiedBy(T object);
}

/**
* A specification for the office id.
*/
public class OfficeIdSpecification
implements Specification<IOffice> {
public Boolean isSatisfiedBy(IOffice o) {
return o.getOfficeId().matches("o\\d+");
}
}

/**
* A specification for the office room availability, determining
* if an office is full.
*/
public class FullOfficeSpecification
implements Specification<IOffice> {

private int limit = 3;

public Boolean isSatisfiedBy(IOffice o) {
return o.getEmployees().size() > this.limit;
}
}


And ... here is how would be our composite specification:


public class CompositeSpecification<T> {

public CompositeSpecification(Class<T> specificationClass,
String specificationMethod,
Class specificationObjectClass) {
// ...
}

public CompositeSpecification compose(T specification) {
// ...
}

public CompositeSpecification and(T specification) {
// ...
}

public CompositeSpecification or(T specification) {
// ...
}

public CompositeSpecification and(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification or(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification andNot(T specification) {
// ...
}

public CompositeSpecification orNot(T specification) {
// ...
}

public CompositeSpecification andNot(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification orNot(CompositeSpecification<T> specification) {
// ...
}

public CompositeSpecification not() {
// ...
}

public boolean evaluate(Object object) {
// ...
}
}


I intentionally omitted implementation details because at the moment I'd like to point you out:

  • The generics-enabled interface, which let you specify your own specification to combine.

  • The constructor, where you have to describe the actual specification you'll combine, specifying its class, its specification method (isSatisfiedBy in our example) and the class of the specification object (IOffice in our example).

  • The fluent-style interface methods for applying logical operators to actual specifications or other composite specifications.


Here is an example about how to use such a class:


CompositeSpecification<Specification> compositeSpecification =
new CompositeSpecification<Specification>(Specification.class,
"isSatisfiedBy",
IOffice.class);

OfficeIdSpecification spec1 = new OfficeIdSpecification();
FullOfficeSpecification spec2 = new FullOfficeSpecification();

IOffice office1 = new Office();
IEmployee emp1 = new Employee();

office1.setOfficeId("o1");
emp1.setMatriculationCode("1");
office1.addEmployee(emp1);

// The office has a valid id and is not full:
assertTrue(compositeSpecification.compose(spec1).andNot(spec2).evaluate(office1));


I'll discuss implementation details in another post.
But for now, what do you think about this approach?

Updates:
04/05/2006 : Fixes in code.