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;
}
}