/*
* Copyright 2007-2010 Brian S O'Neill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2006 Amazon Technologies, Inc. or its affiliates.
* Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
* of Amazon Technologies, Inc. or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cojen.util;
import java.lang.annotation.Annotation;
import org.cojen.classfile.TypeDesc;
/**
* Prints machine readable, self-describing, annotation descriptors.
*
* @author Brian S O'Neill
* @see AnnotationDescParser
* @since 2.1
*/
public class AnnotationDescPrinter extends AnnotationVisitor<Object, Object> {
/**
* Returns an annotation descriptor that has no parameters.
*/
public static String makePlainDescriptor(Class<? extends Annotation> annotationType) {
return "" + TAG_ANNOTATION + TypeDesc.forClass(annotationType).getDescriptor();
}
/**
* Returns an annotation descriptor that has no parameters.
*/
public static String makePlainDescriptor(String annotationType) {
return "" + TAG_ANNOTATION + TAG_OBJECT + annotationType.replace('.', '/') + ';';
}
static final char
TAG_BOOLEAN = 'Z',
TAG_BYTE = 'B',
TAG_SHORT = 'S',
TAG_CHAR = 'C',
TAG_INT = 'I',
TAG_LONG = 'J',
TAG_FLOAT = 'F',
TAG_DOUBLE = 'D',
TAG_VOID = 'V',
TAG_OBJECT = 'L',
TAG_ARRAY = '[',
TAG_STRING = 's',
TAG_CLASS = 'c',
TAG_ENUM = 'e',
TAG_ANNOTATION = '@';
private final StringBuilder mBuilder;
/**
* @param sort when true, sort annotation members by name (case sensitive)
* @param b StringBuilder to get printed results
*/
public AnnotationDescPrinter(boolean sort, StringBuilder b) {
super(sort);
mBuilder = b;
}
/**
* Prints the annotation to the builder passed to the constructor.
*
* @param value Annotation to visit
* @return null
*/
public Object visit(Annotation value) {
return visit(value, null);
}
public Object visit(String name, int pos, Annotation value, Object param) {
if (appendName(name, pos, TAG_ANNOTATION)) {
mBuilder.append(TypeDesc.forClass(value.annotationType()).getDescriptor());
}
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, int value, Object param) {
appendName(name, pos, TAG_INT);
mBuilder.append(value);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, long value, Object param) {
appendName(name, pos, TAG_LONG);
mBuilder.append(value);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, float value, Object param) {
appendName(name, pos, TAG_FLOAT);
mBuilder.append(Float.toString(value));
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, double value, Object param) {
appendName(name, pos, TAG_DOUBLE);
mBuilder.append(Double.toString(value));
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, boolean value, Object param) {
appendName(name, pos, TAG_BOOLEAN);
mBuilder.append(value ? '1' : '0');
return null;
}
public Object visit(String name, int pos, byte value, Object param) {
appendName(name, pos, TAG_BYTE);
mBuilder.append(value);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, short value, Object param) {
appendName(name, pos, TAG_SHORT);
mBuilder.append(value);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, char value, Object param) {
appendName(name, pos, TAG_CHAR);
mBuilder.append(value);
return null;
}
public Object visit(String name, int pos, String value, Object param) {
appendName(name, pos, TAG_STRING);
int length = value.length();
for (int i=0; i<length; i++) {
char c = value.charAt(i);
if (c == '\\' || c == ';') {
mBuilder.append('\\');
}
mBuilder.append(c);
}
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, Class value, Object param) {
appendName(name, pos, TAG_CLASS);
if (value == String.class) {
mBuilder.append(TAG_STRING);
} else if (value == Class.class) {
mBuilder.append(TAG_CLASS);
} else {
mBuilder.append(TypeDesc.forClass(value).getDescriptor());
}
return null;
}
public Object visit(String name, int pos, Enum value, Object param) {
if (appendName(name, pos, TAG_ENUM)) {
mBuilder.append(value.getDeclaringClass().getName());
mBuilder.append('.');
}
mBuilder.append(value.name());
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, Annotation[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, int[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, long[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, float[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, double[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, boolean[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, byte[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, short[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, char[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, String[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, Class[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
public Object visit(String name, int pos, Enum[] value, Object param) {
appendName(name, pos, TAG_ARRAY);
super.visit(name, pos, value, param);
mBuilder.append(';');
return null;
}
/**
* @return true if tag was appended too
*/
private boolean appendName(String name, int pos, char tag) {
if (name != null) {
mBuilder.append(name);
mBuilder.append('=');
}
if (name != null || pos == 0) {
mBuilder.append(tag);
return true;
}
return false;
}
}