1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.blossom.dialog;
35
36 import java.lang.annotation.Annotation;
37 import java.lang.reflect.Method;
38 import java.lang.reflect.Modifier;
39 import java.util.ArrayList;
40 import java.util.List;
41
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.util.ClassUtils;
45 import org.springframework.util.ReflectionUtils;
46
47 import info.magnolia.module.admininterface.SaveHandler;
48 import info.magnolia.module.blossom.annotation.DialogFactory;
49 import info.magnolia.module.blossom.annotation.DialogValidator;
50 import info.magnolia.module.blossom.annotation.I18nBasename;
51 import info.magnolia.module.blossom.annotation.InitSaveHandler;
52 import info.magnolia.module.blossom.annotation.TabFactory;
53 import info.magnolia.module.blossom.annotation.TabOrder;
54 import info.magnolia.module.blossom.annotation.TabValidator;
55
56
57
58
59
60
61 public class DialogDescriptionBuilder {
62
63 private final Logger logger = LoggerFactory.getLogger(getClass());
64
65 private DialogCreator dialogCreator;
66
67 public void setDialogCreator(DialogCreator dialogCreator) {
68 this.dialogCreator = dialogCreator;
69 }
70
71 public DialogCreator getDialogCreator() {
72 if (dialogCreator == null) {
73 dialogCreator = new DefaultDialogCreator();
74 }
75 return dialogCreator;
76 }
77
78 public BlossomDialogDescription buildDescription(Object factoryObject) {
79 return buildDescription(factoryObject, null);
80 }
81
82 public List<BlossomDialogDescription> buildDescriptions(final Object handler) {
83
84 final List<Method> factoryMethods = new ArrayList<Method>();
85
86 ReflectionUtils.doWithMethods(handler.getClass(), new ReflectionUtils.MethodCallback() {
87
88 @Override
89 public void doWith(Method method) {
90 DialogFactory dialogFactory = method.getAnnotation(DialogFactory.class);
91 if (dialogFactory != null && method.equals(ClassUtils.getMostSpecificMethod(method, handler.getClass()))) {
92 if (Modifier.isStatic(method.getModifiers())) {
93 throw new IllegalStateException("DialogFactory annotation is not supported on static methods");
94 }
95 factoryMethods.add(method);
96 }
97 }
98 });
99
100 List<BlossomDialogDescription> descriptions = new ArrayList<BlossomDialogDescription>();
101
102 for (Method method : factoryMethods) {
103 descriptions.add(buildDescription(handler, method));
104 }
105
106 return descriptions;
107 }
108
109 public BlossomDialogDescription buildDescription(Object factoryObject, Method factoryMethod) {
110 DialogFactory annotation = findAnnotation(DialogFactory.class, factoryObject, factoryMethod);
111 return buildDescription(annotation.value(), annotation.label(), factoryObject, factoryMethod);
112 }
113
114 public BlossomDialogDescription buildDescription(String name, String label, Object factoryObject) {
115 return buildDescription(name, label, factoryObject, null);
116 }
117
118 protected BlossomDialogDescription buildDescription(String id, String label, Object factoryObject, Method factoryMethod) {
119 TabOrder tabOrder = findAnnotation(TabOrder.class, factoryObject, factoryMethod);
120 I18nBasename i18nBasename = findAnnotation(I18nBasename.class, factoryObject, factoryMethod);
121 final DialogFactoryMetaData factoryMetaData = new DialogFactoryMetaData();
122 factoryMetaData.setLabel(label);
123 factoryMetaData.setI18nBasename(i18nBasename != null ? i18nBasename.value() : null);
124 factoryMetaData.setFactoryObject(factoryObject);
125 factoryMetaData.setFactoryMethod(factoryMethod);
126 factoryMetaData.setTabOrder(tabOrder != null ? tabOrder.value() : null);
127 factoryMetaData.setInitSaveHandlerMethod(findInitSaveHandlerMethod(factoryObject));
128
129 final Class<?> factoryClass = factoryObject.getClass();
130
131 ReflectionUtils.doWithMethods(factoryClass, new ReflectionUtils.MethodCallback() {
132
133 @Override
134 public void doWith(Method method) {
135 if (method.isAnnotationPresent(TabFactory.class) && method.equals(ClassUtils.getMostSpecificMethod(method, factoryClass))) {
136 if (Modifier.isStatic(method.getModifiers())) {
137 throw new IllegalStateException("TabFactory annotation is not supported on static methods");
138 }
139 factoryMetaData.addTabFactory(method);
140 }
141 if (method.isAnnotationPresent(TabValidator.class) && method.equals(ClassUtils.getMostSpecificMethod(method, factoryClass))) {
142 if (Modifier.isStatic(method.getModifiers())) {
143 throw new IllegalStateException("TabValidator annotation is not supported on static methods");
144 }
145 factoryMetaData.addTabValidator(method);
146 }
147 if (method.isAnnotationPresent(DialogValidator.class) && method.equals(ClassUtils.getMostSpecificMethod(method, factoryClass))) {
148 if (Modifier.isStatic(method.getModifiers())) {
149 throw new IllegalStateException("DialogValidator annotation is not supported on static methods");
150 }
151 factoryMetaData.addDialogValidator(method);
152 }
153 }
154 });
155
156 BlossomDialogDescription dialogDescription = new BlossomDialogDescription();
157 dialogDescription.setId(id);
158 dialogDescription.setFactoryMetaData(factoryMetaData);
159 dialogDescription.setDialogClass(BlossomConfiguredDialog.class.getName());
160 dialogDescription.setDialogCreator(getDialogCreator());
161
162 return dialogDescription;
163 }
164
165 protected <T extends Annotation> T findAnnotation(Class<T> annotationClass, Object factoryObject, Method factoryMethod) {
166 if (factoryMethod != null) {
167 return factoryMethod.getAnnotation(annotationClass);
168 }
169 return factoryObject.getClass().getAnnotation(annotationClass);
170 }
171
172 protected Method findInitSaveHandlerMethod(final Object factoryObject) {
173
174 final Class<?> handlerClass = factoryObject.getClass();
175
176 final List<Method> matchingMethods = new ArrayList<Method>();
177
178
179
180 Class<?> clazz = factoryObject.getClass();
181 while (matchingMethods.isEmpty() && clazz != null) {
182 Method[] methods = clazz.getDeclaredMethods();
183 for (final Method method : methods) {
184
185
186 if (!method.isAnnotationPresent(InitSaveHandler.class)) {
187 continue;
188 }
189
190
191 if (!method.equals(ClassUtils.getMostSpecificMethod(method, handlerClass))) {
192 continue;
193 }
194
195 if (!method.getReturnType().equals(SaveHandler.class)) {
196 if (logger.isDebugEnabled()) {
197 logger.debug("Method annotated with @InitSaveHandler has wrong return type [" + method.getClass() + "] should be SaveHandler.");
198 }
199 continue;
200 }
201
202 matchingMethods.add(method);
203 }
204 clazz = clazz.getSuperclass();
205 }
206
207 if (!matchingMethods.isEmpty()) {
208 if (matchingMethods.size() == 1) {
209 return matchingMethods.get(0);
210 } else {
211 logger.error("Multiple @InitSaveHandler annotated methods found in [" + factoryObject.getClass() + "]");
212 }
213 }
214
215 return null;
216 }
217 }