Source Code Cross Referenced for PropertyParser.java in  » Graphic-Library » fop » org » apache » fop » fo » expr » 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 » Graphic Library » fop » org.apache.fop.fo.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         * 
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         * 
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:
018:        /* $Id: PropertyParser.java 554251 2007-07-07 20:13:41Z adelmelle $ */
019:
020:        package org.apache.fop.fo.expr;
021:
022:        import org.apache.fop.apps.FOUserAgent;
023:        import org.apache.fop.datatypes.Numeric;
024:        import org.apache.fop.datatypes.PercentBase;
025:        import org.apache.fop.fo.properties.ColorProperty;
026:        import org.apache.fop.fo.properties.FixedLength;
027:        import org.apache.fop.fo.properties.ListProperty;
028:        import org.apache.fop.fo.properties.NumberProperty;
029:        import org.apache.fop.fo.properties.PercentLength;
030:        import org.apache.fop.fo.properties.Property;
031:        import org.apache.fop.fo.properties.StringProperty;
032:
033:        import java.util.HashMap;
034:        import java.util.LinkedList;
035:        import java.util.List;
036:
037:        /**
038:         * Class to parse XSL-FO property expressions.
039:         * This class is heavily based on the epxression parser in James Clark's
040:         * XT, an XSLT processor.
041:         */
042:        public final class PropertyParser extends PropertyTokenizer {
043:            private PropertyInfo propInfo; // Maker and propertyList related info
044:
045:            private static final String RELUNIT = "em";
046:            private static final HashMap FUNCTION_TABLE = new HashMap();
047:
048:            static {
049:                // Initialize the HashMap of XSL-defined functions
050:                FUNCTION_TABLE.put("ceiling", new CeilingFunction());
051:                FUNCTION_TABLE.put("floor", new FloorFunction());
052:                FUNCTION_TABLE.put("round", new RoundFunction());
053:                FUNCTION_TABLE.put("min", new MinFunction());
054:                FUNCTION_TABLE.put("max", new MaxFunction());
055:                FUNCTION_TABLE.put("abs", new AbsFunction());
056:                FUNCTION_TABLE.put("rgb", new RGBColorFunction());
057:                FUNCTION_TABLE.put("system-color", new SystemColorFunction());
058:                FUNCTION_TABLE.put("from-table-column",
059:                        new FromTableColumnFunction());
060:                FUNCTION_TABLE.put("inherited-property-value",
061:                        new InheritedPropFunction());
062:                FUNCTION_TABLE.put("from-parent", new FromParentFunction());
063:                FUNCTION_TABLE.put("from-nearest-specified-value",
064:                        new NearestSpecPropFunction());
065:                FUNCTION_TABLE.put("proportional-column-width",
066:                        new PPColWidthFunction());
067:                FUNCTION_TABLE.put("label-end", new LabelEndFunction());
068:                FUNCTION_TABLE.put("body-start", new BodyStartFunction());
069:                FUNCTION_TABLE.put("rgb-icc", new ICCColorFunction());
070:                FUNCTION_TABLE.put("cmyk", new CMYKcolorFunction()); //non-standard!!!
071:
072:                /**
073:                 * * NOT YET IMPLEMENTED!!!
074:                 * FUNCTION_TABLE.put("system-font", new SystemFontFunction());
075:                 * FUNCTION_TABLE.put("merge-property-values", new MergePropsFunction());
076:                 */
077:            }
078:
079:            /**
080:             * Public entrypoint to the Property expression parser.
081:             * @param expr The specified value (attribute on the xml element).
082:             * @param propInfo A PropertyInfo object representing the context in
083:             * which the property expression is to be evaluated.
084:             * @return A Property object holding the parsed result.
085:             * @throws PropertyException If the "expr" cannot be parsed as a Property.
086:             */
087:            public static Property parse(String expr, PropertyInfo propInfo)
088:                    throws PropertyException {
089:                try {
090:                    return new PropertyParser(expr, propInfo).parseProperty();
091:                } catch (PropertyException exc) {
092:                    exc.setPropertyInfo(propInfo);
093:                    throw exc;
094:                }
095:            }
096:
097:            /**
098:             * Private constructor. Called by the static parse() method.
099:             * @param propExpr The specified value (attribute on the xml element).
100:             * @param propInfo A PropertyInfo object representing the context in
101:             * which the property expression is to be evaluated.
102:             */
103:            private PropertyParser(String propExpr, PropertyInfo pInfo) {
104:                super (propExpr);
105:                this .propInfo = pInfo;
106:            }
107:
108:            /**
109:             * Parse the property expression described in the instance variables.
110:             * Note: If the property expression String is empty, a StringProperty
111:             * object holding an empty String is returned.
112:             * @return A Property object holding the parsed result.
113:             * @throws PropertyException If the "expr" cannot be parsed as a Property.
114:             */
115:            private Property parseProperty() throws PropertyException {
116:                next();
117:                if (currentToken == TOK_EOF) {
118:                    // if prop value is empty string, force to StringProperty
119:                    return StringProperty.getInstance("");
120:                }
121:                ListProperty propList = null;
122:                while (true) {
123:                    Property prop = parseAdditiveExpr();
124:                    if (currentToken == TOK_EOF) {
125:                        if (propList != null) {
126:                            propList.addProperty(prop);
127:                            return propList;
128:                        } else {
129:                            return prop;
130:                        }
131:                    } else {
132:                        if (propList == null) {
133:                            propList = new ListProperty(prop);
134:                        } else {
135:                            propList.addProperty(prop);
136:                        }
137:                    }
138:                    // throw new PropertyException("unexpected token");
139:                }
140:                // return prop;
141:            }
142:
143:            /**
144:             * Try to parse an addition or subtraction expression and return the
145:             * resulting Property.
146:             */
147:            private Property parseAdditiveExpr() throws PropertyException {
148:                // Evaluate and put result on the operand stack
149:                Property prop = parseMultiplicativeExpr();
150:                loop: while (true) {
151:                    switch (currentToken) {
152:                    case TOK_PLUS:
153:                        next();
154:                        prop = evalAddition(prop.getNumeric(),
155:                                parseMultiplicativeExpr().getNumeric());
156:                        break;
157:                    case TOK_MINUS:
158:                        next();
159:                        prop = evalSubtraction(prop.getNumeric(),
160:                                parseMultiplicativeExpr().getNumeric());
161:                        break;
162:                    default:
163:                        break loop;
164:                    }
165:                }
166:                return prop;
167:            }
168:
169:            /**
170:             * Try to parse a multiply, divide or modulo expression and return
171:             * the resulting Property.
172:             */
173:            private Property parseMultiplicativeExpr() throws PropertyException {
174:                Property prop = parseUnaryExpr();
175:                loop: while (true) {
176:                    switch (currentToken) {
177:                    case TOK_DIV:
178:                        next();
179:                        prop = evalDivide(prop.getNumeric(), parseUnaryExpr()
180:                                .getNumeric());
181:                        break;
182:                    case TOK_MOD:
183:                        next();
184:                        prop = evalModulo(prop.getNumber(), parseUnaryExpr()
185:                                .getNumber());
186:                        break;
187:                    case TOK_MULTIPLY:
188:                        next();
189:                        prop = evalMultiply(prop.getNumeric(), parseUnaryExpr()
190:                                .getNumeric());
191:                        break;
192:                    default:
193:                        break loop;
194:                    }
195:                }
196:                return prop;
197:            }
198:
199:            /**
200:             * Try to parse a unary minus expression and return the
201:             * resulting Property.
202:             */
203:            private Property parseUnaryExpr() throws PropertyException {
204:                if (currentToken == TOK_MINUS) {
205:                    next();
206:                    return evalNegate(parseUnaryExpr().getNumeric());
207:                }
208:                return parsePrimaryExpr();
209:            }
210:
211:            /**
212:             * Checks that the current token is a right parenthesis
213:             * and throws an exception if this isn't the case.
214:             */
215:            private void expectRpar() throws PropertyException {
216:                if (currentToken != TOK_RPAR) {
217:                    throw new PropertyException("expected )");
218:                }
219:                next();
220:            }
221:
222:            /**
223:             * Try to parse a primary expression and return the
224:             * resulting Property.
225:             * A primary expression is either a parenthesized expression or an
226:             * expression representing a primitive Property datatype, such as a
227:             * string literal, an NCname, a number or a unit expression, or a
228:             * function call expression.
229:             */
230:            private Property parsePrimaryExpr() throws PropertyException {
231:                Property prop;
232:                if (currentToken == TOK_COMMA) {
233:                    //Simply skip commas, for example for font-family
234:                    next();
235:                }
236:                switch (currentToken) {
237:                case TOK_LPAR:
238:                    next();
239:                    prop = parseAdditiveExpr();
240:                    expectRpar();
241:                    return prop;
242:
243:                case TOK_LITERAL:
244:                    prop = StringProperty.getInstance(currentTokenValue);
245:                    break;
246:
247:                case TOK_NCNAME:
248:                    // Interpret this in context of the property or do it later?
249:                    prop = new NCnameProperty(currentTokenValue);
250:                    break;
251:
252:                case TOK_FLOAT:
253:                    prop = NumberProperty.getInstance(new Double(
254:                            currentTokenValue));
255:                    break;
256:
257:                case TOK_INTEGER:
258:                    prop = NumberProperty.getInstance(new Integer(
259:                            currentTokenValue));
260:                    break;
261:
262:                case TOK_PERCENT:
263:                    /*
264:                     * Get the length base value object from the Maker. If null, then
265:                     * this property can't have % values. Treat it as a real number.
266:                     */
267:                    double pcval = new Double(currentTokenValue.substring(0,
268:                            currentTokenValue.length() - 1)).doubleValue() / 100.0;
269:                    PercentBase pcBase = this .propInfo.getPercentBase();
270:                    if (pcBase != null) {
271:                        if (pcBase.getDimension() == 0) {
272:                            prop = NumberProperty.getInstance(pcval
273:                                    * pcBase.getBaseValue());
274:                        } else if (pcBase.getDimension() == 1) {
275:                            prop = new PercentLength(pcval, pcBase);
276:                        } else {
277:                            throw new PropertyException(
278:                                    "Illegal percent dimension value");
279:                        }
280:                    } else {
281:                        // WARNING? Interpret as a decimal fraction, eg. 50% = .5
282:                        prop = NumberProperty.getInstance(pcval);
283:                    }
284:                    break;
285:
286:                case TOK_NUMERIC:
287:                    // A number plus a valid unit name.
288:                    int numLen = currentTokenValue.length() - currentUnitLength;
289:                    String unitPart = currentTokenValue.substring(numLen);
290:                    Double numPart = new Double(currentTokenValue.substring(0,
291:                            numLen));
292:                    if (unitPart.equals(RELUNIT)) {
293:                        prop = (Property) NumericOp.multiply(NumberProperty
294:                                .getInstance(numPart.doubleValue()), propInfo
295:                                .currentFontSize());
296:                    } else {
297:                        prop = FixedLength.getInstance(numPart.doubleValue(),
298:                                unitPart);
299:                    }
300:                    break;
301:
302:                case TOK_COLORSPEC:
303:                    FOUserAgent ua = (propInfo == null) ? null : (propInfo
304:                            .getFO() == null ? null : propInfo.getFO()
305:                            .getUserAgent());
306:                    prop = new ColorProperty(ua, currentTokenValue);
307:                    break;
308:
309:                case TOK_FUNCTION_LPAR:
310:                    Function function = (Function) FUNCTION_TABLE
311:                            .get(currentTokenValue);
312:                    if (function == null) {
313:                        throw new PropertyException("no such function: "
314:                                + currentTokenValue);
315:                    }
316:                    next();
317:                    // Push new function (for function context: getPercentBase())
318:                    propInfo.pushFunction(function);
319:                    if (function.nbArgs() < 0) {
320:                        // Negative nbArgs --> function with variable number of arguments
321:                        prop = function.eval(parseVarArgs(function), propInfo);
322:                    } else {
323:                        prop = function.eval(parseArgs(function), propInfo);
324:                    }
325:                    propInfo.popFunction();
326:                    return prop;
327:
328:                default:
329:                    // TODO: add the token or the expr to the error message.
330:                    throw new PropertyException("syntax error");
331:                }
332:                next();
333:                return prop;
334:            }
335:
336:            /**
337:             * Parse a comma separated list of function arguments. Each argument
338:             * may itself be an expression. This method consumes the closing right
339:             * parenthesis of the argument list.
340:             * @param function The function object for which the arguments are 
341:             * collected.
342:             * @return An array of Property objects representing the arguments
343:             * found.
344:             * @throws PropertyException If the number of arguments found isn't equal
345:             * to the number expected.
346:             */
347:            Property[] parseArgs(Function function) throws PropertyException {
348:                int nbArgs = function.nbArgs();
349:                Property[] args = new Property[nbArgs];
350:                Property prop;
351:                int i = 0;
352:                if (currentToken == TOK_RPAR) {
353:                    // No args: func()
354:                    next();
355:                } else {
356:                    while (true) {
357:
358:                        prop = parseAdditiveExpr();
359:                        if (i < nbArgs) {
360:                            args[i++] = prop;
361:                        }
362:                        // ignore extra args
363:                        if (currentToken != TOK_COMMA) {
364:                            break;
365:                        }
366:                        next();
367:                    }
368:                    expectRpar();
369:                }
370:                if (i == nbArgs - 1 && function.padArgsWithPropertyName()) {
371:                    args[i++] = StringProperty.getInstance(propInfo
372:                            .getPropertyMaker().getName());
373:                }
374:                if (nbArgs != i) {
375:                    throw new PropertyException("Expected " + nbArgs
376:                            + ", but got " + i + " args for function");
377:                }
378:                return args;
379:            }
380:
381:            /**
382:             * 
383:             * Parse a comma separated list of function arguments. Each argument
384:             * may itself be an expression. This method consumes the closing right
385:             * parenthesis of the argument list.
386:             * 
387:             * The method differs from parseArgs in that it accepts a variable 
388:             * number of arguments.
389:             * 
390:             * @param function The function object for which the arguments are 
391:             * collected.
392:             * @return An array of Property objects representing the arguments
393:             * found.
394:             * @throws PropertyException If the number of arguments found isn't equal
395:             * to the number expected.
396:             * 
397:             * TODO Merge this with parseArgs? 
398:             */
399:            Property[] parseVarArgs(Function function) throws PropertyException {
400:                // For variable argument functions the minimum number of arguments is returned as a 
401:                // negative integer from the nbArgs method
402:                int nbArgs = -function.nbArgs();
403:                List args = new LinkedList();
404:                Property prop;
405:                if (currentToken == TOK_RPAR) {
406:                    // No args: func()
407:                    next();
408:                } else {
409:                    while (true) {
410:                        prop = parseAdditiveExpr();
411:                        args.add(prop);
412:                        // ignore extra args
413:                        if (currentToken != TOK_COMMA) {
414:                            break;
415:                        }
416:                        next();
417:                    }
418:                    expectRpar();
419:                }
420:                if (nbArgs > args.size()) {
421:                    throw new PropertyException("Expected at least " + nbArgs
422:                            + ", but got " + args.size() + " args for function");
423:                }
424:                Property[] propArray = new Property[args.size()];
425:                args.toArray(propArray);
426:                return propArray;
427:            }
428:
429:            /**
430:             * Evaluate an addition operation. If either of the arguments is null,
431:             * this means that it wasn't convertible to a Numeric value.
432:             * @param op1 A Numeric object (Number or Length-type object)
433:             * @param op2 A Numeric object (Number or Length-type object)
434:             * @return A new NumericProperty object holding an object which represents
435:             * the sum of the two operands.
436:             * @throws PropertyException If either operand is null.
437:             */
438:            private Property evalAddition(Numeric op1, Numeric op2)
439:                    throws PropertyException {
440:                if (op1 == null || op2 == null) {
441:                    throw new PropertyException(
442:                            "Non numeric operand in addition");
443:                }
444:                return (Property) NumericOp.addition(op1, op2);
445:            }
446:
447:            /**
448:             * Evaluate a subtraction operation. If either of the arguments is null,
449:             * this means that it wasn't convertible to a Numeric value.
450:             * @param op1 A Numeric object (Number or Length-type object)
451:             * @param op2 A Numeric object (Number or Length-type object)
452:             * @return A new NumericProperty object holding an object which represents
453:             * the difference of the two operands.
454:             * @throws PropertyException If either operand is null.
455:             */
456:            private Property evalSubtraction(Numeric op1, Numeric op2)
457:                    throws PropertyException {
458:                if (op1 == null || op2 == null) {
459:                    throw new PropertyException(
460:                            "Non numeric operand in subtraction");
461:                }
462:                return (Property) NumericOp.subtraction(op1, op2);
463:            }
464:
465:            /**
466:             * Evaluate a unary minus operation. If the argument is null,
467:             * this means that it wasn't convertible to a Numeric value.
468:             * @param op A Numeric object (Number or Length-type object)
469:             * @return A new NumericProperty object holding an object which represents
470:             * the negative of the operand (multiplication by *1).
471:             * @throws PropertyException If the operand is null.
472:             */
473:            private Property evalNegate(Numeric op) throws PropertyException {
474:                if (op == null) {
475:                    throw new PropertyException(
476:                            "Non numeric operand to unary minus");
477:                }
478:                return (Property) NumericOp.negate(op);
479:            }
480:
481:            /**
482:             * Evaluate a multiplication operation. If either of the arguments is null,
483:             * this means that it wasn't convertible to a Numeric value.
484:             * @param op1 A Numeric object (Number or Length-type object)
485:             * @param op2 A Numeric object (Number or Length-type object)
486:             * @return A new NumericProperty object holding an object which represents
487:             * the product of the two operands.
488:             * @throws PropertyException If either operand is null.
489:             */
490:            private Property evalMultiply(Numeric op1, Numeric op2)
491:                    throws PropertyException {
492:                if (op1 == null || op2 == null) {
493:                    throw new PropertyException(
494:                            "Non numeric operand in multiplication");
495:                }
496:                return (Property) NumericOp.multiply(op1, op2);
497:            }
498:
499:            /**
500:             * Evaluate a division operation. If either of the arguments is null,
501:             * this means that it wasn't convertible to a Numeric value.
502:             * @param op1 A Numeric object (Number or Length-type object)
503:             * @param op2 A Numeric object (Number or Length-type object)
504:             * @return A new NumericProperty object holding an object which represents
505:             * op1 divided by op2.
506:             * @throws PropertyException If either operand is null.
507:             */
508:            private Property evalDivide(Numeric op1, Numeric op2)
509:                    throws PropertyException {
510:                if (op1 == null || op2 == null) {
511:                    throw new PropertyException(
512:                            "Non numeric operand in division");
513:                }
514:                return (Property) NumericOp.divide(op1, op2);
515:            }
516:
517:            /**
518:             * Evaluate a modulo operation. If either of the arguments is null,
519:             * this means that it wasn't convertible to a Number value.
520:             * @param op1 A Number object
521:             * @param op2 A Number object
522:             * @return A new NumberProperty object holding an object which represents
523:             * op1 mod op2.
524:             * @throws PropertyException If either operand is null.
525:             */
526:            private Property evalModulo(Number op1, Number op2)
527:                    throws PropertyException {
528:                if (op1 == null || op2 == null) {
529:                    throw new PropertyException("Non number operand to modulo");
530:                }
531:                return NumberProperty.getInstance(op1.doubleValue()
532:                        % op2.doubleValue());
533:            }
534:
535:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.