blob: 5da6638bb5e1b3025c5b698f8496c57655998860 [file] [log] [blame]
/*
* Copyright 2007 Google Inc.
*
* 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 com.google.gwt.core.ext.typeinfo;
import com.google.gwt.dev.util.collect.HashMap;
import com.google.gwt.dev.util.collect.Maps;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
/**
* Default implementation of the {@link HasAnnotations} interface.
*/
class Annotations implements HasAnnotations {
private static Map<Class<? extends Annotation>, Annotation> copyOfAnnotations(
Annotations otherAnnotations) {
Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
if (otherAnnotations != null) {
Annotation[] otherDeclaredAnnotations = otherAnnotations.getDeclaredAnnotations();
for (Annotation otherDeclaredAnnotation : otherDeclaredAnnotations) {
Class<? extends Annotation> otherDeclaredAnnotationType = otherDeclaredAnnotation.annotationType();
assert (otherDeclaredAnnotationType != null);
assert (!declaredAnnotations.containsKey(otherDeclaredAnnotationType));
declaredAnnotations.put(otherDeclaredAnnotationType,
otherDeclaredAnnotation);
}
}
return declaredAnnotations;
}
/**
* All annotations declared on the annotated element.
*/
private Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
/**
* Lazily initialized collection of annotations declared on or inherited by
* the annotated element.
*/
private Map<Class<? extends Annotation>, Annotation> lazyAnnotations = null;
/**
* If not <code>null</code> the parent to inherit annotations from.
*/
private Annotations parent;
Annotations() {
this.declaredAnnotations = Maps.create();
}
Annotations(Annotations otherAnnotations) {
this(copyOfAnnotations(otherAnnotations));
}
Annotations(Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
this.declaredAnnotations = Maps.normalize(declaredAnnotations);
}
public void addAnnotations(
Map<Class<? extends Annotation>, Annotation> annotations) {
if (annotations != null) {
assert (!annotations.containsValue(null));
declaredAnnotations = Maps.putAll(declaredAnnotations, annotations);
}
}
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
initializeAnnotations();
return annotationClass.cast(lazyAnnotations.get(annotationClass));
}
public Annotation[] getAnnotations() {
initializeAnnotations();
Collection<Annotation> values = lazyAnnotations.values();
return values.toArray(new Annotation[values.size()]);
}
public Annotation[] getDeclaredAnnotations() {
Collection<Annotation> values = declaredAnnotations.values();
return values.toArray(new Annotation[values.size()]);
}
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
void setParent(Annotations parent) {
this.parent = parent;
}
private void initializeAnnotations() {
if (lazyAnnotations != null) {
return;
}
if (parent != null) {
lazyAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
parent.initializeAnnotations();
for (Entry<Class<? extends Annotation>, Annotation> entry : parent.lazyAnnotations.entrySet()) {
if (entry.getValue().annotationType().isAnnotationPresent(
Inherited.class)) {
lazyAnnotations.put(entry.getKey(), entry.getValue());
}
}
lazyAnnotations.putAll(declaredAnnotations);
lazyAnnotations = Maps.normalize(lazyAnnotations);
} else {
lazyAnnotations = declaredAnnotations;
}
}
}