[seam-commits] Seam SVN: r11235 - in branches/community/Seam_2_2/src/excel/org/jboss/seam/excel: exporter and 1 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Jul 2 03:42:33 EDT 2009


Author: nickarls
Date: 2009-07-02 03:42:33 -0400 (Thu, 02 Jul 2009)
New Revision: 11235

Added:
   branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/CSSParser.java
   branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/StyleStringParser.java
Removed:
   branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/Parser.java
Modified:
   branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/exporter/ExcelExporter.java
   branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/jxl/JXLHelper.java
Log:
CSS parse refactoring, support of '' for escaping ; etc

Copied: branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/CSSParser.java (from rev 11217, branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/Parser.java)
===================================================================
--- branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/CSSParser.java	                        (rev 0)
+++ branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/CSSParser.java	2009-07-02 07:42:33 UTC (rev 11235)
@@ -0,0 +1,368 @@
+package org.jboss.seam.excel.css;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.jboss.seam.core.Interpolator;
+import org.jboss.seam.excel.ExcelWorkbookException;
+import org.jboss.seam.excel.ui.UILink;
+import org.jboss.seam.log.Log;
+import org.jboss.seam.log.Logging;
+
+/**
+ * CSS parser for the XLS-CSS
+ * 
+ * @author Nicklas Karlsson (nickarls at gmail.com)
+ */
+public class CSSParser
+{
+   // Where to look for the style
+   private static final String STYLE_ATTRIBUTE = "style";
+
+   // Where to look for the style class
+   private static final String STYLE_CLASS_ATTRIBUTE = "styleClass";
+
+   // What separates multiple style class references
+   private static final String STYLE_SHORTHAND_SEPARATOR = " ";
+
+   // What starts a rule block in a CSS file
+   private static final String LEFT_BRACE = "{";
+
+   // What ends a rule block in a CSS file
+   private static final String RIGHT_BRACE = "}";
+
+   // The style classes that have been read in from e:link referenced, mapped on
+   // style class name
+   private Map<String, StyleMap> definedStyleClasses = new HashMap<String, StyleMap>();
+
+   // The registered property builders, mapped on attribute name
+   private Map<String, PropertyBuilder> propertyBuilders = new HashMap<String, PropertyBuilder>();
+
+   // A cache of previously parsed css, mapped on component
+   private Map<UIComponent, StyleMap> cellStyleCache = new HashMap<UIComponent, StyleMap>();
+
+   private Log log = Logging.getLog(CSSParser.class);
+
+   /**
+    * Constructor, initializes the property builders
+    */
+   public CSSParser()
+   {
+      initPropertyBuilders();
+   }
+
+   /**
+    * Constructor with stylesheets
+    * 
+    * @param stylesheets The list of referenced stylesheets in UILink elements
+    * @throws MalformedURLException If the URL was bad
+    * @throws IOException If the URL could not be read
+    */
+   public CSSParser(List<UILink> stylesheets) throws MalformedURLException, IOException
+   {
+      initPropertyBuilders();
+      loadStylesheets(stylesheets);
+   }
+
+   /**
+    * Loads stylesheets (merging by class name)
+    * 
+    * @param stylesheets The stylesheets to read/merge
+    * @throws MalformedURLException If the URL was bad
+    * @throws IOException If the URL could not be read
+    */
+   private void loadStylesheets(List<UILink> stylesheets) throws MalformedURLException, IOException
+   {
+      for (UILink stylesheet : stylesheets)
+      {
+         definedStyleClasses.putAll(parseStylesheet(stylesheet.getURL()));
+      }
+   }
+
+   /**
+    * Registers the property builders
+    */
+   private void initPropertyBuilders()
+   {
+      propertyBuilders.put(CSSNames.FONT_FAMILY, new PropertyBuilders.FontFamily());
+      propertyBuilders.put(CSSNames.FONT_SIZE, new PropertyBuilders.FontSize());
+      propertyBuilders.put(CSSNames.FONT_COLOR, new PropertyBuilders.FontColor());
+      propertyBuilders.put(CSSNames.FONT_ITALIC, new PropertyBuilders.FontItalic());
+      propertyBuilders.put(CSSNames.FONT_SCRIPT_STYLE, new PropertyBuilders.FontScriptStyle());
+      propertyBuilders.put(CSSNames.FONT_STRUCK_OUT, new PropertyBuilders.FontStruckOut());
+      propertyBuilders.put(CSSNames.FONT_UNDERLINE_STYLE, new PropertyBuilders.FontUnderlineStyle());
+      propertyBuilders.put(CSSNames.FONT_BOLD, new PropertyBuilders.FontBold());
+      propertyBuilders.put(CSSNames.FONT, new PropertyBuilders.FontShorthand());
+      propertyBuilders.put(CSSNames.BACKGROUND_PATTERN, new PropertyBuilders.BackgroundPattern());
+      propertyBuilders.put(CSSNames.BACKGROUND_COLOR, new PropertyBuilders.BackgroundColor());
+      propertyBuilders.put(CSSNames.BACKGROUND, new PropertyBuilders.BackgroundShorthand());
+      propertyBuilders.put(CSSNames.BORDER_LEFT_COLOR, new PropertyBuilders.BorderLeftColor());
+      propertyBuilders.put(CSSNames.BORDER_LEFT_LINE_STYLE, new PropertyBuilders.BorderLeftLineStyle());
+      propertyBuilders.put(CSSNames.BORDER_LEFT, new PropertyBuilders.BorderLeftShorthand());
+      propertyBuilders.put(CSSNames.BORDER_TOP_COLOR, new PropertyBuilders.BorderTopColor());
+      propertyBuilders.put(CSSNames.BORDER_TOP_LINE_STYLE, new PropertyBuilders.BorderTopLineStyle());
+      propertyBuilders.put(CSSNames.BORDER_TOP, new PropertyBuilders.BorderTopShorthand());
+      propertyBuilders.put(CSSNames.BORDER_RIGHT_COLOR, new PropertyBuilders.BorderRightColor());
+      propertyBuilders.put(CSSNames.BORDER_RIGHT_LINE_STYLE, new PropertyBuilders.BorderRightLineStyle());
+      propertyBuilders.put(CSSNames.BORDER_RIGHT, new PropertyBuilders.BorderRightShorthand());
+      propertyBuilders.put(CSSNames.BORDER_BOTTOM_COLOR, new PropertyBuilders.BorderBottomColor());
+      propertyBuilders.put(CSSNames.BORDER_BOTTOM_LINE_STYLE, new PropertyBuilders.BorderBottomLineStyle());
+      propertyBuilders.put(CSSNames.BORDER_BOTTOM, new PropertyBuilders.BorderBottomShorthand());
+      propertyBuilders.put(CSSNames.BORDER, new PropertyBuilders.BorderShorthand());
+      propertyBuilders.put(CSSNames.FORMAT_MASK, new PropertyBuilders.FormatMask());
+      propertyBuilders.put(CSSNames.ALIGNMENT, new PropertyBuilders.Alignment());
+      propertyBuilders.put(CSSNames.INDENTATION, new PropertyBuilders.Indentation());
+      propertyBuilders.put(CSSNames.ORIENTATION, new PropertyBuilders.Orientation());
+      propertyBuilders.put(CSSNames.LOCKED, new PropertyBuilders.Locked());
+      propertyBuilders.put(CSSNames.SHRINK_TO_FIT, new PropertyBuilders.ShrinkToFit());
+      propertyBuilders.put(CSSNames.WRAP, new PropertyBuilders.Wrap());
+      propertyBuilders.put(CSSNames.VERICAL_ALIGNMENT, new PropertyBuilders.VericalAlignment());
+      propertyBuilders.put(CSSNames.COLUMN_WIDTH, new PropertyBuilders.ColumnWidth());
+      propertyBuilders.put(CSSNames.COLUMN_AUTO_SIZE, new PropertyBuilders.ColumnAutoSize());
+      propertyBuilders.put(CSSNames.COLUMN_HIDDEN, new PropertyBuilders.ColumnHidden());
+      propertyBuilders.put(CSSNames.COLUMN_EXPORT, new PropertyBuilders.ColumnExport());
+      propertyBuilders.put(CSSNames.COLUMN_WIDTHS, new PropertyBuilders.ColumnWidths());
+      propertyBuilders.put(CSSNames.FORCE_TYPE, new PropertyBuilders.ForceType());
+   }
+
+   /**
+    * Reads data from an URL to a String
+    * 
+    * @param url The URL to read
+    * @return The read data as a String
+    * @throws IOException If the stream could not be read
+    */
+   private static String readCSS(InputStream in) throws IOException
+   {
+      BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+      StringBuffer buffer = new StringBuffer();
+      String line;
+      while ((line = reader.readLine()) != null)
+      {
+         buffer.append(line);
+      }
+      reader.close();
+      return buffer.toString();
+   }
+
+   /**
+    * Parses a style sheet. Really crude. Assumes data is nicely formatted on
+    * one line per entry
+    * 
+    * @param urlString The URL to read
+    * @return A map of style class names mapped to StyleMaps
+    * @throws MalformedURLException
+    * @throws IOException
+    */
+   private Map<String, StyleMap> parseStylesheet(String urlString) throws MalformedURLException, IOException
+   {
+      Map<String, StyleMap> styleClasses = new HashMap<String, StyleMap>();
+      InputStream cssStream = null;
+      if (urlString.indexOf("://") < 0) {
+         cssStream = getClass().getResourceAsStream(urlString);
+      } else {
+         cssStream = new URL(urlString).openStream();
+      }
+      String css = readCSS(cssStream).toLowerCase();
+      int firstBrace = -1;
+      int secondBrace = -1;
+      while (!"".equals(css))
+      {
+         firstBrace = css.indexOf(LEFT_BRACE);
+         if (firstBrace >= 0)
+         {
+            secondBrace = css.indexOf(RIGHT_BRACE, firstBrace + 1);
+         }
+         if (firstBrace >= 0 && secondBrace >= 0 && firstBrace != secondBrace)
+         {
+            String styleName = css.substring(0, firstBrace).trim();
+            if (styleName.startsWith(".")) {
+                styleName = styleName.substring(1);
+            }
+            String styleString = css.substring(firstBrace + 1, secondBrace).trim();
+            StyleMap styleMap = StyleStringParser.of(styleString, propertyBuilders).parse();
+            styleClasses.put(styleName, styleMap);
+            css = css.substring(secondBrace + 1);
+         }
+         else
+         {
+            css = "";
+         }
+      }
+      return styleClasses;
+   }
+
+   /**
+    * Gets style from a component
+    * 
+    * @param component The component to examine
+    * @return null if not found, otherwise style string
+    */
+   public static String getStyle(UIComponent component)
+   {
+      return getStyleProperty(component, STYLE_ATTRIBUTE);
+   }
+
+   /**
+    * Gets style class from a component
+    * 
+    * @param component The component to examine
+    * @return null if not found, otherwise style class(es) string
+    */
+   public static String getStyleClass(UIComponent component)
+   {
+      return getStyleProperty(component, STYLE_CLASS_ATTRIBUTE);
+   }
+
+   /**
+    * Reads a property from a component
+    * 
+    * @param component The component to examine
+    * @param field The field to read
+    * @return The value from the field
+    */
+   private static String getStyleProperty(UIComponent component, String field)
+   {
+      try
+      {
+         return (String) PropertyUtils.getProperty(component, field);
+      }
+      catch (NoSuchMethodException e)
+      {
+         // No panic, no property
+         return null;
+      }
+      catch (Exception e)
+      {
+         String message = Interpolator.instance().interpolate("Could not read field #0 of bean #1", field, component.getId());
+         throw new ExcelWorkbookException(message, e);
+      }
+   }
+
+   /**
+    * Cascades on parents, collecting them into list
+    * 
+    * @param component The component to examine
+    * @param styleMaps The list of collected style maps
+    * @return The list of style maps
+    */
+   private List<StyleMap> cascadeStyleMap(UIComponent component, List<StyleMap> styleMaps)
+   {
+      styleMaps.add(getStyleMap(component));
+      if (component.getParent() != null)
+      {
+         cascadeStyleMap(component.getParent(), styleMaps);
+      }
+      return styleMaps;
+   }
+
+   /**
+    * Gets the cascaded style map for a component. Recurses on parents,
+    * collecting style maps. The reverses the list and merges the styles
+    * 
+    * @param component The component to examine
+    * @return The merged style map
+    */
+   public StyleMap getCascadedStyleMap(UIComponent component)
+   {
+      List<StyleMap> styleMaps = cascadeStyleMap(component, new ArrayList<StyleMap>());
+      Collections.reverse(styleMaps);
+      StyleMap cascadedStyleMap = new StyleMap();
+      for (StyleMap styleMap : styleMaps)
+      {
+         cascadedStyleMap.putAll(styleMap);
+      }
+      return cascadedStyleMap;
+   }
+
+   /**
+    * Gets a style map for a component (from cache if available)
+    * 
+    * @param component The component to examine
+    * @return The style map of the component
+    */
+   private StyleMap getStyleMap(UIComponent component)
+   {
+      if (cellStyleCache.containsKey(component))
+      {
+         return cellStyleCache.get(component);
+      }
+
+      StyleMap styleMap = new StyleMap();
+
+      String componentStyleClass = getStyleProperty(component, STYLE_CLASS_ATTRIBUTE);
+      if (componentStyleClass != null)
+      {
+         String[] styleClasses = StyleStringParser.trimArray(componentStyleClass.split(STYLE_SHORTHAND_SEPARATOR));
+         for (String styleClass : styleClasses)
+         {
+            if (!definedStyleClasses.containsKey(styleClass))
+            {
+               log.warn("Uknown style class #0", styleClass);
+               continue;
+            }
+            styleMap.putAll(definedStyleClasses.get(styleClass));
+         }
+      }
+
+      String componentStyle = getStyleProperty(component, STYLE_ATTRIBUTE);
+      if (componentStyle != null)
+      {
+         styleMap.putAll(StyleStringParser.of(componentStyle, propertyBuilders).parse());
+      }
+
+      cellStyleCache.put(component, styleMap);
+      return styleMap;
+   }
+
+//   private StyleMap parseStyleString(String styleString)
+//   {
+//      StyleMap styleMap = new StyleMap();
+//
+//      String[] styles = trimArray(styleString.split(STYLES_SEPARATOR));
+//      for (String style : styles)
+//      {
+//         int breakpoint = style.indexOf(STYLE_NAME_VALUE_SEPARATOR);
+//         if (breakpoint < 0) {
+//             log.warn("Style component #0 should be of form <key>#1<value>", style, STYLE_NAME_VALUE_SEPARATOR);
+//             continue;
+//         }
+//         String styleName = style.substring(0, breakpoint).toLowerCase().trim();
+//         if (!propertyBuilders.containsKey(styleName))
+//         {
+//            log.warn("No property builder (unknown style) for property #0", styleName);
+//            continue;
+//         }
+//         PropertyBuilder propertyBuilder = propertyBuilders.get(styleName);
+//         String styleValue = style.substring(breakpoint + 1);
+//         String[] styleValues = trimArray(styleValue.trim().split(STYLE_SHORTHAND_SEPARATOR));
+//         styleMap.putAll(propertyBuilder.parseProperty(styleName, styleValues));
+//      }
+//
+//      return styleMap;
+//   }
+
+   /**
+    * Setter for stylesheets. Loads them also.
+    * 
+    * @param stylesheets The stylesheets to load
+    * @throws MalformedURLException If the URL is bad
+    * @throws IOException If the URL cannot be read
+    */
+   public void setStylesheets(List<UILink> stylesheets) throws MalformedURLException, IOException
+   {
+      loadStylesheets(stylesheets);
+   }
+}

Deleted: branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/Parser.java
===================================================================
--- branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/Parser.java	2009-07-01 22:32:40 UTC (rev 11234)
+++ branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/Parser.java	2009-07-02 07:42:33 UTC (rev 11235)
@@ -1,399 +0,0 @@
-package org.jboss.seam.excel.css;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.faces.component.UIComponent;
-
-import org.apache.commons.beanutils.PropertyUtils;
-import org.jboss.seam.core.Interpolator;
-import org.jboss.seam.excel.ExcelWorkbookException;
-import org.jboss.seam.excel.ui.UILink;
-import org.jboss.seam.log.Log;
-import org.jboss.seam.log.Logging;
-
-/**
- * CSS parser for the XLS-CSS
- * 
- * @author Nicklas Karlsson (nickarls at gmail.com)
- */
-public class Parser
-{
-   // Where to look for the style
-   private static final String STYLE_ATTRIBUTE = "style";
-
-   // Where to look for the style class
-   private static final String STYLE_CLASS_ATTRIBUTE = "styleClass";
-
-   // What separates multiple XLS-CSS attributes in a style string
-   private static final String STYLES_SEPARATOR = ";";
-
-   // What separates the key and value in a XLS-CSS style
-   private static final String STYLE_NAME_VALUE_SEPARATOR = ":";
-
-   // What separates multiple style class references
-   private static final String STYLE_SHORTHAND_SEPARATOR = " ";
-
-   // What starts a rule block in a CSS file
-   private static final String LEFT_BRACE = "{";
-
-   // What ends a rule block in a CSS file
-   private static final String RIGHT_BRACE = "}";
-
-   // The style classes that have been read in from e:link referenced, mapped on
-   // style class name
-   private Map<String, StyleMap> definedStyleClasses = new HashMap<String, StyleMap>();
-
-   // The registered property builders, mapped on attribute name
-   private Map<String, PropertyBuilder> propertyBuilders = new HashMap<String, PropertyBuilder>();
-
-   // A cache of previously parsed css, mapped on component
-   private Map<UIComponent, StyleMap> cellStyleCache = new HashMap<UIComponent, StyleMap>();
-
-   private Log log = Logging.getLog(Parser.class);
-
-   /**
-    * Constructor, initializes the property builders
-    */
-   public Parser()
-   {
-      initPropertyBuilders();
-   }
-
-   /**
-    * Constructor with stylesheets
-    * 
-    * @param stylesheets The list of referenced stylesheets in UILink elements
-    * @throws MalformedURLException If the URL was bad
-    * @throws IOException If the URL could not be read
-    */
-   public Parser(List<UILink> stylesheets) throws MalformedURLException, IOException
-   {
-      initPropertyBuilders();
-      loadStylesheets(stylesheets);
-   }
-
-   /**
-    * Loads stylesheets (merging by class name)
-    * 
-    * @param stylesheets The stylesheets to read/merge
-    * @throws MalformedURLException If the URL was bad
-    * @throws IOException If the URL could not be read
-    */
-   private void loadStylesheets(List<UILink> stylesheets) throws MalformedURLException, IOException
-   {
-      for (UILink stylesheet : stylesheets)
-      {
-         definedStyleClasses.putAll(parseStylesheet(stylesheet.getURL()));
-      }
-   }
-
-   /**
-    * Registers the property builders
-    */
-   private void initPropertyBuilders()
-   {
-      propertyBuilders.put(CSSNames.FONT_FAMILY, new PropertyBuilders.FontFamily());
-      propertyBuilders.put(CSSNames.FONT_SIZE, new PropertyBuilders.FontSize());
-      propertyBuilders.put(CSSNames.FONT_COLOR, new PropertyBuilders.FontColor());
-      propertyBuilders.put(CSSNames.FONT_ITALIC, new PropertyBuilders.FontItalic());
-      propertyBuilders.put(CSSNames.FONT_SCRIPT_STYLE, new PropertyBuilders.FontScriptStyle());
-      propertyBuilders.put(CSSNames.FONT_STRUCK_OUT, new PropertyBuilders.FontStruckOut());
-      propertyBuilders.put(CSSNames.FONT_UNDERLINE_STYLE, new PropertyBuilders.FontUnderlineStyle());
-      propertyBuilders.put(CSSNames.FONT_BOLD, new PropertyBuilders.FontBold());
-      propertyBuilders.put(CSSNames.FONT, new PropertyBuilders.FontShorthand());
-      propertyBuilders.put(CSSNames.BACKGROUND_PATTERN, new PropertyBuilders.BackgroundPattern());
-      propertyBuilders.put(CSSNames.BACKGROUND_COLOR, new PropertyBuilders.BackgroundColor());
-      propertyBuilders.put(CSSNames.BACKGROUND, new PropertyBuilders.BackgroundShorthand());
-      propertyBuilders.put(CSSNames.BORDER_LEFT_COLOR, new PropertyBuilders.BorderLeftColor());
-      propertyBuilders.put(CSSNames.BORDER_LEFT_LINE_STYLE, new PropertyBuilders.BorderLeftLineStyle());
-      propertyBuilders.put(CSSNames.BORDER_LEFT, new PropertyBuilders.BorderLeftShorthand());
-      propertyBuilders.put(CSSNames.BORDER_TOP_COLOR, new PropertyBuilders.BorderTopColor());
-      propertyBuilders.put(CSSNames.BORDER_TOP_LINE_STYLE, new PropertyBuilders.BorderTopLineStyle());
-      propertyBuilders.put(CSSNames.BORDER_TOP, new PropertyBuilders.BorderTopShorthand());
-      propertyBuilders.put(CSSNames.BORDER_RIGHT_COLOR, new PropertyBuilders.BorderRightColor());
-      propertyBuilders.put(CSSNames.BORDER_RIGHT_LINE_STYLE, new PropertyBuilders.BorderRightLineStyle());
-      propertyBuilders.put(CSSNames.BORDER_RIGHT, new PropertyBuilders.BorderRightShorthand());
-      propertyBuilders.put(CSSNames.BORDER_BOTTOM_COLOR, new PropertyBuilders.BorderBottomColor());
-      propertyBuilders.put(CSSNames.BORDER_BOTTOM_LINE_STYLE, new PropertyBuilders.BorderBottomLineStyle());
-      propertyBuilders.put(CSSNames.BORDER_BOTTOM, new PropertyBuilders.BorderBottomShorthand());
-      propertyBuilders.put(CSSNames.BORDER, new PropertyBuilders.BorderShorthand());
-      propertyBuilders.put(CSSNames.FORMAT_MASK, new PropertyBuilders.FormatMask());
-      propertyBuilders.put(CSSNames.ALIGNMENT, new PropertyBuilders.Alignment());
-      propertyBuilders.put(CSSNames.INDENTATION, new PropertyBuilders.Indentation());
-      propertyBuilders.put(CSSNames.ORIENTATION, new PropertyBuilders.Orientation());
-      propertyBuilders.put(CSSNames.LOCKED, new PropertyBuilders.Locked());
-      propertyBuilders.put(CSSNames.SHRINK_TO_FIT, new PropertyBuilders.ShrinkToFit());
-      propertyBuilders.put(CSSNames.WRAP, new PropertyBuilders.Wrap());
-      propertyBuilders.put(CSSNames.VERICAL_ALIGNMENT, new PropertyBuilders.VericalAlignment());
-      propertyBuilders.put(CSSNames.COLUMN_WIDTH, new PropertyBuilders.ColumnWidth());
-      propertyBuilders.put(CSSNames.COLUMN_AUTO_SIZE, new PropertyBuilders.ColumnAutoSize());
-      propertyBuilders.put(CSSNames.COLUMN_HIDDEN, new PropertyBuilders.ColumnHidden());
-      propertyBuilders.put(CSSNames.COLUMN_EXPORT, new PropertyBuilders.ColumnExport());
-      propertyBuilders.put(CSSNames.COLUMN_WIDTHS, new PropertyBuilders.ColumnWidths());
-      propertyBuilders.put(CSSNames.FORCE_TYPE, new PropertyBuilders.ForceType());
-   }
-
-   /**
-    * Reads data from an URL to a String
-    * 
-    * @param url The URL to read
-    * @return The read data as a String
-    * @throws IOException If the stream could not be read
-    */
-   private static String readCSS(InputStream in) throws IOException
-   {
-      BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-      StringBuffer buffer = new StringBuffer();
-      String line;
-      while ((line = reader.readLine()) != null)
-      {
-         buffer.append(line);
-      }
-      reader.close();
-      return buffer.toString();
-   }
-
-   /**
-    * Parses a style sheet. Really crude. Assumes data is nicely formatted on
-    * one line per entry
-    * 
-    * @param urlString The URL to read
-    * @return A map of style class names mapped to StyleMaps
-    * @throws MalformedURLException
-    * @throws IOException
-    */
-   private Map<String, StyleMap> parseStylesheet(String urlString) throws MalformedURLException, IOException
-   {
-      Map<String, StyleMap> styleClasses = new HashMap<String, StyleMap>();
-      InputStream cssStream = null;
-      if (urlString.indexOf("://") < 0) {
-         cssStream = getClass().getResourceAsStream(urlString);
-      } else {
-         cssStream = new URL(urlString).openStream();
-      }
-      String css = readCSS(cssStream).toLowerCase();
-      int firstBrace = -1;
-      int secondBrace = -1;
-      while (!"".equals(css))
-      {
-         firstBrace = css.indexOf(LEFT_BRACE);
-         if (firstBrace >= 0)
-         {
-            secondBrace = css.indexOf(RIGHT_BRACE, firstBrace + 1);
-         }
-         if (firstBrace >= 0 && secondBrace >= 0 && firstBrace != secondBrace)
-         {
-            String styleName = css.substring(0, firstBrace).trim();
-            if (styleName.startsWith(".")) {
-                styleName = styleName.substring(1);
-            }
-            String styleString = css.substring(firstBrace + 1, secondBrace).trim();
-            StyleMap styleMap = parseStyleString(styleString);
-            styleClasses.put(styleName, styleMap);
-            css = css.substring(secondBrace + 1);
-         }
-         else
-         {
-            css = "";
-         }
-      }
-      return styleClasses;
-   }
-
-   /**
-    * Gets style from a component
-    * 
-    * @param component The component to examine
-    * @return null if not found, otherwise style string
-    */
-   public static String getStyle(UIComponent component)
-   {
-      return getStyleProperty(component, STYLE_ATTRIBUTE);
-   }
-
-   /**
-    * Gets style class from a component
-    * 
-    * @param component The component to examine
-    * @return null if not found, otherwise style class(es) string
-    */
-   public static String getStyleClass(UIComponent component)
-   {
-      return getStyleProperty(component, STYLE_CLASS_ATTRIBUTE);
-   }
-
-   /**
-    * Reads a property from a component
-    * 
-    * @param component The component to examine
-    * @param field The field to read
-    * @return The value from the field
-    */
-   private static String getStyleProperty(UIComponent component, String field)
-   {
-      try
-      {
-         return (String) PropertyUtils.getProperty(component, field);
-      }
-      catch (NoSuchMethodException e)
-      {
-         // No panic, no property
-         return null;
-      }
-      catch (Exception e)
-      {
-         String message = Interpolator.instance().interpolate("Could not read field #0 of bean #1", field, component.getId());
-         throw new ExcelWorkbookException(message, e);
-      }
-   }
-
-   /**
-    * Cascades on parents, collecting them into list
-    * 
-    * @param component The component to examine
-    * @param styleMaps The list of collected style maps
-    * @return The list of style maps
-    */
-   private List<StyleMap> cascadeStyleMap(UIComponent component, List<StyleMap> styleMaps)
-   {
-      styleMaps.add(getStyleMap(component));
-      if (component.getParent() != null)
-      {
-         cascadeStyleMap(component.getParent(), styleMaps);
-      }
-      return styleMaps;
-   }
-
-   /**
-    * Gets the cascaded style map for a component. Recurses on parents,
-    * collecting style maps. The reverses the list and merges the styles
-    * 
-    * @param component The component to examine
-    * @return The merged style map
-    */
-   public StyleMap getCascadedStyleMap(UIComponent component)
-   {
-      List<StyleMap> styleMaps = cascadeStyleMap(component, new ArrayList<StyleMap>());
-      Collections.reverse(styleMaps);
-      StyleMap cascadedStyleMap = new StyleMap();
-      for (StyleMap styleMap : styleMaps)
-      {
-         cascadedStyleMap.putAll(styleMap);
-      }
-      return cascadedStyleMap;
-   }
-
-   /**
-    * Gets a style map for a component (from cache if available)
-    * 
-    * @param component The component to examine
-    * @return The style map of the component
-    */
-   private StyleMap getStyleMap(UIComponent component)
-   {
-      if (cellStyleCache.containsKey(component))
-      {
-         return cellStyleCache.get(component);
-      }
-
-      StyleMap styleMap = new StyleMap();
-
-      String componentStyleClass = getStyleProperty(component, STYLE_CLASS_ATTRIBUTE);
-      if (componentStyleClass != null)
-      {
-         String[] styleClasses = trimArray(componentStyleClass.split(STYLE_SHORTHAND_SEPARATOR));
-         for (String styleClass : styleClasses)
-         {
-            if (!definedStyleClasses.containsKey(styleClass))
-            {
-               log.warn("Uknown style class #0", styleClass);
-               continue;
-            }
-            styleMap.putAll(definedStyleClasses.get(styleClass));
-         }
-      }
-
-      String componentStyle = getStyleProperty(component, STYLE_ATTRIBUTE);
-      if (componentStyle != null)
-      {
-         styleMap.putAll(parseStyleString(componentStyle));
-      }
-
-      cellStyleCache.put(component, styleMap);
-      return styleMap;
-   }
-
-   /**
-    * Parses a stringle style string
-    * 
-    * @param styleString The string to parse
-    * @return The parsed StyleMap
-    */
-   private StyleMap parseStyleString(String styleString)
-   {
-      StyleMap styleMap = new StyleMap();
-
-      String[] styles = trimArray(styleString.split(STYLES_SEPARATOR));
-      for (String style : styles)
-      {
-         int breakpoint = style.indexOf(STYLE_NAME_VALUE_SEPARATOR);
-         if (breakpoint < 0) {
-             log.warn("Style component #0 should be of form <key>#1<value>", style, STYLE_NAME_VALUE_SEPARATOR);
-             continue;
-         }
-         String styleName = style.substring(0, breakpoint).toLowerCase().trim();
-         if (!propertyBuilders.containsKey(styleName))
-         {
-            log.warn("No property builder (unknown style) for property #0", styleName);
-            continue;
-         }
-         PropertyBuilder propertyBuilder = propertyBuilders.get(styleName);
-         String styleValue = style.substring(breakpoint + 1);
-         String[] styleValues = trimArray(styleValue.trim().split(STYLE_SHORTHAND_SEPARATOR));
-         styleMap.putAll(propertyBuilder.parseProperty(styleName, styleValues));
-      }
-
-      return styleMap;
-   }
-
-   /**
-    * Utility for trimming (lowercase & trim) an array of string values
-    * 
-    * @param array The array to trim
-    * @return The trimmed array
-    */
-   private String[] trimArray(String[] array)
-   {
-      List<String> validValues = new ArrayList<String>();
-      for (int i = 0; i < array.length; i++)
-      {
-         if (!"".equals(array[i]) && !" ".equals(array[i]))
-         {
-            validValues.add(array[i].toLowerCase().trim());
-         }
-      }
-      return validValues.toArray(new String[validValues.size()]);
-   }
-
-   /**
-    * Setter for stylesheets. Loads them also.
-    * 
-    * @param stylesheets The stylesheets to load
-    * @throws MalformedURLException If the URL is bad
-    * @throws IOException If the URL cannot be read
-    */
-   public void setStylesheets(List<UILink> stylesheets) throws MalformedURLException, IOException
-   {
-      loadStylesheets(stylesheets);
-   }
-}

Added: branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/StyleStringParser.java
===================================================================
--- branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/StyleStringParser.java	                        (rev 0)
+++ branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/css/StyleStringParser.java	2009-07-02 07:42:33 UTC (rev 11235)
@@ -0,0 +1,103 @@
+package org.jboss.seam.excel.css;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.seam.log.Log;
+import org.jboss.seam.log.Logging;
+
+public class StyleStringParser
+{
+   private static final char STYLE_SEPARATOR = ';';
+   private static final String KEY_VALUE_SEPARATOR = ":";
+   private static final String STYLE_SHORTHAND_SEPARATOR = " ";
+   private static final char ESCAPE_CHAR = '\'';
+   
+   private Log log = Logging.getLog(StyleStringParser.class);
+   
+   private String styleString;
+   private Map<String, PropertyBuilder> propertyBuilderMap;
+   private StyleMap styleMap = new StyleMap();
+   private boolean escaping = false;
+   
+   public static StyleStringParser of(String styleString, Map<String, PropertyBuilder> propertyBuilderMap)
+   {
+      return new StyleStringParser(styleString, propertyBuilderMap);
+   }
+   
+   protected StyleStringParser(String styleString, Map<String, PropertyBuilder> propertyBuilderMap)
+   {
+      this.styleString = styleString;
+      this.propertyBuilderMap = propertyBuilderMap;
+   }
+   
+   private void addStyle(StringBuilder styleBuilder)
+   {
+      String styleString = styleBuilder.toString();
+      int keyValueBreakpointIndex = styleString.indexOf(KEY_VALUE_SEPARATOR);
+      if (keyValueBreakpointIndex < 0)
+      {
+         log.warn("Key-value separator character #0 not found in style #1, dropping", KEY_VALUE_SEPARATOR + styleBuilder.toString());
+         return;
+      }
+      String styleName = styleString.substring(0, keyValueBreakpointIndex).toLowerCase().trim();
+      if (!propertyBuilderMap.containsKey(styleName))
+      {
+         log.warn("No property builder (unknown style) for property #0", styleName);
+         return;
+      }
+      PropertyBuilder propertyBuilder = propertyBuilderMap.get(styleName);
+      String styleValue = styleString.substring(keyValueBreakpointIndex + 1);
+      log.trace("Parsed style #0 to #1 => #2", styleString, styleName, styleValue);
+      String[] styleValues = trimArray(styleValue.trim().split(STYLE_SHORTHAND_SEPARATOR));
+      styleMap.putAll(propertyBuilder.parseProperty(styleName, styleValues));
+   }
+   
+   public static String[] trimArray(String[] array)
+   {
+      List<String> validValues = new ArrayList<String>();
+      for (int i = 0; i < array.length; i++)
+      {
+         if (!"".equals(array[i]) && !" ".equals(array[i]))
+         {
+            validValues.add(array[i].toLowerCase().trim());
+         }
+      }
+      return validValues.toArray(new String[validValues.size()]);
+   }
+   
+   public StyleMap parse()
+   {
+      CharacterIterator iterator = new StringCharacterIterator(styleString);
+      StringBuilder styleBuilder = new StringBuilder();
+      for (char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next())
+      {
+         if (ESCAPE_CHAR == c)
+         {
+            escaping = !escaping;
+         }
+         else if (STYLE_SEPARATOR == c && !escaping)
+         {
+            addStyle(styleBuilder);
+            styleBuilder = new StringBuilder();
+         }
+         else
+         {
+            styleBuilder.append(c);
+         }
+      }
+      if (styleBuilder.length() > 0)
+      {
+         addStyle(styleBuilder);
+      }
+      
+      if (escaping)
+      {
+         log.warn("Unbalanced escape characters #0 in style #1", ESCAPE_CHAR, styleBuilder.toString());
+      }
+      return styleMap;
+   }
+}

Modified: branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/exporter/ExcelExporter.java
===================================================================
--- branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/exporter/ExcelExporter.java	2009-07-01 22:32:40 UTC (rev 11234)
+++ branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/exporter/ExcelExporter.java	2009-07-02 07:42:33 UTC (rev 11235)
@@ -27,7 +27,7 @@
 import org.jboss.seam.excel.ExcelWorkbookException;
 import org.jboss.seam.excel.css.CSSNames;
 import org.jboss.seam.excel.css.ColumnStyle;
-import org.jboss.seam.excel.css.Parser;
+import org.jboss.seam.excel.css.CSSParser;
 import org.jboss.seam.excel.css.StyleMap;
 import org.jboss.seam.excel.ui.ExcelComponent;
 import org.jboss.seam.excel.ui.UICell;
@@ -78,7 +78,7 @@
    {
       excelWorkbook = ExcelFactory.instance().getExcelWorkbook(type);
 
-      Parser parser = new Parser();
+      CSSParser parser = new CSSParser();
 
       // Gets the datatable
       UIData dataTable = (UIData) FacesContext.getCurrentInstance().getViewRoot().findComponent(dataTableId);
@@ -92,8 +92,8 @@
       excelWorkbook.createWorkbook(uiWorkbook);
       UIWorksheet uiWorksheet = new UIWorksheet();
       uiWorkbook.getChildren().add(uiWorksheet);
-      uiWorksheet.setStyle(Parser.getStyle(dataTable));
-      uiWorksheet.setStyleClass(Parser.getStyleClass(dataTable));
+      uiWorksheet.setStyle(CSSParser.getStyle(dataTable));
+      uiWorksheet.setStyleClass(CSSParser.getStyleClass(dataTable));
       excelWorkbook.createOrSelectWorksheet(uiWorksheet);
 
       // Saves the datatable var
@@ -141,7 +141,7 @@
    private Map<Integer, Integer> parseColumnWidths(UIWorksheet worksheet)
    {
       Map<Integer, Integer> columnWidths = new HashMap<Integer, Integer>();
-      Parser parser = new Parser();
+      CSSParser parser = new CSSParser();
 
       StyleMap styleMap = parser.getCascadedStyleMap(worksheet);
       for (Map.Entry<String, Object> entry : styleMap.entrySet())
@@ -235,8 +235,8 @@
          column.getChildren().add(cell);
          cell.setId(output.getId());
          cell.setValue(output.getValue());
-         cell.setStyle(Parser.getStyle(output));
-         cell.setStyleClass(Parser.getStyleClass(output));
+         cell.setStyle(CSSParser.getStyle(output));
+         cell.setStyleClass(CSSParser.getStyleClass(output));
 
          excelWorkbook.addItem(cell);
       }

Modified: branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/jxl/JXLHelper.java
===================================================================
--- branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/jxl/JXLHelper.java	2009-07-01 22:32:40 UTC (rev 11234)
+++ branches/community/Seam_2_2/src/excel/org/jboss/seam/excel/jxl/JXLHelper.java	2009-07-02 07:42:33 UTC (rev 11235)
@@ -32,7 +32,7 @@
 import org.jboss.seam.excel.ExcelWorkbookException;
 import org.jboss.seam.excel.css.CellStyle;
 import org.jboss.seam.excel.css.ColumnStyle;
-import org.jboss.seam.excel.css.Parser;
+import org.jboss.seam.excel.css.CSSParser;
 import org.jboss.seam.excel.ui.ExcelComponent;
 import org.jboss.seam.excel.ui.UICell;
 import org.jboss.seam.excel.ui.UICellBase;
@@ -67,7 +67,7 @@
    private static Log log = Logging.getLog(JXLHelper.class);
 
    // The CSS parser
-   private Parser parser = new Parser();
+   private CSSParser parser = new CSSParser();
 
    // A cache of cell info
    private CellInfoCache cellInfoCache = new CellInfoCache();




More information about the seam-commits mailing list