/* * $Id: CSSValueImpl.java,v 1.3 2008/03/26 02:08:55 sdanig Exp $ * * CSS Parser Project * * Copyright (C) 1999-2005 David Schweinsberg. All rights reserved. * * This library 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 of the License, or (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * To contact the authors of the library: * * http://cssparser.sourceforge.net/ * mailto:davidsch@users.sourceforge.net */ package com.steadystate.css.dom; import java.io.Serializable; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.w3c.css.sac.InputSource; import org.w3c.css.sac.LexicalUnit; import org.w3c.css.sac.Locator; import org.w3c.dom.DOMException; import org.w3c.dom.css.Counter; import org.w3c.dom.css.CSSPrimitiveValue; import org.w3c.dom.css.CSSValue; import org.w3c.dom.css.CSSValueList; import org.w3c.dom.css.Rect; import org.w3c.dom.css.RGBColor; import com.steadystate.css.parser.CSSOMParser; import com.steadystate.css.parser.LexicalUnitImpl; import com.steadystate.css.userdata.UserDataConstants; /** * The <code>CSSValueImpl</code> class can represent either a * <code>CSSPrimitiveValue</code> or a <code>CSSValueList</code> so that * the type can successfully change when using <code>setCssText</code>. * * TODO: * Float unit conversions, * A means of checking valid primitive types for properties * * @author <a href="mailto:davidsch@users.sourceforge.net">David Schweinsberg</a> * @version $Id: CSSValueImpl.java,v 1.3 2008/03/26 02:08:55 sdanig Exp $ */ public class CSSValueImpl extends CSSOMObjectImpl implements CSSPrimitiveValue, CSSValueList, Serializable { private static final long serialVersionUID = 406281136418322579L; private Object _value = null; public Object getValue() { return this._value; } public void setValue(Object value) { this._value = value; } /** * Constructor */ public CSSValueImpl(LexicalUnit value, boolean forcePrimitive) { if (!forcePrimitive && (value.getNextLexicalUnit() != null)) { this._value = this.getValues(value); } else if (value.getParameters() != null) { if (value.getLexicalUnitType() == LexicalUnit.SAC_RECT_FUNCTION) { // Rect this._value = new RectImpl(value.getParameters()); } else if (value.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR) { // RGBColor this._value = new RGBColorImpl(value.getParameters()); } else if (value.getLexicalUnitType() == LexicalUnit.SAC_COUNTER_FUNCTION) { // Counter this._value = new CounterImpl(false, value.getParameters()); } else if (value.getLexicalUnitType() == LexicalUnit.SAC_COUNTERS_FUNCTION) { // Counter this._value = new CounterImpl(true, value.getParameters()); } else { this._value = value; } } else { // We need to be a CSSPrimitiveValue this._value = value; } if (value instanceof LexicalUnitImpl) { Locator locator = ((LexicalUnitImpl) value).getLocator(); if (locator != null) { this.setUserData(UserDataConstants.KEY_LOCATOR, locator); } } } public CSSValueImpl() { } private List<CSSValueImpl> getValues(LexicalUnit value) { // We need to be a CSSValueList // Values in an "expr" can be seperated by "operator"s, which are // either '/' or ',' - ignore these operators List<CSSValueImpl> values = new ArrayList<CSSValueImpl>(); LexicalUnit lu = value; while (lu != null) { if ((lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) && (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_SLASH)) { values.add(new CSSValueImpl(lu, true)); } lu = lu.getNextLexicalUnit(); } return values; } public CSSValueImpl(LexicalUnit value) { this(value, false); } public String getCssText() { if (getCssValueType() == CSS_VALUE_LIST) { // Create the string from the LexicalUnits so we include the correct // operators in the string StringBuilder sb = new StringBuilder(); List list = (List) this._value; java.util.Iterator it = list.iterator(); while (it.hasNext()) { Object o = it.next(); if (o instanceof LexicalUnit) { LexicalUnit lu = (LexicalUnit) ((CSSValueImpl) list.get(0))._value; while (lu != null) { sb.append(lu.toString()); // Step to the next lexical unit, determining what spacing we // need to put around the operators LexicalUnit prev = lu; lu = lu.getNextLexicalUnit(); if ((lu != null) && (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) && (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_SLASH) && (prev.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_SLASH)) { sb.append(" "); } } } else { sb.append(o); } if (it.hasNext()) { sb.append(" "); } } return sb.toString(); } return this._value.toString(); } public void setCssText(String cssText) throws DOMException { try { InputSource is = new InputSource(new StringReader(cssText)); CSSOMParser parser = new CSSOMParser(); CSSValueImpl v2 = (CSSValueImpl) parser.parsePropertyValue(is); this._value = v2._value; } catch (Exception e) { throw new DOMExceptionImpl( DOMException.SYNTAX_ERR, DOMExceptionImpl.SYNTAX_ERROR, e.getMessage() ); } } public short getCssValueType() { if (this._value instanceof List) { return CSS_VALUE_LIST; } else if ((this._value instanceof LexicalUnit) && (((LexicalUnit) this._value).getLexicalUnitType() == LexicalUnit.SAC_INHERIT)) { return CSS_INHERIT; } return CSS_PRIMITIVE_VALUE; } public short getPrimitiveType() { if (this._value instanceof LexicalUnit) { LexicalUnit lu = (LexicalUnit) this._value; switch (lu.getLexicalUnitType()) { case LexicalUnit.SAC_INHERIT: return CSS_IDENT; case LexicalUnit.SAC_INTEGER: case LexicalUnit.SAC_REAL: return CSS_NUMBER; case LexicalUnit.SAC_EM: return CSS_EMS; case LexicalUnit.SAC_EX: return CSS_EXS; case LexicalUnit.SAC_PIXEL: return CSS_PX; case LexicalUnit.SAC_INCH: return CSS_IN; case LexicalUnit.SAC_CENTIMETER: return CSS_CM; case LexicalUnit.SAC_MILLIMETER: return CSS_MM; case LexicalUnit.SAC_POINT: return CSS_PT; case LexicalUnit.SAC_PICA: return CSS_PC; case LexicalUnit.SAC_PERCENTAGE: return CSS_PERCENTAGE; case LexicalUnit.SAC_URI: return CSS_URI; // case LexicalUnit.SAC_COUNTER_FUNCTION: // case LexicalUnit.SAC_COUNTERS_FUNCTION: // return CSS_COUNTER; // case LexicalUnit.SAC_RGBCOLOR: // return CSS_RGBCOLOR; case LexicalUnit.SAC_DEGREE: return CSS_DEG; case LexicalUnit.SAC_GRADIAN: return CSS_GRAD; case LexicalUnit.SAC_RADIAN: return CSS_RAD; case LexicalUnit.SAC_MILLISECOND: return CSS_MS; case LexicalUnit.SAC_SECOND: return CSS_S; case LexicalUnit.SAC_HERTZ: return CSS_KHZ; case LexicalUnit.SAC_KILOHERTZ: return CSS_HZ; case LexicalUnit.SAC_IDENT: return CSS_IDENT; case LexicalUnit.SAC_STRING_VALUE: return CSS_STRING; case LexicalUnit.SAC_ATTR: return CSS_ATTR; // case LexicalUnit.SAC_RECT_FUNCTION: // return CSS_RECT; case LexicalUnit.SAC_UNICODERANGE: case LexicalUnit.SAC_SUB_EXPRESSION: case LexicalUnit.SAC_FUNCTION: return CSS_STRING; case LexicalUnit.SAC_DIMENSION: return CSS_DIMENSION; } } else if (this._value instanceof RectImpl) { return CSS_RECT; } else if (this._value instanceof RGBColorImpl) { return CSS_RGBCOLOR; } else if (this._value instanceof CounterImpl) { return CSS_COUNTER; } return CSS_UNKNOWN; } public void setFloatValue(short unitType, float floatValue) throws DOMException { this._value = LexicalUnitImpl.createNumber(null, floatValue); } public float getFloatValue(short unitType) throws DOMException { if (this._value instanceof LexicalUnit) { LexicalUnit lu = (LexicalUnit) this._value; return lu.getFloatValue(); } throw new DOMExceptionImpl( DOMException.INVALID_ACCESS_ERR, DOMExceptionImpl.FLOAT_ERROR); // We need to attempt a conversion // return 0; } public void setStringValue(short stringType, String stringValue) throws DOMException { switch (stringType) { case CSS_STRING: this._value = LexicalUnitImpl.createString(null, stringValue); break; case CSS_URI: this._value = LexicalUnitImpl.createURI(null, stringValue); break; case CSS_IDENT: this._value = LexicalUnitImpl.createIdent(null, stringValue); break; case CSS_ATTR: // this._value = LexicalUnitImpl.createAttr(null, stringValue); // break; throw new DOMExceptionImpl( DOMException.NOT_SUPPORTED_ERR, DOMExceptionImpl.NOT_IMPLEMENTED); default: throw new DOMExceptionImpl( DOMException.INVALID_ACCESS_ERR, DOMExceptionImpl.STRING_ERROR); } } /** * TODO: return a value for a list type */ public String getStringValue() throws DOMException { if (this._value instanceof LexicalUnit) { LexicalUnit lu = (LexicalUnit) this._value; if ((lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT) || (lu.getLexicalUnitType() == LexicalUnit.SAC_STRING_VALUE) || (lu.getLexicalUnitType() == LexicalUnit.SAC_URI) || (lu.getLexicalUnitType() == LexicalUnit.SAC_INHERIT)) { return lu.getStringValue(); } else if (lu.getLexicalUnitType() == LexicalUnit.SAC_ATTR) { return lu.getParameters().getStringValue(); } } else if (this._value instanceof List) { return null; } throw new DOMExceptionImpl( DOMException.INVALID_ACCESS_ERR, DOMExceptionImpl.STRING_ERROR); } public Counter getCounterValue() throws DOMException { if ((this._value instanceof Counter) == false) { throw new DOMExceptionImpl( DOMException.INVALID_ACCESS_ERR, DOMExceptionImpl.COUNTER_ERROR); } return (Counter) this._value; } public Rect getRectValue() throws DOMException { if ((this._value instanceof Rect) == false) { throw new DOMExceptionImpl( DOMException.INVALID_ACCESS_ERR, DOMExceptionImpl.RECT_ERROR); } return (Rect) this._value; } public RGBColor getRGBColorValue() throws DOMException { if ((this._value instanceof RGBColor) == false) { throw new DOMExceptionImpl( DOMException.INVALID_ACCESS_ERR, DOMExceptionImpl.RGBCOLOR_ERROR); } return (RGBColor) this._value; } public int getLength() { return (this._value instanceof List) ? ((List)this._value).size() : 0; } public CSSValue item(int index) { return (this._value instanceof List) ? ((CSSValue)((List)this._value).get(index)) : null; } public String toString() { return getCssText(); } }