Package org.jboss.weld.resolution

Source Code of org.jboss.weld.resolution.ResolvableBuilder

/*
* 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.resolution;

import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.lang.reflect.Member;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.New;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.Interceptor;
import javax.inject.Named;
import javax.inject.Provider;

import org.jboss.weld.literal.NamedLiteral;
import org.jboss.weld.literal.NewLiteral;
import org.jboss.weld.logging.BeanManagerLogger;
import org.jboss.weld.logging.ResolutionLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.metadata.cache.MetaAnnotationStore;
import org.jboss.weld.util.reflection.Reflections;

public class ResolvableBuilder {

    private static final Class<?>[] FACADE_TYPES = new Class<?>[] { Event.class, Instance.class, Provider.class };
    private static final Class<?>[] METADATA_TYPES = new Class<?>[] { Interceptor.class, Decorator.class, Bean.class };
    private static final Set<QualifierInstance> ANY_SINGLETON = Collections.singleton(QualifierInstance.ANY);

    protected Class<?> rawType;
    protected final Set<Type> types;
    protected final Set<Annotation> qualifiers;
    protected final Set<QualifierInstance> qualifierInstances;
    protected final Map<Class<? extends Annotation>, Annotation> mappedQualifiers;
    protected Bean<?> declaringBean;
    private final MetaAnnotationStore store;
    protected boolean delegate;

    public ResolvableBuilder(final MetaAnnotationStore store) {
        this.store = store;
        this.types = new HashSet<Type>();
        this.qualifiers = new HashSet<Annotation>();
        this.mappedQualifiers = new HashMap<Class<? extends Annotation>, Annotation>();
        this.qualifierInstances = new HashSet<QualifierInstance>();
    }

    public ResolvableBuilder(BeanManagerImpl manager) {
        this(manager.getServices().get(MetaAnnotationStore.class));
    }

    public ResolvableBuilder(Type type, final BeanManagerImpl beanManager) {
        this(beanManager);
        if (type != null) {
            this.rawType = Reflections.getRawType(type);
            if (rawType == null || type instanceof TypeVariable<?>) {
                throw ResolutionLogger.LOG.cannotExtractRawType(type);
            }
            this.types.add(type);
        }
    }

    public ResolvableBuilder(InjectionPoint injectionPoint, final BeanManagerImpl manager) {
        this(injectionPoint.getType(), manager);
        addQualifiers(injectionPoint.getQualifiers());
        if (mappedQualifiers.containsKey(Named.class)) {
            Named named = (Named) mappedQualifiers.get(Named.class);
            QualifierInstance qualifierInstance = QualifierInstance.of(named, store);
            if (named.value().equals("")) {
                qualifiers.remove(named);
                qualifierInstances.remove(qualifierInstance);

                // WELD-1739
                // This is an injection point with an @Named qualifier, with no value specified, we need to assume the name of the field or parameter is the
                // value
                Member member = injectionPoint.getMember();
                if (member instanceof Executable) {
                    // Method or constructor injection
                    Executable executable = (Executable) member;
                    AnnotatedParameter<?> annotatedParameter = (AnnotatedParameter<?>) injectionPoint.getAnnotated();
                    Parameter parameter = executable.getParameters()[annotatedParameter.getPosition()];
                    named = new NamedLiteral(parameter.getName());
                } else {
                    named = new NamedLiteral(injectionPoint.getMember().getName());
                }

                qualifierInstance = QualifierInstance.of(named, store);
                qualifiers.add(named);
                qualifierInstances.add(qualifierInstance);
                mappedQualifiers.put(Named.class, named);
            }
        }
        setDeclaringBean(injectionPoint.getBean());
        this.delegate = injectionPoint.isDelegate();
    }

    public ResolvableBuilder setDeclaringBean(Bean<?> declaringBean) {
        this.declaringBean = declaringBean;
        return this;
    }

    public ResolvableBuilder addType(Type type) {
        this.types.add(type);
        return this;
    }

    public ResolvableBuilder addTypes(Set<Type> types) {
        this.types.addAll(types);
        return this;
    }

    public boolean isDelegate() {
        return delegate;
    }

    public void setDelegate(boolean delegate) {
        this.delegate = delegate;
    }

    public Resolvable create() {
        if (qualifiers.size() == 0) {
            this.qualifierInstances.add(QualifierInstance.DEFAULT);
        }
        for (Type type : types) {
            Class<?> rawType = Reflections.getRawType(type);
            for (Class<?> facadeType : FACADE_TYPES) {
                if (facadeType.equals(rawType)) {
                    return createFacade(facadeType);
                }
            }
            for (Class<?> metadataType : METADATA_TYPES) {
                if (metadataType.equals(rawType)) {
                    return createMetadataProvider(metadataType);
                }
            }
        }
        return new ResolvableImpl(rawType, types, mappedQualifiers, declaringBean, qualifierInstances, delegate);
    }

    private Resolvable createFacade(Class<?> rawType) {
        Set<Type> types = Collections.<Type>singleton(rawType);
        return new ResolvableImpl(rawType, types, mappedQualifiers, declaringBean, ANY_SINGLETON, delegate);
    }

    // just as facade but we keep the qualifiers so that we can recognize Bean from @Intercepted Bean.
    private Resolvable createMetadataProvider(Class<?> rawType) {
        Set<Type> types = Collections.<Type>singleton(rawType);
        return new ResolvableImpl(rawType, types, mappedQualifiers, declaringBean, qualifierInstances, delegate);
    }

    public ResolvableBuilder addQualifier(Annotation qualifier) {
        // Handle the @New qualifier special case
        QualifierInstance qualifierInstance = QualifierInstance.of(qualifier, store);
        final Class<? extends Annotation> annotationType = qualifierInstance.getAnnotationClass();
        if (annotationType.equals(New.class)) {
            New newQualifier = New.class.cast(qualifier);
            if (newQualifier.value().equals(New.class) && rawType == null) {
                throw new IllegalStateException("Cannot transform @New when there is no known raw type");
            } else if (newQualifier.value().equals(New.class)) {
                qualifier = new NewLiteral(rawType);
                qualifierInstance = QualifierInstance.of(qualifier, store);
            }
        }

        checkQualifier(qualifier, qualifierInstance, annotationType);
        this.qualifiers.add(qualifier);
        this.qualifierInstances.add(qualifierInstance);
        this.mappedQualifiers.put(annotationType, qualifier);
        return this;
    }

    public ResolvableBuilder addQualifierIfAbsent(Annotation qualifier) {
        if (!qualifiers.contains(qualifier)) {
            addQualifier(qualifier);
        }
        return this;
    }

    public ResolvableBuilder addQualifiers(Annotation[] qualifiers) {
        for (Annotation qualifier : qualifiers) {
            addQualifier(qualifier);
        }
        return this;
    }

    public ResolvableBuilder addQualifiers(Collection<Annotation> qualifiers) {
        for (Annotation qualifier : qualifiers) {
            addQualifier(qualifier);
        }
        return this;
    }

    protected void checkQualifier(Annotation qualifier, final QualifierInstance qualifierInstance, Class<? extends Annotation> annotationType) {
        if (!store.getBindingTypeModel(annotationType).isValid()) {
            throw BeanManagerLogger.LOG.invalidQualifier(qualifier);
        }
        if (qualifierInstances.contains(qualifierInstance)) {
            throw BeanManagerLogger.LOG.duplicateQualifiers(qualifiers);
        }
    }

    protected static class ResolvableImpl implements Resolvable {

        private final Set<QualifierInstance> qualifierInstances;
        private final Map<Class<? extends Annotation>, Annotation> mappedQualifiers;
        private final Set<Type> typeClosure;
        private final Class<?> rawType;
        private final Bean<?> declaringBean;
        private final boolean delegate;

        protected ResolvableImpl(Class<?> rawType, Set<Type> typeClosure, Map<Class<? extends Annotation>, Annotation> mappedQualifiers, Bean<?> declaringBean, final Set<QualifierInstance> qualifierInstances, boolean delegate) {
            this.mappedQualifiers = mappedQualifiers;
            this.typeClosure = typeClosure;
            this.rawType = rawType;
            this.declaringBean = declaringBean;
            this.qualifierInstances = qualifierInstances;
            this.delegate = delegate;
        }

        @Override
        public Set<QualifierInstance> getQualifiers() {
            return qualifierInstances;
        }

        @Override
        public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
            return mappedQualifiers.containsKey(annotationType);
        }

        @Override
        public Set<Type> getTypes() {
            return typeClosure;
        }

        @Override
        public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
            return Reflections.<A>cast(mappedQualifiers.get(annotationType));
        }

        @Override
        public Class<?> getJavaClass() {
            return rawType;
        }

        @Override
        public Bean<?> getDeclaringBean() {
            return declaringBean;
        }

        @Override
        public String toString() {
            return "Types: " + getTypes() + "; Bindings: " + getQualifiers();
        }

        @Override
        public int hashCode() {
            int result = 17;
            result = 31 * result + this.getTypes().hashCode();
            result = 31 * result + this.qualifierInstances.hashCode();
            return result;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof ResolvableImpl) {
                ResolvableImpl r = (ResolvableImpl) o;
                return this.getTypes().equals(r.getTypes()) && this.qualifierInstances.equals(r.qualifierInstances);
            }
            return false;
        }

        @Override
        public boolean isDelegate() {
            return delegate;
        }
    }

    protected MetaAnnotationStore getMetaAnnotationStore() {
        return store;
    }
}
TOP

Related Classes of org.jboss.weld.resolution.ResolvableBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.