Monday, June 18, 2007

Abstract Enum on KSL

The reasons in few lines
Give the ability to create abstract classes between the final enum declaration containing the static enumerated values, and the abstract superclass for all enum java.lang.Enum.
So an AbstractColumn.java file can contain:

public abstract enum AbstractColumn {
String columnName;
int precision;
AbstractColumn() {
columnName = name();
precision = 0;
}
AbstractColumn(String c, int p) {
....
}
public String getColumnName() {return columnName();}
}

And inside an O/R Mapping framework an annotation can be:
public interface @Column {AbstractColumn definition();}

And then the application users have the level of indirection they need to provide logic to the framework using the static annotations. For example:

public enum CustomerColumn extends AbstractColumn {
firstName, lastName, age;
public String getColumnName() {
return StringUtils.capitalizeWithUnderscore(name());
}
}

@Entity
public class Customer {
@Column(definition = CustomerColumn.firstName)
private String firstName;
}

Then all the problems of hardcoded schema names in JPA entities (quite annoying), copy/paste, string based errors (no type safety), and so on disappear.
From my experience, the limitations of Annotations are really pushing developers away, and this feature can unlock the issue.

The KSL or OpenJDK patch
Please check A dive into the KSL A big dive (more like drowning) into the Kitchen Sink Language!, for how this patch was made and the references.

So, I finally manage to write a patch for abstract enum with the following limitations:
  1. Abstract enum cannot extends other abstract enums (the extends close needs to be empty)
  2. You need to declare the constructors you are using in the final enum extending the abstract enum and use super() calls if needed
  3. You can declare the generics signature > in the abstract Enum, and use enum MyEnum for the final one. It does not mean generics are allowed for enum,
  4. but for the moment I did not find synthetic sugar for generating generics that I could based my work on?
  5. I had the following problem: '''The enum containing anonymous classes does not work anymore with this patch'''. The main problem is that after Check an implicit abstract flag is set on the enum and don't find a way to distinguish between the implicit and explicit abstract flag :-( I solved it using tree.mods and check for protected constructors in the second version of the patch.
  6. So the only problem left is the usage of Abstract Enum in Annotations. It works at compile time but failed at runtime. So I need to work on the OpenJDK now. I'm getting:
java.lang.annotation.AnnotationTypeMismatchException: Incorrectly typed data found for annotation element public abstract abstractEnum.annotation.AbstractE2 abstractEnum.annotation.AnnoAETest.ae2() (Found data of type LabstractEnum/annotation/E21;.one)
at sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy.generateException(AnnotationTypeMismatchExceptionProxy.java:56)
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:74)
at $Proxy3.ae2(Unknown Source)
at abstractEnum.annotation.AnnoAEUsage.main(AnnoAEUsage.java:21)

The patch is here Abstract_Enum_in_KSL_second_version.patch which is based on "compiler-1.7.0-ea-b05". I applied the patch to "openjdk/jdk7/b13" in the folder "j2se" and it matches. I did not test the rebuild, yet.
The test code is based on a closed bug number about abstract enum (Bug ID: 6507006) is here here JtregTests.jar, and only the test of abstract enum in annotations fails.

The draft for JSL modifications

8.1.1.1 abstract Classes
Enum types (§8.9) can be declared abstract.

8.1.4 Superclasses and Subclasses
The optional extends clause in a normal class declaration specifies the direct
superclass of the current class.

Super:
extends ClassType

The following is repeated from §4.3 to make the presentation here clearer:

ClassType:
TypeDeclSpecifier TypeArgumentsopt

A class is said to be a direct subclass of its direct superclass. The direct super-class is the class from whose implementation the implementation of the current class is derived. The direct superclass of an enum type E is Enum, unless a SuperEnum is declared.

8.9 Enums
An enum declaration has the form:
EnumDeclaration:
ClassModifiers ''opt'' enum Identifier SuperEnum''opt'' Interfaces''opt'' EnumBody
SuperEnum:
extends EnumType
EnumType:
TypeDeclSpecifier
EnumBody:
{ EnumConstants''opt'' ,''opt'' EnumBodyDeclarations''opt'' }

The body of an enum type may contain enum constants, if the enum is not declared abstract. An enum constant defines an instance of the enum type. A non abstract enum type has no instances other than those defined by its enum constants.
The superclass of an enum can only be another enum declared abstract.
Generics declaration enum are not allowed, and will result in a compile-time error.


14.11 The switch Statement

The type of the Expression must be char, byte, short, int, Character,
Byte, Short, Integer, or a non abstract enum type (§8.9), or a compile-time error occurs.

No comments: