/*!
* 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.engine.classic.core.style.css;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.style.css.namespaces.DefaultNamespaceCollection;
import org.pentaho.reporting.engine.classic.core.style.css.namespaces.DefaultNamespaceDefinition;
import org.pentaho.reporting.engine.classic.core.style.css.namespaces.NamespaceCollection;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.SelectorList;
import java.io.IOException;
import java.io.StringReader;
import java.util.StringTokenizer;
public class StyleSheetParserUtil {
private static final StyleSheetParserUtil instance = new StyleSheetParserUtil();
private DefaultNamespaceCollection namespaceCollection;
public static StyleSheetParserUtil getInstance() {
return instance;
}
private StyleSheetParserUtil() {
namespaceCollection = new DefaultNamespaceCollection();
addNamespaceDefinition( AttributeNames.Html.NAMESPACE, "html" );
addNamespaceDefinition( AttributeNames.Core.NAMESPACE, AttributeNames.Core.STYLE_CLASS, "core" );
addNamespaceDefinition( AttributeNames.Pdf.NAMESPACE, "pdf" );
addNamespaceDefinition( AttributeNames.Crosstab.NAMESPACE, "crosstab" );
addNamespaceDefinition( AttributeNames.Excel.NAMESPACE, "excel" );
addNamespaceDefinition( AttributeNames.Swing.NAMESPACE, "action" );
addNamespaceDefinition( AttributeNames.Internal.NAMESPACE, "internal" );
addNamespaceDefinition( AttributeNames.Wizard.NAMESPACE, "wizard" );
addNamespaceDefinition( AttributeNames.Pentaho.NAMESPACE, "pentaho" );
addNamespaceDefinition( AttributeNames.Table.NAMESPACE, "table" );
addNamespaceDefinition( AttributeNames.Xml.NAMESPACE, "xml" );
namespaceCollection.setDefaultNamespaceURI( AttributeNames.Core.NAMESPACE );
}
public void addNamespaceDefinition( final String uri, final String preferredPrefix ) {
namespaceCollection.addDefinition( new DefaultNamespaceDefinition( uri, null, null, null, preferredPrefix ) );
}
public void addNamespaceDefinition( final String uri, final String classAttribute, final String preferredPrefix ) {
namespaceCollection
.addDefinition( new DefaultNamespaceDefinition( uri, null, classAttribute, null, preferredPrefix ) );
}
public void addNamespaceDefinition( final String uri, final ResourceKey defaultStyleSheet,
final String classAttribute, final String styleAttribute, final String preferredPrefix ) {
namespaceCollection.addDefinition( new DefaultNamespaceDefinition( uri, defaultStyleSheet, classAttribute,
styleAttribute, preferredPrefix ) );
}
public NamespaceCollection getNamespaceCollection() {
return namespaceCollection;
}
/**
* 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 String[] parseNamespaceIdent( final String attrName, final NamespaceCollection namespaceCollection ) {
final String name;
final String namespace;
final StringTokenizer strtok = new StringTokenizer( attrName, "|" );
// explicitly undefined is different from default namespace..
// With that construct I definitely 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 compatibility. Still,
// if the stylesheet does not carry a @namespace rule, this is the same
// as if the namespace was omitted.
if ( strtok.countTokens() == 2 ) {
final String tkNamespace = strtok.nextToken();
if ( tkNamespace.length() == 0 ) {
namespace = null;
} else if ( "*".equals( tkNamespace ) ) {
namespace = "*";
} else {
namespace = namespaceCollection.lookupNamespaceURI( tkNamespace );
}
name = strtok.nextToken();
} else {
name = strtok.nextToken();
namespace = null;
}
return new String[] { namespace, name };
}
public SelectorList parseSelector( final NamespaceCollection nc, final String selectorText ) throws CSSParseException {
try {
return CSSParserFactory.getInstance().createCSSParser( nc ).parseSelectors(
new InputSource( new StringReader( selectorText ) ) );
} catch ( CSSException e ) {
throw new CSSParseException( "Failed to parse selector", e );
} catch ( InstantiationException e ) {
throw new CSSParseException( "Failed to instantiate CSS parser", e );
} catch ( IOException e ) {
throw new CSSParseException( "IO error while parsing selector", e );
}
}
}