w3c.css.values.CssAttr Maven / Gradle / Ivy
//
// @author Yves Lafon
//
// (c) COPYRIGHT MIT, ERCIM, Keio, Beihang, 2016.
// Please first read the full copyright statement in file COPYRIGHT.html
package org.w3c.css.values;
import org.w3c.css.properties.css.CssProperty;
import org.w3c.css.util.ApplContext;
import org.w3c.css.util.CssVersion;
import org.w3c.css.util.InvalidParamException;
import java.math.BigDecimal;
import java.util.HashMap;
import static org.w3c.css.values.CssOperator.COMMA;
import static org.w3c.css.values.CssOperator.SPACE;
/**
* A CSS Attr.
*
* @spec https://www.w3.org/TR/2015/CR-css-values-3-20150611/#attr-notation
*/
public class CssAttr extends CssCheckableValue {
public static HashMap typeMap;
static {
/* @spec https://www.w3.org/TR/2015/CR-css-values-3-20150611/#typedef-type-or-unit */
typeMap = new HashMap<>();
typeMap.put(CssIdent.getIdent("color"), CssTypes.CSS_COLOR);
typeMap.put(CssIdent.getIdent("string"), CssTypes.CSS_STRING);
typeMap.put(CssIdent.getIdent("url"), CssTypes.CSS_URL);
typeMap.put(CssIdent.getIdent("integer"), CssTypes.CSS_NUMBER);
typeMap.put(CssIdent.getIdent("number"), CssTypes.CSS_NUMBER);
typeMap.put(CssIdent.getIdent("%"), CssTypes.CSS_PERCENTAGE);
// length
String[] _length_tokens = {"length", "em", "ex", "ch", "rem",
"vw", "vh", "vmin", "vmax",
"mm", "cm", "q", "in", "pt", "pc", "px"};
for (String s : _length_tokens) {
typeMap.put(CssIdent.getIdent(s), CssTypes.CSS_LENGTH);
}
// angle
String[] _angle_tokens = {"angle", "deg", "rad", "grad", "turn"};
for (String s : _angle_tokens) {
typeMap.put(CssIdent.getIdent(s), CssTypes.CSS_ANGLE);
}
// time
String[] _time_tokens = {"time", "ms", "s"};
for (String s : _time_tokens) {
typeMap.put(CssIdent.getIdent(s), CssTypes.CSS_TIME);
}
// frequency
String[] _frequency_tokens = {"frequency", "Hz", "kHz"};
for (String s : _frequency_tokens) {
typeMap.put(CssIdent.getIdent(s), CssTypes.CSS_FREQUENCY);
}
}
public static final int type = CssTypes.CSS_ATTR;
public final int getRawType() {
return type;
}
public final int getType() {
if (computed_type == CssTypes.CSS_UNKNOWN) {
return type;
}
return computed_type;
}
ApplContext ac;
int computed_type = CssTypes.CSS_UNKNOWN;
CssValue value = null;
CssValue value_type = null;
CssValue fallback_value = null;
String _ts = null;
/**
* Create a new CssAttr
*/
public CssAttr() {
}
public void set(String s, ApplContext ac) throws InvalidParamException {
// we don't support this way of setting the value
// as we rely on the parsing a CssExpression
throw new InvalidParamException("unrecognize", s, ac);
}
public void setValue(BigDecimal d) {
// we don't support this way of setting the value
// as we rely on the parsing a CssExpression
}
public void setValue(CssExpression exp, ApplContext ac)
throws InvalidParamException {
CssValue val;
char op;
int count = exp.getCount();
// for levels before CSS3, attr only got a single value
if (count > 3 || (count > 1 && ac.getCssVersion().compareTo(CssVersion.CSS3) < 0)) {
throw new InvalidParamException("unrecognize", ac);
}
val = exp.getValue();
op = exp.getOperator();
if (val.getType() != CssTypes.CSS_IDENT) {
throw new InvalidParamException("value",
val.toString(), "attr()", ac);
}
value = val;
// by default we have a Css_String
computed_type = CssTypes.CSS_STRING;
exp.next();
// check the
while (!exp.end()) {
val = exp.getValue();
switch (op) {
case SPACE:
// first we must ensure that we didn't get the fallback value first
if (fallback_value != null || value_type != null) {
throw new InvalidParamException("unrecognize", ac);
}
if (val.getType() == CssTypes.CSS_IDENT) {
computed_type = _checkType((CssIdent) val);
value_type = val;
break;
}
throw new InvalidParamException("value",
val.toString(), "attr()", ac);
case COMMA:
fallback_value = val;
// we should have a computed_type by then.
// let's check the value.
if (fallback_value.getType() != computed_type) {
// deal with percentage and numbers
int fb_type = fallback_value.getType();
if (fb_type == CssTypes.CSS_NUMBER) {
// number can be another type only when its value is zero
fallback_value.getCheckableValue().checkEqualsZero(ac, null);
}
if (fb_type == CssTypes.CSS_PERCENTAGE || fb_type == CssTypes.CSS_NUMBER) {
if ((computed_type == CssTypes.CSS_LENGTH) ||
(computed_type == CssTypes.CSS_ANGLE) ||
(computed_type == CssTypes.CSS_FREQUENCY) ||
(computed_type == CssTypes.CSS_NUMBER) ||
(computed_type == CssTypes.CSS_TIME)) {
break;
}
}
// else, invalid type
throw new InvalidParamException("typevaluemismatch",
fallback_value, value_type, ac);
}
break;
default:
throw new InvalidParamException("operator",
Character.toString(op),
ac);
}
op = exp.getOperator();
exp.next();
}
}
private int _checkType(CssIdent ident)
throws InvalidParamException {
Integer t = typeMap.get(ident);
if (t == null) {
throw new InvalidParamException("invalidtype", ident.toString(), "attr()", ac);
}
return t;
}
/**
* Returns the value
*/
public Object get() {
return toString();
}
public String toString() {
if (_ts == null) {
StringBuilder sb = new StringBuilder();
sb.append("attr(").append(value);
if (value_type != null) {
sb.append(' ').append(value_type);
}
if (fallback_value != null) {
sb.append(", ").append(fallback_value);
}
sb.append(')');
_ts = sb.toString();
}
return _ts;
}
public boolean isInteger() {
return false;
}
/**
* Returns true is the value is positive of null
*
* @return a boolean
*/
public boolean isPositive() {
// TODO do our best...
return false;
}
/**
* Returns true is the value is positive of null
*
* @return a boolean
*/
public boolean isStrictlyPositive() {
return false;
// TODO do our best...
}
/**
* Returns true is the value is zero
*
* @return a boolean
*/
public boolean isZero() {
// TODO do our best...
return false;
}
/**
* Compares two values for equality.
*
* @param value The other value.
*/
public boolean equals(Object value) {
return (value instanceof CssAttr &&
toString().equals(((CssAttr) value).toString()));
}
/**
* check if the value is positive or null
*
* @param ac the validation context
* @param property the property the value is defined in
* @throws org.w3c.css.util.InvalidParamException
*
*/
public void checkPositiveness(ApplContext ac, CssProperty property)
throws InvalidParamException {
// TODO do our best...
if (false /*!isPositive()*/) {
throw new InvalidParamException("negative-value",
toString(), property.getPropertyName(), ac);
}
}
/**
* check if the value is strictly positive
*
* @param ac the validation context
* @param property the property the value is defined in
* @throws org.w3c.css.util.InvalidParamException
*
*/
public void checkStrictPositiveness(ApplContext ac, CssProperty property)
throws InvalidParamException {
// TODO do our best...
if (false/*!isStrictlyPositive()*/) {
throw new InvalidParamException("strictly-positive",
toString(), property.getPropertyName(), ac);
}
}
/**
* check if the value is an integer
*
* @param ac the validation context
* @param property the property the value is defined in
* @throws org.w3c.css.util.InvalidParamException
*
*/
public void checkInteger(ApplContext ac, CssProperty property)
throws InvalidParamException {
// TODO do our best...
if (false/*!isInteger()*/) {
throw new InvalidParamException("integer",
toString(), property.getPropertyName(), ac);
}
}
/**
* warn if the value is not positive or null
*
* @param ac the validation context
* @param property the property the value is defined in
*/
public void warnPositiveness(ApplContext ac, CssProperty property) {
// TODO do our best...
if (false/*!isPositive()*/) {
ac.getFrame().addWarning("negative", toString());
}
}
public CssLength getLength() throws InvalidParamException {
if (computed_type == CssTypes.CSS_LENGTH) {
// TODO fixme...
// we might change this to CssCheckableValue instead.
}
throw new ClassCastException("unknown");
}
public CssPercentage getPercentage() throws InvalidParamException {
if (computed_type == CssTypes.CSS_PERCENTAGE) {
// TODO
}
throw new ClassCastException("unknown");
}
public CssNumber getNumber() throws InvalidParamException {
if (computed_type == CssTypes.CSS_NUMBER) {
//TODO
}
throw new ClassCastException("unknown");
}
public CssTime getTime() throws InvalidParamException {
if (computed_type == CssTypes.CSS_TIME) {
//TODO
}
throw new ClassCastException("unknown");
}
public CssAngle getAngle() throws InvalidParamException {
if (computed_type == CssTypes.CSS_ANGLE) {
//TODO
}
throw new ClassCastException("unknown");
}
public CssFrequency getFrequency() throws InvalidParamException {
if (computed_type == CssTypes.CSS_FREQUENCY) {
//TODO
}
throw new ClassCastException("unknown");
}
/**
* check if the value is equal to zero
*
* @param ac the validation context
* @param property the property the value is defined in
* @throws InvalidParamException
*/
public void checkEqualsZero(ApplContext ac, CssProperty property)
throws InvalidParamException {
// we can't check so we only warn.
// TODO should we do that only for CSS_NUMBER type?
warnEqualsZero(ac, property);
}
/**
* warn if the value is not zero
*
* @param ac the validation context
* @param property the property the value is defined in
*/
public void warnEqualsZero(ApplContext ac, CssProperty property) {
// TODO should we do that only for CSS_NUMBER type?
if (!isZero()) {
ac.getFrame().addWarning("dynamic", toString());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy