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


001:        /*
002:         * Copyright 1999-2004 The Apache Software Foundation
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.apache.commons.jxpath;
017:
018:        import java.text.DecimalFormatSymbols;
019:        import java.util.ArrayList;
020:        import java.util.HashMap;
021:        import java.util.Iterator;
022:        import java.util.List;
023:        import java.util.Locale;
024:
025:        /**
026:         * JXPathContext  provides APIs for the traversal of graphs of JavaBeans using
027:         * the XPath syntax. Using JXPathContext, you can read and write properties of
028:         * JavaBeans, arrays, collections and maps. JXPathContext uses JavaBeans
029:         * introspection to enumerate and access JavaBeans properties.
030:         * <p>
031:         * JXPathContext  allows alternative implementations. This is why instead of
032:         * allocating JXPathContext directly, you should call a static
033:         * <code>newContext</code> method.  This method will utilize the
034:         * JXPathContextFactory API to locate a suitable implementation of JXPath.
035:         * Bundled with JXPath comes a default implementation called Reference
036:         * Implementation.
037:         * </p>
038:         *
039:         * <h2>JXPath Interprets XPath Syntax on Java Object Graphs</h2>
040:         *
041:         * JXPath uses an intuitive interpretation of the xpath syntax in the context
042:         * of Java object graphs. Here are some examples:
043:         *
044:         * <h3>Example 1: JavaBean Property Access</h3>
045:         *
046:         * JXPath can be used to access properties of a JavaBean.
047:         *
048:         * <pre><blockquote>
049:         * public class Employee {
050:         *    public String getFirstName(){
051:         *       ...
052:         *    }
053:         * }
054:         *
055:         * Employee emp = new Employee();
056:         * ...
057:         *
058:         * JXPathContext context = JXPathContext.newContext(emp);
059:         * String fName = (String)context.getValue("firstName");
060:         * </blockquote></pre>
061:         *
062:         * In  this example, we are using JXPath to access a property of the
063:         * <code>emp</code> bean. In this simple case the invocation of JXPath is
064:         * equivalent to invocation of getFirstName() on the bean.
065:         *
066:         * <h3>Example 2: Nested Bean Property Access</h3>
067:         * JXPath can traverse object graphs:
068:         *
069:         * <pre><blockquote>
070:         * public class Employee {
071:         *    public Address getHomeAddress(){
072:         *       ...
073:         *    }
074:         * }
075:         * public class Address {
076:         *    public String getStreetNumber(){
077:         *       ...
078:         *    }
079:         * }
080:         *
081:         * Employee emp = new Employee();
082:         * ...
083:         *
084:         * JXPathContext context = JXPathContext.newContext(emp);
085:         * String sNumber = (String)context.getValue("homeAddress/streetNumber");
086:         * </blockquote></pre>
087:         *
088:         * In this case XPath is used to access a property of a nested bean.
089:         * <p>
090:         * A property identified by the xpath does not have to be a "leaf" property.
091:         * For instance, we can extract the whole Address object in above example:
092:         *
093:         * <pre><blockquote>
094:         *    Address addr = (Address)context.getValue("homeAddress");
095:         * </blockquote></pre>
096:         * </p>
097:         *
098:         * <h3>Example 3: Collection Subscripts</h3>
099:         * JXPath can extract elements from arrays and collections.
100:         *
101:         * <pre><blockquote>
102:         * public class Integers {
103:         *    public int[] getNumbers(){
104:         *       ...
105:         *    }
106:         * }
107:         *
108:         * Integers ints = new Integers();
109:         * ...
110:         *
111:         * JXPathContext context = JXPathContext.newContext(ints);
112:         * Integer thirdInt = (Integer)context.getValue("numbers[3]");
113:         * </blockquote></pre>
114:         * A  collection can be an arbitrary array or an instance of java.util.
115:         * Collection.
116:         * <p>
117:         * Note: in XPath the first element of a collection has index 1, not 0.<br>
118:         *
119:         * <h3>Example 4: Map Element Access</h3>
120:         *
121:         * JXPath supports maps. To get a value use its key.
122:         *
123:         * <pre><blockquote>
124:         * public class Employee {
125:         *    public Map getAddresses(){
126:         *       return addressMap;
127:         *    }
128:         *
129:         *    public void addAddress(String key, Address address){
130:         *       addressMap.put(key, address);
131:         *    }
132:         *    ...
133:         * }
134:         *
135:         * Employee emp = new Employee();
136:         * emp.addAddress("home", new Address(...));
137:         * emp.addAddress("office", new Address(...));
138:         * ...
139:         *
140:         * JXPathContext context = JXPathContext.newContext(emp);
141:         * String homeZipCode = (String)context.getValue("addresses/home/zipCode");
142:         * </blockquote></pre>
143:         *
144:         * Often you will need to use the alternative syntax for accessing Map
145:         * elements:
146:         *
147:         * <pre><blockquote>
148:         * String homeZipCode = 
149:         *     (String) context.getValue("addresses[@name='home']/zipCode");
150:         * </blockquote></pre>
151:         *
152:         * In this case, the key can be an expression, e.g. a variable.<br>
153:         *
154:         * Note: At this point JXPath only supports Maps that use strings for keys.<br>
155:         * Note: JXPath supports the extended notion of Map: any object with
156:         *       dynamic properties can be handled by JXPath provided that its
157:         *       class is registered with the {@link JXPathIntrospector}.
158:         *
159:         * <h3>Example 5: Retrieving Multiple Results</h3>
160:         *
161:         * JXPath can retrieve multiple objects from a graph. Note that the method
162:         * called in this case is not <code>getValue</code>, but <code>iterate</code>.
163:         *
164:         * <pre><blockquote>
165:         * public class Author {
166:         *    public Book[] getBooks(){
167:         *       ...
168:         *    }
169:         * }
170:         *
171:         * Author auth = new Author();
172:         * ...
173:         *
174:         * JXPathContext context = JXPathContext.newContext(auth);
175:         * Iterator threeBooks = context.iterate("books[position() &lt; 4]");
176:         * </blockquote></pre>
177:         *
178:         * This returns a list of at most three books from the array of all books
179:         * written by the author.
180:         *
181:         * <h3>Example 6: Setting Properties</h3>
182:         * JXPath can be used to modify property values.
183:         *
184:         * <pre><blockquote>
185:         * public class Employee {
186:         *    public Address getAddress() {
187:         *       ...
188:         *    }
189:         *
190:         *    public void setAddress(Address address) {
191:         *       ...
192:         *    }
193:         * }
194:         *
195:         * Employee emp = new Employee();
196:         * Address addr = new Address();
197:         * ...
198:         *
199:         * JXPathContext context = JXPathContext.newContext(emp);
200:         * context.setValue("address", addr);
201:         * context.setValue("address/zipCode", "90190");
202:         *
203:         * </blockquote></pre>
204:         *
205:         * <h3>Example 7: Creating objects</h3>
206:         * JXPath  can be used to create new objects. First, create a subclass of {@link
207:         * AbstractFactory AbstractFactory} and install it on the JXPathContext. Then
208:         * call {@link JXPathContext#createPath createPathAndSetValue()} instead of
209:         * "setValue". JXPathContext will invoke your AbstractFactory when it discovers
210:         * that an intermediate node of the path is <b>null</b>.  It will not override
211:         * existing nodes.
212:         *
213:         * <pre><blockquote>
214:         * public class AddressFactory extends AbstractFactory {
215:         *    public boolean createObject(JXPathContext context, 
216:         *               Pointer pointer, Object parent, String name, int index){
217:         *     if ((parent instanceof Employee) &amp;&amp; name.equals("address"){
218:         *       ((Employee)parent).setAddress(new Address());
219:         *       return true;
220:         *     }
221:         *     return false;
222:         *   }
223:         * }
224:         *
225:         * JXPathContext context = JXPathContext.newContext(emp);
226:         * context.setFactory(new AddressFactory());
227:         * context.createPathAndSetValue("address/zipCode", "90190");
228:         * </blockquote></pre>
229:         *
230:         * <h3>Example 8: Using Variables</h3>
231:         * JXPath supports the notion of variables. The XPath syntax for accessing
232:         * variables is <i>"$varName"</i>.
233:         *
234:         * <pre><blockquote>
235:         * public class Author {
236:         *    public Book[] getBooks(){
237:         *       ...
238:         *    }
239:         * }
240:         *
241:         * Author auth = new Author();
242:         * ...
243:         *
244:         * JXPathContext context = JXPathContext.newContext(auth);
245:         * context.getVariables().declareVariable("index", new Integer(2));
246:         *
247:         * Book secondBook = (Book)context.getValue("books[$index]");
248:         * </blockquote></pre>
249:         *
250:         * You can also set variables using JXPath:
251:         *
252:         * <pre><blockquote>
253:         * context.setValue("$index", new Integer(3));
254:         * </blockquote></pre>
255:         *
256:         * Note: you can only <i>change</i> the value of an existing variable this
257:         * way, you cannot <i>define</i> a new variable.
258:         *
259:         * <p>
260:         * When a variable contains a JavaBean or a collection, you can
261:         * traverse the bean or collection as well:
262:         * <pre><blockquote>
263:         * ...
264:         * context.getVariables().declareVariable("book", myBook);
265:         * String title = (String)context.getValue("$book/title);
266:         *
267:         * Book array[] = new Book[]{...};
268:         *
269:         * context.getVariables().declareVariable("books", array);
270:         *
271:         * String title = (String)context.getValue("$books[2]/title);
272:         * </blockquote></pre>
273:         *
274:         * <h3>Example 9: Using Nested Contexts</h3>
275:         * If  you need to use the same set of variable while interpreting XPaths with
276:         * different beans, it makes sense to put the variables in a separate context
277:         * and specify that context as a parent context every time you allocate a new
278:         * JXPathContext for a JavaBean.
279:         *
280:         * <pre><blockquote>
281:         * JXPathContext varContext = JXPathContext.newContext(null);
282:         * varContext.getVariables().declareVariable("title", "Java");
283:         *
284:         * JXPathContext context = JXPathContext.newContext(varContext, auth);
285:         *
286:         * Iterator javaBooks = context.iterate("books[title = $title]");
287:         * </blockquote></pre>
288:         *
289:         * <h3>Using Custom Variable Pools</h3>
290:         * By default, JXPathContext creates a HashMap of variables. However,
291:         * you can substitute a custom implementation of the Variables
292:         * interface to make JXPath work with an alternative source of variables.
293:         * For example, you can define implementations of Variables that
294:         * cover a servlet context, HTTP request or any similar structure.
295:         *
296:         * <h3>Example 10: Using Standard Extension Functions</h3>
297:         * Using the standard extension functions, you can call methods on objects,
298:         * static methods on classes and create objects using any constructor.
299:         * The class names should be fully qualified.
300:         * <p>
301:         * Here's how you can create new objects:
302:         * <pre><blockquote>
303:         * Book book = 
304:         *    (Book) context.getValue(
305:         *         "org.apache.commons.jxpath.example.Book.new ('John Updike')");
306:         * </blockquote></pre>
307:         *
308:         * Here's how you can call static methods:
309:         * <pre><blockquote>
310:         *   Book book = 
311:         *    (Book) context.getValue( 
312:         *       "org. apache.commons.jxpath.example.Book.getBestBook('John Updike')");
313:         * </blockquote></pre>
314:         *
315:         * Here's how you can call regular methods:
316:         * <pre><blockquote>
317:         * String firstName = (String)context.getValue("getAuthorsFirstName($book)");
318:         * </blockquote></pre>
319:         * As you can see, the target of the method is specified as the first parameter
320:         * of the function.
321:         *
322:         * <h3>Example 11: Using Custom Extension Functions</h3>
323:         * Collections of custom extension functions can be implemented
324:         * as {@link Functions Functions} objects or as Java classes, whose methods
325:         * become extenstion functions.
326:         * <p>
327:         * Let's say the following class implements various formatting operations:
328:         * <pre><blockquote>
329:         * public class Formats {
330:         *    public static String date(Date d, String pattern){
331:         *        return new SimpleDateFormat(pattern).format(d);
332:         *    }
333:         *    ...
334:         * }
335:         * </blockquote></pre>
336:         *
337:         * We can register this class with a JXPathContext:
338:         *
339:         * <pre><blockquote>
340:         * context.setFunctions(new ClassFunctions(Formats.class, "format"));
341:         * ...
342:         *
343:         * context.getVariables().declareVariable("today", new Date());
344:         * String today = (String)context.getValue("format:date($today, 'MM/dd/yyyy')");
345:         *
346:         * </blockquote></pre>
347:         * You can also register whole packages of Java classes using PackageFunctions.
348:         * <p>
349:         * Also, see {@link FunctionLibrary FunctionLibrary}, which is a class
350:         * that allows you to register multiple sets of extension functions with
351:         * the same JXPathContext.
352:         *
353:         * <h2>Configuring JXPath</h2>
354:         *
355:         * JXPath uses JavaBeans introspection to discover properties of JavaBeans.
356:         * You can provide alternative property lists by supplying
357:         * custom JXPathBeanInfo classes (see {@link JXPathBeanInfo JXPathBeanInfo}).
358:         *
359:         * <h2>Notes</h2>
360:         * <ul>
361:         * <li> JXPath does not support DOM attributes for non-DOM objects. Even though
362:         * XPaths like "para[@type='warning']" are legitimate, they will always produce
363:         * empty results. The only attribute supported for JavaBeans is "name".  The
364:         * XPath "foo/bar" is equivalent to "foo[@name='bar']".
365:         * </ul>
366:         *
367:         * See  <a href="http://www.w3schools.com/xpath">XPath Tutorial by
368:         * W3Schools</a><br>. Also see <a href="http://www.w3.org/TR/xpath">XML Path
369:         * Language (XPath) Version 1.0</a><br><br> 
370:         * 
371:         * You will also find more information and examples in
372:         * <a href="http://jakarta.apache.org/commons/jxpath/users-guide.html">
373:         * JXPath User's Guide</a>
374:         *
375:         *
376:         * @author Dmitri Plotnikov
377:         * @version $Revision: 1.25 $ $Date: 2004/06/29 21:15:46 $
378:         */
379:        public abstract class JXPathContext {
380:            protected JXPathContext parentContext;
381:            protected Object contextBean;
382:            protected Variables vars;
383:            protected Functions functions;
384:            protected AbstractFactory factory;
385:            private Locale locale;
386:            private boolean lenientSet = false;
387:            private boolean lenient = false;
388:            protected IdentityManager idManager;
389:            protected KeyManager keyManager;
390:            protected HashMap decimalFormats;
391:
392:            private static JXPathContextFactory contextFactory;
393:            private static JXPathContext compilationContext;
394:
395:            private static final PackageFunctions GENERIC_FUNCTIONS = new PackageFunctions(
396:                    "", null);
397:
398:            /**
399:             * Creates a new JXPathContext with the specified object as the root node.
400:             */
401:            public static JXPathContext newContext(Object contextBean) {
402:                return getContextFactory().newContext(null, contextBean);
403:            }
404:
405:            /**
406:             * Creates a new JXPathContext with the specified bean as the root node and
407:             * the specified parent context. Variables defined in a parent context can
408:             * be referenced in XPaths passed to the child context.
409:             */
410:            public static JXPathContext newContext(JXPathContext parentContext,
411:                    Object contextBean) {
412:                return getContextFactory().newContext(parentContext,
413:                        contextBean);
414:            }
415:
416:            /**
417:             * Acquires a context factory and caches it. 
418:             */
419:            private static JXPathContextFactory getContextFactory() {
420:                if (contextFactory == null) {
421:                    contextFactory = JXPathContextFactory.newInstance();
422:                }
423:                return contextFactory;
424:            }
425:
426:            /**
427:             * This  constructor should remain protected - it is to be overridden by
428:             * subclasses, but never explicitly invoked by clients.
429:             */
430:            protected JXPathContext(JXPathContext parentContext,
431:                    Object contextBean) {
432:                this .parentContext = parentContext;
433:                this .contextBean = contextBean;
434:            }
435:
436:            /**
437:             * Returns the parent context of this context or null.
438:             */
439:            public JXPathContext getParentContext() {
440:                return parentContext;
441:            }
442:
443:            /**
444:             * Returns the JavaBean associated with this context.
445:             */
446:            public Object getContextBean() {
447:                return contextBean;
448:            }
449:
450:            /**
451:             * Returns a Pointer for the context bean.
452:             */
453:            public abstract Pointer getContextPointer();
454:
455:            /**
456:             * Returns a JXPathContext that is relative to the current JXPathContext.
457:             * The supplied pointer becomes the context pointer of the new context.
458:             * The relative context inherits variables, extension functions, locale etc
459:             * from the parent context.
460:             */
461:            public abstract JXPathContext getRelativeContext(Pointer pointer);
462:
463:            /**
464:             * Installs a custom implementation of the Variables interface.
465:             */
466:            public void setVariables(Variables vars) {
467:                this .vars = vars;
468:            }
469:
470:            /**
471:             * Returns the variable pool associated with the context. If no such
472:             * pool was specified with the <code>setVariables()</code> method,
473:             * returns the default implementation of Variables,
474:             * {@link BasicVariables BasicVariables}.
475:             */
476:            public Variables getVariables() {
477:                if (vars == null) {
478:                    vars = new BasicVariables();
479:                }
480:                return vars;
481:            }
482:
483:            /**
484:             * Install a library of extension functions.
485:             *
486:             * @see FunctionLibrary
487:             */
488:            public void setFunctions(Functions functions) {
489:                this .functions = functions;
490:            }
491:
492:            /**
493:             * Returns the set of functions installed on the context.
494:             */
495:            public Functions getFunctions() {
496:                if (functions != null) {
497:                    return functions;
498:                }
499:                if (parentContext == null) {
500:                    return GENERIC_FUNCTIONS;
501:                }
502:                return null;
503:            }
504:
505:            /**
506:             * Install an abstract factory that should be used by the
507:             * <code>createPath()</code> and <code>createPathAndSetValue()</code>
508:             * methods.
509:             */
510:            public void setFactory(AbstractFactory factory) {
511:                this .factory = factory;
512:            }
513:
514:            /**
515:             * Returns the AbstractFactory installed on this context.
516:             * If none has been installed and this context has a parent context,
517:             * returns the parent's factory.  Otherwise returns null.
518:             */
519:            public AbstractFactory getFactory() {
520:                if (factory == null && parentContext != null) {
521:                    return parentContext.getFactory();
522:                }
523:                return factory;
524:            }
525:
526:            /**
527:             * Set the locale for this context.  The value of the "lang"
528:             * attribute as well as the the lang() function will be
529:             * affected by the locale.  By default, JXPath uses
530:             * <code>Locale.getDefault()</code>
531:             */
532:            public void setLocale(Locale locale) {
533:                this .locale = locale;
534:            }
535:
536:            /**
537:             * Returns the locale set with setLocale. If none was set and
538:             * the context has a parent, returns the parent's locale.
539:             * Otherwise, returns Locale.getDefault().
540:             */
541:            public Locale getLocale() {
542:                if (locale == null) {
543:                    if (parentContext != null) {
544:                        return parentContext.getLocale();
545:                    } else {
546:                        locale = Locale.getDefault();
547:                    }
548:                }
549:                return locale;
550:            }
551:
552:            /**
553:             * Sets DecimalFormatSymbols for a given name. The DecimalFormatSymbols can
554:             * be referenced as the third, optional argument in the invocation of
555:             * <code>format-number (number,format,decimal-format-name)</code> function.
556:             * By default, JXPath uses the symbols for the current locale.
557:             * 
558:             * @param name the format name or null for default format.
559:             */
560:            public void setDecimalFormatSymbols(String name,
561:                    DecimalFormatSymbols symbols) {
562:                if (decimalFormats == null) {
563:                    decimalFormats = new HashMap();
564:                }
565:                decimalFormats.put(name, symbols);
566:            }
567:
568:            /**
569:             * @see #setDecimalFormatSymbols(String, DecimalFormatSymbols)
570:             */
571:            public DecimalFormatSymbols getDecimalFormatSymbols(String name) {
572:                if (decimalFormats == null) {
573:                    if (parentContext != null) {
574:                        return parentContext.getDecimalFormatSymbols(name);
575:                    }
576:                    return null;
577:                }
578:                return (DecimalFormatSymbols) decimalFormats.get(name);
579:            }
580:
581:            /**
582:             * If the context is in the lenient mode, then getValue() returns null
583:             * for inexistent paths.  Otherwise, a path that does not map to
584:             * an existing property will throw an exception.  Note that if the
585:             * property exists, but its value is null, the exception is <i>not</i>
586:             * thrown.
587:             * <p>
588:             * By default, lenient = false
589:             */
590:            public void setLenient(boolean lenient) {
591:                this .lenient = lenient;
592:                lenientSet = true;
593:            }
594:
595:            /**
596:             * @see #setLenient(boolean)
597:             */
598:            public boolean isLenient() {
599:                if (!lenientSet && parentContext != null) {
600:                    return parentContext.isLenient();
601:                }
602:                return lenient;
603:            }
604:
605:            /**
606:             * Compiles the supplied XPath and returns an internal representation
607:             * of the path that can then be evaluated.  Use CompiledExpressions
608:             * when you need to evaluate the same expression multiple times
609:             * and there is a convenient place to cache CompiledExpression
610:             * between invocations.
611:             */
612:            public static CompiledExpression compile(String xpath) {
613:                if (compilationContext == null) {
614:                    compilationContext = JXPathContext.newContext(null);
615:                }
616:                return compilationContext.compilePath(xpath);
617:            }
618:
619:            /**
620:             * Overridden by each concrete implementation of JXPathContext
621:             * to perform compilation. Is called by <code>compile()</code>.
622:             */
623:            protected abstract CompiledExpression compilePath(String xpath);
624:
625:            /**
626:             * Finds the first object that matches the specified XPath. It is equivalent
627:             * to <code>getPointer(xpath).getNode()</code>. Note, that this method
628:             * produces the same result as <code>getValue()</code> on object models
629:             * like JavaBeans, but a different result for DOM/JDOM etc., because it
630:             * returns the Node itself, rather than its textual contents.
631:             * 
632:             * @param xpath the xpath to be evaluated
633:             * @return the found object
634:             */
635:            public Object selectSingleNode(String xpath) {
636:                Pointer pointer = getPointer(xpath);
637:                if (pointer == null) {
638:                    return null;
639:                }
640:                return pointer.getNode();
641:            }
642:
643:            /**
644:             * Finds all nodes that match the specified XPath. 
645:             *   
646:             * @param xpath the xpath to be evaluated
647:             * @return a list of found objects
648:             */
649:            public List selectNodes(String xpath) {
650:                ArrayList list = new ArrayList();
651:                Iterator iterator = iteratePointers(xpath);
652:                while (iterator.hasNext()) {
653:                    Pointer pointer = (Pointer) iterator.next();
654:                    list.add(pointer.getNode());
655:                }
656:                return list;
657:            }
658:
659:            /**
660:             * Evaluates the xpath and returns the resulting object. Primitive
661:             * types are wrapped into objects.
662:             */
663:            public abstract Object getValue(String xpath);
664:
665:            /**
666:             * Evaluates the xpath, converts the result to the specified class and
667:             * returns the resulting object.
668:             */
669:            public abstract Object getValue(String xpath, Class requiredType);
670:
671:            /**
672:             * Modifies the value of the property described by the supplied xpath.
673:             * Will throw an exception if one of the following conditions occurs:
674:             * <ul>
675:             * <li>The xpath does not in fact describe an existing property
676:             * <li>The property is not writable (no public, non-static set method)
677:             * </ul>
678:             */
679:            public abstract void setValue(String xpath, Object value);
680:
681:            /**
682:             * Creates missing elements of the path by invoking an AbstractFactory,
683:             * which should first be installed on the context by calling "setFactory".
684:             * <p>
685:             * Will throw an exception if the AbstractFactory fails to create
686:             * an instance for a path element.
687:             */
688:            public abstract Pointer createPath(String xpath);
689:
690:            /**
691:             * The same as setValue, except it creates intermediate elements of
692:             * the path by invoking an AbstractFactory, which should first be
693:             * installed on the context by calling "setFactory".
694:             * <p>
695:             * Will throw an exception if one of the following conditions occurs:
696:             * <ul>
697:             * <li>Elements of the xpath aleady exist, but the path does not in
698:             *  fact describe an existing property
699:             * <li>The AbstractFactory fails to create an instance for an intermediate
700:             * element.
701:             * <li>The property is not writable (no public, non-static set method)
702:             * </ul>
703:             */
704:            public abstract Pointer createPathAndSetValue(String xpath,
705:                    Object value);
706:
707:            /**
708:             * Removes the element of the object graph described by the xpath.
709:             */
710:            public abstract void removePath(String xpath);
711:
712:            /**
713:             * Removes all elements of the object graph described by the xpath.
714:             */
715:            public abstract void removeAll(String xpath);
716:
717:            /**
718:             * Traverses the xpath and returns an Iterator of all results found
719:             * for the path. If the xpath matches no properties
720:             * in the graph, the Iterator will be empty, but not null.
721:             */
722:            public abstract Iterator iterate(String xpath);
723:
724:            /**
725:             * Traverses the xpath and returns a Pointer.
726:             * A Pointer provides easy access to a property.
727:             * If the xpath matches no properties
728:             * in the graph, the pointer will be null.
729:             */
730:            public abstract Pointer getPointer(String xpath);
731:
732:            /**
733:             * Traverses the xpath and returns an Iterator of Pointers.
734:             * A Pointer provides easy access to a property.
735:             * If the xpath matches no properties
736:             * in the graph, the Iterator be empty, but not null.
737:             */
738:            public abstract Iterator iteratePointers(String xpath);
739:
740:            /**
741:             * Install an identity manager that will be used by the context
742:             * to look up a node by its ID.
743:             */
744:            public void setIdentityManager(IdentityManager idManager) {
745:                this .idManager = idManager;
746:            }
747:
748:            /**
749:             * Returns this context's identity manager. If none has been installed,
750:             * returns the identity manager of the parent context.
751:             */
752:            public IdentityManager getIdentityManager() {
753:                if (idManager == null && parentContext != null) {
754:                    return parentContext.getIdentityManager();
755:                }
756:                return idManager;
757:            }
758:
759:            /**
760:             * Locates a Node by its ID.
761:             *
762:             * @param id is the ID of the sought node.
763:             */
764:            public Pointer getPointerByID(String id) {
765:                IdentityManager manager = getIdentityManager();
766:                if (manager != null) {
767:                    return manager.getPointerByID(this , id);
768:                } else {
769:                    throw new JXPathException("Cannot find an element by ID - "
770:                            + "no IdentityManager has been specified");
771:                }
772:            }
773:
774:            /**
775:             * Install a key manager that will be used by the context
776:             * to look up a node by a key value.
777:             */
778:            public void setKeyManager(KeyManager keyManager) {
779:                this .keyManager = keyManager;
780:            }
781:
782:            /**
783:             * Returns this context's key manager. If none has been installed,
784:             * returns the key manager of the parent context.
785:             */
786:            public KeyManager getKeyManager() {
787:                if (keyManager == null && parentContext != null) {
788:                    return parentContext.getKeyManager();
789:                }
790:                return keyManager;
791:            }
792:
793:            /**
794:             * Locates a Node by a key value.
795:             */
796:            public Pointer getPointerByKey(String key, String value) {
797:                KeyManager manager = getKeyManager();
798:                if (manager != null) {
799:                    return manager.getPointerByKey(this , key, value);
800:                } else {
801:                    throw new JXPathException(
802:                            "Cannot find an element by key - "
803:                                    + "no KeyManager has been specified");
804:                }
805:            }
806:
807:            /**
808:             * Registers a namespace prefix.
809:             * 
810:             * @param prefix A namespace prefix
811:             * @param namespaceURI A URI for that prefix
812:             */
813:            public void registerNamespace(String prefix, String namespaceURI) {
814:                throw new UnsupportedOperationException(
815:                        "Namespace registration is not implemented by "
816:                                + getClass());
817:            }
818:
819:            /**
820:             * Given a prefix, returns a registered namespace URI. If the requested
821:             * prefix was not defined explicitly using the registerNamespace method,
822:             * JXPathContext will then check the context node to see if the prefix is
823:             * defined there. See
824:             * {@link #setNamespaceContextPointer(Pointer) setNamespaceContextPointer}.
825:             * 
826:             * @param prefix The namespace prefix to look up
827:             * @return namespace URI or null if the prefix is undefined.
828:             */
829:            public String getNamespaceURI(String prefix) {
830:                throw new UnsupportedOperationException(
831:                        "Namespace registration is not implemented by "
832:                                + getClass());
833:            }
834:
835:            /**
836:             * Namespace prefixes can be defined implicitly by specifying a pointer to a
837:             * context where the namespaces are defined. By default,
838:             * NamespaceContextPointer is the same as the Context Pointer, see
839:             * {@link #getContextPointer() getContextPointer()}
840:             * 
841:             * @param contextPointer The pointer to the context where prefixes used in
842:             *        XPath expressions should be resolved.
843:             */
844:            public void setNamespaceContextPointer(
845:                    Pointer namespaceContextPointer) {
846:                throw new UnsupportedOperationException(
847:                        "Namespace registration is not implemented by "
848:                                + getClass());
849:            }
850:
851:            /**
852:             * Returns the namespace context pointer set with
853:             * {@link #setNamespaceContextPointer(Pointer) setNamespaceContextPointer()}
854:             * or, if none has been specified, the context pointer otherwise.
855:             * 
856:             * @return The namespace context pointer.
857:             */
858:            public Pointer getNamespaceContextPointer() {
859:                throw new UnsupportedOperationException(
860:                        "Namespace registration is not implemented by "
861:                                + getClass());
862:            }
863:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.