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.template;
35
36 import java.util.Collection;
37 import java.util.List;
38 import javax.jcr.RepositoryException;
39
40 import org.apache.commons.lang.StringUtils;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.springframework.aop.support.AopUtils;
44 import org.springframework.beans.factory.InitializingBean;
45 import org.springframework.context.ApplicationEvent;
46 import org.springframework.context.ApplicationListener;
47
48 import info.magnolia.module.blossom.annotation.Area;
49 import info.magnolia.module.blossom.annotation.Template;
50 import info.magnolia.module.blossom.dialog.BlossomDialogDescription;
51 import info.magnolia.module.blossom.dialog.BlossomDialogRegistry;
52 import info.magnolia.module.blossom.dialog.DialogDescriptionBuilder;
53 import info.magnolia.module.blossom.dispatcher.BlossomDispatcher;
54 import info.magnolia.module.blossom.dispatcher.BlossomDispatcherAware;
55 import info.magnolia.module.blossom.dispatcher.BlossomDispatcherInitializedEvent;
56 import info.magnolia.module.blossom.support.AbstractUrlMappedHandlerPostProcessor;
57 import info.magnolia.objectfactory.Components;
58 import info.magnolia.rendering.template.AreaDefinition;
59 import info.magnolia.rendering.template.registry.TemplateDefinitionRegistry;
60
61
62
63
64
65
66 public class TemplateExporter extends AbstractUrlMappedHandlerPostProcessor implements InitializingBean, ApplicationListener, BlossomDispatcherAware {
67
68 private static final String TEMPLATE_DIALOG_PREFIX = "blossom-template-dialog:";
69 private static final String AREA_DIALOG_PREFIX = "blossom-area-dialog:";
70
71 private final Logger logger = LoggerFactory.getLogger(getClass());
72
73 private BlossomDispatcher dispatcher;
74 private TemplateDefinitionBuilder templateDefinitionBuilder;
75 private DialogDescriptionBuilder dialogDescriptionBuilder;
76
77 private DetectedHandlersMetaData detectedHandlers = new DetectedHandlersMetaData();
78
79 public void setTemplateDefinitionBuilder(TemplateDefinitionBuilder templateDefinitionBuilder) {
80 this.templateDefinitionBuilder = templateDefinitionBuilder;
81 }
82
83 public void setDialogDescriptionBuilder(DialogDescriptionBuilder dialogDescriptionBuilder) {
84 this.dialogDescriptionBuilder = dialogDescriptionBuilder;
85 }
86
87 @Override
88 public void setBlossomDispatcher(BlossomDispatcher dispatcher) {
89 this.dispatcher = dispatcher;
90 }
91
92 @Override
93 protected void postProcessHandler(Object handler, String handlerPath) {
94 Class<?> handlerClass = AopUtils.getTargetClass(handler);
95 if (handlerClass.isAnnotationPresent(Area.class)) {
96 detectedHandlers.addArea(new HandlerMetaData(handler, handlerPath, handlerClass));
97 } else if (handlerClass.isAnnotationPresent(Template.class)) {
98 detectedHandlers.addTemplate(new HandlerMetaData(handler, handlerPath, handlerClass));
99 }
100 }
101
102 @Override
103 public void onApplicationEvent(ApplicationEvent event) {
104 if (event instanceof BlossomDispatcherInitializedEvent && event.getSource() == dispatcher) {
105 exportTemplates();
106 }
107 }
108
109 protected void exportTemplates() {
110 for (HandlerMetaData template : detectedHandlers.getTemplates()) {
111
112 BlossomTemplateDefinition definition = templateDefinitionBuilder.buildTemplateDefinition(dispatcher, detectedHandlers, template);
113
114 Components.getComponent(TemplateDefinitionRegistry.class).register(new BlossomTemplateDefinitionProvider(definition));
115
116 if (StringUtils.isEmpty(definition.getDialog())) {
117 registerTemplateDialog(definition);
118 }
119
120 registerDialogFactories(definition);
121
122 registerAreaDialogs(definition.getAreas().values());
123 }
124
125
126 detectedHandlers = null;
127 }
128
129 protected void registerDialogFactories(BlossomTemplateDefinition templateDefinition) {
130
131 List<BlossomDialogDescription> dialogDescriptions = dialogDescriptionBuilder.buildDescriptions(templateDefinition.getHandler());
132 for (BlossomDialogDescription dialogDescription : dialogDescriptions) {
133 try {
134 Components.getComponent(BlossomDialogRegistry.class).addDialogDescription(dialogDescription);
135 } catch (RepositoryException e) {
136 logger.error("Unable to register dialog factory within template [" + dialogDescription.getFactoryMetaData().getFactoryMethod() + "] with handlerPath [" + templateDefinition.getHandlerPath() + "]", e);
137 }
138
139 if (logger.isDebugEnabled()) {
140 logger.debug("Registered dialog factory within template [" + templateDefinition.getId() + "] with id [" + dialogDescription.getId() + "]");
141 }
142 }
143 }
144
145 protected void registerTemplateDialog(BlossomTemplateDefinition templateDefinition) {
146
147 String templateId = templateDefinition.getId();
148
149 String dialogId = TEMPLATE_DIALOG_PREFIX + AopUtils.getTargetClass(templateDefinition.getHandler()).getName();
150
151 BlossomDialogDescription dialogDescription = dialogDescriptionBuilder.buildDescription(dialogId, templateDefinition.getTitle(), templateDefinition.getHandler());
152
153 if (dialogDescription.getFactoryMetaData().isEmpty()) {
154 return;
155 }
156
157 templateDefinition.setDialog(dialogId);
158
159 try {
160 Components.getComponent(BlossomDialogRegistry.class).addDialogDescription(dialogDescription);
161 } catch (RepositoryException e) {
162 logger.error("Failed to register dialog for template [" + templateId + "] with id [" + dialogId + "]", e);
163 return;
164 }
165
166 if (logger.isDebugEnabled()) {
167 logger.debug("Registered dialog for template [" + templateId + "] with id [" + dialogId + "]");
168 }
169 }
170
171 protected void registerAreaDialogs(Collection<AreaDefinition> areas) {
172 for (AreaDefinition areaDefinition : areas) {
173 if (StringUtils.isEmpty(areaDefinition.getDialog())) {
174 registerAreaDialog((BlossomAreaDefinition) areaDefinition);
175 }
176 registerAreaDialogs(areaDefinition.getAreas().values());
177 }
178 }
179
180 protected void registerAreaDialog(BlossomAreaDefinition areaDefinition) {
181
182 String areaName = areaDefinition.getName();
183
184 String dialogId = AREA_DIALOG_PREFIX + AopUtils.getTargetClass(areaDefinition.getHandler()).getName();
185
186 BlossomDialogDescription dialogDescription = dialogDescriptionBuilder.buildDescription(dialogId, areaDefinition.getTitle(), areaDefinition.getHandler());
187
188 if (dialogDescription.getFactoryMetaData().isEmpty()) {
189 return;
190 }
191
192 areaDefinition.setDialog(dialogId);
193
194 try {
195 Components.getComponent(BlossomDialogRegistry.class).addDialogDescription(dialogDescription);
196 } catch (RepositoryException e) {
197 logger.error("Failed to register dialog for area [" + areaName + "] with id [" + dialogId + "]", e);
198 return;
199 }
200
201 if (logger.isDebugEnabled()) {
202 logger.debug("Registered dialog for area [" + areaName + "] with id [" + dialogId + "]");
203 }
204 }
205
206 @Override
207 public void afterPropertiesSet() throws Exception {
208 if (templateDefinitionBuilder == null) {
209 templateDefinitionBuilder = new TemplateDefinitionBuilder();
210 }
211 if (dialogDescriptionBuilder == null) {
212 dialogDescriptionBuilder = new DialogDescriptionBuilder();
213 }
214 }
215 }