org.jboss.weld.resources.MemberTransformer.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.weld.resources.MemberTransformer.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2010, 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.resources;

import static org.jboss.weld.util.cache.LoadingCacheUtils.getCastCacheValue;
import static org.jboss.weld.util.reflection.Reflections.cast;

import java.lang.reflect.Member;
import java.util.Collection;

import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;

import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedCallable;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedField;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMember;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMethod;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedParameter;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.slim.backed.BackedAnnotatedMember;
import org.jboss.weld.annotated.slim.unbacked.UnbackedAnnotatedMember;
import org.jboss.weld.annotated.slim.unbacked.UnbackedAnnotatedType;
import org.jboss.weld.annotated.slim.unbacked.UnbackedMemberIdentifier;
import org.jboss.weld.bootstrap.api.BootstrapService;
import org.jboss.weld.logging.BeanLogger;
import org.jboss.weld.util.AnnotatedTypes;
import org.jboss.weld.util.reflection.Reflections;

import com.google.common.base.Objects;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

/**
 * Serves several functions. Firstly, transforms a given {@link AnnotatedMember} into its richer counterpart
 * {@link EnhancedAnnotatedMember}. Secondly, a {@link BackedAnnotatedMember} or {@link UnbackedAnnotatedMember} can be looked
 * up.
 *
 * @author Jozef Hartinger
 *
 */
public class MemberTransformer implements BootstrapService {

    private static class MemberKey<X, A extends AnnotatedMember<X>> {
        private final EnhancedAnnotatedType<X> type;
        private final A member;
        private final int hashCode;

        public MemberKey(EnhancedAnnotatedType<X> type, A member) {
            this.type = type;
            this.member = member;
            this.hashCode = Objects.hashCode(type, member);
        }

        @Override
        public int hashCode() {
            return hashCode;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof MemberKey) {
                MemberKey<?, ?> that = (MemberKey<?, ?>) obj;
                return Objects.equal(this.type, that.type) && Objects.equal(this.member, that.member);
            }
            return false;
        }
    }

    private final ClassTransformer transformer;

    private final LoadingCache<UnbackedMemberIdentifier<?>, UnbackedAnnotatedMember<?>> unbackedAnnotatedMembersById;

    private final LoadingCache<MemberKey<?, ?>, EnhancedAnnotatedMember<?, ?, ?>> enhancedMemberCache;
    private final EnhancedFieldLoader enhancedFieldLoader;
    private final EnhancedMethodLoader enhancedMethodLoader;
    private final EnhancedConstructorLoader enhancedConstructorLoader;

    public MemberTransformer(ClassTransformer transformer) {
        CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder();
        this.transformer = transformer;
        this.unbackedAnnotatedMembersById = cacheBuilder.build(new UnbackedMemberById());
        this.enhancedFieldLoader = new EnhancedFieldLoader();
        this.enhancedMethodLoader = new EnhancedMethodLoader();
        this.enhancedConstructorLoader = new EnhancedConstructorLoader();
        this.enhancedMemberCache = cacheBuilder.build(new EnhancedMemberLoaderFunction());
    }

    // Unbacked members

    public <X> UnbackedAnnotatedMember<X> getUnbackedMember(UnbackedMemberIdentifier<X> identifier) {
        return getCastCacheValue(unbackedAnnotatedMembersById, identifier);
    }

    /**
     * If an unbacked member is being deserialized it is looked in all the members of the declaring type and cached.
     */
    private static class UnbackedMemberById
            extends CacheLoader<UnbackedMemberIdentifier<?>, UnbackedAnnotatedMember<?>> {

        @Override
        public UnbackedAnnotatedMember<?> load(UnbackedMemberIdentifier<?> identifier) {
            return findMatchingMember(identifier.getType(), identifier.getMemberId());
        }

        private <T> UnbackedAnnotatedMember<T> findMatchingMember(UnbackedAnnotatedType<T> type, String id) {
            for (AnnotatedField<? super T> field : type.getFields()) {
                if (id.equals(AnnotatedTypes.createFieldId(field))) {
                    return cast(field);
                }
            }
            for (AnnotatedMethod<? super T> method : type.getMethods()) {
                if (id.equals(AnnotatedTypes.createMethodId(method.getJavaMember(), method.getAnnotations(),
                        method.getParameters()))) {
                    return Reflections.cast(method);
                }
            }
            for (AnnotatedConstructor<T> constructor : type.getConstructors()) {
                if (id.equals(AnnotatedTypes.createConstructorId(constructor.getJavaMember(),
                        constructor.getAnnotations(), constructor.getParameters()))) {
                    return cast(constructor);
                }
            }
            throw BeanLogger.LOG.unableToLoadMember(id);
        }
    }

    // Enhanced members

    public <X, A extends EnhancedAnnotatedMember<?, X, ? extends Member>> A loadEnhancedMember(
            AnnotatedMember<X> member, String bdaId) {
        if (member instanceof EnhancedAnnotatedMember<?, ?, ?>) {
            return Reflections.cast(member);
        }
        EnhancedAnnotatedType<X> declaringType = transformer.getEnhancedAnnotatedType(member.getDeclaringType(),
                bdaId);
        return getCastCacheValue(enhancedMemberCache, new MemberKey<X, AnnotatedMember<X>>(declaringType, member));
    }

    public <X> EnhancedAnnotatedParameter<?, X> loadEnhancedParameter(AnnotatedParameter<X> parameter,
            String bdaId) {
        if (parameter instanceof EnhancedAnnotatedParameter<?, ?>) {
            return Reflections.cast(parameter);
        }
        EnhancedAnnotatedCallable<?, X, Member> callable = loadEnhancedMember(parameter.getDeclaringCallable(),
                bdaId);
        return callable.getEnhancedParameters().get(parameter.getPosition());
    }

    private class EnhancedMemberLoaderFunction
            extends CacheLoader<MemberKey<?, ?>, EnhancedAnnotatedMember<?, ?, ?>> {
        @Override
        public EnhancedAnnotatedMember<?, ?, ?> load(MemberKey<?, ?> from) {
            if (from.member instanceof AnnotatedField<?>) {
                return enhancedFieldLoader.load(Reflections.<MemberKey<?, AnnotatedField<?>>>cast(from));
            }
            if (from.member instanceof AnnotatedMethod<?>) {
                return enhancedMethodLoader.load(Reflections.<MemberKey<?, AnnotatedMethod<?>>>cast(from));
            }
            if (from.member instanceof AnnotatedConstructor<?>) {
                return enhancedConstructorLoader
                        .load(Reflections.<MemberKey<?, AnnotatedConstructor<?>>>cast(from));
            }
            throw BeanLogger.LOG.invalidAnnotatedMember(from);
        }
    }

    private abstract class AbstractEnhancedMemberLoader<A extends AnnotatedMember<?>, W extends EnhancedAnnotatedMember<?, ?, ?>> {

        public W load(MemberKey<?, A> source) {
            return findMatching(getMembersOfDeclaringType(source), source.member);
        }

        public W findMatching(Collection<W> members, A source) {
            for (W member : members) {
                if (equals(member, source)) {
                    return member;
                }
            }
            throw BeanLogger.LOG.unableToLoadMember(source);
        }

        public abstract boolean equals(W member1, A member2);

        public abstract Collection<W> getMembersOfDeclaringType(MemberKey<?, A> source);
    }

    private class EnhancedFieldLoader
            extends AbstractEnhancedMemberLoader<AnnotatedField<?>, EnhancedAnnotatedField<?, ?>> {
        @Override
        public boolean equals(EnhancedAnnotatedField<?, ?> member1, AnnotatedField<?> member2) {
            return AnnotatedTypes.compareAnnotatedField(member1, member2);
        }

        @Override
        public Collection<EnhancedAnnotatedField<?, ?>> getMembersOfDeclaringType(
                MemberKey<?, AnnotatedField<?>> source) {
            return cast(source.type.getFields());
        }
    }

    private class EnhancedMethodLoader
            extends AbstractEnhancedMemberLoader<AnnotatedMethod<?>, EnhancedAnnotatedMethod<?, ?>> {
        @Override
        public boolean equals(EnhancedAnnotatedMethod<?, ?> member1, AnnotatedMethod<?> member2) {
            return AnnotatedTypes.compareAnnotatedCallable(member1, member2);
        }

        @Override
        public Collection<EnhancedAnnotatedMethod<?, ?>> getMembersOfDeclaringType(
                MemberKey<?, AnnotatedMethod<?>> source) {
            return cast(source.type.getMethods());
        }
    }

    private class EnhancedConstructorLoader
            extends AbstractEnhancedMemberLoader<AnnotatedConstructor<?>, EnhancedAnnotatedConstructor<?>> {
        @Override
        public boolean equals(EnhancedAnnotatedConstructor<?> member1, AnnotatedConstructor<?> member2) {
            return AnnotatedTypes.compareAnnotatedCallable(member1, member2);
        }

        @Override
        public Collection<EnhancedAnnotatedConstructor<?>> getMembersOfDeclaringType(
                MemberKey<?, AnnotatedConstructor<?>> source) {
            return cast(source.type.getConstructors());
        }
    }

    public void cleanupAfterBoot() {
        enhancedMemberCache.invalidateAll();
    }

    @Override
    public void cleanup() {
        cleanupAfterBoot();
        unbackedAnnotatedMembersById.invalidateAll();
    }
}