Skip to content
This repository has been archived by the owner on Jun 23, 2020. It is now read-only.

Commit

Permalink
Fixing OS to work with abstract services
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw committed Aug 17, 2010
1 parent 52fedd8 commit 9a2c563
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 12 deletions.
Expand Up @@ -37,20 +37,30 @@ public class ObjectServiceExtension implements Extension {
private BeanManager beanManager;

private Set<ObjectServiceSpecification> objectServicesSpecs = new HashSet<ObjectServiceSpecification>();
private Set<ObjectServiceSpecification> objectServicesProviderSpecs = new HashSet<ObjectServiceSpecification>();

private Type getObjectServiceTypeParameter(Iterable<Type> flattenedTypes) {
for (Type flattenedType : flattenedTypes) {
if (flattenedType instanceof ParameterizedType && ((ParameterizedType) flattenedType).getRawType().equals(OS.class)) {
return ((ParameterizedType) flattenedType).getActualTypeArguments()[0];
}
}

return null;
}

/**
* Looks for the type parameter of the given annotated type, which has a raw type {@link pl.softwaremill.cdiext.objectservice.OS}.
* @param at The class on which to look for the type parameter.
* @return The type parameter or {@code null}, if no type parameter is specified.
*/
private Type getObjectServiceTypeParameter(WeldClassImpl<?> at) {
for (Type flattenedType : at.getInterfaceClosure()) {
if (flattenedType instanceof ParameterizedType && ((ParameterizedType) flattenedType).getRawType().equals(OS.class)) {
return ((ParameterizedType) flattenedType).getActualTypeArguments()[0];
}
Type typeParameter = getObjectServiceTypeParameter(at.getInterfaceClosure());
if (typeParameter != null) {
return typeParameter;
} else {
return getObjectServiceTypeParameter(at.getTypeClosure());
}

return null;
}

private Type[] createWildcards(int count) {
Expand All @@ -62,15 +72,15 @@ private Type[] createWildcards(int count) {
return ret;
}

public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event) {
public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event) {
AnnotatedType<X> at = event.getAnnotatedType();

// Checking if the class implements the OS interface
if (OS.class.isAssignableFrom(at.getJavaClass()) && at instanceof WeldClassImpl) {
// Getting the type parameter type parameter for the OS implementation
Type osTypeParameter = getObjectServiceTypeParameter((WeldClassImpl) at);

// If the type parameter is a type variable, searching for hat type variable in the main class declaration.
// If the type parameter is a type variable, searching for that type variable in the main class declaration.
if (osTypeParameter instanceof TypeVariable) {
String typeVariableName = ((TypeVariable) osTypeParameter).getName();
for (TypeVariable<Class<X>> classTypeVariable : at.getJavaClass().getTypeParameters()) {
Expand All @@ -85,9 +95,16 @@ public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event) {

// Checking if the found type variable is a class. If so, registering a new object service.
if (osTypeParameter instanceof Class) {
// TODO: the service type should always be the class directly implementing OS!
Class<?> serviceClass = at.getJavaClass();

// Checking if the class directly implements OS.
boolean osFound = false;
for (Class<?> serviceClassInterface : serviceClass.getInterfaces()) {
if (serviceClassInterface.isAssignableFrom(OS.class)) {
osFound = true;
}
}

// If the class has any type parameters, filling them in with wildcards
Type serviceType;
if (serviceClass.getTypeParameters().length > 0) {
Expand All @@ -96,15 +113,22 @@ public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event) {
serviceType = serviceClass;
}

// Registering a new OSP for class: osTypeParameter and service: serviceType
objectServicesSpecs.add(new ObjectServiceSpecification((Class<?>) osTypeParameter, serviceType, serviceClass));
ObjectServiceSpecification osSpec = new ObjectServiceSpecification((Class<?>) osTypeParameter, serviceType, serviceClass);

// Registering a new spec so that the bean can be found by the provider
objectServicesSpecs.add(osSpec);

if (osFound) {
// Registering a new OSP for class: osTypeParameter and service: serviceType
objectServicesProviderSpecs.add(osSpec);
}
}
}
}

public void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
// Adding OSP beans according to the specifications gathered
for (ObjectServiceSpecification objectServicesSpec : objectServicesSpecs) {
for (ObjectServiceSpecification objectServicesSpec : objectServicesProviderSpecs) {
abd.addBean(new ObjectServiceProviderBean(this, objectServicesSpec));
}

Expand Down
@@ -0,0 +1,8 @@
package pl.softwaremill.cdiext.objectservice;

/**
* @author Adam Warski (adam at warski dot org)
*/
public abstract class AbstractService3<T extends A> implements Service3<T> {

}
Expand Up @@ -34,6 +34,9 @@ public static JavaArchive createTestArchive() {
@Inject
private OSP<A, Service2<A>> service2;

@Inject
private OSP<A, Service3<A>> service3;

@Test
public void testService1WithB() {
Assert.assertEquals(service1.f(new B(10)).get(), 10);
Expand Down Expand Up @@ -73,4 +76,14 @@ public void testNewServiceInstances2WithC() {
int instancesEnd = Service2C.instanceCount();
Assert.assertEquals(instancesEnd - instancesStart, 2);
}

@Test
public void testService3WithB() {
Assert.assertEquals(service3.f(new B(10)).get(), 10);
}

@Test
public void testService3WithC() {
Assert.assertEquals(service3.f(new C("x")).get(), "x");
}
}
@@ -0,0 +1,9 @@
package pl.softwaremill.cdiext.objectservice;

/**
* A service for which implementations inherit from an abtract service.
* @author Adam Warski (adam at warski dot org)
*/
public interface Service3<T extends A> extends OS<T> {
Object get();
}
@@ -0,0 +1,18 @@
package pl.softwaremill.cdiext.objectservice;

/**
* @author Adam Warski (adam at warski dot org)
*/
public class Service3B extends AbstractService3<B> {
private B serviced;

@Override
public void setServiced(B serviced) {
this.serviced = serviced;
}

@Override
public Object get() {
return serviced.getValue();
}
}
@@ -0,0 +1,18 @@
package pl.softwaremill.cdiext.objectservice;

/**
* @author Adam Warski (adam at warski dot org)
*/
public class Service3C extends AbstractService3<C> {
private C serviced;

@Override
public void setServiced(C serviced) {
this.serviced = serviced;
}

@Override
public Object get() {
return serviced.getValue();
}
}

0 comments on commit 9a2c563

Please sign in to comment.