All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.resources.MemberTransformer Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha1
Show newest version
/*
 * 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.reflection.Reflections.cast;

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

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.Function;
import org.jboss.weld.util.cache.ComputingCache;
import org.jboss.weld.util.cache.ComputingCacheBuilder;
import org.jboss.weld.util.reflection.Reflections;

/**
 * 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> {
        private final EnhancedAnnotatedType type;
        private final A member;
        private final int hashCode;

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

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

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

    private final ClassTransformer transformer;

    private final ComputingCache, UnbackedAnnotatedMember> unbackedAnnotatedMembersById;

    private final ComputingCache, EnhancedAnnotatedMember> enhancedMemberCache;
    private final EnhancedFieldLoader enhancedFieldLoader;
    private final EnhancedMethodLoader enhancedMethodLoader;
    private final EnhancedConstructorLoader enhancedConstructorLoader;

    public MemberTransformer(ClassTransformer transformer) {
        ComputingCacheBuilder cacheBuilder = ComputingCacheBuilder.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  UnbackedAnnotatedMember getUnbackedMember(UnbackedMemberIdentifier identifier) {
        return unbackedAnnotatedMembersById.getCastValue(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 implements Function, UnbackedAnnotatedMember> {

        @Override
        public UnbackedAnnotatedMember apply(UnbackedMemberIdentifier identifier) {
            return findMatchingMember(identifier.getType(), identifier.getMemberId());
        }

        private  UnbackedAnnotatedMember findMatchingMember(UnbackedAnnotatedType type, String id) {
            for (AnnotatedField field : type.getFields()) {
                if (id.equals(AnnotatedTypes.createFieldId(field))) {
                    return cast(field);
                }
            }
            for (AnnotatedMethod method : type.getMethods()) {
                if (id.equals(AnnotatedTypes.createMethodId(method.getJavaMember(), method.getAnnotations(), method.getParameters()))) {
                    return Reflections.cast(method);
                }
            }
            for (AnnotatedConstructor 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 > A loadEnhancedMember(AnnotatedMember member, String bdaId) {
        if (member instanceof EnhancedAnnotatedMember) {
            return Reflections.cast(member);
        }
        EnhancedAnnotatedType declaringType = transformer.getEnhancedAnnotatedType(member.getDeclaringType(), bdaId);
        return enhancedMemberCache.getCastValue(new MemberKey>(declaringType, member));
    }

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

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

    private abstract class AbstractEnhancedMemberLoader, W extends EnhancedAnnotatedMember> {

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

        public W findMatching(Collection 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 getMembersOfDeclaringType(MemberKey source);
    }

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

        @Override
        public Collection> getMembersOfDeclaringType(MemberKey> source) {
            return cast(source.type.getFields());
        }
    }

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

        @Override
        public Collection> getMembersOfDeclaringType(MemberKey> source) {
            return cast(source.type.getMethods());
        }
    }

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

        @Override
        public Collection> getMembersOfDeclaringType(MemberKey> source) {
            return cast(source.type.getConstructors());
        }
    }

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

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy