News
Quickbooks import and export
Do you have a need to import and export data to Quickbooks? If so we have experience in doing this and can help you integrate your existing applications with Quickbooks to stop you having to re-type data.
Read more...Lombok Beans extension published
Read more...Windows 7 release
Windows 7 has been released by Microsoft, so now is the time to consider Open Source.
Read more...New web site
DGA has a new Web site (the one you are reading). It is built with Open Source tools written in Java.
Read more...Lombok Beans
Project Lombok is a playground for extending Java by use of Annotations and some rather sneaky Annotation processors. It can be found at Project Lombok.
This package extends the normal Lombok Data annotation to add beans handling, in particular it adds a PropertyChangeSupport object (called $pcs) and it has a different generator for Setters (BeanSetter) which fires PropertyChage events when the setters are called.
ChangeLog
Version 0.0.4
- added addPropertyChangeListener and removePropertyChangeListener methods
- added JUnit-4 tests
Version 0.0.3
- fieldRef processor added
Version 0.0.2
- Minor changes notices after first release
Version 0.0.1
- Initial release
NOTE
In order to use this code, you MUST be running at least version 0.9.2 lombok.
Download and Installation
You can get the binary from http://dga.co.uk/download/, and the source (using git clone git://dga.co.uk/git/lombok-beans.git). To install just copy the binary jar into the same directory as lombok was installed - this will be the directory containing eclipse.ini for your version of Eclipse. You will need to add beans.jar to your classpath for Eclipse, or the classpath for Javac in exactly the same way that you do (or the installer did for you) in Lombok. I will add an installer later.
Using Lombok Beans
So you can have a class:-
@Bean class BeanPojo {
private String field;
}
and this will act as though you have:-
@Bean class BeanPojo {
private final transient PropertyChangeSupport $pcs = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) { $pcs.addPropertyChangeListener(listener); }
public void removePropertyChangeListener(PropertyChangeListener listener) { $pcs.removePropertyChangeListener(listener); }
private String field;
public String getField() { return field; }
public void setField(String field) { $pcs.firePropertyChange("field",this.field,this.field = field); }
@java.lang.Override public java.lang.String toString() {
return "BeanAnnotated(field=" + field + ")";
}
@java.lang.Override public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != this.getClass()) return false;
final BeanAnnotated other = (BeanAnnotated)o;
if (this.field == null ? other.field != null : !this.field.equals(other.field)) return false;
return true;
}
@java.lang.Override public int hashCode() {
final int PRIME = 31;
int result = 1;
result = result * PRIME + (this.field == null ? 0 : this.field.hashCode());
return result;
}
public BeanAnnotated() { }
}
The only differences between this as a Lombok @Data annotated Pojo is the $pcs field and the updated setter.
FieldRef
Inside the package is also a class called FieldRef, which is a further extension provided by this package.
Beans, and Binding mechanisms (and SQL bindings like JPA) all use Strings to reference fields. This is error prone and messy to maintain, and most importantly of all the compiler and IDEs like Eclipse can not check that you have got the field name right.
FieldRef gets around this, and provides a uniform way of referencing fields, which Eclipse and later Javac will be able to check at compile time.
A FieldRef object can be build using the static method FieldRef.fieldref which takes one of two types of arguements:-
Internally it takes an object or Class followed by a set of String field names. So if you have a Pojo (with @Bean of course) foo of type Foo, with a field bar of class Bar which in turn has a field field of type String you create a FieldRef (having imported the static method) by either of:-
FieldRef<Foo,String> pojoRef = fieldRef(foo,"bar","field");
FieldRef<Foo,String> classRef fieldRef(Foo.class,"bar","field");
The first of these created a bound FieldRef, and you can use it to get the value of the field using:-
String value = pojoRef.get();
The second version created an unbound FieldRef (for use in places like defining columns in tables) where you have to pass an object of type Foo to the getter to get the value:-
String value = classRef.get(foo);
Actually you can use the second form of getter with the pojoRef as well, but the usefulness of the second form is that you do not need an instance of Foo to hand when you create the FieldRef.
The magic that is to come, is that you will be able to code:-
FieldRef<Foo,String>pojoRef = fieldRef(foo.bar.field);
FieldRef<Foo,String>classReg = fieldRef(Foo.bar.field);
and using the magic of Lombok this is converted into the first form, but without checking the types and that bar and field are fields in Foo and Bar respecitively - that requires an extension to Lombok which is not yet available. This form can only be checked by Eclipse or Javac when bar and field are visible to the calling code.
Another form, which can be checked by Eclipse and will work properly with refactoring and content assist is:-
FieldRef<Foo,String>pojoRef = fieldRef(foo.getBar().getField());
Note that the Class form of this does not work, Eclipse (or Javac) does not understand it.
You will notice that in this last form there are no strings. Thus Eclipse will refactor correctly, and you have full name and type checking at all times.
Note that for the fieldRef processor to work you MUST include:-
import static uk.co.dga.lombok.FieldRef.fieldRef;
in your code. You can NOT use the wildcard form.
Note
If you are declaring a FieldRef which has the proper Generic attributions then the compiler seems to pass these properly to the fieldRef method. However if you are creating the object as part of a method call, e.g.:-
new BoundTextField<Foo,String>(fieldRef(foo.getBar().getField());
then the complier complains that the FieldRef returned by fieldRef is of generic type <Foo,Object> and fails. In this case, until the type handling is incorporated into Lombok, you have to code:-
new BoundTextField<Foo,String>(FieldRef.<Foo,String>fieldRef(foo.getBar().getFieldI());
