Source Code Cross Referenced for DigesterRuleParser.java in  » Library » Apache-commons-digester-1.8-src » org » apache » commons » digester » xmlrules » 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 » Library » Apache commons digester 1.8 src » org.apache.commons.digester.xmlrules 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* $Id: DigesterRuleParser.java 471661 2006-11-06 08:09:25Z skitching $
002:         *
003:         * Licensed to the Apache Software Foundation (ASF) under one or more
004:         * contributor license agreements.  See the NOTICE file distributed with
005:         * this work for additional information regarding copyright ownership.
006:         * The ASF licenses this file to You under the Apache License, Version 2.0
007:         * (the "License"); you may not use this file except in compliance with
008:         * the License.  You may obtain a copy of the License at
009:         * 
010:         *      http://www.apache.org/licenses/LICENSE-2.0
011:         * 
012:         * Unless required by applicable law or agreed to in writing, software
013:         * distributed under the License is distributed on an "AS IS" BASIS,
014:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015:         * See the License for the specific language governing permissions and
016:         * limitations under the License.
017:         */
018:
019:        package org.apache.commons.digester.xmlrules;
020:
021:        import java.io.FileNotFoundException;
022:        import java.io.IOException;
023:        import java.net.URL;
024:        import java.util.ArrayList;
025:        import java.util.HashSet;
026:        import java.util.List;
027:        import java.util.Set;
028:        import java.util.StringTokenizer;
029:
030:        import org.apache.commons.beanutils.ConvertUtils;
031:
032:        import org.apache.commons.collections.ArrayStack;
033:
034:        import org.apache.commons.digester.AbstractObjectCreationFactory;
035:        import org.apache.commons.digester.BeanPropertySetterRule;
036:        import org.apache.commons.digester.CallMethodRule;
037:        import org.apache.commons.digester.CallParamRule;
038:        import org.apache.commons.digester.Digester;
039:        import org.apache.commons.digester.FactoryCreateRule;
040:        import org.apache.commons.digester.NodeCreateRule;
041:        import org.apache.commons.digester.ObjectCreateRule;
042:        import org.apache.commons.digester.Rule;
043:        import org.apache.commons.digester.RuleSetBase;
044:        import org.apache.commons.digester.Rules;
045:        import org.apache.commons.digester.SetNestedPropertiesRule;
046:        import org.apache.commons.digester.SetNextRule;
047:        import org.apache.commons.digester.SetPropertiesRule;
048:        import org.apache.commons.digester.SetPropertyRule;
049:        import org.apache.commons.digester.SetRootRule;
050:        import org.apache.commons.digester.SetTopRule;
051:        import org.apache.commons.digester.ObjectParamRule;
052:
053:        import org.w3c.dom.Node;
054:        import org.xml.sax.Attributes;
055:        import org.xml.sax.SAXException;
056:
057:        /**
058:         * This is a RuleSet that parses XML into Digester rules, and then
059:         * adds those rules to a 'target' Digester.
060:         *
061:         * @since 1.2
062:         */
063:
064:        public class DigesterRuleParser extends RuleSetBase {
065:
066:            public static final String DIGESTER_PUBLIC_ID = "-//Jakarta Apache //DTD digester-rules XML V1.0//EN";
067:
068:            /**
069:             * path to the DTD
070:             */
071:            private String digesterDtdUrl;
072:
073:            /**
074:             * This is the digester to which we are adding the rules that we parse
075:             * from the Rules XML document.
076:             */
077:            protected Digester targetDigester;
078:
079:            /** See {@link #setBasePath}. */
080:            protected String basePath = "";
081:
082:            /**
083:             * A stack whose toString method returns a '/'-separated concatenation
084:             * of all the elements in the stack.
085:             */
086:            protected class PatternStack extends ArrayStack {
087:                public String toString() {
088:                    StringBuffer str = new StringBuffer();
089:                    for (int i = 0; i < size(); i++) {
090:                        String elem = get(i).toString();
091:                        if (elem.length() > 0) {
092:                            if (str.length() > 0) {
093:                                str.append('/');
094:                            }
095:                            str.append(elem);
096:                        }
097:                    }
098:                    return str.toString();
099:                }
100:            }
101:
102:            /**
103:             * A stack used to maintain the current pattern. The Rules XML document
104:             * type allows nesting of patterns. If an element defines a matching
105:             * pattern, the resulting pattern is a concatenation of that pattern with
106:             * all the ancestor elements' patterns. Hence the need for a stack.
107:             */
108:            protected PatternStack patternStack;
109:
110:            /**
111:             * Used to detect circular includes
112:             */
113:            private Set includedFiles = new HashSet();
114:
115:            /**
116:             * Constructs a DigesterRuleParser. This object will be inoperable
117:             * until the target digester is set, via <code>setTarget(Digester)</code>
118:             */
119:            public DigesterRuleParser() {
120:                patternStack = new PatternStack();
121:            }
122:
123:            /**
124:             * Constructs a rule set for converting XML digester rule descriptions
125:             * into Rule objects, and adding them to the given Digester
126:             * @param targetDigester the Digester to add the rules to
127:             */
128:            public DigesterRuleParser(Digester targetDigester) {
129:                this .targetDigester = targetDigester;
130:                patternStack = new PatternStack();
131:            }
132:
133:            /**
134:             * Constructs a rule set for parsing an XML digester rule file that
135:             * has been included within an outer XML digester rule file. In this
136:             * case, we must pass the pattern stack and the target digester
137:             * to the rule set, as well as the list of files that have already
138:             * been included, for cycle detection.
139:             * @param targetDigester the Digester to add the rules to
140:             * @param stack Stack containing the prefix pattern string to be prepended
141:             * to any pattern parsed by this rule set.
142:             */
143:            private DigesterRuleParser(Digester targetDigester,
144:                    PatternStack stack, Set includedFiles) {
145:                this .targetDigester = targetDigester;
146:                patternStack = stack;
147:                this .includedFiles = includedFiles;
148:            }
149:
150:            /**
151:             * Sets the digester into which to add the parsed rules
152:             * @param d the Digester to add the rules to
153:             */
154:            public void setTarget(Digester d) {
155:                targetDigester = d;
156:            }
157:
158:            /**
159:             * Set a base pattern beneath which all the rules loaded by this
160:             * object will be registered. If this string is not empty, and does
161:             * not end in a "/", then one will be added.
162:             *
163:             * @since 1.6
164:             */
165:            public void setBasePath(String path) {
166:                if (path == null) {
167:                    basePath = "";
168:                } else if ((path.length() > 0) && !path.endsWith("/")) {
169:                    basePath = path + "/";
170:                } else {
171:                    basePath = path;
172:                }
173:            }
174:
175:            /**
176:             * Sets the location of the digester rules DTD. This is the DTD used
177:             * to validate the rules XML file.
178:             */
179:            public void setDigesterRulesDTD(String dtdURL) {
180:                digesterDtdUrl = dtdURL;
181:            }
182:
183:            /**
184:             * Returns the location of the DTD used to validate the digester rules
185:             * XML document.
186:             */
187:            protected String getDigesterRulesDTD() {
188:                //ClassLoader classLoader = getClass().getClassLoader();
189:                //URL url = classLoader.getResource(DIGESTER_DTD_PATH);
190:                //return url.toString();
191:                return digesterDtdUrl;
192:            }
193:
194:            /**
195:             * Adds a rule the the target digester. After a rule has been created by
196:             * parsing the XML, it is added to the digester by calling this method.
197:             * Typically, this method is called via reflection, when executing
198:             * a SetNextRule, from the Digester that is parsing the rules XML.
199:             * @param rule a Rule to add to the target digester.
200:             */
201:            public void add(Rule rule) {
202:                targetDigester
203:                        .addRule(basePath + patternStack.toString(), rule);
204:            }
205:
206:            /**
207:             * Add to the given digester the set of Rule instances used to parse an XML
208:             * document defining Digester rules. When the digester parses an XML file,
209:             * it will add the resulting rules & patterns to the 'target digester'
210:             * that was passed in this RuleSet's constructor.<P>
211:             * If you extend this class to support additional rules, your implementation
212:             * should of this method should call this implementation first: i.e.
213:             * <code>super.addRuleInstances(digester);</code>
214:             */
215:            public void addRuleInstances(Digester digester) {
216:                final String ruleClassName = Rule.class.getName();
217:                digester.register(DIGESTER_PUBLIC_ID, getDigesterRulesDTD());
218:
219:                digester.addRule("*/pattern", new PatternRule("value"));
220:
221:                digester.addRule("*/include", new IncludeRule());
222:
223:                digester.addFactoryCreate("*/bean-property-setter-rule",
224:                        new BeanPropertySetterRuleFactory());
225:                digester.addRule("*/bean-property-setter-rule",
226:                        new PatternRule("pattern"));
227:                digester.addSetNext("*/bean-property-setter-rule", "add",
228:                        ruleClassName);
229:
230:                digester.addFactoryCreate("*/call-method-rule",
231:                        new CallMethodRuleFactory());
232:                digester.addRule("*/call-method-rule", new PatternRule(
233:                        "pattern"));
234:                digester.addSetNext("*/call-method-rule", "add", ruleClassName);
235:
236:                digester.addFactoryCreate("*/object-param-rule",
237:                        new ObjectParamRuleFactory());
238:                digester.addRule("*/object-param-rule", new PatternRule(
239:                        "pattern"));
240:                digester
241:                        .addSetNext("*/object-param-rule", "add", ruleClassName);
242:
243:                digester.addFactoryCreate("*/call-param-rule",
244:                        new CallParamRuleFactory());
245:                digester.addRule("*/call-param-rule",
246:                        new PatternRule("pattern"));
247:                digester.addSetNext("*/call-param-rule", "add", ruleClassName);
248:
249:                digester.addFactoryCreate("*/factory-create-rule",
250:                        new FactoryCreateRuleFactory());
251:                digester.addRule("*/factory-create-rule", new PatternRule(
252:                        "pattern"));
253:                digester.addSetNext("*/factory-create-rule", "add",
254:                        ruleClassName);
255:
256:                digester.addFactoryCreate("*/object-create-rule",
257:                        new ObjectCreateRuleFactory());
258:                digester.addRule("*/object-create-rule", new PatternRule(
259:                        "pattern"));
260:                digester.addSetNext("*/object-create-rule", "add",
261:                        ruleClassName);
262:
263:                digester.addFactoryCreate("*/node-create-rule",
264:                        new NodeCreateRuleFactory());
265:                digester.addRule("*/node-create-rule", new PatternRule(
266:                        "pattern"));
267:                digester.addSetNext("*/node-create-rule", "add", ruleClassName);
268:
269:                digester.addFactoryCreate("*/set-properties-rule",
270:                        new SetPropertiesRuleFactory());
271:                digester.addRule("*/set-properties-rule", new PatternRule(
272:                        "pattern"));
273:                digester.addSetNext("*/set-properties-rule", "add",
274:                        ruleClassName);
275:
276:                digester.addRule("*/set-properties-rule/alias",
277:                        new SetPropertiesAliasRule());
278:
279:                digester.addFactoryCreate("*/set-property-rule",
280:                        new SetPropertyRuleFactory());
281:                digester.addRule("*/set-property-rule", new PatternRule(
282:                        "pattern"));
283:                digester
284:                        .addSetNext("*/set-property-rule", "add", ruleClassName);
285:
286:                digester.addFactoryCreate("*/set-nested-properties-rule",
287:                        new SetNestedPropertiesRuleFactory());
288:                digester.addRule("*/set-nested-properties-rule",
289:                        new PatternRule("pattern"));
290:                digester.addSetNext("*/set-nested-properties-rule", "add",
291:                        ruleClassName);
292:
293:                digester.addRule("*/set-nested-properties-rule/alias",
294:                        new SetNestedPropertiesAliasRule());
295:
296:                digester.addFactoryCreate("*/set-top-rule",
297:                        new SetTopRuleFactory());
298:                digester.addRule("*/set-top-rule", new PatternRule("pattern"));
299:                digester.addSetNext("*/set-top-rule", "add", ruleClassName);
300:
301:                digester.addFactoryCreate("*/set-next-rule",
302:                        new SetNextRuleFactory());
303:                digester.addRule("*/set-next-rule", new PatternRule("pattern"));
304:                digester.addSetNext("*/set-next-rule", "add", ruleClassName);
305:                digester.addFactoryCreate("*/set-root-rule",
306:                        new SetRootRuleFactory());
307:                digester.addRule("*/set-root-rule", new PatternRule("pattern"));
308:                digester.addSetNext("*/set-root-rule", "add", ruleClassName);
309:            }
310:
311:            /**
312:             * A rule for extracting the pattern matching strings from the rules XML.
313:             * In the digester-rules document type, a pattern can either be declared
314:             * in the 'value' attribute of a <pattern> element (in which case the pattern
315:             * applies to all rules elements contained within the <pattern> element),
316:             * or it can be declared in the optional 'pattern' attribute of a rule
317:             * element.
318:             */
319:            private class PatternRule extends Rule {
320:
321:                private String attrName;
322:                private String pattern = null;
323:
324:                /**
325:                 * @param attrName The name of the attribute containing the pattern
326:                 */
327:                public PatternRule(String attrName) {
328:                    super ();
329:                    this .attrName = attrName;
330:                }
331:
332:                /**
333:                 * If a pattern is defined for the attribute, push it onto the
334:                 * pattern stack.
335:                 */
336:                public void begin(Attributes attributes) {
337:                    pattern = attributes.getValue(attrName);
338:                    if (pattern != null) {
339:                        patternStack.push(pattern);
340:                    }
341:                }
342:
343:                /**
344:                 * If there was a pattern for this element, pop it off the pattern
345:                 * stack.
346:                 */
347:                public void end() {
348:                    if (pattern != null) {
349:                        patternStack.pop();
350:                    }
351:                }
352:            }
353:
354:            /**
355:             * A rule for including one rules XML file within another. Included files
356:             * behave as if they are 'macro-expanded' within the includer. This means
357:             * that the values of the pattern stack are prefixed to every pattern
358:             * in the included rules. <p>This rule will detect 'circular' includes,
359:             * which would result in infinite recursion. It throws a
360:             * CircularIncludeException when a cycle is detected, which will terminate
361:             * the parse.
362:             */
363:            private class IncludeRule extends Rule {
364:                public IncludeRule() {
365:                    super ();
366:                }
367:
368:                /**
369:                 * To include a rules xml file, we instantiate another Digester, and
370:                 * another DigesterRulesRuleSet. We pass the
371:                 * pattern stack and the target Digester to the new rule set, and
372:                 * tell the Digester to parse the file.
373:                 */
374:                public void begin(Attributes attributes) throws Exception {
375:                    // The path attribute gives the URI to another digester rules xml file
376:                    String fileName = attributes.getValue("path");
377:                    if (fileName != null && fileName.length() > 0) {
378:                        includeXMLRules(fileName);
379:                    }
380:
381:                    // The class attribute gives the name of a class that implements
382:                    // the DigesterRulesSource interface
383:                    String className = attributes.getValue("class");
384:                    if (className != null && className.length() > 0) {
385:                        includeProgrammaticRules(className);
386:                    }
387:                }
388:
389:                /**
390:                 * Creates another DigesterRuleParser, and uses it to extract the rules
391:                 * out of the give XML file. The contents of the current pattern stack
392:                 * will be prepended to all of the pattern strings parsed from the file.
393:                 */
394:                private void includeXMLRules(String fileName)
395:                        throws IOException, SAXException,
396:                        CircularIncludeException {
397:                    ClassLoader cl = Thread.currentThread()
398:                            .getContextClassLoader();
399:                    if (cl == null) {
400:                        cl = DigesterRuleParser.this .getClass()
401:                                .getClassLoader();
402:                    }
403:                    URL fileURL = cl.getResource(fileName);
404:                    if (fileURL == null) {
405:                        throw new FileNotFoundException("File \"" + fileName
406:                                + "\" not found.");
407:                    }
408:                    fileName = fileURL.toExternalForm();
409:                    if (includedFiles.add(fileName) == false) {
410:                        // circular include detected
411:                        throw new CircularIncludeException(fileName);
412:                    }
413:                    // parse the included xml file
414:                    DigesterRuleParser includedSet = new DigesterRuleParser(
415:                            targetDigester, patternStack, includedFiles);
416:                    includedSet.setDigesterRulesDTD(getDigesterRulesDTD());
417:                    Digester digester = new Digester();
418:                    digester.addRuleSet(includedSet);
419:                    digester.push(DigesterRuleParser.this );
420:                    digester.parse(fileName);
421:                    includedFiles.remove(fileName);
422:                }
423:
424:                /**
425:                 * Creates an instance of the indicated class. The class must implement
426:                 * the DigesterRulesSource interface. Passes the target digester to
427:                 * that instance. The DigesterRulesSource instance is supposed to add
428:                 * rules into the digester. The contents of the current pattern stack
429:                 * will be automatically prepended to all of the pattern strings added
430:                 * by the DigesterRulesSource instance.
431:                 */
432:                private void includeProgrammaticRules(String className)
433:                        throws ClassNotFoundException, ClassCastException,
434:                        InstantiationException, IllegalAccessException {
435:
436:                    Class cls = Class.forName(className);
437:                    DigesterRulesSource rulesSource = (DigesterRulesSource) cls
438:                            .newInstance();
439:
440:                    // wrap the digester's Rules object, to prepend pattern
441:                    Rules digesterRules = targetDigester.getRules();
442:                    Rules prefixWrapper = new RulesPrefixAdapter(patternStack
443:                            .toString(), digesterRules);
444:
445:                    targetDigester.setRules(prefixWrapper);
446:                    try {
447:                        rulesSource.getRules(targetDigester);
448:                    } finally {
449:                        // Put the unwrapped rules back
450:                        targetDigester.setRules(digesterRules);
451:                    }
452:                }
453:            }
454:
455:            /**
456:             * Wraps a Rules object. Delegates all the Rules interface methods
457:             * to the underlying Rules object. Overrides the add method to prepend
458:             * a prefix to the pattern string.
459:             */
460:            private class RulesPrefixAdapter implements  Rules {
461:
462:                private Rules delegate;
463:                private String prefix;
464:
465:                /**
466:                 * @param patternPrefix the pattern string to prepend to the pattern
467:                 * passed to the add method.
468:                 * @param rules The wrapped Rules object. All of this class's methods
469:                 * pass through to this object.
470:                 */
471:                public RulesPrefixAdapter(String patternPrefix, Rules rules) {
472:                    prefix = patternPrefix;
473:                    delegate = rules;
474:                }
475:
476:                /**
477:                 * Register a new Rule instance matching a pattern which is constructed
478:                 * by concatenating the pattern prefix with the given pattern.
479:                 */
480:                public void add(String pattern, Rule rule) {
481:                    StringBuffer buffer = new StringBuffer();
482:                    buffer.append(prefix);
483:                    if (!pattern.startsWith("/")) {
484:                        buffer.append('/');
485:                    }
486:                    buffer.append(pattern);
487:                    delegate.add(buffer.toString(), rule);
488:                }
489:
490:                /**
491:                 * This method passes through to the underlying Rules object.
492:                 */
493:                public void clear() {
494:                    delegate.clear();
495:                }
496:
497:                /**
498:                 * This method passes through to the underlying Rules object.
499:                 */
500:                public Digester getDigester() {
501:                    return delegate.getDigester();
502:                }
503:
504:                /**
505:                 * This method passes through to the underlying Rules object.
506:                 */
507:                public String getNamespaceURI() {
508:                    return delegate.getNamespaceURI();
509:                }
510:
511:                /**
512:                 * @deprecated Call match(namespaceURI,pattern) instead.
513:                 */
514:                public List match(String pattern) {
515:                    return delegate.match(pattern);
516:                }
517:
518:                /**
519:                 * This method passes through to the underlying Rules object.
520:                 */
521:                public List match(String namespaceURI, String pattern) {
522:                    return delegate.match(namespaceURI, pattern);
523:                }
524:
525:                /**
526:                 * This method passes through to the underlying Rules object.
527:                 */
528:                public List rules() {
529:                    return delegate.rules();
530:                }
531:
532:                /**
533:                 * This method passes through to the underlying Rules object.
534:                 */
535:                public void setDigester(Digester digester) {
536:                    delegate.setDigester(digester);
537:                }
538:
539:                /**
540:                 * This method passes through to the underlying Rules object.
541:                 */
542:                public void setNamespaceURI(String namespaceURI) {
543:                    delegate.setNamespaceURI(namespaceURI);
544:                }
545:            }
546:
547:            ///////////////////////////////////////////////////////////////////////
548:            // Classes beyond this point are ObjectCreationFactory implementations,
549:            // used to create Rule objects and initialize them from SAX attributes.
550:            ///////////////////////////////////////////////////////////////////////
551:
552:            /**
553:             * Factory for creating a BeanPropertySetterRule.
554:             */
555:            private class BeanPropertySetterRuleFactory extends
556:                    AbstractObjectCreationFactory {
557:                public Object createObject(Attributes attributes)
558:                        throws Exception {
559:                    Rule beanPropertySetterRule = null;
560:                    String propertyname = attributes.getValue("propertyname");
561:
562:                    if (propertyname == null) {
563:                        // call the setter method corresponding to the element name.
564:                        beanPropertySetterRule = new BeanPropertySetterRule();
565:                    } else {
566:                        beanPropertySetterRule = new BeanPropertySetterRule(
567:                                propertyname);
568:                    }
569:
570:                    return beanPropertySetterRule;
571:                }
572:
573:            }
574:
575:            /**
576:             * Factory for creating a CallMethodRule.
577:             */
578:            protected class CallMethodRuleFactory extends
579:                    AbstractObjectCreationFactory {
580:                public Object createObject(Attributes attributes) {
581:                    Rule callMethodRule = null;
582:                    String methodName = attributes.getValue("methodname");
583:
584:                    // Select which element is to be the target. Default to zero,
585:                    // ie the top object on the stack.
586:                    int targetOffset = 0;
587:                    String targetOffsetStr = attributes
588:                            .getValue("targetoffset");
589:                    if (targetOffsetStr != null) {
590:                        targetOffset = Integer.parseInt(targetOffsetStr);
591:                    }
592:
593:                    if (attributes.getValue("paramcount") == null) {
594:                        // call against empty method
595:                        callMethodRule = new CallMethodRule(targetOffset,
596:                                methodName);
597:
598:                    } else {
599:                        int paramCount = Integer.parseInt(attributes
600:                                .getValue("paramcount"));
601:
602:                        String paramTypesAttr = attributes
603:                                .getValue("paramtypes");
604:                        if (paramTypesAttr == null
605:                                || paramTypesAttr.length() == 0) {
606:                            callMethodRule = new CallMethodRule(targetOffset,
607:                                    methodName, paramCount);
608:                        } else {
609:                            String[] paramTypes = getParamTypes(paramTypesAttr);
610:                            callMethodRule = new CallMethodRule(targetOffset,
611:                                    methodName, paramCount, paramTypes);
612:                        }
613:                    }
614:                    return callMethodRule;
615:                }
616:
617:                /**
618:                 * Process the comma separated list of paramTypes
619:                 * into an array of String class names
620:                 */
621:                private String[] getParamTypes(String paramTypes) {
622:                    String[] paramTypesArray;
623:                    if (paramTypes != null) {
624:                        ArrayList paramTypesList = new ArrayList();
625:                        StringTokenizer tokens = new StringTokenizer(
626:                                paramTypes, " \t\n\r,");
627:                        while (tokens.hasMoreTokens()) {
628:                            paramTypesList.add(tokens.nextToken());
629:                        }
630:                        paramTypesArray = (String[]) paramTypesList
631:                                .toArray(new String[0]);
632:                    } else {
633:                        paramTypesArray = new String[0];
634:                    }
635:                    return paramTypesArray;
636:                }
637:            }
638:
639:            /**
640:             * Factory for creating a CallParamRule.
641:             */
642:            protected class CallParamRuleFactory extends
643:                    AbstractObjectCreationFactory {
644:
645:                public Object createObject(Attributes attributes) {
646:                    // create callparamrule
647:                    int paramIndex = Integer.parseInt(attributes
648:                            .getValue("paramnumber"));
649:                    String attributeName = attributes.getValue("attrname");
650:                    String fromStack = attributes.getValue("from-stack");
651:                    String stackIndex = attributes.getValue("stack-index");
652:                    Rule callParamRule = null;
653:
654:                    if (attributeName == null) {
655:                        if (stackIndex != null) {
656:                            callParamRule = new CallParamRule(paramIndex,
657:                                    Integer.parseInt(stackIndex));
658:                        } else if (fromStack != null) {
659:                            callParamRule = new CallParamRule(paramIndex,
660:                                    Boolean.valueOf(fromStack).booleanValue());
661:                        } else {
662:                            callParamRule = new CallParamRule(paramIndex);
663:                        }
664:                    } else {
665:                        if (fromStack == null) {
666:                            callParamRule = new CallParamRule(paramIndex,
667:                                    attributeName);
668:                        } else {
669:                            // specifying both from-stack and attribute name is not allowed
670:                            throw new RuntimeException(
671:                                    "Attributes from-stack and attrname cannot both be present.");
672:                        }
673:                    }
674:                    return callParamRule;
675:                }
676:            }
677:
678:            /**
679:             * Factory for creating a ObjectParamRule
680:             */
681:            protected class ObjectParamRuleFactory extends
682:                    AbstractObjectCreationFactory {
683:                public Object createObject(Attributes attributes)
684:                        throws Exception {
685:                    // create callparamrule
686:                    int paramIndex = Integer.parseInt(attributes
687:                            .getValue("paramnumber"));
688:                    String attributeName = attributes.getValue("attrname");
689:                    String type = attributes.getValue("type");
690:                    String value = attributes.getValue("value");
691:
692:                    Rule objectParamRule = null;
693:
694:                    // type name is requried
695:                    if (type == null) {
696:                        throw new RuntimeException(
697:                                "Attribute 'type' is required.");
698:                    }
699:
700:                    // create object instance
701:                    Object param = null;
702:                    Class clazz = Class.forName(type);
703:                    if (value == null) {
704:                        param = clazz.newInstance();
705:                    } else {
706:                        param = ConvertUtils.convert(value, clazz);
707:                    }
708:
709:                    if (attributeName == null) {
710:                        objectParamRule = new ObjectParamRule(paramIndex, param);
711:                    } else {
712:                        objectParamRule = new ObjectParamRule(paramIndex,
713:                                attributeName, param);
714:                    }
715:                    return objectParamRule;
716:                }
717:            }
718:
719:            /**
720:             * Factory for creating a NodeCreateRule
721:             */
722:            protected class NodeCreateRuleFactory extends
723:                    AbstractObjectCreationFactory {
724:
725:                public Object createObject(Attributes attributes)
726:                        throws Exception {
727:
728:                    String nodeType = attributes.getValue("type");
729:                    if (nodeType == null || "".equals(nodeType)) {
730:
731:                        // uses Node.ELEMENT_NODE
732:                        return new NodeCreateRule();
733:                    } else if ("element".equals(nodeType)) {
734:
735:                        return new NodeCreateRule(Node.ELEMENT_NODE);
736:                    } else if ("fragment".equals(nodeType)) {
737:
738:                        return new NodeCreateRule(Node.DOCUMENT_FRAGMENT_NODE);
739:                    } else {
740:
741:                        throw new RuntimeException(
742:                                "Unrecognized node type: "
743:                                        + nodeType
744:                                        + ".  This attribute is optional or can have a value of element|fragment.");
745:                    }
746:                }
747:            }
748:
749:            /**
750:             * Factory for creating a FactoryCreateRule
751:             */
752:            protected class FactoryCreateRuleFactory extends
753:                    AbstractObjectCreationFactory {
754:                public Object createObject(Attributes attributes) {
755:                    String className = attributes.getValue("classname");
756:                    String attrName = attributes.getValue("attrname");
757:                    boolean ignoreExceptions = "true"
758:                            .equalsIgnoreCase(attributes
759:                                    .getValue("ignore-exceptions"));
760:                    return (attrName == null || attrName.length() == 0) ? new FactoryCreateRule(
761:                            className, ignoreExceptions)
762:                            : new FactoryCreateRule(className, attrName,
763:                                    ignoreExceptions);
764:                }
765:            }
766:
767:            /**
768:             * Factory for creating a ObjectCreateRule
769:             */
770:            protected class ObjectCreateRuleFactory extends
771:                    AbstractObjectCreationFactory {
772:                public Object createObject(Attributes attributes) {
773:                    String className = attributes.getValue("classname");
774:                    String attrName = attributes.getValue("attrname");
775:                    return (attrName == null || attrName.length() == 0) ? new ObjectCreateRule(
776:                            className)
777:                            : new ObjectCreateRule(className, attrName);
778:                }
779:            }
780:
781:            /**
782:             * Factory for creating a SetPropertiesRule
783:             */
784:            protected class SetPropertiesRuleFactory extends
785:                    AbstractObjectCreationFactory {
786:                public Object createObject(Attributes attributes) {
787:                    return new SetPropertiesRule();
788:                }
789:            }
790:
791:            /**
792:             * Factory for creating a SetPropertyRule
793:             */
794:            protected class SetPropertyRuleFactory extends
795:                    AbstractObjectCreationFactory {
796:                public Object createObject(Attributes attributes) {
797:                    String name = attributes.getValue("name");
798:                    String value = attributes.getValue("value");
799:                    return new SetPropertyRule(name, value);
800:                }
801:            }
802:
803:            /**
804:             * Factory for creating a SetNestedPropertiesRule
805:             */
806:            protected class SetNestedPropertiesRuleFactory extends
807:                    AbstractObjectCreationFactory {
808:                public Object createObject(Attributes attributes) {
809:                    boolean allowUnknownChildElements = "true"
810:                            .equalsIgnoreCase(attributes
811:                                    .getValue("allow-unknown-child-elements"));
812:                    SetNestedPropertiesRule snpr = new SetNestedPropertiesRule();
813:                    snpr
814:                            .setAllowUnknownChildElements(allowUnknownChildElements);
815:                    return snpr;
816:                }
817:            }
818:
819:            /**
820:             * Factory for creating a SetTopRuleFactory
821:             */
822:            protected class SetTopRuleFactory extends
823:                    AbstractObjectCreationFactory {
824:                public Object createObject(Attributes attributes) {
825:                    String methodName = attributes.getValue("methodname");
826:                    String paramType = attributes.getValue("paramtype");
827:                    return (paramType == null || paramType.length() == 0) ? new SetTopRule(
828:                            methodName)
829:                            : new SetTopRule(methodName, paramType);
830:                }
831:            }
832:
833:            /**
834:             * Factory for creating a SetNextRuleFactory
835:             */
836:            protected class SetNextRuleFactory extends
837:                    AbstractObjectCreationFactory {
838:                public Object createObject(Attributes attributes) {
839:                    String methodName = attributes.getValue("methodname");
840:                    String paramType = attributes.getValue("paramtype");
841:                    return (paramType == null || paramType.length() == 0) ? new SetNextRule(
842:                            methodName)
843:                            : new SetNextRule(methodName, paramType);
844:                }
845:            }
846:
847:            /**
848:             * Factory for creating a SetRootRuleFactory
849:             */
850:            protected class SetRootRuleFactory extends
851:                    AbstractObjectCreationFactory {
852:                public Object createObject(Attributes attributes) {
853:                    String methodName = attributes.getValue("methodname");
854:                    String paramType = attributes.getValue("paramtype");
855:                    return (paramType == null || paramType.length() == 0) ? new SetRootRule(
856:                            methodName)
857:                            : new SetRootRule(methodName, paramType);
858:                }
859:            }
860:
861:            /**
862:             * A rule for adding a attribute-property alias to the custom alias mappings of
863:             * the containing SetPropertiesRule rule.
864:             */
865:            protected class SetPropertiesAliasRule extends Rule {
866:
867:                /**
868:                 * <p>Base constructor.</p>
869:                 */
870:                public SetPropertiesAliasRule() {
871:                    super ();
872:                }
873:
874:                /**
875:                 * Add the alias to the SetPropertiesRule object created by the
876:                 * enclosing <set-properties-rule> tag.
877:                 */
878:                public void begin(Attributes attributes) {
879:                    String attrName = attributes.getValue("attr-name");
880:                    String propName = attributes.getValue("prop-name");
881:
882:                    SetPropertiesRule rule = (SetPropertiesRule) digester
883:                            .peek();
884:                    rule.addAlias(attrName, propName);
885:                }
886:            }
887:
888:            /**
889:             * A rule for adding a attribute-property alias to the custom alias mappings of
890:             * the containing SetNestedPropertiesRule rule.
891:             */
892:            protected class SetNestedPropertiesAliasRule extends Rule {
893:
894:                /**
895:                 * <p>Base constructor.</p>
896:                 */
897:                public SetNestedPropertiesAliasRule() {
898:                    super ();
899:                }
900:
901:                /**
902:                 * Add the alias to the SetNestedPropertiesRule object created by the
903:                 * enclosing <set-nested-properties-rule> tag.
904:                 */
905:                public void begin(Attributes attributes) {
906:                    String attrName = attributes.getValue("attr-name");
907:                    String propName = attributes.getValue("prop-name");
908:
909:                    SetNestedPropertiesRule rule = (SetNestedPropertiesRule) digester
910:                            .peek();
911:                    rule.addAlias(attrName, propName);
912:                }
913:            }
914:
915:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.