/*
* {{{ header & license
* Copyright (c) 2007 Wisconsin Court System
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* }}}
*/
package org.xhtmlrenderer.css.parser.property;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.xhtmlrenderer.css.constants.CSSName;
import org.xhtmlrenderer.css.constants.IdentValue;
import org.xhtmlrenderer.css.parser.CSSParseException;
import org.xhtmlrenderer.css.parser.FSRGBColor;
import org.xhtmlrenderer.css.parser.PropertyValue;
import org.xhtmlrenderer.css.sheet.PropertyDeclaration;
public class BorderPropertyBuilders {
private static abstract class BorderSidePropertyBuilder extends AbstractPropertyBuilder {
protected abstract CSSName[][] getProperties();
private void addAll(List result, CSSName[] properties, CSSPrimitiveValue value, int origin, boolean important) {
for (int i = 0; i < properties.length; i++) {
result.add(new PropertyDeclaration(
properties[i], value, important, origin));
}
}
public List buildDeclarations(
CSSName cssName, List values, int origin, boolean important, boolean inheritAllowed) {
CSSName[][] props = getProperties();
List result = new ArrayList(3);
if (values.size() == 1 &&
((CSSPrimitiveValue)values.get(0)).getCssValueType() == CSSPrimitiveValue.CSS_INHERIT) {
CSSPrimitiveValue value = (CSSPrimitiveValue)values.get(0);
addAll(result, props[0], value, origin, important);
addAll(result, props[1], value, origin, important);
addAll(result, props[2], value, origin, important);
return result;
} else {
checkValueCount(cssName, 1, 3, values.size());
boolean haveBorderStyle = false;
boolean haveBorderColor = false;
boolean haveBorderWidth = false;
for (Iterator i = values.iterator(); i.hasNext(); ) {
CSSPrimitiveValue value = (CSSPrimitiveValue)i.next();
checkInheritAllowed(value, false);
boolean matched = false;
CSSPrimitiveValue borderWidth = convertToBorderWidth(value);
if (borderWidth != null) {
if (haveBorderWidth) {
throw new CSSParseException("A border width cannot be set twice", -1);
}
haveBorderWidth = true;
matched = true;
addAll(result, props[0], borderWidth, origin, important);
}
if (isBorderStyle(value)) {
if (haveBorderStyle) {
throw new CSSParseException("A border style cannot be set twice", -1);
}
haveBorderStyle = true;
matched = true;
addAll(result, props[1], value, origin, important);
}
CSSPrimitiveValue borderColor = convertToBorderColor(value);
if (borderColor != null) {
if (haveBorderColor) {
throw new CSSParseException("A border color cannot be set twice", -1);
}
haveBorderColor = true;
matched = true;
addAll(result, props[2], borderColor, origin, important);
}
if (! matched) {
throw new CSSParseException(value.getCssText() + " is not a border width, style, or color", -1);
}
}
if (! haveBorderWidth) {
addAll(result, props[0], new PropertyValue(IdentValue.FS_INITIAL_VALUE), origin, important);
}
if (! haveBorderStyle) {
addAll(result, props[1], new PropertyValue(IdentValue.FS_INITIAL_VALUE), origin, important);
}
if (! haveBorderColor) {
addAll(result, props[2], new PropertyValue(IdentValue.FS_INITIAL_VALUE), origin, important);
}
return result;
}
}
private boolean isBorderStyle(CSSPrimitiveValue value) {
if (value.getPrimitiveType() != CSSPrimitiveValue.CSS_IDENT) {
return false;
}
IdentValue ident = IdentValue.valueOf(value.getCssText());
if (ident == null) {
return false;
}
return PrimitivePropertyBuilders.BORDER_STYLES.get(ident.FS_ID);
}
private CSSPrimitiveValue convertToBorderWidth(CSSPrimitiveValue value) {
int type = value.getPrimitiveType();
if (type != CSSPrimitiveValue.CSS_IDENT && ! isLength(value)) {
return null;
}
if (isLength(value)) {
return value;
} else {
IdentValue ident = IdentValue.valueOf(value.getStringValue());
if (ident == null) {
return null;
}
if (PrimitivePropertyBuilders.BORDER_WIDTHS.get(ident.FS_ID)) {
return Conversions.getBorderWidth(ident.toString());
} else {
return null;
}
}
}
private CSSPrimitiveValue convertToBorderColor(CSSPrimitiveValue value) {
int type = value.getPrimitiveType();
if (type != CSSPrimitiveValue.CSS_IDENT && type != CSSPrimitiveValue.CSS_RGBCOLOR) {
return null;
}
if (type == CSSPrimitiveValue.CSS_RGBCOLOR) {
return value;
} else {
FSRGBColor color = Conversions.getColor(value.getStringValue());
if (color != null) {
return new PropertyValue(color);
}
IdentValue ident = IdentValue.valueOf(value.getCssText());
if (ident == null || ident != IdentValue.TRANSPARENT) {
return null;
}
return value;
}
}
}
public static class BorderTop extends BorderSidePropertyBuilder {
protected CSSName[][] getProperties() {
return new CSSName[][] {
new CSSName[] { CSSName.BORDER_TOP_WIDTH },
new CSSName[] { CSSName.BORDER_TOP_STYLE },
new CSSName[] { CSSName.BORDER_TOP_COLOR } };
}
}
public static class BorderRight extends BorderSidePropertyBuilder {
protected CSSName[][] getProperties() {
return new CSSName[][] {
new CSSName[] { CSSName.BORDER_RIGHT_WIDTH },
new CSSName[] { CSSName.BORDER_RIGHT_STYLE },
new CSSName[] { CSSName.BORDER_RIGHT_COLOR } };
}
}
public static class BorderBottom extends BorderSidePropertyBuilder {
protected CSSName[][] getProperties() {
return new CSSName[][] {
new CSSName[] { CSSName.BORDER_BOTTOM_WIDTH },
new CSSName[] { CSSName.BORDER_BOTTOM_STYLE },
new CSSName[] { CSSName.BORDER_BOTTOM_COLOR } };
}
}
public static class BorderLeft extends BorderSidePropertyBuilder {
protected CSSName[][] getProperties() {
return new CSSName[][] {
new CSSName[] { CSSName.BORDER_LEFT_WIDTH },
new CSSName[] { CSSName.BORDER_LEFT_STYLE },
new CSSName[] { CSSName.BORDER_LEFT_COLOR } };
}
}
public static class Border extends BorderSidePropertyBuilder {
protected CSSName[][] getProperties() {
return new CSSName[][] {
new CSSName[] {
CSSName.BORDER_TOP_WIDTH, CSSName.BORDER_RIGHT_WIDTH,
CSSName.BORDER_BOTTOM_WIDTH, CSSName.BORDER_LEFT_WIDTH },
new CSSName[] {
CSSName.BORDER_TOP_STYLE, CSSName.BORDER_RIGHT_STYLE,
CSSName.BORDER_BOTTOM_STYLE, CSSName.BORDER_LEFT_STYLE },
new CSSName[] {
CSSName.BORDER_TOP_COLOR, CSSName.BORDER_RIGHT_COLOR,
CSSName.BORDER_BOTTOM_COLOR, CSSName.BORDER_LEFT_COLOR } };
}
}
}