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