/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and/or its affiliates, 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.solder.messages;
import java.util.Collection;
import java.util.HashSet;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessProducerMethod;
import org.jboss.solder.bean.NarrowingBeanBuilder;
import org.jboss.solder.literal.MessageBundleLiteral;
import org.jboss.solder.messages.MessageBundle;
/**
* Detects typed message bundles and registers a dedicated producer method for each one discovered.
*
* @author Pete Muir
* @author <a href="http://community.jboss.org/people/dan.j.allen">Dan Allen</a>
*/
public class TypedMessageBundleExtension implements Extension {
private final Collection<AnnotatedType<?>> messageBundleTypes;
private Bean<Object> bundleProducerBean;
public TypedMessageBundleExtension() {
this.messageBundleTypes = new HashSet<AnnotatedType<?>>();
}
void detectInterfaces(@Observes ProcessAnnotatedType<?> event, BeanManager beanManager) {
AnnotatedType<?> type = event.getAnnotatedType();
if (type.isAnnotationPresent(MessageBundle.class)) {
messageBundleTypes.add(type);
}
}
// according to the Java EE 6 javadoc (the authority according to the powers that be),
// this is the correct order of type parameters
void detectProducers(@Observes ProcessProducerMethod<Object, TypedMessageBundleProducer> event) {
captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
}
// according to JSR-299 spec, this is the correct order of type parameters
@Deprecated
void detectProducersInverted(@Observes ProcessProducerMethod<TypedMessageBundleProducer, Object> event) {
captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
}
@SuppressWarnings("unchecked")
void captureProducers(AnnotatedMethod<?> method, Bean<?> bean) {
if (method.isAnnotationPresent(TypedMessageBundle.class)) {
this.bundleProducerBean = (Bean<Object>) bean;
}
}
void installBeans(@Observes AfterBeanDiscovery event, BeanManager beanManager) {
for (AnnotatedType<?> type : messageBundleTypes) {
event.addBean(createMessageBundleBean(bundleProducerBean, type, beanManager));
}
}
private static <T> Bean<T> createMessageBundleBean(Bean<Object> delegate, AnnotatedType<T> type, BeanManager beanManager) {
return new NarrowingBeanBuilder<T>(delegate, beanManager).readFromType(type).types(type.getBaseType(), Object.class).addQualifier(MessageBundleLiteral.INSTANCE).create();
}
void cleanup(@Observes AfterDeploymentValidation event) {
// defensively clear the set to help with gc
this.messageBundleTypes.clear();
}
}