1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package net.sf.autodao.impl;
19
20 import java.lang.reflect.Method;
21 import java.lang.reflect.ParameterizedType;
22 import java.lang.reflect.Type;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import net.sf.autodao.Dao;
28 import net.sf.autodao.PersistentEntity;
29 import net.sf.autodao.QueryArgumentTransformer;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
32 import org.springframework.aop.framework.ProxyFactoryBean;
33 import org.springframework.beans.factory.BeanFactory;
34 import org.springframework.beans.factory.InitializingBean;
35 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
36 import org.springframework.transaction.PlatformTransactionManager;
37 import org.springframework.transaction.TransactionDefinition;
38 import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
39 import org.springframework.transaction.interceptor.TransactionAttribute;
40 import org.springframework.transaction.interceptor.TransactionAttributeSource;
41 import org.springframework.transaction.interceptor.TransactionInterceptor;
42 import org.springframework.util.Assert;
43
44
45
46
47
48
49 public abstract class AbstractDaoFactoryBean extends ProxyFactoryBean implements InitializingBean, TransactionAttributeSource {
50 @NotNull
51 private static final String QUERY_ARGUMENT_TRANSFORMERS_BEAN_NAME = "autodaoQueryArgumentTransformers";
52 private static final TransactionAttribute MANDATORY_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_MANDATORY);
53
54 @NotNull
55 static final Map<Class<?>, QueryArgumentTransformer<?, ?>> DEFAULT_TRANSFORMERS = defaultTransformers();
56
57 @NotNull
58 private static Map<Class<?>, QueryArgumentTransformer<?, ?>> defaultTransformers() {
59 final Map<Class<?>, QueryArgumentTransformer<?, ?>> result = new HashMap<>();
60
61 ReadableInstantTransformer.register(result);
62
63 return Collections.unmodifiableMap(result);
64 }
65
66 @NotNull
67 private Map<Class<?>, QueryArgumentTransformer<?, ?>> transformers = DEFAULT_TRANSFORMERS;
68 @NotNull
69 private final Class<?> daoInterface;
70 @NotNull
71 private final PlatformTransactionManager transactionManager;
72 @Nullable
73 private final Class<? extends PersistentEntity<?>> entityType;
74
75 protected AbstractDaoFactoryBean(@NotNull Class<?> daoInterface,
76 @Nullable Class<? extends PersistentEntity<?>> entityType,
77 @NotNull PlatformTransactionManager transactionManager) {
78 this.daoInterface = daoInterface;
79 this.entityType = entityType;
80 this.transactionManager = transactionManager;
81 }
82
83 @NotNull
84 protected abstract FinderExecutor createDao(@Nullable final Class<?> entityType);
85
86 protected abstract void validate(@NotNull final Class<?> daoInterface, @NotNull Map<Class<?>, QueryArgumentTransformer<?, ?>> transformers);
87
88 @Override
89 @SuppressWarnings({ "unchecked" })
90 public final void setBeanFactory(final BeanFactory beanFactory) {
91 transformers = new HashMap<>();
92 transformers.putAll(DEFAULT_TRANSFORMERS);
93
94 try {
95 transformers.putAll((Map<Class<?>, QueryArgumentTransformer<?, ?>>) beanFactory.getBean(QUERY_ARGUMENT_TRANSFORMERS_BEAN_NAME, Map.class));
96 } catch (NoSuchBeanDefinitionException e) {
97
98 }
99
100 super.setBeanFactory(beanFactory);
101 }
102
103 @Override
104 public final void afterPropertiesSet() {
105 validate(daoInterface, transformers);
106 final Class<? extends PersistentEntity<?>> realEntityType = getEntityType(daoInterface, entityType);
107 addInterface(daoInterface);
108 setTarget(createDao(realEntityType));
109 addAdvice(new TransactionInterceptor(transactionManager, this));
110 addAdvice(new FinderIntroductionInterceptor(transformers));
111 }
112
113 @Nullable
114 private static Class<? extends PersistentEntity<?>> getEntityType(@NotNull final Class<?> daoInterface,
115 @Nullable final Class<? extends PersistentEntity<?>> explicit) {
116 final Class<? extends PersistentEntity<?>> result;
117 if (explicit == null && Dao.class.isAssignableFrom(daoInterface)) {
118 result = autoDiscoverEntityType(daoInterface);
119 Assert.notNull(result, "No entity type found for " + daoInterface);
120 } else {
121 result = explicit;
122 }
123 if (result != null) {
124 Assert.isAssignable(PersistentEntity.class, result, "Invalid entity type: ");
125 }
126 return result;
127 }
128
129 @SuppressWarnings({ "unchecked" })
130 private static Class<? extends PersistentEntity<?>> autoDiscoverEntityType(final Class<?> daoInterface) {
131
132 for (final Type t : daoInterface.getGenericInterfaces()) {
133 if (t instanceof ParameterizedType) {
134 final ParameterizedType pt = (ParameterizedType) t;
135 if (pt.getRawType() == Dao.class) {
136 final Type type = pt.getActualTypeArguments()[0];
137 if (type instanceof ParameterizedType) {
138
139 return (Class<? extends PersistentEntity<?>>) ((ParameterizedType) type).getRawType();
140 } else {
141 Assert.isInstanceOf(
142 Class.class,
143 type,
144 "Don't know how to handle " + type + " entity type for " + daoInterface.getName() + ".\n"
145 + "Please update to latest AutoDAO release.\n"
146 + "If that doesn't help, please file a bugreport to AutoDAO bugtracker.");
147 return (Class<? extends PersistentEntity<?>>) type;
148 }
149 }
150 }
151 }
152 return null;
153 }
154
155 @Override
156 public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
157 return method.getDeclaringClass() == Object.class ? null : MANDATORY_TRANSACTION_ATTRIBUTE;
158 }
159 }