Archiv für die Kategorie ‘propertysheet’

Jarvis, PropertySheets and Annotations

Donnerstag, 07. Dezember 2006

I’m using my new Annotations (see these entries ) to create PropertySheets for Jarvis. I have added support for nested Properties, so you can not only access superclasses, but also configure nested Properties via the PropertySheet (“Generic” holds the properties of the nested ReportElement). Only two lines of annotations are neccessary to get this:

These are the annotations:

8<————– BaseBean.java—————–>8

 @BeanDescriptorAnnotation( simpleProperties = {"Text","ReportElement"})
public class StaticText extends BaseBean {

8<——————————————————->8

and the nested elements

8<———From ReportElement.java—————–>8

@BeanDescriptorAnnotation(
featureDescriptorAnnotation=@FeatureDescriptorAnnotation( displayName= "Generic"),simpleProperties = {"X","Y","Width","Height"})
public class ReportElement extends org.netbeans.modules.schema2beans.BaseBean

8<——————————————————->8

BeanInfo and Annotations

Donnerstag, 07. Dezember 2006

In my last blog entry I wrote about how the BeanInfo part in Java could be replaced by Annotations. My first tests were successful, and it seems that this approach would work nicely. Now for the details:

First there is a FeatureDescriptorAnnotation that holds the elements shared by all Descriptors. Annotations don’t support inheritance, so this is used as a MetaAnnotation (@Target({ ElementType.ANNOTATION_TYPE})) for the other Descriptors. I created default values for the elements, so the elements do not need to be set in an annotation explicitely. If, for example, the AnnotationIntrospector finds DEFAULT_NAME as name() it will use reflection to set the default name of the Descriptor. I found out that you can’t check elements for identity at runtime, so this:

featureDescriptorAnnotation.name() == FeatureDescriptorAnnotation.DEFAULT_NAME

will always be false. It’s a bit dangerous to use equals here, but I don’t know a better aproach yet.

8<——————————————>8

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE})
public @interface FeatureDescriptorAnnotation {
    public static String DEFAULT_NAME = "Default_Name";
    public static String DEFAULT_DISPLAY_NAME = "Default_Display_ Name";
    public static String DEFAULT_DESCRIPTION = "Default_Description";

    String displayName() default DEFAULT_DISPLAY_NAME;
    String name() default DEFAULT_NAME;
    String shortDescription() default DEFAULT_DESCRIPTION;
    boolean expert() default false;
    boolean hidden() default false;
    boolean preferred() default false;
}

8<——————————————>8

Next I needed a BeanDescriptor-equivalent, that can be used to mark up Beans for the AnnotationIntrospector. The PropertyDescriptor is split up into two parts. SimpleProperties refers to properties that only use default methods, names, etc. This will cover most cases, so the code to annotate a bean is very reduced. For Properties with more advanced settings there is the customizedProperties Array.

8<——————————————>8

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeanDescriptorAnnotation {
    public static String DEFAULT_CUSTOMIZER = "Default_Customizer";
    FeatureDescriptorAnnotation featureDescriptorAnnotation() default @FeatureDescriptorAnnotation;
    String customizerClassName() default DEFAULT_CUSTOMIZER;
    PropertyDescriptorAnnotation [] customizedProperties() default {};
    String [] simpleProperties() default {};
}

8<——————————————>8

Next there is the PropertyDescriptorAnnotation ( and the MethodDescriptorAnnotation, ParameterDescriptorAnnotation,EventSetDescriptorAnnotation but I won’t show those now ). It can be used either in the customizedProperties Array, or as a marker for Fields, which would make the code look cleaner:

8<——————————————>8

 @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface PropertyDescriptorAnnotation {
    public static String DEFAULT_PROPERTY_EDITOR = "Default_Property_Editor";
    public static String DEFAULT_GETTER = "Default_Getter";
    public static String DEFAULT_SETTER = "Default_Setter";

    FeatureDescriptorAnnotation featureDescriptorAnnotation() default @FeatureDescriptorAnnotation;
    String propertyEditorClassName() default DEFAULT_PROPERTY_EDITOR;
    BeanMethodAnnotation readMethod() default @BeanMethodAnnotation(name=DEFAULT_GETTER);
    BeanMethodAnnotation writeMethod() default @BeanMethodAnnotation(name=DEFAULT_SETTER) ;

    boolean bound() default false;
    boolean constrained() default false;
}

8<——————————————>8

At last we need an Introspector, that can retrofit those into a generic BeanInfo Here is for example how the simpleProperties are converted to PropertyDescriptors:

8<——————————————>8

	String [] simpleProperties = beanAnnotation.simpleProperties();
        if (simpleProperties!=null){
            for (int i = 0; i < simpleProperties.length; i++) {
                try {
                    PropertyDescriptor propertyDescriptor=new PropertyDescriptor(simpleProperties[i],beanClass);
                    propertyDescriptors.add(propertyDescriptor );
                } catch (IntrospectionException ex) {
                    ex.printStackTrace();
                }
            }
        }

8<——————————————>8

I created an AnnotatedBeanNode that uses the AnnotationIntrospector for generating PropertySheets and my annotated beans work fine with it, although there is still a lot to implement (EventSets, Methods …).

PropertySheets and Annotations

Dienstag, 05. Dezember 2006

There’s a lot of boilerplate code if you want to display PropertySheets for a Bean in NetBeans. You need to create a nodewrapper and write code to create the PropertySheet. There are some classes like the BeanNode to make things easier, but the functionality is very basic, unless you want to write BeanInfo classes. I’ve got a lot of beans for the XML binding in project Jarvis  and I never liked the concept of BeanInfo classes, because you have to keep two classes in sync, so I decided to use a different approach.

BeanInfo classes are carrying MetaInformation for the Beans and I guess that’s  rather a job for Annotations.  So it would be best to create a set of Annotations to provide the same MetaInformation in a more appropriate way. I did a quick google search to find something like this on the web, but I didn’t find to much (Beehive seems to go in that direction and there is a RFE related to this). I never needed to declare my own annotations before, so playing with annotations was another good reason to do it this way.

The RFE I mentioned suggests to replace the whole FeatureDescriptor and BeanInfo stuff by equivalent annotations, but when you look at the annotations in the example, the code looks awful, and the annotations get way too complicated. I want something simple. Most important, there must be default values for everything. In most cases a simple @BeanAnnotation should be enough.

The first tests with this approach were quite promising, and I guess this will ease the creation of PropertySheets a lot in Jarvis. To make it reuseable I created this in a separate module.