juzu.impl.metamodel.AnnotationState Maven / Gradle / Ivy
/*
* Copyright 2013 eXo Platform SAS
*
* 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 juzu.impl.metamodel;
import juzu.impl.compiler.ElementHandle;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* Captures the precise state of an annotation in a serializable object. The content of the map are the value declared
* by the annotation, however the state keeps also track of the default values and those can be queried using the
* {@link #safeGet(String)} method.
*
* @author Julien Viet
*/
public class AnnotationState extends HashMap {
/** Set indicating which member were really declared in the annotation (i.e the default values). */
private HashMap undeclared;
/**
* Returns the annotation member if present, otherwise the default value.
*
* @param key the member key
* @return the serializable value
*/
public Serializable safeGet(String key) {
Serializable value = get(key);
if (value == null && undeclared != null) {
value = undeclared.get(key);
}
return value;
}
/**
* Return true if the member is present and not declared.
*
* @param key the member key
* @return true if the
*/
public boolean isDeclared(String key) {
return containsKey(key);
}
/**
* Return true if the member is present and not declared.
*
* @param key the member key
* @return true if the
*/
public boolean isUndeclared(String key) {
return undeclared == null || undeclared.containsKey(key);
}
/**
* Get an annotation state from the specified element and annotation type element, or null when
* it cannot be found.
*
* @param element the element
* @param annotationType the annotation type
* @return the annotation state
* @throws NullPointerException
*/
public static AnnotationState get(Element element, TypeMirror annotationType) throws NullPointerException {
for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
if (annotation.getAnnotationType().equals(annotationType)) {
return AnnotationState.create(annotation);
}
}
return null;
}
public static AnnotationState create(AnnotationMirror annotation) throws NullPointerException {
if (annotation == null) {
throw new NullPointerException("No null annotation allowed");
}
//
AnnotationState state = new AnnotationState();
//
TypeElement annotationTypeElement = (TypeElement)annotation.getAnnotationType().asElement();
Map extends ExecutableElement, ? extends AnnotationValue> values = annotation.getElementValues();
for (Element member : annotationTypeElement.getEnclosedElements()) {
if (member instanceof ExecutableElement) {
ExecutableElement xMember = (ExecutableElement)member;
AnnotationValue value = values.get(xMember);
String key = xMember.getSimpleName().toString();
HashMap target;
if (value == null) {
if (state.undeclared == null) {
state.undeclared = new HashMap();
}
target = state.undeclared;
value = xMember.getDefaultValue();
} else {
target = state;
}
if (value != null) {
Serializable serialized = unwrap(value, xMember.getReturnType());
target.put(key, serialized);
}
}
}
//
return state;
}
private static Serializable unwrap(Object value, TypeMirror type) {
if (value instanceof AnnotationValue) {
value = ((AnnotationValue)value).getValue();
}
//
if (type instanceof ArrayType) {
TypeMirror componentType = ((ArrayType)type).getComponentType();
if (value instanceof List) {
List> array = (List>)value;
if (array.size() == 0) {
// Need to force the cast, javadoc says it is serializable
return (Serializable)Collections.emptyList();
} else {
ArrayList