package org.jboss.weld.annotated.slim.unbacked;
import static org.jboss.weld.util.reflection.Reflections.cast;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.Objects;
import java.util.Set;
import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import org.jboss.weld.annotated.slim.AnnotatedTypeIdentifier;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.exceptions.InvalidObjectException;
import org.jboss.weld.logging.BeanLogger;
import org.jboss.weld.resources.SharedObjectCache;
import org.jboss.weld.util.collections.ImmutableSet;
import org.jboss.weld.util.reflection.Formats;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Wrapper for extension-provided {@link AnnotatedType}. This may seem unnecessary, however it does mean we are providing a
* consistent view for debugging, error reporting etc. This implementation is also serializable no matter if the original
* extension-provided {@link AnnotatedType} implementation is.
*
* @author Pete Muir
* @author Jozef Hartinger
*
* @param <X> the type
*/
@SuppressFBWarnings(value = { "SE_NO_SUITABLE_CONSTRUCTOR", "SE_NO_SERIALVERSIONID" }, justification = "False positive from FindBugs - serialization is handled by SerializationProxy.")
public class UnbackedAnnotatedType<X> extends UnbackedAnnotated implements SlimAnnotatedType<X>, Serializable {
public static <X> UnbackedAnnotatedType<X> additionalAnnotatedType(String contextId, AnnotatedType<X> source, String bdaId, String suffix, SharedObjectCache cache) {
return new UnbackedAnnotatedType<X>(source, AnnotatedTypeIdentifier.of(contextId, bdaId, source.getJavaClass().getName(), suffix, false), cache);
}
public static <X> UnbackedAnnotatedType<X> modifiedAnnotatedType(SlimAnnotatedType<X> originalType, AnnotatedType<X> source, SharedObjectCache cache) {
AnnotatedTypeIdentifier identifier = AnnotatedTypeIdentifier.forModifiedAnnotatedType(originalType.getIdentifier());
return new UnbackedAnnotatedType<X>(source, identifier, cache);
}
private final Class<X> javaClass;
private final Set<AnnotatedConstructor<X>> constructors;
private final Set<AnnotatedMethod<? super X>> methods;
private final Set<AnnotatedField<? super X>> fields;
private final AnnotatedTypeIdentifier identifier;
private UnbackedAnnotatedType(AnnotatedType<X> source, AnnotatedTypeIdentifier identifier, SharedObjectCache cache) {
super(source.getBaseType(), source.getTypeClosure(), source.getAnnotations());
this.javaClass = source.getJavaClass();
ImmutableSet.Builder<AnnotatedConstructor<X>> constructors = ImmutableSet.builder();
for (AnnotatedConstructor<X> constructor : source.getConstructors()) {
constructors.add(UnbackedAnnotatedConstructor.of(constructor, this, cache));
}
this.constructors = constructors.build();
ImmutableSet.Builder<AnnotatedMethod<? super X>> methods = ImmutableSet.builder();
for (AnnotatedMethod<? super X> originalMethod : source.getMethods()) {
methods.add(UnbackedAnnotatedMethod.of(originalMethod, this, cache));
}
this.methods = methods.build();
ImmutableSet.Builder<AnnotatedField<? super X>> fields = ImmutableSet.builder();
for (AnnotatedField<? super X> originalField : source.getFields()) {
fields.add(UnbackedAnnotatedField.of(originalField, this, cache));
}
this.fields = fields.build();
this.identifier = identifier;
}
@Override
public Class<X> getJavaClass() {
return javaClass;
}
@Override
public Set<AnnotatedConstructor<X>> getConstructors() {
return constructors;
}
@Override
public Set<AnnotatedMethod<? super X>> getMethods() {
return methods;
}
@Override
public Set<AnnotatedField<? super X>> getFields() {
return fields;
}
@Override
public String toString() {
return Formats.formatAnnotatedType(this);
}
// Serialization
private Object writeReplace() throws ObjectStreamException {
return new SerializationProxy<X>(getIdentifier());
}
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw BeanLogger.LOG.serializationProxyRequired();
}
@Override
public void clear() {
// noop
}
@Override
public int hashCode() {
return identifier.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof UnbackedAnnotatedType<?>) {
UnbackedAnnotatedType<?> that = cast(obj);
return Objects.equals(this.identifier, that.identifier);
}
return false;
}
@Override
public AnnotatedTypeIdentifier getIdentifier() {
return identifier;
}
}