View Javadoc

1   /**
2    * This file Copyright (c) 2010 Magnolia International
3    * Ltd.  (http://www.magnolia.info). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia.info/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.templating.engine;
35  
36  import java.io.IOException;
37  import java.io.Writer;
38  
39  import info.magnolia.cms.core.AggregationState;
40  import info.magnolia.cms.core.Content;
41  import info.magnolia.cms.core.ItemType;
42  import info.magnolia.context.MgnlContext;
43  import info.magnolia.module.templating.Paragraph;
44  import info.magnolia.module.templating.ParagraphManager;
45  import info.magnolia.module.templating.ParagraphRenderer;
46  import info.magnolia.module.templating.ParagraphRendererManager;
47  import info.magnolia.module.templating.RenderException;
48  import info.magnolia.module.templating.RenderableDefinition;
49  import info.magnolia.module.templating.Template;
50  import info.magnolia.module.templating.TemplateManager;
51  import info.magnolia.module.templating.TemplateRenderer;
52  import info.magnolia.module.templating.TemplateRendererManager;
53  
54  
55  /**
56   * Default implementation which determines the definition (template/paragraph) from the content's
57   * meta data. Based on the node type (mgln:contentNode for paragraphs) a paragraph rendering or a
58   * template rendering is performed.
59   * @author pbaerfuss
60   * @version $Id$
61   *
62   */
63  public class DefaultRenderingEngine implements RenderingEngine {
64  
65      protected enum RenderingHelper {
66          PARAGRAPH {
67  
68              public RenderableDefinition getDefinition(String definitionName) {
69                  return ParagraphManager.getInstance().getParagraphDefinition(definitionName);
70              }
71  
72              public Object getRenderer(RenderableDefinition definition) {
73                  return ParagraphRendererManager.getInstance().getRenderer(definition.getType());
74              }
75  
76              void render(Content content, RenderableDefinition definition, Object renderer, Writer out) throws RenderException, IOException {
77                  ((ParagraphRenderer) renderer).render(content, (Paragraph) definition, out);
78              }
79          },
80  
81          TEMPLATE {
82  
83              public RenderableDefinition getDefinition(String definitionName) {
84                  AggregationState state = getAggregationStateSafely();
85                  String extension = null;
86                  if (state != null) {
87                      extension = state.getExtension();
88                  }
89                  Template template = TemplateManager.getInstance().getTemplateDefinition(definitionName);
90                  if (template != null && extension != null) {
91                      Template subTemplate = template.getSubTemplate(extension);
92                      if (subTemplate != null) {
93                          template = subTemplate;
94                      }
95                  }
96                  return template;
97  
98              }
99  
100             public Object getRenderer(RenderableDefinition definition) {
101                 return TemplateRendererManager.getInstance().getRenderer(definition.getType());
102             }
103 
104             public void render(Content content, RenderableDefinition definition, Object renderer, Writer out) throws RenderException, IOException {
105                 ((TemplateRenderer) renderer).renderTemplate(content, (Template) definition, out);
106             }
107         };
108 
109         abstract RenderableDefinition getDefinition(String definitionName);
110 
111         abstract Object getRenderer(RenderableDefinition definition);
112 
113         abstract void render(Content content, RenderableDefinition definition, Object renderer, Writer out) throws RenderException, IOException;
114     }
115 
116     public void render(Content content, Writer out) throws RenderException  {
117         render(content, determineAssignedDefinitionName(content), out);
118     }
119 
120     public void render(Content content, String definitionName, Writer out) throws RenderException {
121         // FIXME content can be null in case of a request to a node date having a template attribute set for the binary
122         // this is probably not used anymore and should not be supported
123         if (content != null && content.isNodeType(ItemType.CONTENTNODE.getSystemName())) {
124             render(content, definitionName, RenderingHelper.PARAGRAPH, out);
125         }
126         else {
127             render(content, definitionName, RenderingHelper.TEMPLATE, out);
128         }
129     }
130 
131     /**
132      * Reads the template name from the meta data.
133      */
134     protected String determineAssignedDefinitionName(Content content) {
135         return content.getMetaData().getTemplate();
136     }
137 
138     /**
139      * Will update the aggregation state and perform the rendering by using the helper.
140      */
141     protected void render(Content content, String definitionName, RenderingHelper helper, Writer out) throws RenderException {
142         Content orgMainContent = null;
143         Content orgCurrentContent = null;
144 
145         AggregationState state = getAggregationStateSafely();
146         if (state != null) {
147             orgMainContent = state.getMainContent();
148             orgCurrentContent = state.getCurrentContent();
149 
150             state.setCurrentContent(content);
151             // if not yet set the passed content is the entry point of the rendering
152             if (orgMainContent == null) {
153                 state.setMainContent(content);
154             }
155         }
156 
157         RenderableDefinition definition = helper.getDefinition(definitionName);
158         if (definition == null) {
159             throw new RenderException("Can't find renderable definition " + definitionName);
160         }
161 
162         Object renderer = helper.getRenderer(definition);
163         if (renderer == null) {
164             throw new RenderException("Can't find renderer for type " + definition.getType());
165         }
166 
167         try {
168             helper.render(content, definition, renderer, out);
169         }
170         catch (IOException e) {
171             throw new RenderException("Can't render " + content.getHandle(), e);
172         }
173 
174         if (state != null) {
175             state.setMainContent(orgMainContent);
176             state.setCurrentContent(orgCurrentContent);
177         }
178     }
179 
180     protected static AggregationState getAggregationStateSafely() {
181         if (MgnlContext.isWebContext()) {
182             return MgnlContext.getAggregationState();
183         }
184         return null;
185     }
186 
187 }