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 info.magnolia.cms.gui.dialog.Dialog;
37 import info.magnolia.cms.gui.dialog.DialogTab;
38 import info.magnolia.cms.util.AlertUtil;
39 import info.magnolia.module.blossom.annotation.DialogValidator;
40 import info.magnolia.module.blossom.annotation.TabFactory;
41 import info.magnolia.module.blossom.annotation.TabValidator;
42 import info.magnolia.module.blossom.support.MethodInvocationUtils;
43 import info.magnolia.module.blossom.support.ParameterResolver;
44 import org.apache.commons.lang.ArrayUtils;
45 import org.apache.commons.lang.StringUtils;
46 import org.springframework.util.ClassUtils;
47 import org.springframework.util.ReflectionUtils;
48
49 import java.lang.reflect.Method;
50 import java.lang.reflect.Modifier;
51 import java.util.ArrayList;
52 import java.util.Collections;
53 import java.util.Comparator;
54 import java.util.List;
55
56
57
58
59 public class DefaultDialogCreator implements DialogCreator {
60
61 public void createDialog(DialogFactoryMetaData metaData, final DialogCreationContext context) throws Exception {
62
63 Dialog dialog = new Dialog() {
64 @Override
65 public boolean validate() {
66 if (!super.validate())
67 return false;
68 context.executeValidators();
69 return !AlertUtil.isMessageSet();
70 }
71 };
72 dialog.init(context.getRequest(), context.getResponse(), context.getWebsiteNode(), context.getConfigNode());
73
74 context.setDialog(dialog);
75
76 DialogBuilder dialogBuilder = new DialogBuilder(context);
77
78 if (metaData.getFactoryMethod() != null) {
79
80 ParameterResolver parameters = getDialogFactoryParameters(metaData, context, dialogBuilder);
81 MethodInvocationUtils.invoke(metaData.getFactoryMethod(), metaData.getFactoryObject(), parameters);
82 } else {
83
84 invokeTabFactoriesAndRegisterValidators(metaData, context, dialogBuilder);
85 }
86
87 if (StringUtils.isNotEmpty(metaData.getLabel())) {
88 context.getDialog().setLabel(metaData.getLabel());
89 }
90
91 if (StringUtils.isNotEmpty(metaData.getI18nBasename()))
92 context.getDialog().setConfig("i18nBasename", metaData.getI18nBasename());
93
94 if (metaData.getTabOrder() != null)
95 sortTabs(context.getDialog(), metaData.getTabOrder());
96 }
97
98 private void sortTabs(Dialog dialog, final String[] order) {
99 Collections.sort(dialog.getSubs(), new Comparator<Object>() {
100 public int compare(Object o1, Object o2) {
101 switch (((o1 instanceof DialogTab) ? 2 : 0) + ((o2 instanceof DialogTab) ? 1 : 0)) {
102 case 0:
103 return 0;
104 case 1:
105 return -1;
106 case 2:
107 return 1;
108 case 3:
109 return ArrayUtils.indexOf(order, ((DialogTab) o1).getLabel()) - ArrayUtils.indexOf(order, ((DialogTab) o2).getLabel());
110 }
111 return 0;
112 }
113 });
114 }
115
116 private void invokeTabFactoriesAndRegisterValidators(final DialogFactoryMetaData metaData, final DialogCreationContext context, DialogBuilder dialogBuilder) {
117
118 final Object factoryObject = metaData.getFactoryObject();
119 final Class<?> factoryClass = factoryObject.getClass();
120
121 final List<Method> tabFactories = new ArrayList<Method>();
122 final List<Method> dialogValidators = new ArrayList<Method>();
123 final List<Method> tabValidators = new ArrayList<Method>();
124
125 ReflectionUtils.doWithMethods(factoryClass, new ReflectionUtils.MethodCallback() {
126 public void doWith(Method method) {
127 if (method.isAnnotationPresent(TabFactory.class) && method.equals(ClassUtils.getMostSpecificMethod(method, factoryClass))) {
128 if (Modifier.isStatic(method.getModifiers())) {
129 throw new IllegalStateException("TabFactory annotation is not supported on static methods");
130 }
131 tabFactories.add(method);
132 }
133 if (method.isAnnotationPresent(TabValidator.class) && method.equals(ClassUtils.getMostSpecificMethod(method, factoryClass))) {
134 if (Modifier.isStatic(method.getModifiers())) {
135 throw new IllegalStateException("TabValidator annotation is not supported on static methods");
136 }
137 tabValidators.add(method);
138 }
139 if (method.isAnnotationPresent(DialogValidator.class) && method.equals(ClassUtils.getMostSpecificMethod(method, factoryClass))) {
140 if (Modifier.isStatic(method.getModifiers())) {
141 throw new IllegalStateException("DialogValidator annotation is not supported on static methods");
142 }
143 dialogValidators.add(method);
144 }
145 }
146 });
147
148 for (Method tabFactory : tabFactories) {
149
150 TabFactory annotation = tabFactory.getAnnotation(TabFactory.class);
151 TabBuilder tabBuilder = dialogBuilder.addTab(annotation.value());
152
153 ParameterResolver parameters = getTabFactoryParameters(metaData, context, tabBuilder);
154 MethodInvocationUtils.invoke(tabFactory, metaData.getFactoryObject(), parameters);
155 }
156
157 for (final Method tabValidator : tabValidators) {
158 context.addValidator(new ValidationCallback() {
159 public void validate(Dialog dialog) {
160 TabValidator annotation = tabValidator.getAnnotation(TabValidator.class);
161 DialogTab dialogTab = context.getTab(annotation.value());
162 if (dialogTab != null) {
163
164 ParameterResolver parameters = getTabValidatorParameters(metaData, context, dialogTab);
165 MethodInvocationUtils.invoke(tabValidator, metaData.getFactoryObject(), parameters);
166 }
167 }
168 });
169 }
170
171 for (final Method dialogValidator : dialogValidators) {
172 context.addValidator(new ValidationCallback() {
173 public void validate(Dialog dialog) {
174 ParameterResolver parameters = getDialogValidatorParameters(metaData, context);
175 MethodInvocationUtils.invoke(dialogValidator, metaData.getFactoryObject(), parameters);
176 }
177 });
178 }
179 }
180
181 protected ParameterResolver getDialogFactoryParameters(DialogFactoryMetaData metaData, final DialogCreationContext context, final DialogBuilder dialogBuilder) {
182 return new ParameterResolver() {
183 public Object resolveParameter(Class<?> parameterType) {
184 if (parameterType.equals(DialogBuilder.class))
185 return dialogBuilder;
186 if (parameterType.equals(Dialog.class))
187 return context.getDialog();
188 if (parameterType.equals(DialogCreationContext.class))
189 return context;
190 return super.resolveParameter(parameterType);
191 }
192 };
193 }
194
195 protected ParameterResolver getTabFactoryParameters(DialogFactoryMetaData metaData, final DialogCreationContext context, final TabBuilder tabBuilder) {
196 return new ParameterResolver() {
197 public Object resolveParameter(Class<?> parameterType) {
198 if (parameterType.equals(TabBuilder.class))
199 return tabBuilder;
200 if (parameterType.equals(Dialog.class))
201 return context.getDialog();
202 if (parameterType.equals(DialogCreationContext.class))
203 return context;
204 return super.resolveParameter(parameterType);
205 }
206 };
207 }
208
209 protected ParameterResolver getTabValidatorParameters(DialogFactoryMetaData metaData, final DialogCreationContext context, final DialogTab dialogTab) {
210 return new ParameterResolver() {
211 public Object resolveParameter(Class<?> parameterType) {
212 if (parameterType.equals(DialogTab.class))
213 return dialogTab;
214 if (parameterType.equals(Dialog.class))
215 return context.getDialog();
216 return super.resolveParameter(parameterType);
217 }
218 };
219 }
220
221 protected ParameterResolver getDialogValidatorParameters(DialogFactoryMetaData metaData, final DialogCreationContext context) {
222 return new ParameterResolver() {
223 public Object resolveParameter(Class<?> parameterType) {
224 if (parameterType.equals(Dialog.class))
225 return context.getDialog();
226 return super.resolveParameter(parameterType);
227 }
228 };
229 }
230 }