By default, for a class inheriting from NewTypeWizardPage
, the creation of the Java type is performed by the inherited method
public void createType(IProgressMonitor monitor)
This method in turn calls
protected void createTypeMembers(
IType newType,
ImportsManager imports,
IProgressMonitor monitor)
throws
CoreException
which is documented as a hook method, and it is this method which the example in the documentation overrides.
To create the annotated definition we need to add the referenced Annotation types and Enums to the list of imports and annotate the created Annotation. Both the created type, in this case the Annotation, and the ImportsManager are being passed to the hook method, so it looks as though it should be possible to do what is necessary by overriding this method.
Adding the imports to the ImportsManager is easily done.
...
if (documented)
{
imports.addImport(DOCUMENTED_ANNOTATION_TYPE);
}
if (inherited)
{
imports.addImport(INHERITED_ANNOTATION_TYPE);
}
switch (retention)
{
case CLASS:
break;
default:
imports.addImport(RETENTION_ANNOTATION_TYPE);
imports.addImport(RETENTION_POLICY_ENUM_TYPE);
}
if (targets.size() != 0)
{
imports.addImport(TARGET_ANNOTATION_TYPE);
imports.addImport(ELEMENT_TYPE_ENUM_TYPE);
}
...
with the constants being defined as follows
private static final String DOCUMENTED_ANNOTATION_TYPE = "java.lang.annotation.Documented";
private static final String INHERITED_ANNOTATION_TYPE = "java.lang.annotation.Inherited";
private static final String RETENTION_ANNOTATION_TYPE = "java.lang.annotation.Retention";
private static final String TARGET_ANNOTATION_TYPE = "java.lang.annotation.Target";
private static final String ELEMENT_TYPE_ENUM_TYPE = "java.lang.annotation.ElementType";
private static final String RETENTION_POLICY_ENUM_TYPE = "java.lang.annotation.RetentionPolicy";
For the Documented
and Inherited
meta-annotations only the Annotation types themselves need to be imported. In the Retention
and Target
cases the Enum value types are also imported.
Adding the Annotations themselves to the newly created type turns out to be more difficult. The IType
interface extends the IAnnotable
amongst others, but none of the methods on IAnnotable
or any of the super-interfaces, or on IType
itself apparently enable the addition of Annotations.
It is entirely possible that somewhere in the maze of twisty little interfaces there is a way to do so, but I have yet to stumble upon it.
In the end, following a good deal of random experimentation I discovered the
protected String constructCUContent(
ICompilationUnit cu,
String typeContent,
String lineDelimiter)
throws
CoreException
method on NewTypeWizardPage
.
The typeContent
argument contains the source of the annotation as created.
Overriding this method modifying the typeContent
argument and then invoking the overridden method turns out to have the required effect.
@Override
protected String constructCUContent(
ICompilationUnit theCompilationUnit,
String theTypeContent,
String theLineDelimiter)
throws
CoreException
{
StringBuilder builder = new StringBuilder();
if (documented)
{
builder.append("@Documented ");
}
if (inherited)
{
builder.append("@Inherited ");
}
switch (retention)
{
case CLASS:
break;
default:
builder.append("@Retention(RetentionPolicy.");
builder.append(retention);
builder.append(") ");
}
int nTargets = targets.size();
if (nTargets != 0)
{
builder.append("@Target(");
if (nTargets != 1)
{
boolean first = true;
builder.append("{");
for (ElementType type : targets)
{
if (!first)
{
builder.append(", ");
}
else
{
first = false;
}
builder.append("ElementType.");
builder.append(type);
}
builder.append("}");
}
else
{
for (ElementType type : targets)
{
builder.append("ElementType.");
builder.append(type);
}
}
builder.append(") ");
}
builder.append(theTypeContent);
return super.constructCUContent(theCompilationUnit, builder.toString(), theLineDelimiter);
}
In CLOS this would have been an :around
method. Sigh …
Copyright (c) 2009 By Simon Lewis. All Rights Reserved