2010년 4월 5일 월요일

AST로 배열값을 설정하는 annotation 추가하기

javax.ws.rs.Produces annotation은 문자열 배열을 값으로 가진다.
@Produces({"application/xml", "application/json"})

배열값을 가지는 annotation들은 기본적으로 1개만 지정되더라고 또는 전혀 지정되지 않더라도 문제가 되지 않는다.

@Produces("application/xml") 처럼 문자열 1개만 설정하도록 자바 소스를 생성하는 예제는 http://credemol.blogspot.com/2010/03/jdt-ast-abstract-syntax-tree.html에서 예제 소스를 작성해 두었다.

이번 글은 배열 값을 처리하는 것을 중심으로 설명하도록 한다.

@Produces(new String[] { "application/xml", "application/json"})

위와 같이 annotation을 설정했다면 어떻게 될까?
예상하는 바와 같이 "The value for annotation attribute Produces.value must be an array initializer" 라는 메시지가 출력되는 컴파일에러가 발생한다.

AST 용어로 접근하자면 new String[]은 ArrayCreation 이고, {"application/xml", "application/json"} 은 ArrayInitializer가 된다.
위의 에러메시지에서도 확인할 수 있듯이 annotation의 값은 array initializer가 되어야 한다.

@Produces와 같이 name=value 포맷으로 속성을 지정하는 것이 아니라 단순히 값만 지정하는 annotation은 SingleMemberAnnotation이다.

아래의 소스코드를 살펴보면 쉽게 이해할 수 있을 것이다.

예제 소스

public static void addSingleMemberAnnotation(AST ast, TypeDeclaration type, String annotationType, String[] literalValues) {
SingleMemberAnnotation anno = ast.newSingleMemberAnnotation();
anno.setTypeName(createTypeName(ast, annotationType));

ArrayInitializer arrayInitializer = ast.newArrayInitializer();
for(String value : literalValues) {
StringLiteral literal = ast.newStringLiteral();
literal.setLiteralValue(value.trim());
arrayInitializer.expressions().add(literal);
}

anno.setValue(arrayInitializer);
List list = (List) type.getStructuralProperty(TypeDeclaration.MODIFIERS2_PROPERTY);
list.add(anno);

}

댓글 없음:

댓글 쓰기