TimeConditionParserpublic class TimeConditionParser extends ClockParser Parser for SVG time condition values, as defined in the SVG specification
for timing attributes:
http://www.w3.org/TR/SVG11/animate.html#TimingAttributes |
Fields Summary |
---|
private Vector | conditionsThe list of time conditions being parsed. | private boolean | isBeginIf true, a "begin" attribute is being parsed; otherwise, an "end"
attribute is being parsed. | private com.sun.perseus.model.TimedElementNode | tenThe TimedElementNode for the attribute being parsed. | private com.sun.perseus.model.TimedElementSupport | tesThe TimedElementSupport for the TimedElementNode associated with
the attribute being parsed. |
Methods Summary |
---|
public static final boolean | isLetterOrDigit(char c)Do not use Character.isLetterOrDigit because it is not supported on
all Java platforms.
return (Character.isDigit(c) || Character.isUpperCase(c) || Character.isLowerCase(c));
| protected final void | parseAccessKey()Parses an accessKey time condition. The current character is assumed
to be the first character after "accesskey(". If parsing is successful,
an AccessKeyCondition is added to the list of time conditions and the
current character is the character that immediately follows the
access key value (either the ')' or the optional offset).
// parse access key character (followed by ')')
if ((current == -1) || (current == ')")) {
throw new IllegalArgumentException();
}
char accesskey = (char) current;
current = read();
if (current != ')") {
throw new IllegalArgumentException();
}
// parse whitespace followed by optional offset
current = read();
skipSpaces();
long offset = parseOptionalOffset();
conditions.addElement(new AccessKeyCondition(tes, isBegin,
offset, accesskey));
| public com.sun.perseus.model.TimeCondition[] | parseBeginEndAttribute(java.lang.String attrValue, com.sun.perseus.model.TimedElementNode ten, boolean isBegin)Parses a begin/end timing attribute value. This method throws an
IllegalArgumentException if the input argument's
syntax does not conform to that of a clock value, as defined
by the SVG animate tag specification.
setString(attrValue);
if (attrValue.length() == 0) {
throw new IllegalArgumentException();
}
this.conditions = new Vector();
this.ten = ten;
this.tes = ten.getTimedElementSupport();
this.isBegin = isBegin;
loop: for (;;) {
// parse leading whitespace
current = read();
skipSpaces();
m1: switch (current) {
case ';":
throw new IllegalArgumentException();
case -1:
if (isBegin && (conditions.size() == 0)) {
// an empty begin attribute maps to offset(0)
conditions.addElement(new OffsetCondition(tes, isBegin, 0L));
}
break loop;
case '+": case '-":
case '0": case '1": case '2": case '3": case '4":
case '5": case '6": case '7": case '8": case '9":
parseOffset();
break m1;
default:
if (currentStartsWith("accessKey(")) {
parseAccessKey();
} else if (currentStartsWith("repeat(")) {
parseRepeat(null);
} else if (currentStartsWith("indefinite")) {
// indefinite maps to no time condition
break m1;
} else {
parseOther();
}
break m1;
}
// parse trailing whitespace (current should point to the character
// just following the last time condition)
skipSpaces();
// detect ';' separator, or -1
m2: switch (current) {
case ';":
break m2;
case -1:
break loop;
default:
throw new IllegalArgumentException();
}
}
TimeCondition[] ret = new TimeCondition[conditions.size()];
conditions.copyInto(ret);
return ret;
| protected final void | parseEvent(java.lang.String id, java.lang.String eventType)Parses an event base time condition. If id is
null , the event base id will be "unspecified", and the
eventType is assumed to be non-null (the current character
is assumed to be the first character after the event type). If
eventType is null , the event type will be
parsed (the current character is assumed to be the first character after
the event base id and dot, e.g. "foo.").
If parsing is successful, an EventBaseCondition is added to the list
of time conditions and the current character is the character that
immediately follows the event base value (either the id, eventType,
or the optional offset).
if (eventType == null) {
StringBuffer etbuf = new StringBuffer();
loop: for (;;) {
switch (current) {
case '\\":
// skip escape characters
current = read();
switch (current) {
case '.":
case '-":
case '_":
etbuf.append((char) current);
break;
default:
if (isLetterOrDigit((char) current)) {
etbuf.append((char) current);
} else {
throw new IllegalArgumentException();
}
break;
}
break;
case '.":
throw new IllegalArgumentException();
case '+":
case '-":
case ';":
case -1:
if (etbuf.length() == 0) {
throw new IllegalArgumentException();
}
eventType = etbuf.toString();
break loop;
case 0x20:
case 0x09:
case 0x0D:
case 0x0A:
skipSpaces();
switch (current) {
case '+":
case '-":
case ';":
case -1:
// no id, must be an event
if (etbuf.length() == 0) {
throw new IllegalArgumentException();
}
eventType = etbuf.toString();
break loop;
default:
throw new IllegalArgumentException();
}
default:
etbuf.append((char) current);
break;
}
current = read();
}
}
// parse optional offset (whitespace has already been parsed)
long offset = parseOptionalOffset();
conditions.addElement(new EventBaseCondition(tes, isBegin,
id, toDOMEventType(eventType),
offset));
| protected final void | parseOffset()Parses an offset time condition. The current character is assumed
to be '+', '-', or a numeral. If parsing is successful, an
OffsetCondition is added to the list of time conditions and the
current character is the character that immediately follows the offset
value.
long offset = parseSignedClockValue();
conditions.addElement(new OffsetCondition(tes, isBegin, offset));
| protected final long | parseOptionalOffset()Parses an optional offset value. If the current character is a sign
value ('+' or '-'), the offset value is parsed and returned as a long
value. If the offset value is not present (current is
';' or -1), this method returns zero. If some other character is
encountered, an IllegalArgumentException is thrown.
long offset = 0L;
switch (current) {
case '+": case '-":
offset = parseSignedClockValue();
break;
case ';":
case -1:
break;
default:
throw new IllegalArgumentException("Unsupported character in optional offset value: " + ((char) current));
}
return offset;
| protected final void | parseOther()Parses a time condition with an optional id prefix. Delegates to one
of the other parse*() methods, depending on whether the
string matches a repeat, syncbase, or event time condition.
StringBuffer idbuf = new StringBuffer();
String id = null;
String eventType = null;
loopid: for (;;) {
switch (current) {
case '\\":
// skip escape characters
current = read();
switch (current) {
case '.":
case '-":
case '_":
idbuf.append((char) current);
break;
default:
if (isLetterOrDigit((char) current)) {
idbuf.append((char) current);
} else {
throw new IllegalArgumentException();
}
break;
}
break;
case '.":
if (idbuf.length() == 0) {
throw new IllegalArgumentException();
}
id = idbuf.toString();
current = read();
break loopid;
case '+":
case '-":
case ';":
case -1:
// no id, must be an event (we will never enter this method
// with one of these characters as the current character, so
// idbuf will always have a non-zero length at this point)
eventType = idbuf.toString();
break loopid;
case 0x20:
case 0x09:
case 0x0D:
case 0x0A:
skipSpaces();
switch (current) {
case '+":
case '-":
case ';":
case -1:
// no id, must be an event (we will never enter this method
// with one of these characters as the current character,
// so idbuf will always have a non-zero length at this
// point)
eventType = idbuf.toString();
break loopid;
default:
throw new IllegalArgumentException();
}
default:
idbuf.append((char) current);
break;
}
current = read();
}
if (id != null) {
if (currentStartsWith("repeat(")) {
parseRepeat(id);
} else if (currentStartsWith("begin")) {
parseSyncBase(id, true);
} else if (currentStartsWith("end")) {
parseSyncBase(id, false);
} else {
parseEvent(id, null);
}
} else {
parseEvent(null, eventType);
}
| protected final void | parseRepeat(java.lang.String id)Parses a repeat time condition. The current character is assumed
to be the first character after "repeat(". If parsing is successful,
a RepeatCondition is added to the list of time conditions and the
current character is the character that immediately follows the
repeat value (either the ')' or the optional offset).
// parse iteration value (followed by ')')
int repeatCount = 0;
loop: for (;;) {
switch (current) {
case '0": case '1": case '2": case '3": case '4":
case '5": case '6": case '7": case '8": case '9":
repeatCount = repeatCount * 10 + (current - '0");
break;
case ')":
break loop;
default:
throw new IllegalArgumentException("Illegal character in repeat condition: " + ((char) current));
}
current = read();
}
// parse whitespace followed by optional offset
current = read();
skipSpaces();
long offset = parseOptionalOffset();
conditions.addElement(new RepeatCondition(tes, isBegin, id,
offset, repeatCount));
| protected final long | parseSignedClockValue()Helper method that parses a signed clock value (one that may or may
not be preceded by a '-' or '+' sign. Returns the parsed clock value
as a long offset. If the clock string begins with a '-' sign, the
returned offset value will be negative. If the clock string begins
with a '+' sign (or is unsigned), the returned offset value will be
positive.
boolean pos = true;
switch (current) {
case '-":
pos = false;
// FALLTHROUGH
case '+":
current = read();
skipSpaces();
break;
default:
break;
}
long offset = parseClock(false);
if (!pos) {
offset = -offset;
}
return offset;
| protected final void | parseSyncBase(java.lang.String id, boolean isBeginSync)Parses a syncbase time condition. The current character is assumed
to be the first character after "begin" or "end". If parsing is
successful, a SyncBaseCondition is added to the list of time conditions
and the current character is the character that immediately follows the
syncbase value (either the "begin", "end", or the optional offset).
// parse whitespace followed by optional offset
skipSpaces();
long offset = parseOptionalOffset();
conditions.addElement(new SyncBaseCondition(ten, isBegin, id,
isBeginSync, offset));
| public static final java.lang.String | toDOMEventType(java.lang.String smilEventType)Converts the event to the DOMEvent type. This is required because for some
events, the name used in the SMIL begin/end attribute is not the same as
the DOM event so some translation is needed.
if (SVGConstants.SVG_SMIL_FOCUS_IN_EVENT_TYPE.equals(smilEventType)) {
return SVGConstants.SVG_DOMFOCUSIN_EVENT_TYPE;
} else if (SVGConstants.SVG_SMIL_FOCUS_OUT_EVENT_TYPE.equals(smilEventType)) {
return SVGConstants.SVG_DOMFOCUSOUT_EVENT_TYPE;
} else if (SVGConstants.SVG_SMIL_ACTIVATE_EVENT_TYPE.equals(smilEventType)) {
return SVGConstants.SVG_DOMACTIVATE_EVENT_TYPE;
}
return smilEventType;
|
|