com.steadystate.css.dom.CSSValueImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cssparser Show documentation
Show all versions of cssparser Show documentation
A CSS parser which implements SAC (the Simple API for CSS).
/*
* Copyright (C) 1999-2018 David Schweinsberg.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.steadystate.css.dom;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
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.CSSPrimitiveValue;
import org.w3c.dom.css.CSSValue;
import org.w3c.dom.css.CSSValueList;
import org.w3c.dom.css.Counter;
import org.w3c.dom.css.RGBColor;
import org.w3c.dom.css.Rect;
import com.steadystate.css.format.CSSFormat;
import com.steadystate.css.format.CSSFormatable;
import com.steadystate.css.parser.CSSOMParser;
import com.steadystate.css.parser.LexicalUnitImpl;
import com.steadystate.css.userdata.UserDataConstants;
import com.steadystate.css.util.LangUtils;
/**
* The CSSValueImpl
class can represent either a
* CSSPrimitiveValue
or a CSSValueList
so that
* the type can successfully change when using setCssText
.
*
* TODO:
* Float unit conversions,
* A means of checking valid primitive types for properties
*
* @author David Schweinsberg
* @author rbri
*/
public class CSSValueImpl extends CSSOMObjectImpl implements CSSPrimitiveValue, CSSValueList, CSSFormatable {
private static final long serialVersionUID = 406281136418322579L;
private Object value_;
public Object getValue() {
return value_;
}
public void setValue(final Object value) {
value_ = value;
}
/**
* Constructor
*/
public CSSValueImpl(final LexicalUnit value, final boolean forcePrimitive) {
LexicalUnit parameters = null;
try {
parameters = value.getParameters();
}
catch (final IllegalStateException e) {
// Batik SAC parser throws IllegalStateException in some cases
}
if (!forcePrimitive && (value.getNextLexicalUnit() != null)) {
value_ = getValues(value);
}
else if (parameters != null) {
if (value.getLexicalUnitType() == LexicalUnit.SAC_RECT_FUNCTION) {
// Rect
value_ = new RectImpl(value.getParameters());
}
else if (value.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR) {
// RGBColor
value_ = new RGBColorImpl(value.getParameters());
}
else if (value.getLexicalUnitType() == LexicalUnit.SAC_COUNTER_FUNCTION) {
// Counter
value_ = new CounterImpl(false, value.getParameters());
}
else if (value.getLexicalUnitType() == LexicalUnit.SAC_COUNTERS_FUNCTION) {
// Counter
value_ = new CounterImpl(true, value.getParameters());
}
else {
value_ = value;
}
}
else {
// We need to be a CSSPrimitiveValue
value_ = value;
}
if (value instanceof LexicalUnitImpl) {
final Locator locator = ((LexicalUnitImpl) value).getLocator();
if (locator != null) {
setUserData(UserDataConstants.KEY_LOCATOR, locator);
}
}
}
public CSSValueImpl() {
super();
}
private List getValues(final LexicalUnit value) {
final List values = new ArrayList();
LexicalUnit lu = value;
while (lu != null) {
values.add(new CSSValueImpl(lu, true));
lu = lu.getNextLexicalUnit();
}
return values;
}
public CSSValueImpl(final LexicalUnit value) {
this(value, false);
}
public String getCssText() {
return getCssText(null);
}
/**
* {@inheritDoc}
*/
public String getCssText(final CSSFormat format) {
if (getCssValueType() == CSS_VALUE_LIST) {
// Create the string from the LexicalUnits so we include the correct
// operators in the string
final StringBuilder sb = new StringBuilder();
final List> list = (List>) value_;
final Iterator> it = list.iterator();
boolean separate = false;
while (it.hasNext()) {
final Object o = it.next();
final CSSValueImpl cssValue = (CSSValueImpl) o;
if (separate) {
if (cssValue.value_ instanceof LexicalUnit) {
final LexicalUnit lu = (LexicalUnit) cssValue.value_;
if (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
sb.append(" ");
}
}
else {
sb.append(" ");
}
}
if (cssValue.value_ instanceof CSSFormatable) {
sb.append(((CSSFormatable) o).getCssText(format));
}
else {
sb.append(o.toString());
}
separate = true;
}
return sb.toString();
}
if (value_ instanceof CSSFormatable) {
return ((CSSFormatable) value_).getCssText(format);
}
return value_ != null ? value_.toString() : "";
}
public void setCssText(final String cssText) throws DOMException {
try {
final InputSource is = new InputSource(new StringReader(cssText));
final CSSOMParser parser = new CSSOMParser();
final CSSValueImpl v2 = (CSSValueImpl) parser.parsePropertyValue(is);
value_ = v2.value_;
setUserDataMap(v2.getUserDataMap());
}
catch (final Exception e) {
throw new DOMExceptionImpl(
DOMException.SYNTAX_ERR,
DOMExceptionImpl.SYNTAX_ERROR,
e.getMessage());
}
}
public short getCssValueType() {
if (value_ instanceof List) {
return CSS_VALUE_LIST;
}
if ((value_ instanceof LexicalUnit)
&& (((LexicalUnit) value_).getLexicalUnitType() == LexicalUnit.SAC_INHERIT)) {
return CSS_INHERIT;
}
return CSS_PRIMITIVE_VALUE;
}
public short getPrimitiveType() {
if (value_ instanceof LexicalUnit) {
final LexicalUnit lu = (LexicalUnit) 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_HZ;
case LexicalUnit.SAC_KILOHERTZ:
return CSS_KHZ;
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;
default:
return CSS_UNKNOWN;
}
}
else if (value_ instanceof RectImpl) {
return CSS_RECT;
}
else if (value_ instanceof RGBColorImpl) {
return CSS_RGBCOLOR;
}
else if (value_ instanceof CounterImpl) {
return CSS_COUNTER;
}
return CSS_UNKNOWN;
}
public void setFloatValue(final short unitType, final float floatValue) throws DOMException {
value_ = LexicalUnitImpl.createNumber(null, floatValue);
}
public float getFloatValue(final short unitType) throws DOMException {
if (value_ instanceof LexicalUnit) {
final LexicalUnit lu = (LexicalUnit) 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(final short stringType, final String stringValue) throws DOMException {
switch (stringType) {
case CSS_STRING:
value_ = LexicalUnitImpl.createString(null, stringValue);
break;
case CSS_URI:
value_ = LexicalUnitImpl.createURI(null, stringValue);
break;
case CSS_IDENT:
value_ = LexicalUnitImpl.createIdent(null, stringValue);
break;
case CSS_ATTR:
// _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 (value_ instanceof LexicalUnit) {
final LexicalUnit lu = (LexicalUnit) value_;
if ((lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT)
|| (lu.getLexicalUnitType() == LexicalUnit.SAC_STRING_VALUE)
|| (lu.getLexicalUnitType() == LexicalUnit.SAC_URI)
|| (lu.getLexicalUnitType() == LexicalUnit.SAC_INHERIT)
|| (lu.getLexicalUnitType() == LexicalUnit.SAC_ATTR)) {
return lu.getStringValue();
}
// for rgba values we are using this type
if (lu.getLexicalUnitType() == LexicalUnit.SAC_FUNCTION) {
return lu.toString();
}
}
else if (value_ instanceof List) {
return null;
}
throw new DOMExceptionImpl(
DOMException.INVALID_ACCESS_ERR,
DOMExceptionImpl.STRING_ERROR);
}
public Counter getCounterValue() throws DOMException {
if (value_ instanceof Counter) {
return (Counter) value_;
}
throw new DOMExceptionImpl(
DOMException.INVALID_ACCESS_ERR,
DOMExceptionImpl.COUNTER_ERROR);
}
public Rect getRectValue() throws DOMException {
if (value_ instanceof Rect) {
return (Rect) value_;
}
throw new DOMExceptionImpl(
DOMException.INVALID_ACCESS_ERR,
DOMExceptionImpl.RECT_ERROR);
}
public RGBColor getRGBColorValue() throws DOMException {
if (value_ instanceof RGBColor) {
return (RGBColor) value_;
}
throw new DOMExceptionImpl(
DOMException.INVALID_ACCESS_ERR,
DOMExceptionImpl.RGBCOLOR_ERROR);
}
@SuppressWarnings("unchecked")
public int getLength() {
if (value_ instanceof List) {
return ((List) value_).size();
}
return 0;
}
@SuppressWarnings("unchecked")
public CSSValue item(final int index) {
if (value_ instanceof List) {
final List list = (List) value_;
return list.get(index);
}
return null;
}
@Override
public String toString() {
return getCssText(null);
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CSSValue)) {
return false;
}
final CSSValue cv = (CSSValue) obj;
// TODO to be improved!
return super.equals(obj)
&& (getCssValueType() == cv.getCssValueType())
&& LangUtils.equals(getCssText(), cv.getCssText());
}
@Override
public int hashCode() {
int hash = super.hashCode();
hash = LangUtils.hashCode(hash, value_);
return hash;
}
}