
com.oneandone.ejbcdiunit.cfganalyzer.CdiRelBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ejb-cdi-unit Show documentation
Show all versions of ejb-cdi-unit Show documentation
A module that can be used together with cdiunit to build en ejb-test-environment.
The newest version!
package com.oneandone.ejbcdiunit.cfganalyzer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jboss.resteasy.spi.NotImplementedYetException;
/**
* @author aschoerk
*/
public class CdiRelBuilder {
public enum RelType {
ROOT,
PRODUCER_FIELD,
PRODUCER_METHOD,
INJECTED_FIELD,
INJECTED_PARAMETER,
ADDED_BEAN,
ADDED_CLASS,
ADDED_ANNOTATION,
SIMPLE_BEAN,
CONSTRUCTOR_INJECT;
}
public interface RelVisitor {
Object visit(ProducerFieldRel producerMethodRel, Object p);
Object visit(ProducerMethodRel producerMethodRel, Object p);
Object visit(InjectedFieldRel producerMethodRel, Object p);
Object visit(BeanClassRel producerMethodRel, Object p);
Object visit(SimpleClassRel producerMethodRel, Object p);
Object visit(ConstructorInjectRel producerMethodRel, Object p);
Object visit(ParameterInjectRel producerMethodRel, Object p);
Object visit(RootRel producerMethodRel, Object p);
}
public interface Rel {
Rel parent();
RelType type();
Class> getAffectedClass();
Object accept(RelVisitor visitor, Object p);
}
public interface Intermediate extends Rel {
List children();
default void add(Rel rel) {
Objects.requireNonNull(rel);
children().add(rel);
}
}
public static abstract class BaseRel implements Rel {
private Rel parent;
Class> affectedClass;
public BaseRel(final Intermediate parent, final Class> affectedClass) {
Objects.requireNonNull(parent);
this.parent = parent;
this.affectedClass = affectedClass;
if (parent != null) {
parent.add(this);
}
}
@Override
public Class> getAffectedClass() {
return affectedClass;
}
@Override
public Rel parent() {
return parent;
}
}
public static abstract class BaseIntermediateRel extends BaseRel implements Intermediate {
List children = new ArrayList<>();
public BaseIntermediateRel(final Intermediate parent, final Class> affectedClass) {
super(parent, affectedClass);
}
public List children() {
return children;
}
}
public static class BeanClassRel extends BaseIntermediateRel {
public BeanClassRel(final Intermediate parent, final Class> affectedClass) {
super(parent, affectedClass);
}
@Override
public RelType type() {
return RelType.ADDED_BEAN;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
}
public static class SimpleClassRel extends BaseIntermediateRel {
public SimpleClassRel(final Intermediate parent, final Class> affectedClass) {
super(parent, affectedClass);
}
@Override
public RelType type() {
return RelType.SIMPLE_BEAN;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
}
public static class RootRel implements Intermediate {
private final Collection> initialClasses;
private Map, Intermediate> beanClasses;
private List children = new ArrayList<>();
public RootRel(Collection> initialClasses) {
this.initialClasses = initialClasses;
}
@Override
public Rel parent() {
return null;
}
@Override
public Class> getAffectedClass() {
return null;
}
@Override
public List children() {
return children;
}
@Override
public RelType type() {
return RelType.ROOT;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
public void setBeanClasses(final Map, Intermediate> beanClasses) {
this.beanClasses = beanClasses;
}
public Map, Intermediate> getBeanClasses() {
return beanClasses;
}
}
public static abstract class BaseFieldRel extends BaseRel {
protected Field f;
public BaseFieldRel(final BeanClassRel r, final Field field) {
super(r, (Class) field.getType());
this.f = field;
}
}
public static class InjectedFieldRel extends BaseFieldRel {
private Intermediate bean;
public InjectedFieldRel(final BeanClassRel r, final Field field) {
super(r, field);
}
@Override
public RelType type() {
return RelType.INJECTED_FIELD;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
public void setBean(final Intermediate bean) {
this.bean = bean;
}
public Intermediate getBean() {
return bean;
}
}
public static class ProducerFieldRel extends BaseFieldRel {
public ProducerFieldRel(final BeanClassRel r, final Field field) {
super(r, field);
}
@Override
public RelType type() {
return RelType.PRODUCER_FIELD;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
}
public static class ConstructorInjectRel extends BaseIntermediateRel {
protected Constructor m;
public ConstructorInjectRel(final BeanClassRel r, final Constructor constructor) {
super(r, constructor.getDeclaringClass());
this.m = constructor;
}
@Override
public RelType type() {
return RelType.CONSTRUCTOR_INJECT;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
}
public static class ParameterInjectRel extends BaseRel {
protected Parameter p;
public ParameterInjectRel(final Intermediate r, final Parameter parameter) {
super(r, parameter.getType());
this.p = parameter;
}
@Override
public RelType type() {
return RelType.INJECTED_PARAMETER;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
private Intermediate bean;
public void setBean(final Intermediate bean) {
this.bean = bean;
}
public Intermediate getBean() {
return bean;
}
}
public static class ProducerMethodRel extends BaseIntermediateRel {
protected Method m;
public ProducerMethodRel(final BeanClassRel r, final Method method) {
super(r, method.getReturnType());
this.m = method;
}
@Override
public RelType type() {
return RelType.PRODUCER_METHOD;
}
@Override
public Object accept(RelVisitor visitor, Object p) {
return visitor.visit(this, p);
}
}
public static class RelFactory {
Map, Intermediate> beanClasses = new HashMap<>();
SimpleClassRel createSimple(Intermediate parent, Class> c) throws AnalyzerException {
SimpleClassRel r = new SimpleClassRel(parent, c);
return r;
}
Intermediate createBeanFromClass(Intermediate parent, Class> c) throws AnalyzerException {
if (beanClasses.containsKey(c))
return beanClasses.get(c);
Intermediate res = null;
try {
if (c.isInterface()) {
res = new SimpleClassRel(parent, c);
} else {
BeanClassRel br = new BeanClassRel(parent, c);
res = br;
Type superClass = c.getGenericSuperclass();
if (superClass != null && superClass != Object.class) {
createBeanFromClass(br, (Class) superClass);
}
for (Field field : c.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class)) {
createInjectField(br, field);
} else if (field.isAnnotationPresent(Produces.class)) {
createProducedField(br, field);
}
}
for (Constructor constructor : c.getDeclaredConstructors()) {
if (constructor.isAnnotationPresent(Inject.class)) {
createInjectConstructor(br, constructor);
}
}
for (Method method : c.getDeclaredMethods()) {
if (method.isAnnotationPresent(Produces.class)) {
createProducerMethod(br, method);
}
}
}
} finally {
beanClasses.put(c, res);
}
return res;
}
private void createProducerMethod(final BeanClassRel r, final Method method) throws AnalyzerException {
ProducerMethodRel res = new ProducerMethodRel(r, method);
for (Parameter p : method.getParameters()) {
ParameterInjectRel pRel = createInjectParameter(res, p);
res.add(pRel);
Intermediate bean = createTypeBean(r, p.getParameterizedType());
pRel.setBean(bean);
}
}
private void createInjectConstructor(final BeanClassRel r, final Constructor constructor) throws AnalyzerException {
ConstructorInjectRel res = new ConstructorInjectRel(r, constructor);
for (Parameter p : constructor.getParameters()) {
ParameterInjectRel pRel = createInjectParameter(r, p);
res.add(pRel);
Intermediate bean = createTypeBean(r, p.getParameterizedType());
pRel.setBean(bean);
}
}
private ParameterInjectRel createInjectParameter(final Intermediate parent, final Parameter p) {
return new ParameterInjectRel(parent, p);
}
private InjectedFieldRel createInjectField(final BeanClassRel r, final Field field) throws AnalyzerException {
if (field.getType().equals(Provider.class)) {
throw new NotImplementedYetException();
}
if (field.getType().equals(Instance.class)) {
throw new NotImplementedYetException();
}
InjectedFieldRel res = new InjectedFieldRel(r, field);
Intermediate bean = createTypeBean(r, field.getType());
res.setBean(bean);
return res;
}
private ProducerFieldRel createProducedField(final BeanClassRel r, final Field field) {
return new ProducerFieldRel(r, field);
}
Intermediate createParameterized(Intermediate parent, ParameterizedType type) throws AnalyzerException {
Intermediate raw = this.createBeanFromClass(parent, (Class) (type.getRawType()));
for (Type arg : type.getActualTypeArguments()) {
createTypeBean(parent, arg);
}
return raw;
}
Intermediate createTypeBean(Intermediate parent, Type type) throws AnalyzerException {
if (type instanceof Class) {
return this.createBeanFromClass(parent, (Class) type);
}
if (type instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) type;
return createParameterized(parent, ptype);
}
throw new NotSupportedTypeYet();
}
}
public static class NotSupportedTypeYet extends AnalyzerException {
public static final long serialVersionUID = -7645090605110467195L;
}
public static class AnalyzerException extends Exception {
public static final long serialVersionUID = -4731804312861785688L;
}
private final RootRel rootRel;
public RootRel getRootRel() {
return rootRel;
}
public CdiRelBuilder(Collection> initialClasses) throws AnalyzerException {
this.rootRel = new RootRel(initialClasses);
RelFactory relFactory = new RelFactory();
for (Class> clazz : initialClasses) {
relFactory.createBeanFromClass(this.rootRel, clazz);
}
rootRel.setBeanClasses(relFactory.beanClasses);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy