Package org.pentaho.reporting.libraries.css.parser

Source Code of org.pentaho.reporting.libraries.css.parser.StyleSheetParserUtil

/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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 for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.libraries.css.parser;

import java.io.StringReader;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

import org.pentaho.reporting.libraries.css.model.CSSDeclarationRule;
import org.pentaho.reporting.libraries.css.model.CSSStyleRule;
import org.pentaho.reporting.libraries.css.model.StyleKey;
import org.pentaho.reporting.libraries.css.model.StyleKeyRegistry;
import org.pentaho.reporting.libraries.css.model.StyleSheet;
import org.pentaho.reporting.libraries.css.values.CSSValue;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.LexicalUnit;
import org.w3c.css.sac.Parser;

/**
* A helper class that simplifies the parsing of stylesheets.
*
* @author Thomas Morgner
*/
public final class StyleSheetParserUtil
{
  private static StyleSheetParserUtil singleton;
  private Parser parser;

  public StyleSheetParserUtil()
  {
  }

  public static synchronized StyleSheetParserUtil getInstance()
  {
    if (singleton == null)
    {
      singleton = new StyleSheetParserUtil();
    }
    return singleton;
  }

  private void setupNamespaces(final Map namespaces,
                               final StyleSheetHandler handler)
  {
    if (namespaces == null)
    {
      return;
    }

    final Iterator entries = namespaces.entrySet().iterator();
    while (entries.hasNext())
    {
      final Map.Entry entry = (Map.Entry) entries.next();
      final String prefix = (String) entry.getKey();
      final String uri = (String) entry.getValue();
      handler.registerNamespace(prefix, uri);
    }
  }

  /**
   * Parses a single style value for the given key. Returns <code>null</code>,
   * if the key denotes a compound definition, which has no internal
   * representation.
   *
   * @param namespaces an optional map of known namespaces (prefix -> uri)
   * @param key        the stylekey to which the value should be assigned.
   * @param value      the value text
   * @param baseURL    an optional base url
   * @return the parsed value or null, if the value was not valid.
   */
  public CSSValue parseStyleValue(final Map namespaces,
                                  final StyleKey key,
                                  final String value,
                                  final ResourceKey baseURL,
                                  final ResourceManager resourceManager,
                                  final StyleKeyRegistry styleKeyRegistry)
  {
    if (key == null)
    {
      throw new NullPointerException();
    }
    if (value == null)
    {
      throw new NullPointerException();
    }

    try
    {
      final Parser parser = getParser();
      synchronized (parser)
      {
        final StyleSheetHandler handler = new StyleSheetHandler();
        setupNamespaces(namespaces, handler);

        handler.init(styleKeyRegistry, resourceManager, baseURL, -1, null);

        final InputSource source = new InputSource();
        source.setCharacterStream(new StringReader(value));

        handler.initParseContext(source);
        handler.setStyleRule(new CSSStyleRule(new StyleSheet(), null));
        parser.setDocumentHandler(handler);
        final LexicalUnit lu = parser.parsePropertyValue(source);
        handler.property(key.getName(), lu, false);
        final CSSStyleRule rule = (CSSStyleRule) handler.getStyleRule();

        CSSParserContext.getContext().destroy();

        return rule.getPropertyCSSValue(key);
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Parses a style rule.
   *
   * @param namespaces an optional map of known namespaces (prefix -> uri)
   * @param styleText  the css text that should be parsed
   * @param baseURL    an optional base url
   * @param baseRule   an optional base-rule to which the result gets added.
   * @return the CSS-Style-Rule that contains all values for the given text.
   */
  public CSSDeclarationRule parseStyleRule(final Map namespaces,
                                           final String styleText,
                                           final ResourceKey baseURL,
                                           final CSSDeclarationRule baseRule,
                                           final ResourceManager resourceManager,
                                           final StyleKeyRegistry styleKeyRegistry)
  {
    if (styleText == null)
    {
      throw new NullPointerException("Name is null");
    }
    if (resourceManager == null)
    {
      throw new NullPointerException("ResourceManager must not be null");
    }
    if (styleKeyRegistry == null)
    {
      throw new NullPointerException("Style-Key Registry must not be null");
    }

    try
    {
      final Parser parser = getParser();
      synchronized (parser)
      {
        final StyleSheetHandler handler = new StyleSheetHandler();
        setupNamespaces(namespaces, handler);
        handler.init(styleKeyRegistry, resourceManager, baseURL, -1, null);

        final InputSource source = new InputSource();
        source.setCharacterStream(new StringReader(styleText));

        handler.initParseContext(source);
        if (baseRule != null)
        {
          handler.setStyleRule(baseRule);
        }
        else
        {
          handler.setStyleRule(new CSSStyleRule(new StyleSheet(), null));
        }
        parser.setDocumentHandler(handler);
        parser.parseStyleDeclaration(source);
        final CSSDeclarationRule rule = handler.getStyleRule();
        CSSParserContext.getContext().destroy();
        return rule;
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return null;
    }
  }


  /**
   * Parses a style value. If the style value is a compound key, the
   * corresonding style entries will be added to the style rule.
   *
   * @param namespaces an optional map of known namespaces (prefix -> uri)
   * @param name       the stylekey-name to which the value should be assigned.
   * @param value      the value text
   * @param baseURL    an optional base url
   * @return the CSS-Style-Rule that contains all values for the given text.
   */
  public CSSStyleRule parseStyles(final Map namespaces,
                                  final String name,
                                  final String value,
                                  final ResourceKey baseURL,
                                  final ResourceManager resourceManager,
                                  final StyleKeyRegistry styleKeyRegistry)
  {
    final CSSStyleRule cssStyleRule = new CSSStyleRule(new StyleSheet(), null);
    return parseStyles(namespaces, name, value, baseURL, cssStyleRule, resourceManager, styleKeyRegistry);
  }


  /**
   * Parses a style value. If the style value is a compound key, the
   * corresonding style entries will be added to the style rule.
   *
   * @param namespaces an optional map of known namespaces (prefix -> uri)
   * @param name       the stylekey-name to which the value should be assigned.
   * @param value      the value text
   * @param baseURL    an optional base url
   * @param baseRule   an optional base-rule to which the result gets added.
   * @return the CSS-Style-Rule that contains all values for the given text.
   */
  public CSSStyleRule parseStyles(final Map namespaces,
                                  final String name,
                                  final String value,
                                  final ResourceKey baseURL,
                                  final CSSDeclarationRule baseRule,
                                  final ResourceManager resourceManager,
                                  final StyleKeyRegistry styleKeyRegistry)
  {
    if (name == null)
    {
      throw new NullPointerException("Name is null");
    }
    if (value == null)
    {
      throw new NullPointerException("Value is null");
    }

    try
    {
      final Parser parser = getParser();
      synchronized (parser)
      {
        final StyleSheetHandler handler = new StyleSheetHandler();
        handler.init(styleKeyRegistry, resourceManager, baseURL, -1, null);

        setupNamespaces(namespaces, handler);
        final InputSource source = new InputSource();
        source.setCharacterStream(new StringReader(value));

        handler.initParseContext(source);
        handler.setStyleRule(baseRule);
        parser.setDocumentHandler(handler);
        final LexicalUnit lu = parser.parsePropertyValue(source);
        handler.property(name, lu, false);
        final CSSStyleRule rule = (CSSStyleRule) handler.getStyleRule();

        CSSParserContext.getContext().destroy();
        return rule;
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Returns the initialized parser.
   *
   * @return the parser's local instance.
   * @throws CSSParserInstantiationException
   *          if the parser cannot be instantiated.
   */
  private synchronized Parser getParser()
      throws CSSParserInstantiationException
  {
    if (parser == null)
    {
      parser = CSSParserFactory.getInstance().createCSSParser();
    }
    return parser;
  }

  /**
   * Parses a single namespace identifier. This simply splits the given
   * attribute name when a namespace separator is encountered ('|').
   *
   * @param attrName the attribute name
   * @return the parsed attribute.
   */
  public static String[] parseNamespaceIdent(final String attrName)
  {
    final String name;
    final String namespace;
    final StringTokenizer strtok = new StringTokenizer(attrName, "|");
    final CSSParserContext context = CSSParserContext.getContext();
    // explicitly undefined is different from default namespace..
    // With that construct I definitly violate the standard, but
    // most stylesheets are not yet written with namespaces in mind
    // (and most tools dont support namespaces in CSS).
    //
    // by acknowledging the explicit rule but redefining the rule where
    // no namespace syntax is used at all, I create compatiblity. Still,
    // if the stylesheet does not carry a @namespace rule, this is the same
    // as if the namespace was omited.
    if (strtok.countTokens() == 2)
    {
      final String tkNamespace = strtok.nextToken();
      if (tkNamespace.length() == 0)
      {
        namespace = null;
      }
      else if ("*".equals(tkNamespace))
      {
        namespace = "*";
      }
      else
      {
        namespace = (String)
            context.getNamespaces().get(tkNamespace);
      }
      name = strtok.nextToken();
    }
    else
    {
      name = strtok.nextToken();
      namespace = context.getDefaultNamespace();
    }
    return new String[]{namespace, name};
  }
}
TOP

Related Classes of org.pentaho.reporting.libraries.css.parser.StyleSheetParserUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.