/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.weld.metadata.cache;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.enterprise.context.NormalScope;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.Stereotype;
import javax.inject.Named;
import javax.inject.Qualifier;
import javax.inject.Scope;
import javax.interceptor.InterceptorBinding;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotation;
import org.jboss.weld.logging.MetadataLogger;
import org.jboss.weld.logging.ReflectionLogger;
import org.jboss.weld.util.collections.Arrays2;
/**
* A meta model for a stereotype, allows us to cache a stereotype and to
* validate it
*
* @author Pete Muir
*/
public class StereotypeModel<T extends Annotation> extends AnnotationModel<T> {
private static final Set<Class<? extends Annotation>> META_ANNOTATIONS = Collections.<Class<? extends Annotation>>singleton(Stereotype.class);
// Is the stereotype an alternative
private boolean alternative;
// The default scope type
private Annotation defaultScopeType;
// Is the bean name defaulted
private boolean beanNameDefaulted;
// The interceptor bindings
private Set<Annotation> interceptorBindings;
private Set<Annotation> inheritedStereotypes;
private Set<Annotation> metaAnnotations;
/**
* Constructor
*/
public StereotypeModel(EnhancedAnnotation<T> enhancedAnnotatedAnnotation) {
super(enhancedAnnotatedAnnotation);
}
@Override
protected void init(EnhancedAnnotation<T> annotatedAnnotation) {
super.init(annotatedAnnotation);
initAlternative(annotatedAnnotation);
initDefaultScopeType(annotatedAnnotation);
initBeanNameDefaulted(annotatedAnnotation);
initInterceptorBindings(annotatedAnnotation);
initInheritedStereotypes(annotatedAnnotation);
checkBindings(annotatedAnnotation);
this.metaAnnotations = annotatedAnnotation.getAnnotations();
}
/**
* Validates the binding types
*/
private void checkBindings(EnhancedAnnotation<T> annotatedAnnotation) {
Set<Annotation> bindings = annotatedAnnotation.getMetaAnnotations(Qualifier.class);
if (bindings.size() > 0) {
for (Annotation annotation : bindings) {
if (!annotation.annotationType().equals(Named.class)) {
throw MetadataLogger.LOG.qualifierOnStereotype(annotatedAnnotation);
}
}
}
}
/**
* Initializes the interceptor bindings
*/
private void initInterceptorBindings(EnhancedAnnotation<T> annotatedAnnotation) {
interceptorBindings = annotatedAnnotation.getMetaAnnotations(InterceptorBinding.class);
}
private void initInheritedStereotypes(EnhancedAnnotation<T> annotatedAnnotation) {
this.inheritedStereotypes = annotatedAnnotation.getMetaAnnotations(Stereotype.class);
}
/**
* Initializes the bean name defaulted
*/
private void initBeanNameDefaulted(EnhancedAnnotation<T> annotatedAnnotation) {
if (annotatedAnnotation.isAnnotationPresent(Named.class)) {
if (!"".equals(annotatedAnnotation.getAnnotation(Named.class).value())) {
throw MetadataLogger.LOG.valueOnNamedStereotype(annotatedAnnotation);
}
beanNameDefaulted = true;
}
}
/**
* Initializes the default scope type
*/
private void initDefaultScopeType(EnhancedAnnotation<T> annotatedAnnotation) {
Set<Annotation> scopeTypes = new HashSet<Annotation>();
scopeTypes.addAll(annotatedAnnotation.getMetaAnnotations(Scope.class));
scopeTypes.addAll(annotatedAnnotation.getMetaAnnotations(NormalScope.class));
if (scopeTypes.size() > 1) {
throw MetadataLogger.LOG.multipleScopes(annotatedAnnotation);
} else if (scopeTypes.size() == 1) {
this.defaultScopeType = scopeTypes.iterator().next();
}
}
/**
* Initializes the default deployment type
*/
private void initAlternative(EnhancedAnnotation<T> annotatedAnnotation) {
if (annotatedAnnotation.isAnnotationPresent(Alternative.class)) {
this.alternative = true;
}
}
@Override
protected void check(EnhancedAnnotation<T> annotatedAnnotation) {
super.check(annotatedAnnotation);
if (isValid()) {
if (!annotatedAnnotation.isAnnotationPresent(Target.class)) {
ReflectionLogger.LOG.missingTarget(annotatedAnnotation);
} else {
ElementType[] elementTypes = annotatedAnnotation.getAnnotation(Target.class).value();
if (!(Arrays2.unorderedEquals(elementTypes, METHOD, FIELD, TYPE) ||
Arrays2.unorderedEquals(elementTypes, TYPE) ||
Arrays2.unorderedEquals(elementTypes, METHOD) ||
Arrays2.unorderedEquals(elementTypes, FIELD) ||
Arrays2.unorderedEquals(elementTypes, METHOD, TYPE)
)) {
ReflectionLogger.LOG.missingTargetMethodFieldTypeParameterOrTargetMethodTypeOrTargetMethodOrTargetTypeOrTargetField(annotatedAnnotation);
}
}
}
}
/**
* Get the default scope type the stereotype specifies
*
* @return The default scope type, or null if none is specified
*/
public Annotation getDefaultScopeType() {
return defaultScopeType;
}
/**
* Get any interceptor bindings the the stereotype specifies
*
* @return The interceptor bindings, or an empty set if none are specified.
*/
public Set<Annotation> getInterceptorBindings() {
return interceptorBindings;
}
/**
* Indicates if the bean name is defaulted
*
* @return True if defaulted, false otherwise
*/
public boolean isBeanNameDefaulted() {
return beanNameDefaulted;
}
/**
* Gets the meta-annotation type
*
* @return The Stereotype class
*/
@Override
protected Set<Class<? extends Annotation>> getMetaAnnotationTypes() {
return META_ANNOTATIONS;
}
/**
* @return
*/
public boolean isAlternative() {
return alternative;
}
public Set<Annotation> getInheritedStereotypes() {
return inheritedStereotypes;
}
/**
* @return the metaAnnotations
*/
public Set<Annotation> getMetaAnnotations() {
return metaAnnotations;
}
}