Skip to content

Commit

Permalink
Refactor event handling (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
backpaper0 authored and making committed Jul 30, 2017
1 parent 0073471 commit 279817d
Show file tree
Hide file tree
Showing 16 changed files with 519 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
package org.seasar.doma.boot.autoconfigure;

import javax.sql.DataSource;

import org.seasar.doma.boot.event.AnnotatedDomaEventHandlerInvoker;
import org.seasar.doma.boot.event.DomaEventEntityListener;
import org.seasar.doma.boot.event.DomaEventListenerFactory;
import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.EntityListenerProvider;
import org.seasar.doma.jdbc.Naming;
Expand Down Expand Up @@ -77,8 +76,8 @@ public Naming naming() {
}

@Bean
public AnnotatedDomaEventHandlerInvoker eventHandlerInvoker() {
return new AnnotatedDomaEventHandlerInvoker();
public DomaEventListenerFactory domaEventListenerFactory() {
return new DomaEventListenerFactory();
}

@Bean
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.seasar.doma.boot.event;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Objects;
import java.util.Set;
import org.seasar.doma.Entity;
import org.seasar.doma.boot.event.annotation.HandleDomaEvent;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;

public class DomaApplicationListener implements ApplicationListener<DomaEvent<?, ?>> {

private final Set<Class<?>> contextClasses;
private final String beanName;
private final Method method;
private final BeanFactory beanFactory;

public DomaApplicationListener(String beanName, Method method, BeanFactory beanFactory) {

int parameterCount = method.getParameterCount();
if (parameterCount < 1) {
throw new IllegalArgumentException("Must receive an entity");
} else if (parameterCount > 2) {
throw new IllegalArgumentException("Too many parameters");
}

Class<?> entityClass = method.getParameterTypes()[0];
if (entityClass.isAnnotationPresent(Entity.class) == false) {
throw new IllegalArgumentException("First parameter must be entity class");
}

Set<Class<?>> contextClasses = Collections.newSetFromMap(new IdentityHashMap<>());
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
for (Annotation annotation : annotations) {
HandleDomaEvent handleDomaEvent = AnnotationUtils
.findAnnotation(annotation.annotationType(), HandleDomaEvent.class);
if (handleDomaEvent != null) {
contextClasses.add(handleDomaEvent.contextClass());
}
}

if (parameterCount == 2) {
if (contextClasses.size() > 1) {
throw new IllegalArgumentException(
"To annotate with multi annotations must be only entity parameter");
}

Class<?> contextClass = method.getParameterTypes()[1];
if (contextClass != contextClasses.iterator().next()) {
throw new IllegalArgumentException(
"Mismatch between annotation and event context");
}
Type t = method.getGenericParameterTypes()[1];
if (t instanceof ParameterizedType) {
Type typeArg = ((ParameterizedType) t).getActualTypeArguments()[0];
if (typeArg != entityClass) {
throw new IllegalArgumentException(
"Mismatch between entity class and variable bound to event context");
}
}
}

ReflectionUtils.makeAccessible(method);

this.contextClasses = Objects.requireNonNull(contextClasses);
this.beanName = Objects.requireNonNull(beanName);
this.method = Objects.requireNonNull(method);
this.beanFactory = Objects.requireNonNull(beanFactory);
}

@Override
public void onApplicationEvent(DomaEvent<?, ?> event) {
Object entity = event.getSource();
Object context = event.getContext();
if (shouldHandle(context.getClass())
&& entity.getClass() == method.getParameterTypes()[0]) {
Object[] args;
if (method.getParameterCount() == 1) {
args = new Object[] { entity };
} else {
args = new Object[] { entity, context };
}
Object target = beanFactory.getBean(beanName);
ReflectionUtils.invokeMethod(method, target, args);
}
}

private boolean shouldHandle(Class<?> clazz) {
for (Class<?> contextClasse : contextClasses) {
if (contextClasse.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import org.springframework.context.ApplicationEventPublisherAware;

/**
* {@link EntityListener} implementation that publishes {@link DomaEvent} and delegates
* actual processing on the event lister class which is annoteted with
* {@link org.seasar.doma.boot.event.annotation.DomaEventHandler}. <br>
* {@link EntityListener} implementation that publishes {@link DomaEvent}. <br>
* <br>
* This class extends {@link NullEntityListener} so that {@link org.seasar.doma.Entity} is
* available with default parameters.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.seasar.doma.boot.event;

import java.lang.reflect.Method;
import org.seasar.doma.boot.event.annotation.HandleDomaEvent;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListenerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;

public class DomaEventListenerFactory implements EventListenerFactory, Ordered, BeanFactoryAware {

private int order = Ordered.HIGHEST_PRECEDENCE;
private BeanFactory beanFactory;

@Override
public boolean supportsMethod(Method method) {
return AnnotationUtils.findAnnotation(method, HandleDomaEvent.class) != null;
}

@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type,
Method method) {
return new DomaApplicationListener(beanName, method, beanFactory);
}

@Override
public int getOrder() {
return order;
}

public void setOrder(int order) {
this.order = order;
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.event.EventListener;

@EventListener
@Target({ ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface HandleDomaEvent {
Class<?> contextClass();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.*;
import org.seasar.doma.jdbc.entity.PostDeleteContext;

@HandleDomaEvent(contextClass = PostDeleteContext.class)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.*;
import org.seasar.doma.jdbc.entity.PostInsertContext;

@HandleDomaEvent(contextClass = PostInsertContext.class)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.*;
import org.seasar.doma.jdbc.entity.PostUpdateContext;

@HandleDomaEvent(contextClass = PostUpdateContext.class)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.*;
import org.seasar.doma.jdbc.entity.PreDeleteContext;

@HandleDomaEvent(contextClass = PreDeleteContext.class)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.*;
import org.seasar.doma.jdbc.entity.PreInsertContext;

@HandleDomaEvent(contextClass = PreInsertContext.class)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.seasar.doma.boot.event.annotation;

import java.lang.annotation.*;
import org.seasar.doma.jdbc.entity.PreUpdateContext;

@HandleDomaEvent(contextClass = PreUpdateContext.class)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
Expand Down
Loading

0 comments on commit 279817d

Please sign in to comment.