001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019     */
020    
021    package org.granite.tide.cdi;
022    
023    import java.lang.annotation.Annotation;
024    import java.lang.reflect.Type;
025    import java.util.HashSet;
026    import java.util.Set;
027    
028    import javax.enterprise.event.Observes;
029    import javax.enterprise.inject.spi.AnnotatedConstructor;
030    import javax.enterprise.inject.spi.AnnotatedField;
031    import javax.enterprise.inject.spi.AnnotatedMethod;
032    import javax.enterprise.inject.spi.AnnotatedType;
033    import javax.enterprise.inject.spi.BeanManager;
034    import javax.enterprise.inject.spi.Extension;
035    import javax.enterprise.inject.spi.ProcessAnnotatedType;
036    import javax.enterprise.util.AnnotationLiteral;
037    import javax.inject.Inject;
038    
039    import org.granite.messaging.service.annotations.RemoteDestination;
040    import org.granite.tide.annotations.TideEnabled;
041    
042    
043    /**
044     * @author William DRAI
045     */
046    public class TideExtension implements Extension {
047            
048            @Inject
049            BeanManager manager;
050    
051            
052            public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event) {
053                    AnnotatedType<X> annotatedType = event.getAnnotatedType();
054                    
055                    boolean tideComponent = false;
056                    for (Type type : annotatedType.getTypeClosure()) {
057                            if (type instanceof Class<?> 
058                                    && (((Class<?>)type).isAnnotationPresent(RemoteDestination.class) || ((Class<?>)type).isAnnotationPresent(TideEnabled.class))) {
059                                    tideComponent = true;
060                                    break;
061                            }
062                    }
063                    
064                    if (tideComponent)
065                            event.setAnnotatedType(new TideComponentAnnotatedType<X>(annotatedType));
066            }
067            
068            
069            @SuppressWarnings("serial")
070            public static class TideComponentAnnotatedType<T> implements AnnotatedType<T> {
071                    
072                    private final AnnotatedType<T> annotatedType;
073                    private final Annotation componentQualifier = new AnnotationLiteral<TideComponent>() {};
074                    private final Set<Annotation> annotations;
075                    
076                    
077                    public TideComponentAnnotatedType(AnnotatedType<T> annotatedType) {
078                            this.annotatedType = annotatedType;
079                            annotations = new HashSet<Annotation>(annotatedType.getAnnotations());
080                            annotations.add(componentQualifier);
081                    }
082    
083                    public Set<AnnotatedConstructor<T>> getConstructors() {
084                            return annotatedType.getConstructors();
085                    }
086    
087                    public Set<AnnotatedField<? super T>> getFields() {
088                            return annotatedType.getFields();
089                    }
090    
091                    public Class<T> getJavaClass() {
092                            return annotatedType.getJavaClass();
093                    }
094    
095                    public Set<AnnotatedMethod<? super T>> getMethods() {
096                            return annotatedType.getMethods();
097                    }
098    
099                    @SuppressWarnings("unchecked")
100                    public <X extends Annotation> X getAnnotation(Class<X> annotationClass) {
101                            if (annotationClass.equals(TideComponent.class))
102                                    return (X)componentQualifier;                   
103                            return annotatedType.getAnnotation(annotationClass);
104                    }
105    
106                    public Set<Annotation> getAnnotations() {
107                            return annotations;
108                    }
109    
110                    public Type getBaseType() {
111                            return annotatedType.getBaseType();
112                    }
113    
114                    public Set<Type> getTypeClosure() {
115                            return annotatedType.getTypeClosure();
116                    }
117    
118                    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
119                            if (annotationClass.equals(TideComponent.class))
120                                    return true;                    
121                            return annotatedType.isAnnotationPresent(annotationClass);
122                    }
123            }
124    }