1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package com.sun.star.report.pentaho.output.text;
24 
25 import com.sun.star.report.pentaho.OfficeNamespaces;
26 import com.sun.star.report.pentaho.model.OfficeMasterPage;
27 import com.sun.star.report.pentaho.model.OfficeMasterStyles;
28 import com.sun.star.report.pentaho.model.OfficeStyles;
29 import com.sun.star.report.pentaho.model.PageLayout;
30 import com.sun.star.report.pentaho.model.RawText;
31 
32 import java.util.HashMap;
33 import java.util.Map;
34 
35 import org.jfree.layouting.input.style.values.CSSNumericValue;
36 import org.jfree.report.ReportProcessingException;
37 import org.jfree.report.structure.Element;
38 import org.jfree.report.structure.Section;
39 import org.jfree.report.util.AttributeNameGenerator;
40 
41 
42 /**
43  * Todo: Document me!
44  *
45  * @author Thomas Morgner
46  * @since 14.03.2007
47  */
48 public class MasterPageFactory
49 {
50 
51     private static class MasterPageFactoryKey
52     {
53 
54         private final String template;
55         private final String pageHeader;
56         private final String pageFooter;
57 
MasterPageFactoryKey(final String template, final String pageHeader, final String pageFooter)58         public MasterPageFactoryKey(final String template,
59                 final String pageHeader,
60                 final String pageFooter)
61         {
62             this.template = template;
63             this.pageHeader = pageHeader;
64             this.pageFooter = pageFooter;
65         }
66 
equals(final Object o)67         public boolean equals(final Object o)
68         {
69             if (this != o)
70             {
71                 if (o == null || getClass() != o.getClass())
72                 {
73                     return false;
74                 }
75 
76                 final MasterPageFactoryKey that = (MasterPageFactoryKey) o;
77 
78                 if (pageFooter != null ? !pageFooter.equals(
79                         that.pageFooter) : that.pageFooter != null)
80                 {
81                     return false;
82                 }
83                 if (pageHeader != null ? !pageHeader.equals(
84                         that.pageHeader) : that.pageHeader != null)
85                 {
86                     return false;
87                 }
88                 if (template != null ? !template.equals(
89                         that.template) : that.template != null)
90                 {
91                     return false;
92                 }
93             }
94 
95             return true;
96         }
97 
hashCode()98         public int hashCode()
99         {
100             int result = (template != null ? template.hashCode() : 0);
101             result = 31 * result + (pageHeader != null ? pageHeader.hashCode() : 0);
102             result = 31 * result + (pageFooter != null ? pageFooter.hashCode() : 0);
103             return result;
104         }
105 
getTemplate()106         public String getTemplate()
107         {
108             return template;
109         }
110 
getPageHeader()111         public String getPageHeader()
112         {
113             return pageHeader;
114         }
115 
getPageFooter()116         public String getPageFooter()
117         {
118             return pageFooter;
119         }
120     }
121 
122     private static class PageLayoutKey
123     {
124 
125         private final String templateName;
126         private final CSSNumericValue headerHeight;
127         private final CSSNumericValue footerHeight;
128 
PageLayoutKey(final String templateName, final CSSNumericValue headerHeight, final CSSNumericValue footerHeight)129         public PageLayoutKey(final String templateName,
130                 final CSSNumericValue headerHeight,
131                 final CSSNumericValue footerHeight)
132         {
133             this.templateName = templateName;
134             this.headerHeight = headerHeight;
135             this.footerHeight = footerHeight;
136         }
137 
getTemplateName()138         public String getTemplateName()
139         {
140             return templateName;
141         }
142 
getHeaderHeight()143         public CSSNumericValue getHeaderHeight()
144         {
145             return headerHeight;
146         }
147 
getFooterHeight()148         public CSSNumericValue getFooterHeight()
149         {
150             return footerHeight;
151         }
152 
equals(final Object o)153         public boolean equals(final Object o)
154         {
155             if (this == o)
156             {
157                 return true;
158             }
159             if (o == null || getClass() != o.getClass())
160             {
161                 return false;
162             }
163 
164             final PageLayoutKey key = (PageLayoutKey) o;
165 
166             if (footerHeight != null ? !footerHeight.equals(
167                     key.footerHeight) : key.footerHeight != null)
168             {
169                 return false;
170             }
171             if (headerHeight != null ? !headerHeight.equals(
172                     key.headerHeight) : key.headerHeight != null)
173             {
174                 return false;
175             }
176             return !(templateName != null ? !templateName.equals(
177                     key.templateName) : key.templateName != null);
178 
179         }
180 
hashCode()181         public int hashCode()
182         {
183             int result;
184             result = (templateName != null ? templateName.hashCode() : 0);
185             result = 31 * result + (headerHeight != null ? headerHeight.hashCode() : 0);
186             result = 31 * result + (footerHeight != null ? footerHeight.hashCode() : 0);
187             return result;
188         }
189     }
190     // todo: Patch the page-layout ...
191     private static final String DEFAULT_PAGE_NAME = "Default";
192     private final OfficeMasterStyles predefinedStyles;
193     private final AttributeNameGenerator masterPageNameGenerator;
194     private final Map masterPages;
195     private final AttributeNameGenerator pageLayoutNameGenerator;
196     private final Map pageLayouts;
197 
MasterPageFactory(final OfficeMasterStyles predefinedStyles)198     public MasterPageFactory(final OfficeMasterStyles predefinedStyles)
199     {
200         this.predefinedStyles = predefinedStyles;
201         this.masterPages = new HashMap();
202         this.masterPageNameGenerator = new AttributeNameGenerator();
203         this.pageLayouts = new HashMap();
204         this.pageLayoutNameGenerator = new AttributeNameGenerator();
205     }
206 
getMasterPage(final String template, final String pageHeader, final String pageFooter)207     public OfficeMasterPage getMasterPage(final String template,
208             final String pageHeader,
209             final String pageFooter)
210     {
211         final MasterPageFactoryKey key =
212                 new MasterPageFactoryKey(template, pageHeader, pageFooter);
213         return (OfficeMasterPage) masterPages.get(key);
214     }
215 
containsMasterPage(final String template, final String pageHeader, final String pageFooter)216     public boolean containsMasterPage(final String template,
217             final String pageHeader,
218             final String pageFooter)
219     {
220         final MasterPageFactoryKey key =
221                 new MasterPageFactoryKey(template, pageHeader, pageFooter);
222         return masterPages.containsKey(key);
223     }
224 
createMasterPage(final String template, final String pageHeader, final String pageFooter)225     public OfficeMasterPage createMasterPage(final String template,
226             final String pageHeader,
227             final String pageFooter)
228     {
229         final MasterPageFactoryKey key =
230                 new MasterPageFactoryKey(template, pageHeader, pageFooter);
231         final OfficeMasterPage cached = (OfficeMasterPage) masterPages.get(key);
232         if (cached != null)
233         {
234             return cached;
235         }
236 
237         final String targetName = (masterPages.isEmpty()) ? "Standard" : template;
238 
239         OfficeMasterPage predef = predefinedStyles.getMasterPage(template);
240         if (predef == null)
241         {
242             // This is a 'magic' name ..
243             // todo: It could be that this should be called 'Standard' instead
244             predef = predefinedStyles.getMasterPage(MasterPageFactory.DEFAULT_PAGE_NAME);
245         }
246 
247         if (predef != null)
248         {
249             try
250             {
251                 // derive
252                 final OfficeMasterPage derived = (OfficeMasterPage) predef.clone();
253                 return setupMasterPage(derived, targetName, pageHeader, pageFooter,
254                         key);
255             }
256             catch (CloneNotSupportedException cne)
257             {
258                 throw new IllegalStateException("Implementation error: Unable to derive page", cne);
259             }
260         }
261 
262         final OfficeMasterPage masterPage = new OfficeMasterPage();
263         masterPage.setNamespace(OfficeNamespaces.STYLE_NS);
264         masterPage.setType("master-page");
265         return setupMasterPage(masterPage, targetName, pageHeader, pageFooter, key);
266     }
267 
setupMasterPage(final OfficeMasterPage derived, final String targetName, final String pageHeader, final String pageFooter, final MasterPageFactoryKey key)268     private OfficeMasterPage setupMasterPage(final OfficeMasterPage derived,
269             final String targetName,
270             final String pageHeader,
271             final String pageFooter,
272             final MasterPageFactoryKey key)
273     {
274         derived.setStyleName(masterPageNameGenerator.generateName(targetName));
275         masterPages.put(key, derived);
276 
277         if (pageHeader != null)
278         {
279             final Section header = new Section();
280             header.setNamespace(OfficeNamespaces.STYLE_NS);
281             header.setType("header");
282             header.addNode(new RawText(pageHeader));
283             derived.addNode(header);
284         }
285 
286         if (pageFooter != null)
287         {
288             final Section footer = new Section();
289             footer.setNamespace(OfficeNamespaces.STYLE_NS);
290             footer.setType("footer");
291             footer.addNode(new RawText(pageFooter));
292             derived.addNode(footer);
293         }
294 
295         return derived;
296     }
297 
createPageStyle(final OfficeStyles commonStyles, final CSSNumericValue headerHeight, final CSSNumericValue footerHeight)298     public String createPageStyle(final OfficeStyles commonStyles,
299             final CSSNumericValue headerHeight,
300             final CSSNumericValue footerHeight)
301     {
302         final PageLayoutKey key =
303                 new PageLayoutKey(null, headerHeight, footerHeight);
304         final PageLayout derived = new PageLayout();
305         final String name = pageLayoutNameGenerator.generateName("autogenerated");
306         derived.setStyleName(name);
307         commonStyles.addPageStyle(derived);
308 
309         if (headerHeight != null)
310         {
311             final Section headerStyle = new Section();
312             headerStyle.setNamespace(OfficeNamespaces.STYLE_NS);
313             headerStyle.setType("header-style");
314             derived.addNode(headerStyle);
315             MasterPageFactory.applyHeaderFooterHeight(headerStyle, headerHeight);
316         }
317 
318         if (footerHeight != null)
319         {
320             final Section footerStyle = new Section();
321             footerStyle.setNamespace(OfficeNamespaces.STYLE_NS);
322             footerStyle.setType("footer-style");
323             derived.addNode(footerStyle);
324             MasterPageFactory.applyHeaderFooterHeight(footerStyle, footerHeight);
325         }
326         pageLayouts.put(key, name);
327         return name;
328     }
329 
derivePageStyle(final String pageStyleTemplate, final OfficeStyles predefined, final OfficeStyles commonStyles, final CSSNumericValue headerHeight, final CSSNumericValue footerHeight)330     public String derivePageStyle(final String pageStyleTemplate,
331             final OfficeStyles predefined,
332             final OfficeStyles commonStyles,
333             final CSSNumericValue headerHeight,
334             final CSSNumericValue footerHeight)
335             throws ReportProcessingException
336     {
337         if (pageStyleTemplate == null)
338         {
339             throw new NullPointerException("A style-name must be given");
340         }
341 
342         final PageLayoutKey key =
343                 new PageLayoutKey(pageStyleTemplate, headerHeight, footerHeight);
344         final String pageLayoutName = (String) pageLayouts.get(key);
345         if (pageLayoutName != null)
346         {
347             // there's already a suitable version included.
348             return pageLayoutName;
349         }
350 
351         final PageLayout original = predefined.getPageStyle(pageStyleTemplate);
352         if (original == null)
353         {
354             throw new ReportProcessingException("Invalid page-layout '" + pageStyleTemplate + "', will not continue.");
355         }
356 
357         try
358         {
359             final PageLayout derived = (PageLayout) original.clone();
360             final String name = pageLayoutNameGenerator.generateName(
361                     pageStyleTemplate);
362             derived.setStyleName(name);
363             commonStyles.addPageStyle(derived);
364 
365             if (headerHeight != null)
366             {
367                 Section headerStyle = derived.getHeaderStyle();
368                 if (headerStyle == null)
369                 {
370                     headerStyle = new Section();
371                     headerStyle.setNamespace(OfficeNamespaces.STYLE_NS);
372                     headerStyle.setType("header-style");
373                     derived.addNode(headerStyle);
374                 }
375                 MasterPageFactory.applyHeaderFooterHeight(headerStyle, headerHeight);
376             }
377 
378             if (footerHeight != null)
379             {
380                 Section footerStyle = derived.getFooterStyle();
381                 if (footerStyle == null)
382                 {
383                     footerStyle = new Section();
384                     footerStyle.setNamespace(OfficeNamespaces.STYLE_NS);
385                     footerStyle.setType("footer-style");
386                     derived.addNode(footerStyle);
387                 }
388 
389                 MasterPageFactory.applyHeaderFooterHeight(footerStyle, footerHeight);
390             }
391             pageLayouts.put(key, name);
392             return name;
393         }
394         catch (CloneNotSupportedException e)
395         {
396             throw new IllegalStateException("Clone failed.", e);
397         }
398     }
399 
applyHeaderFooterHeight(final Section headerFooterStyle, final CSSNumericValue style)400     private static void applyHeaderFooterHeight(final Section headerFooterStyle,
401             final CSSNumericValue style)
402     {
403         Element headerFooterProps = headerFooterStyle.findFirstChild(OfficeNamespaces.STYLE_NS, "header-footer-properties");
404         if (headerFooterProps == null)
405         {
406             headerFooterProps = new Section();
407             headerFooterProps.setNamespace(OfficeNamespaces.STYLE_NS);
408             headerFooterProps.setType("header-footer-properties");
409             headerFooterStyle.addNode(headerFooterProps);
410         }
411         headerFooterProps.setAttribute(OfficeNamespaces.SVG_NS, "height", style.getValue() + style.getType().getType());
412     }
413 }
414