vasily
vasily

Reputation: 2920

Java Annotation "Inheritance"

I would like to generate tables from annotated objects. Right now I have the following schema in mind. I would like to annotate the object as follows:

@UI.App(
    name = "locations",
    columns = {
            @UI.Presenter.PropertyColumn("title"),
            @UI.Presenter.PropertyColumn("enabled"),
            @UI.Presenter.StatusColumn,
            @UI.Presenter.LastModifiedColumn
    }
)
public class Location {
    private String title;
    private Boolean enabled;
}

For that I intended to use the following annotations

public interface UI {

    @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})
    public @interface App {
        public String name();
        public Presenter.Column[] columns() default {};
    }

    public interface Presenter {

        @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})
        public @interface Column {}

        @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})
        public @interface PropertyColumn {
            public String value();
            public boolean editable() default false;
        }

        @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})
        public @interface StatusColumn {}

        @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})
        public @interface LastModifiedColumn {}
    }
}

With annotation inheritance I would just let PropertyColumn, StatusColumn, and LastModifiedColumn to extend the Column interface. But there's no interface inheritance.

The main goal here is to have the overview annotation as concise as possible. What is the best way to achieve my goal?

Upvotes: 2

Views: 233

Answers (1)

kapex
kapex

Reputation: 29949

This might be a case where annotations simply aren't flexible enough to represent complex structures. Although not as clean looking, I would consider using a single column annotation and creating enum constants for each column type like this:

@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})
public @interface Column {
    ColumnType value();
    String property() default "";
    boolean editable() default false;
}

@UI.App(
    name = "locations",
    columns = {
            @UI.Presenter.Column(value=ColumnType.PROPERTY, property="title"),
            @UI.Presenter.Column(value=ColumnType.PROPERTY, property="enabled"),
            @UI.Presenter.Column(ColumnType.STATUS),
            @UI.Presenter.Column(ColumnType.LAST_MODIFIED)
    }
)

Caveats are you need additional checking and documentation to prevent property and editable to be used with any column type. This approach won't work if you plan to add more column types with additional values, as it probably gets too complex then.

Upvotes: 1

Related Questions