Source Code Cross Referenced for TimeConditionParser.java in  » 6.0-JDK-Modules » j2me » com » sun » perseus » parser » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.perseus.parser 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         */
026:
027:        package com.sun.perseus.parser;
028:
029:        import java.util.Date;
030:        import java.util.Vector;
031:
032:        import com.sun.perseus.model.TimedElementNode;
033:        import com.sun.perseus.model.TimedElementSupport;
034:
035:        import com.sun.perseus.model.AccessKeyCondition;
036:        import com.sun.perseus.model.EventBaseCondition;
037:        import com.sun.perseus.model.OffsetCondition;
038:        import com.sun.perseus.model.RepeatCondition;
039:        import com.sun.perseus.model.SyncBaseCondition;
040:        import com.sun.perseus.model.TimeCondition;
041:
042:        import com.sun.perseus.util.SVGConstants;
043:
044:        /**
045:         * Parser for SVG time condition values, as defined in the SVG specification
046:         * for timing attributes:
047:         *   http://www.w3.org/TR/SVG11/animate.html#TimingAttributes
048:         *
049:         * @author <a href="mailto:christopher.campbell@sun.com">Chris Campbell</a>
050:         * @version $Id: TimeConditionParser.java,v 1.4 2006/04/21 06:40:40 st125089 Exp $
051:         */
052:        public class TimeConditionParser extends ClockParser {
053:
054:            /**
055:             * The list of time conditions being parsed.
056:             */
057:            private Vector conditions;
058:
059:            /**
060:             * If true, a "begin" attribute is being parsed; otherwise, an "end"
061:             * attribute is being parsed.
062:             */
063:            private boolean isBegin;
064:
065:            /**
066:             * The TimedElementNode for the attribute being parsed.
067:             */
068:            private TimedElementNode ten;
069:
070:            /**
071:             * The TimedElementSupport for the TimedElementNode associated with
072:             * the attribute being parsed.
073:             */
074:            private TimedElementSupport tes;
075:
076:            /**
077:             * Parses a begin/end timing attribute value.  This method throws an
078:             * <code>IllegalArgumentException</code> if the input argument's
079:             * syntax does not conform to that of a clock value, as defined
080:             * by the SVG animate tag specification.
081:             *
082:             * @param attrValue the value to parse.
083:             * @param ten the TimedElementNode for which the attribute is parsed.
084:             * @param isBegin defines whether this is a begin attribute.
085:             * @return an array of <code>TimeConditions</code> corresponding to the
086:             * input attrubute value.
087:             */
088:            public TimeCondition[] parseBeginEndAttribute(
089:                    final String attrValue, final TimedElementNode ten,
090:                    final boolean isBegin) {
091:                setString(attrValue);
092:
093:                if (attrValue.length() == 0) {
094:                    throw new IllegalArgumentException();
095:                }
096:
097:                this .conditions = new Vector();
098:                this .ten = ten;
099:                this .tes = ten.getTimedElementSupport();
100:                this .isBegin = isBegin;
101:
102:                loop: for (;;) {
103:                    // parse leading whitespace
104:                    current = read();
105:                    skipSpaces();
106:
107:                    m1: switch (current) {
108:                    case ';':
109:                        throw new IllegalArgumentException();
110:                    case -1:
111:                        if (isBegin && (conditions.size() == 0)) {
112:                            // an empty begin attribute maps to offset(0)
113:                            conditions.addElement(new OffsetCondition(tes,
114:                                    isBegin, 0L));
115:                        }
116:                        break loop;
117:                    case '+':
118:                    case '-':
119:                    case '0':
120:                    case '1':
121:                    case '2':
122:                    case '3':
123:                    case '4':
124:                    case '5':
125:                    case '6':
126:                    case '7':
127:                    case '8':
128:                    case '9':
129:                        parseOffset();
130:                        break m1;
131:                    default:
132:                        if (currentStartsWith("accessKey(")) {
133:                            parseAccessKey();
134:                        } else if (currentStartsWith("repeat(")) {
135:                            parseRepeat(null);
136:                        } else if (currentStartsWith("indefinite")) {
137:                            // indefinite maps to no time condition
138:                            break m1;
139:                        } else {
140:                            parseOther();
141:                        }
142:                        break m1;
143:                    }
144:
145:                    // parse trailing whitespace (current should point to the character
146:                    // just following the last time condition)
147:                    skipSpaces();
148:
149:                    // detect ';' separator, or -1
150:                    m2: switch (current) {
151:                    case ';':
152:                        break m2;
153:                    case -1:
154:                        break loop;
155:                    default:
156:                        throw new IllegalArgumentException();
157:                    }
158:                }
159:
160:                TimeCondition[] ret = new TimeCondition[conditions.size()];
161:                conditions.copyInto(ret);
162:                return ret;
163:            }
164:
165:            /**
166:             * Helper method that parses a signed clock value (one that may or may
167:             * not be preceded by a '-' or '+' sign.  Returns the parsed clock value
168:             * as a long offset.  If the clock string begins with a '-' sign, the
169:             * returned offset value will be negative.  If the clock string begins
170:             * with a '+' sign (or is unsigned), the returned offset value will be
171:             * positive.
172:             *
173:             * @return a signed long offset value (in milliseconds)
174:             * @see ClockParser
175:             */
176:            protected final long parseSignedClockValue() {
177:                boolean pos = true;
178:                switch (current) {
179:                case '-':
180:                    pos = false;
181:                    // FALLTHROUGH
182:                case '+':
183:                    current = read();
184:                    skipSpaces();
185:                    break;
186:                default:
187:                    break;
188:                }
189:
190:                long offset = parseClock(false);
191:                if (!pos) {
192:                    offset = -offset;
193:                }
194:
195:                return offset;
196:            }
197:
198:            /**
199:             * Parses an optional offset value.  If the current character is a sign
200:             * value ('+' or '-'), the offset value is parsed and returned as a long
201:             * value.  If the offset value is not present (<code>current</code> is
202:             * ';' or -1), this method returns zero.  If some other character is
203:             * encountered, an <code>IllegalArgumentException</code> is thrown.
204:             *
205:             * @return a signed long offset value (in milliseconds)
206:             * @see #parseSignedClockValue
207:             */
208:            protected final long parseOptionalOffset() {
209:                long offset = 0L;
210:
211:                switch (current) {
212:                case '+':
213:                case '-':
214:                    offset = parseSignedClockValue();
215:                    break;
216:                case ';':
217:                case -1:
218:                    break;
219:                default:
220:                    throw new IllegalArgumentException(
221:                            "Unsupported character in optional offset value: "
222:                                    + ((char) current));
223:                }
224:
225:                return offset;
226:            }
227:
228:            /**
229:             * Parses an offset time condition.  The current character is assumed
230:             * to be '+', '-', or a numeral.  If parsing is successful, an
231:             * OffsetCondition is added to the list of time conditions and the
232:             * current character is the character that immediately follows the offset
233:             * value.
234:             *
235:             * @see #parseSignedClockValue
236:             */
237:            protected final void parseOffset() {
238:                long offset = parseSignedClockValue();
239:                conditions
240:                        .addElement(new OffsetCondition(tes, isBegin, offset));
241:            }
242:
243:            /**
244:             * Parses an accessKey time condition.  The current character is assumed
245:             * to be the first character after "accesskey(".  If parsing is successful,
246:             * an AccessKeyCondition is added to the list of time conditions and the
247:             * current character is the character that immediately follows the
248:             * access key value (either the ')' or the optional offset).
249:             */
250:            protected final void parseAccessKey() {
251:                // parse access key character (followed by ')')
252:                if ((current == -1) || (current == ')')) {
253:                    throw new IllegalArgumentException();
254:                }
255:                char accesskey = (char) current;
256:                current = read();
257:                if (current != ')') {
258:                    throw new IllegalArgumentException();
259:                }
260:
261:                // parse whitespace followed by optional offset
262:                current = read();
263:                skipSpaces();
264:                long offset = parseOptionalOffset();
265:
266:                conditions.addElement(new AccessKeyCondition(tes, isBegin,
267:                        offset, accesskey));
268:            }
269:
270:            /**
271:             * Parses a repeat time condition.  The current character is assumed
272:             * to be the first character after "repeat(".  If parsing is successful,
273:             * a RepeatCondition is added to the list of time conditions and the
274:             * current character is the character that immediately follows the
275:             * repeat value (either the ')' or the optional offset).
276:             *
277:             * @param id the identifier for this time condition; if null, the event
278:             * base id will be "unspecified"
279:             */
280:            protected final void parseRepeat(final String id) {
281:                // parse iteration value (followed by ')')
282:                int repeatCount = 0;
283:                loop: for (;;) {
284:                    switch (current) {
285:                    case '0':
286:                    case '1':
287:                    case '2':
288:                    case '3':
289:                    case '4':
290:                    case '5':
291:                    case '6':
292:                    case '7':
293:                    case '8':
294:                    case '9':
295:                        repeatCount = repeatCount * 10 + (current - '0');
296:                        break;
297:                    case ')':
298:                        break loop;
299:                    default:
300:                        throw new IllegalArgumentException(
301:                                "Illegal character in repeat condition: "
302:                                        + ((char) current));
303:                    }
304:                    current = read();
305:                }
306:
307:                // parse whitespace followed by optional offset
308:                current = read();
309:                skipSpaces();
310:                long offset = parseOptionalOffset();
311:
312:                conditions.addElement(new RepeatCondition(tes, isBegin, id,
313:                        offset, repeatCount));
314:            }
315:
316:            /**
317:             * Parses a syncbase time condition.  The current character is assumed
318:             * to be the first character after "begin" or "end".  If parsing is
319:             * successful, a SyncBaseCondition is added to the list of time conditions
320:             * and the current character is the character that immediately follows the
321:             * syncbase value (either the "begin", "end", or the optional offset).
322:             *
323:             * @param id the identifier for this time condition; should not be null
324:             * @param isBeginSync true if this condition is on the syncBase's begin
325:             * condition; false if this condition is on the syncBase's end condition.
326:             */
327:            protected final void parseSyncBase(final String id,
328:                    final boolean isBeginSync) {
329:                // parse whitespace followed by optional offset
330:                skipSpaces();
331:                long offset = parseOptionalOffset();
332:
333:                conditions.addElement(new SyncBaseCondition(ten, isBegin, id,
334:                        isBeginSync, offset));
335:            }
336:
337:            /**
338:             * Parses an event base time condition.  If <code>id</code> is
339:             * <code>null</code>, the event base id will be "unspecified", and the
340:             * eventType is assumed to be non-<code>null</code> (the current character
341:             * is assumed to be the first character after the event type).  If
342:             * <code>eventType</code> is <code>null</code>, the event type will be
343:             * parsed (the current character is assumed to be the first character after
344:             * the event base id and dot, e.g. "foo.").
345:             *
346:             * If parsing is successful, an EventBaseCondition is added to the list
347:             * of time conditions and the current character is the character that
348:             * immediately follows the event base value (either the id, eventType,
349:             * or the optional offset).
350:             *
351:             * @param id the identifier for this time condition; can be null
352:             * @param eventType the event type for this time condition; can be null
353:             * if the id was already parsed
354:             */
355:            protected final void parseEvent(final String id, String eventType) {
356:                if (eventType == null) {
357:                    StringBuffer etbuf = new StringBuffer();
358:                    loop: for (;;) {
359:                        switch (current) {
360:                        case '\\':
361:                            // skip escape characters
362:                            current = read();
363:                            switch (current) {
364:                            case '.':
365:                            case '-':
366:                            case '_':
367:                                etbuf.append((char) current);
368:                                break;
369:                            default:
370:                                if (isLetterOrDigit((char) current)) {
371:                                    etbuf.append((char) current);
372:                                } else {
373:                                    throw new IllegalArgumentException();
374:                                }
375:                                break;
376:                            }
377:                            break;
378:                        case '.':
379:                            throw new IllegalArgumentException();
380:                        case '+':
381:                        case '-':
382:                        case ';':
383:                        case -1:
384:                            if (etbuf.length() == 0) {
385:                                throw new IllegalArgumentException();
386:                            }
387:                            eventType = etbuf.toString();
388:                            break loop;
389:                        case 0x20:
390:                        case 0x09:
391:                        case 0x0D:
392:                        case 0x0A:
393:                            skipSpaces();
394:                            switch (current) {
395:                            case '+':
396:                            case '-':
397:                            case ';':
398:                            case -1:
399:                                // no id, must be an event
400:                                if (etbuf.length() == 0) {
401:                                    throw new IllegalArgumentException();
402:                                }
403:                                eventType = etbuf.toString();
404:                                break loop;
405:                            default:
406:                                throw new IllegalArgumentException();
407:                            }
408:                        default:
409:                            etbuf.append((char) current);
410:                            break;
411:                        }
412:                        current = read();
413:                    }
414:                }
415:
416:                // parse optional offset (whitespace has already been parsed)
417:                long offset = parseOptionalOffset();
418:
419:                conditions.addElement(new EventBaseCondition(tes, isBegin, id,
420:                        toDOMEventType(eventType), offset));
421:            }
422:
423:            /**
424:             * Parses a time condition with an optional id prefix.  Delegates to one
425:             * of the other <code>parse*()</code> methods, depending on whether the
426:             * string matches a repeat, syncbase, or event time condition.
427:             */
428:            protected final void parseOther() {
429:                StringBuffer idbuf = new StringBuffer();
430:                String id = null;
431:                String eventType = null;
432:
433:                loopid: for (;;) {
434:                    switch (current) {
435:                    case '\\':
436:                        // skip escape characters
437:                        current = read();
438:                        switch (current) {
439:                        case '.':
440:                        case '-':
441:                        case '_':
442:                            idbuf.append((char) current);
443:                            break;
444:                        default:
445:                            if (isLetterOrDigit((char) current)) {
446:                                idbuf.append((char) current);
447:                            } else {
448:                                throw new IllegalArgumentException();
449:                            }
450:                            break;
451:                        }
452:                        break;
453:                    case '.':
454:                        if (idbuf.length() == 0) {
455:                            throw new IllegalArgumentException();
456:                        }
457:                        id = idbuf.toString();
458:                        current = read();
459:                        break loopid;
460:                    case '+':
461:                    case '-':
462:                    case ';':
463:                    case -1:
464:                        // no id, must be an event (we will never enter this method
465:                        // with one of these characters as the current character, so
466:                        // idbuf will always have a non-zero length at this point)
467:                        eventType = idbuf.toString();
468:                        break loopid;
469:                    case 0x20:
470:                    case 0x09:
471:                    case 0x0D:
472:                    case 0x0A:
473:                        skipSpaces();
474:                        switch (current) {
475:                        case '+':
476:                        case '-':
477:                        case ';':
478:                        case -1:
479:                            // no id, must be an event (we will never enter this method
480:                            // with one of these characters as the current character,
481:                            // so idbuf will always have a non-zero length at this
482:                            // point)
483:                            eventType = idbuf.toString();
484:                            break loopid;
485:                        default:
486:                            throw new IllegalArgumentException();
487:                        }
488:                    default:
489:                        idbuf.append((char) current);
490:                        break;
491:                    }
492:                    current = read();
493:                }
494:
495:                if (id != null) {
496:                    if (currentStartsWith("repeat(")) {
497:                        parseRepeat(id);
498:                    } else if (currentStartsWith("begin")) {
499:                        parseSyncBase(id, true);
500:                    } else if (currentStartsWith("end")) {
501:                        parseSyncBase(id, false);
502:                    } else {
503:                        parseEvent(id, null);
504:                    }
505:                } else {
506:                    parseEvent(null, eventType);
507:                }
508:            }
509:
510:            /**
511:             * Do not use Character.isLetterOrDigit because it is not supported on 
512:             * all Java platforms.
513:             * 
514:             * @param c the character to test.
515:             * @return true if c is a letter or a digit.
516:             */
517:            public static final boolean isLetterOrDigit(final char c) {
518:                return (Character.isDigit(c) || Character.isUpperCase(c) || Character
519:                        .isLowerCase(c));
520:            }
521:
522:            /**
523:             * Converts the event to the DOMEvent type. This is required because for some
524:             * events, the name used in the SMIL begin/end attribute is not the same as
525:             * the DOM event so some translation is needed.
526:             *
527:             * @param smilEventType the name of the animation event type.
528:             * @return the DOM Level 2 Event name.
529:             *
530:             * @see http://www.w3.org/TR/SVG11/interact.html#SVGEvents
531:             */
532:            public static final String toDOMEventType(final String smilEventType) {
533:                if (SVGConstants.SVG_SMIL_FOCUS_IN_EVENT_TYPE
534:                        .equals(smilEventType)) {
535:                    return SVGConstants.SVG_DOMFOCUSIN_EVENT_TYPE;
536:                } else if (SVGConstants.SVG_SMIL_FOCUS_OUT_EVENT_TYPE
537:                        .equals(smilEventType)) {
538:                    return SVGConstants.SVG_DOMFOCUSOUT_EVENT_TYPE;
539:                } else if (SVGConstants.SVG_SMIL_ACTIVATE_EVENT_TYPE
540:                        .equals(smilEventType)) {
541:                    return SVGConstants.SVG_DOMACTIVATE_EVENT_TYPE;
542:                }
543:
544:                return smilEventType;
545:            }
546:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.