diff options
Diffstat (limited to 'reportbuilder/java/com/sun/star/report/pentaho/output/StyleUtilities.java')
-rw-r--r-- | reportbuilder/java/com/sun/star/report/pentaho/output/StyleUtilities.java | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/reportbuilder/java/com/sun/star/report/pentaho/output/StyleUtilities.java b/reportbuilder/java/com/sun/star/report/pentaho/output/StyleUtilities.java new file mode 100644 index 000000000000..939583be8365 --- /dev/null +++ b/reportbuilder/java/com/sun/star/report/pentaho/output/StyleUtilities.java @@ -0,0 +1,615 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package com.sun.star.report.pentaho.output; + +import com.sun.star.report.pentaho.OfficeNamespaces; +import com.sun.star.report.pentaho.model.DataStyle; +import com.sun.star.report.pentaho.model.FontFaceDeclsSection; +import com.sun.star.report.pentaho.model.FontFaceElement; +import com.sun.star.report.pentaho.model.OfficeStyle; +import com.sun.star.report.pentaho.model.OfficeStyles; +import com.sun.star.report.pentaho.model.OfficeStylesCollection; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.jfree.report.ReportProcessingException; +import org.jfree.report.structure.Element; +import org.jfree.report.structure.Section; +import org.jfree.report.util.AttributeNameGenerator; + + +/** + * Todo: Document me! + * + * @author Thomas Morgner + * @since 13.03.2007 + */ +public class StyleUtilities +{ + + private static final Log LOGGER = LogFactory.getLog(StyleUtilities.class); + private static final String STYLE = "style"; + + private StyleUtilities() + { + } + + /** + * Copies the specififed style (keyed by its family and name) into the current styles collection. This copies the + * style and all inherited styles into the target collection. Inherited common styles will be always be added to the + * common collection (which will be written into the 'styles.xml' later). + * <p/> + * This method does nothing if the specified style already exists in the styles collection. + * + * @param styleFamily the family of the style to copy + * @param styleName the unique name of the style. + * @param stylesCollection the current styles collection + * @param commonCollection the global styles collection + * @param predefCollection the predefined styles from where to copy the styles. + * @throws ReportProcessingException if the style copying failed. + */ + public static void copyStyle(final String styleFamily, + final String styleName, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection commonCollection, + final OfficeStylesCollection predefCollection) + throws ReportProcessingException + { + copyStyle(styleFamily, styleName, stylesCollection, + commonCollection, predefCollection, new HashSet()); + } + + /** + * Copies the specififed style (keyed by its family and name) into the current styles collection. This copies the + * style and all inherited styles into the target collection. Inherited common styles will be always be added to the + * common collection (which will be written into the 'styles.xml' later). + * <p/> + * This method does nothing if the specified style already exists in the styles collection. + * + * @param styleFamily the family of the style to copy + * @param styleName the unique name of the style. + * @param stylesCollection the current styles collection + * @param commonCollection the global styles collection + * @param predefCollection the predefined styles from where to copy the styles. + * @param inheritanceTracker a collection of all styles that have been touched. This is used to prevent infinite + * loops and duplicates. + * @throws ReportProcessingException if the style copying failed. + */ + private static void copyStyle(final String styleFamily, + final String styleName, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection commonCollection, + final OfficeStylesCollection predefCollection, + final Set inheritanceTracker) + throws ReportProcessingException + { + if (inheritanceTracker.contains(styleName)) + { + return; + } + inheritanceTracker.add(styleName); + + if (stylesCollection.containsStyle(styleFamily, styleName) || commonCollection.getCommonStyles().containsStyle(styleFamily, styleName)) + { + // fine, there's already a copy of the stylesheet. + return; + } + + final OfficeStyle predefCommonStyle = + predefCollection.getCommonStyles().getStyle(styleFamily, styleName); + if (predefCommonStyle != null) + { + // so we have an style from the predefined collection. + // copy it an add it to the current stylescollection + final OfficeStyles commonStyles = commonCollection.getCommonStyles(); + + copyStyleInternal(predefCommonStyle, commonStyles, stylesCollection, + commonCollection, predefCollection, styleFamily, inheritanceTracker); + return; + } + + final OfficeStyle predefAutoStyle = + predefCollection.getAutomaticStyles().getStyle(styleFamily, styleName); + if (predefAutoStyle != null) + { + // so we have an style from the predefined collection. + // copy it an add it to the current stylescollection + final OfficeStyles autoStyles = stylesCollection.getAutomaticStyles(); + copyStyleInternal(predefAutoStyle, autoStyles, stylesCollection, + commonCollection, predefCollection, styleFamily, inheritanceTracker); + return; + } + + // There is no automatic style either. Now this means that someone + // messed up the fileformat. Lets create a new empty style for this. + final OfficeStyle autostyle = new OfficeStyle(); + autostyle.setNamespace(OfficeNamespaces.STYLE_NS); + autostyle.setType(STYLE); + autostyle.setStyleFamily(styleFamily); + autostyle.setStyleName(styleName); + + final OfficeStyles autoStyles = stylesCollection.getAutomaticStyles(); + autoStyles.addStyle(autostyle); + } + + private static OfficeStyle copyStyleInternal( + final OfficeStyle predefCommonStyle, + final OfficeStyles styles, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection commonCollection, + final OfficeStylesCollection predefCollection, + final String styleFamily, + final Set inheritanceTracker) + throws ReportProcessingException + { + try + { + final OfficeStyle preStyle = (OfficeStyle) predefCommonStyle.clone(); + styles.addStyle(preStyle); + performFontFaceProcessing(preStyle, stylesCollection, predefCollection); + performDataStyleProcessing(preStyle, stylesCollection, predefCollection); + + // Lookup the parent style .. + final String styleParent = preStyle.getStyleParent(); + final OfficeStyle inherited = + stylesCollection.getStyle(styleFamily, styleParent); + if (inherited != null) + { + // OK, recurse (and hope that we dont run into an infinite loop) .. + copyStyle(styleFamily, styleParent, stylesCollection, + commonCollection, predefCollection, inheritanceTracker); + } + else if (styleParent != null) + { + LOGGER.warn("Inconsistent styles: " + styleFamily + ":" + styleParent + " does not exist."); + } + return preStyle; + } + catch (CloneNotSupportedException e) + { + throw new ReportProcessingException("Failed to derive a stylesheet", e); + } + } + + private static void performFontFaceProcessing(final OfficeStyle style, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection predefCollection) + throws ReportProcessingException + { + final Element textProperties = style.getTextProperties(); + if (textProperties == null) + { + return; + } + + try + { + final FontFaceDeclsSection currentFonts = stylesCollection.getFontFaceDecls(); + final FontFaceDeclsSection predefFonts = predefCollection.getFontFaceDecls(); + + final String fontName = (String) textProperties.getAttribute(OfficeNamespaces.STYLE_NS, "font-name"); + if (fontName != null && !currentFonts.containsFont(fontName)) + { + final FontFaceElement element = predefFonts.getFontFace(fontName); + if (element != null) + { + currentFonts.addFontFace((FontFaceElement) element.clone()); + } + } + + final String fontNameAsian = (String) textProperties.getAttribute(OfficeNamespaces.STYLE_NS, + "font-name-asian"); + if (fontNameAsian != null && !currentFonts.containsFont(fontNameAsian)) + { + final FontFaceElement element = predefFonts.getFontFace( + fontNameAsian); + if (element != null) + { + currentFonts.addFontFace((FontFaceElement) element.clone()); + } + } + + final String fontNameComplex = (String) textProperties.getAttribute(OfficeNamespaces.STYLE_NS, + "font-name-complex"); + if (fontNameComplex != null && !currentFonts.containsFont(fontNameComplex)) + { + final FontFaceElement element = predefFonts.getFontFace( + fontNameComplex); + if (element != null) + { + currentFonts.addFontFace((FontFaceElement) element.clone()); + } + } + } + catch (CloneNotSupportedException e) + { + throw new ReportProcessingException("Failed to clone font-face element"); + } + } + + private static void performDataStyleProcessing(final OfficeStyle style, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection predefCollection) + throws ReportProcessingException + { + final Section derivedStyle = performDataStyleProcessing(style, stylesCollection, predefCollection, "data-style-name"); + if (derivedStyle != null) + { + try + { + final Section styleMap = (Section) derivedStyle.findFirstChild(OfficeNamespaces.STYLE_NS, "map"); + if (styleMap != null) + { + performDataStyleProcessing(styleMap, stylesCollection, predefCollection, "apply-style-name"); + } + } + catch (Exception e) + { + } + } + } + + private static Section performDataStyleProcessing(final Section style, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection predefCollection, + final String attributeName) + throws ReportProcessingException + { + final Object attribute = style.getAttribute(OfficeNamespaces.STYLE_NS, attributeName); + final DataStyle derivedStyle; + if (attribute != null) + { + final String styleName = String.valueOf(attribute); + if (!stylesCollection.getAutomaticStyles().containsDataStyle(styleName) && !stylesCollection.getCommonStyles().containsDataStyle(styleName)) + { + try + { + final OfficeStyles automaticStyles = predefCollection.getAutomaticStyles(); + final DataStyle autoDataStyle = automaticStyles.getDataStyle(styleName); + if (autoDataStyle != null) + { + derivedStyle = (DataStyle) autoDataStyle.clone(); + stylesCollection.getAutomaticStyles().addDataStyle(derivedStyle); + } + else + { + final OfficeStyles commonStyles = predefCollection.getCommonStyles(); + final DataStyle commonDataStyle = commonStyles.getDataStyle(styleName); + if (commonDataStyle != null) + { + derivedStyle = (DataStyle) commonDataStyle.clone(); + stylesCollection.getCommonStyles().addDataStyle(derivedStyle); + } + else + { + LOGGER.warn("Dangling data style: " + styleName); + derivedStyle = null; + } + } + } + catch (CloneNotSupportedException e) + { + throw new ReportProcessingException("Failed to copy style. This should not have happened."); + } + } + else + { + derivedStyle = null; + } + } + else + { + derivedStyle = null; + } + return derivedStyle; + } + + /** + * Derives the named style. If the style is a common style, a new automatic style is generated and inserted into the + * given stylesCollection. If the named style is an automatic style, the style is copied and inserted as new automatic + * style. + * <p/> + * After the style has been created, the style's inheritance hierarchy will be copied as well. + * <p/> + * If there is no style with the given name and family, a new empty automatic style will be created. + * + * @param styleFamily the family of the style to copy + * @param styleName the unique name of the style. + * @param stylesCollection the current styles collection + * @param commonCollection the global styles collection + * @param predefCollection the predefined styles from where to copy the styles. + * @param generator the style-name-generator of the current report-target + * @return the derived style instance. + * @throws ReportProcessingException if the style copying failed. + */ + public static OfficeStyle deriveStyle(final String styleFamily, + final String styleName, + final OfficeStylesCollection stylesCollection, + final OfficeStylesCollection commonCollection, + final OfficeStylesCollection predefCollection, + final AttributeNameGenerator generator) + throws ReportProcessingException + { + if (styleFamily == null) + { + throw new NullPointerException("StyleFamily must not be null"); + } + if (styleName != null) + { + + final OfficeStyle currentAuto = + stylesCollection.getAutomaticStyles().getStyle(styleFamily, + styleName); + if (currentAuto != null) + { + // handle an automatic style .. + final OfficeStyle derivedStyle = + deriveAutomaticStyle(currentAuto, styleFamily, styleName, + generator, commonCollection, predefCollection); + stylesCollection.getAutomaticStyles().addStyle(derivedStyle); + return derivedStyle; + } + + final OfficeStyle currentCommon = + stylesCollection.getCommonStyles().getStyle(styleFamily, styleName); + if (currentCommon != null) + { + // handle an common style .. + final OfficeStyle derivedStyle = + deriveCommonStyle(currentCommon, styleFamily, styleName, + generator, commonCollection, predefCollection); + stylesCollection.getAutomaticStyles().addStyle(derivedStyle); + return derivedStyle; + } + +// final OfficeStyle commonAuto = +// commonCollection.getAutomaticStyles().getStyle(styleFamily, +// styleName); +// if (commonAuto != null) +// { +// // handle an automatic style .. +// final OfficeStyle derivedStyle = +// deriveAutomaticStyle(commonAuto, styleFamily, styleName, +// generator, commonCollection, predefCollection); +// stylesCollection.getAutomaticStyles().addStyle(derivedStyle); +// return derivedStyle; +// } + + final OfficeStyle commonCommon = + commonCollection.getCommonStyles().getStyle(styleFamily, styleName); + if (commonCommon != null) + { + // handle an common style .. + final OfficeStyle derivedStyle = + deriveCommonStyle(commonCommon, styleFamily, styleName, + generator, commonCollection, predefCollection); + stylesCollection.getAutomaticStyles().addStyle(derivedStyle); + return derivedStyle; + } + + final OfficeStyle predefAuto = + predefCollection.getAutomaticStyles().getStyle(styleFamily, + styleName); + if (predefAuto != null) + { + // handle an automatic style .. + final OfficeStyle derivedStyle = + deriveAutomaticStyle(predefAuto, styleFamily, styleName, + generator, commonCollection, predefCollection); + stylesCollection.getAutomaticStyles().addStyle(derivedStyle); + return derivedStyle; + } + + final OfficeStyle predefCommon = + predefCollection.getCommonStyles().getStyle(styleFamily, styleName); + if (predefCommon != null) + { + // handle an common style .. + final OfficeStyle derivedStyle = + deriveCommonStyle(predefCommon, styleFamily, styleName, + generator, commonCollection, predefCollection); + stylesCollection.getAutomaticStyles().addStyle(derivedStyle); + return derivedStyle; + } + } + + // No such style. Create a new one .. + final OfficeStyle autostyle = new OfficeStyle(); + autostyle.setNamespace(OfficeNamespaces.STYLE_NS); + autostyle.setType(STYLE); + autostyle.setStyleFamily(styleFamily); + if (styleName != null) + { + autostyle.setStyleName(styleName); + } + else + { + autostyle.setStyleName(generator.generateName("derived_anonymous")); + } + + final OfficeStyles autoStyles = stylesCollection.getAutomaticStyles(); + autoStyles.addStyle(autostyle); + return autostyle; + } + + private static OfficeStyle deriveCommonStyle(final OfficeStyle commonStyle, + final String styleFamily, + final String styleName, + final AttributeNameGenerator nameGenerator, + final OfficeStylesCollection commonCollection, + final OfficeStylesCollection predefCollection) + throws ReportProcessingException + { + final OfficeStyle autostyle = new OfficeStyle(); + autostyle.setNamespace(OfficeNamespaces.STYLE_NS); + autostyle.setType(STYLE); + autostyle.setStyleFamily(styleFamily); + autostyle.setStyleName(nameGenerator.generateName("derived_" + styleName)); + autostyle.setStyleParent(styleName); + + // now copy the common style .. + final OfficeStyles commonStyles = commonCollection.getCommonStyles(); + if (!commonStyles.containsStyle(styleFamily, styleName)) + { + copyStyleInternal(commonStyle, commonStyles, + commonCollection, commonCollection, predefCollection, + styleFamily, new HashSet()); + } + return autostyle; + } + + private static OfficeStyle deriveAutomaticStyle(final OfficeStyle commonStyle, + final String styleFamily, + final String styleName, + final AttributeNameGenerator nameGenerator, + final OfficeStylesCollection commonCollection, + final OfficeStylesCollection predefCollection) + throws ReportProcessingException + { + try + { + final OfficeStyle autostyle = (OfficeStyle) commonStyle.clone(); + autostyle.setNamespace(OfficeNamespaces.STYLE_NS); + autostyle.setType(STYLE); + autostyle.setStyleFamily(styleFamily); + autostyle.setStyleName(nameGenerator.generateName("derived_auto_" + styleName)); + + + final String parent = autostyle.getStyleParent(); + if (parent != null) + { + copyStyle(styleFamily, parent, commonCollection, commonCollection, + predefCollection); + } + return autostyle; + } + catch (CloneNotSupportedException e) + { + throw new ReportProcessingException( + "Deriving the style failed. Clone error: ", e); + } + } + + public static String queryStyle(final OfficeStylesCollection predefCollection, + final String styleFamily, + final String styleName, + final String sectionName, + final String propertyNamespace, + final String propertyName) + { + return queryStyle(predefCollection, styleFamily, + styleName, sectionName, propertyNamespace, propertyName, new HashSet()); + } + + public static OfficeStyle queryStyleByProperties(final OfficeStylesCollection predefCollection, + final String styleFamily, + final String sectionName, + final ArrayList propertyNamespace, + final ArrayList propertyName, + final ArrayList propertyValues) + { + if (propertyNamespace.size() != propertyName.size()) + { + return null; + } + final OfficeStyle[] styles = predefCollection.getAutomaticStyles().getAllStyles(); + for (int i = 0; i < styles.length; i++) + { + final OfficeStyle officeStyle = styles[i]; + if (officeStyle.getStyleFamily().equals(styleFamily)) + { + final Element section = officeStyle.findFirstChild(OfficeNamespaces.STYLE_NS, sectionName); + if (section != null) + { + int j = 0; + for (; j < propertyNamespace.size(); j++) + { + final String ns = (String) propertyNamespace.get(j); + final String prop = (String) propertyName.get(j); + final Object obj = section.getAttribute(ns, prop); + final Object value = propertyValues.get(j); + if (obj == null || value == null) + { + continue; + } + if (!propertyValues.get(j).equals(obj)) + { + break; + } + } + if (j == propertyName.size()) + { + return officeStyle; + } + } + } + } + return null; + } + + private static String queryStyle(final OfficeStylesCollection predefCollection, + final String styleFamily, + final String styleName, + final String sectionName, + final String propertyNamespace, + final String propertyName, + final Set seenStyles) + { + if (seenStyles.contains(styleName)) + { + return null; + } + seenStyles.add(styleName); + + final OfficeStyle style = predefCollection.getStyle(styleFamily, styleName); + if (style == null) + { + return null; // no such style + + } + final Element section = style.findFirstChild(OfficeNamespaces.STYLE_NS, sectionName); + if (section != null) + { + final Object attribute = section.getAttribute(propertyNamespace, propertyName); + if (attribute != null) + { + return String.valueOf(attribute); + } + } + final String parent = style.getStyleParent(); + if (parent == null) + { + return null; + } + return queryStyle(predefCollection, styleFamily, parent, sectionName, propertyNamespace, propertyName, seenStyles); + } +} |