/*
* 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.bootstrap.events;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.configurator.AnnotatedTypeConfigurator;
import org.jboss.weld.annotated.AnnotatedTypeValidator;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.bootstrap.events.configurator.AnnotatedTypeConfiguratorImpl;
import org.jboss.weld.logging.BootstrapLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resources.ClassTransformer;
/**
* Container lifecycle event for each Java class or interface discovered by the container.
*
* @author pmuir
* @author David Allen
* @author Jozef Hartinger
*/
@SuppressWarnings("rawtypes")
public class ProcessAnnotatedTypeImpl<X> extends ContainerEvent implements ProcessAnnotatedType<X> {
private final SlimAnnotatedType<X> originalAnnotatedType;
private final BeanManagerImpl manager;
private AnnotatedType<X> annotatedType;
private AnnotatedTypeConfiguratorImpl<X> configurator;
private boolean veto;
// we need this to ensure that configurator and set method are not invoked within one observer
private boolean annotatedTypeSet;
public ProcessAnnotatedTypeImpl(BeanManagerImpl beanManager, SlimAnnotatedType<X> annotatedType) {
this(beanManager, annotatedType, ProcessAnnotatedType.class);
}
protected ProcessAnnotatedTypeImpl(BeanManagerImpl beanManager, SlimAnnotatedType<X> annotatedType, Class<? extends ProcessAnnotatedType> rawType) {
this.manager = beanManager;
this.annotatedType = annotatedType;
this.originalAnnotatedType = annotatedType;
}
@Override
public AnnotatedType<X> getAnnotatedType() {
checkWithinObserverNotification();
return annotatedType;
}
/**
* Call this method after all observer methods of this event have been invoked to get the final value of this {@link AnnotatedType}.
*
* @return the resulting annotated type
*/
public SlimAnnotatedType<X> getResultingAnnotatedType() {
if (isDirty()) {
return ClassTransformer.instance(manager).getUnbackedAnnotatedType(originalAnnotatedType, annotatedType);
} else {
return originalAnnotatedType;
}
}
public SlimAnnotatedType<X> getOriginalAnnotatedType() {
return originalAnnotatedType;
}
@Override
public void setAnnotatedType(AnnotatedType<X> type) {
if (configurator != null) {
throw BootstrapLogger.LOG.configuratorAndSetMethodBothCalled(ProcessAnnotatedType.class.getSimpleName(), getReceiver());
}
checkWithinObserverNotification();
if (type == null) {
throw BootstrapLogger.LOG.annotationTypeNull(this);
}
replaceAnnotatedType(type);
annotatedTypeSet = true;
BootstrapLogger.LOG.setAnnotatedTypeCalled(getReceiver(), annotatedType, type);
}
@Override
public AnnotatedTypeConfigurator<X> configureAnnotatedType() {
if (annotatedTypeSet) {
throw BootstrapLogger.LOG.configuratorAndSetMethodBothCalled(ProcessAnnotatedType.class.getSimpleName(), getReceiver());
}
checkWithinObserverNotification();
if (configurator == null) {
configurator = new AnnotatedTypeConfiguratorImpl<>(annotatedType);
}
BootstrapLogger.LOG.configureAnnotatedTypeCalled(getReceiver(), annotatedType);
return configurator;
}
@Override
public void veto() {
checkWithinObserverNotification();
this.veto = true;
BootstrapLogger.LOG.annotatedTypeVetoed(getReceiver(), annotatedType);
}
public boolean isVeto() {
return veto;
}
public boolean isDirty() {
return originalAnnotatedType != annotatedType;
}
@Override
public void postNotify(Extension extension) {
super.postNotify(extension);
if (configurator != null) {
replaceAnnotatedType(configurator.complete());
configurator = null;
}
annotatedTypeSet = false;
}
@Override
public String toString() {
return annotatedType.toString();
}
private void replaceAnnotatedType(AnnotatedType<X> type) {
if (!this.originalAnnotatedType.getJavaClass().equals(type.getJavaClass())) {
throw BootstrapLogger.LOG.annotatedTypeJavaClassMismatch(this.annotatedType.getJavaClass(), type.getJavaClass());
}
AnnotatedTypeValidator.validateAnnotatedType(type);
this.annotatedType = type;
}
}