/*!
* 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.model;
import java.util.Arrays;
import org.pentaho.reporting.libraries.css.parser.StyleSheetParserUtil;
import org.pentaho.reporting.libraries.css.values.CSSValue;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
/**
* This class is a merger between the CSSStyleDeclaration and the other
* stylerule classes holding property name pairs. Actually, this is what once
* was called a stylesheet in JFreeReport.
* <p/>
* StyleProperties are key as Strings and have CSSValues as mapped values..
*
* @author Thomas Morgner
*/
public abstract class CSSDeclarationRule extends StyleRule
{
private CSSValue[] styleValues;
private boolean[] importantValues;
private StyleSheetParserUtil styleSheetParserUtil;
protected CSSDeclarationRule(final StyleSheet parentStyle,
final StyleRule parentRule)
{
super(parentStyle, parentRule);
}
public boolean isImportant(StyleKey propertyName)
{
if (propertyName == null)
{
throw new NullPointerException();
}
if (importantValues == null)
{
return false;
}
return importantValues[propertyName.index];
}
protected void setImportant(StyleKey propertyName, final boolean important)
{
if (propertyName == null)
{
throw new NullPointerException();
}
if (importantValues == null)
{
final StyleKeyRegistry styleKeyRegistry = getStyleKeyRegistry();
importantValues = new boolean[styleKeyRegistry.getKeyCount()];
}
importantValues[propertyName.index] = important;
}
public CSSValue getPropertyCSSValue(StyleKey propertyName)
{
if (propertyName == null)
{
throw new NullPointerException();
}
if (styleValues == null)
{
return null;
}
return styleValues[propertyName.index];
}
/**
* Parses the given value for the stylekey. As stylekeys are only defined for
* atomic style declarations, this method will only affect a single name-value
* pair.
*
* @param styleKey
* @param value
*/
public void setPropertyValueAsString(final StyleKey styleKey,
final String value)
{
final StyleSheet parentStyle = getParentStyle();
final ResourceKey source;
if (parentStyle == null)
{
source = null;
}
else
{
source = parentStyle.getSource();
}
if (styleSheetParserUtil == null)
{
styleSheetParserUtil = new StyleSheetParserUtil();
}
final StyleSheet parent = getParentStyle();
final CSSStyleRule cssValues;
if (parent != null)
{
cssValues = styleSheetParserUtil.parseStyles
(parent.getNamespaces(), styleKey.getName(), value, source,
parent.getResourceManager(), StyleKeyRegistry.getRegistry());
}
else
{
final ResourceManager resourceManager = new ResourceManager();
resourceManager.registerDefaults();
cssValues = styleSheetParserUtil.parseStyles
(null, styleKey.getName(), value, source, resourceManager, StyleKeyRegistry.getRegistry());
}
if (cssValues != null)
{
if (cssValues.isEmpty())
{
return;
}
final boolean[] importantFlags = cssValues.getImportantValues();
final CSSValue[] values = cssValues.getStyleValues();
final StyleKey[] keys = cssValues.getPropertyKeysAsArray();
for (int i = 0; i < values.length; i++)
{
final CSSValue cssValue = values[i];
if (cssValue != null)
{
setPropertyValue(keys[i], cssValue, importantFlags[i]);
}
}
}
}
public void setPropertyValue(StyleKey propertyName, CSSValue value)
{
setPropertyValue(propertyName, value, false);
}
public void setPropertyValue(StyleKey propertyName, CSSValue value, boolean important)
{
if (styleValues == null)
{
final StyleKeyRegistry styleKeyRegistry = getStyleKeyRegistry();
styleValues = new CSSValue[styleKeyRegistry.getKeyCount()];
}
styleValues[propertyName.index] = value;
setImportant(propertyName, important);
}
public void removeProperty(StyleKey name)
{
if (styleValues == null)
{
return;
}
setPropertyValue(name, null);
}
public void clear()
{
if (styleValues != null)
{
Arrays.fill(styleValues, null);
}
if (importantValues != null)
{
Arrays.fill(importantValues, false);
}
}
public StyleKey[] getPropertyKeysAsArray()
{
return getStyleKeyRegistry().getKeys();
}
public CSSValue[] getStyleValues()
{
if (styleValues == null)
{
final StyleKeyRegistry styleKeyRegistry = getStyleKeyRegistry();
styleValues = new CSSValue[styleKeyRegistry.getKeyCount()];
}
return (CSSValue[]) styleValues.clone();
}
public boolean[] getImportantValues()
{
if (importantValues == null)
{
importantValues = new boolean[getStyleKeyRegistry().getKeyCount()];
}
return (boolean[]) importantValues.clone();
}
public Object clone() throws CloneNotSupportedException
{
final CSSDeclarationRule rule = (CSSDeclarationRule) super.clone();
if (importantValues != null)
{
rule.importantValues = (boolean[]) importantValues.clone();
}
if (styleValues != null)
{
rule.styleValues = (CSSValue[]) styleValues.clone();
}
return rule;
}
public boolean isEmpty()
{
return importantValues == null && styleValues == null;
}
}