Source Code Cross Referenced for DefaultConfigurationKey.java in  » Library » Apache-commons-configuration-1.4-src » org » apache » commons » configuration » tree » 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 configuration 1.4 src » org.apache.commons.configuration.tree 
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:        package org.apache.commons.configuration.tree;
018:
019:        import java.util.Iterator;
020:        import java.util.NoSuchElementException;
021:
022:        import org.apache.commons.lang.StringUtils;
023:
024:        /**
025:         * <p>
026:         * A simple class that supports creation of and iteration on configuration keys
027:         * supported by a <code>{@link DefaultExpressionEngine}</code> object.
028:         * </p>
029:         * <p>
030:         * For key creation the class works similar to a StringBuffer: There are several
031:         * <code>appendXXXX()</code> methods with which single parts of a key can be
032:         * constructed. All these methods return a reference to the actual object so
033:         * they can be written in a chain. When using this methods the exact syntax for
034:         * keys need not be known.
035:         * </p>
036:         * <p>
037:         * This class also defines a specialized iterator for configuration keys. With
038:         * such an iterator a key can be tokenized into its single parts. For each part
039:         * it can be checked whether it has an associated index.
040:         * </p>
041:         * <p>
042:         * Instances of this class are always associated with an instance of
043:         * <code>{@link DefaultExpressionEngine}</code>, from which the current
044:         * delimiters are obtained. So key creation and parsing is specific to this
045:         * associated expression engine.
046:         * </p>
047:         *
048:         * @since 1.3
049:         * @author Oliver Heger
050:         * @version $Id: DefaultConfigurationKey.java 439648 2006-09-02 20:42:10Z oheger $
051:         */
052:        public class DefaultConfigurationKey {
053:            /** Constant for the initial StringBuffer size. */
054:            private static final int INITIAL_SIZE = 32;
055:
056:            /** Stores a reference to the associated expression engine. */
057:            private DefaultExpressionEngine expressionEngine;
058:
059:            /** Holds a buffer with the so far created key. */
060:            private StringBuffer keyBuffer;
061:
062:            /**
063:             * Creates a new instance of <code>DefaultConfigurationKey</code> and sets
064:             * the associated expression engine.
065:             *
066:             * @param engine the expression engine
067:             */
068:            public DefaultConfigurationKey(DefaultExpressionEngine engine) {
069:                keyBuffer = new StringBuffer(INITIAL_SIZE);
070:                setExpressionEngine(engine);
071:            }
072:
073:            /**
074:             * Creates a new instance of <code>DefaultConfigurationKey</code> and sets
075:             * the associated expression engine and an initial key.
076:             *
077:             * @param engine the expression engine
078:             * @param key the key to be wrapped
079:             */
080:            public DefaultConfigurationKey(DefaultExpressionEngine engine,
081:                    String key) {
082:                setExpressionEngine(engine);
083:                keyBuffer = new StringBuffer(trim(key));
084:            }
085:
086:            /**
087:             * Returns the associated default expression engine.
088:             *
089:             * @return the associated expression engine
090:             */
091:            public DefaultExpressionEngine getExpressionEngine() {
092:                return expressionEngine;
093:            }
094:
095:            /**
096:             * Sets the associated expression engine.
097:             *
098:             * @param expressionEngine the expression engine (must not be <b>null</b>)
099:             */
100:            public void setExpressionEngine(
101:                    DefaultExpressionEngine expressionEngine) {
102:                if (expressionEngine == null) {
103:                    throw new IllegalArgumentException(
104:                            "Expression engine must not be null!");
105:                }
106:                this .expressionEngine = expressionEngine;
107:            }
108:
109:            /**
110:             * Appends the name of a property to this key. If necessary, a property
111:             * delimiter will be added. If the boolean argument is set to <b>true</b>,
112:             * property delimiters contained in the property name will be escaped.
113:             *
114:             * @param property the name of the property to be added
115:             * @param escape a flag if property delimiters in the passed in property name
116:             * should be escaped
117:             * @return a reference to this object
118:             */
119:            public DefaultConfigurationKey append(String property,
120:                    boolean escape) {
121:                String key;
122:                if (escape && property != null) {
123:                    key = escapeDelimiters(property);
124:                } else {
125:                    key = property;
126:                }
127:                key = trim(key);
128:
129:                if (keyBuffer.length() > 0 && !isAttributeKey(property)
130:                        && key.length() > 0) {
131:                    keyBuffer.append(getExpressionEngine()
132:                            .getPropertyDelimiter());
133:                }
134:
135:                keyBuffer.append(key);
136:                return this ;
137:            }
138:
139:            /**
140:             * Appends the name of a property to this key. If necessary, a property
141:             * delimiter will be added. Property delimiters in the given string will not
142:             * be escaped.
143:             *
144:             * @param property the name of the property to be added
145:             * @return a reference to this object
146:             */
147:            public DefaultConfigurationKey append(String property) {
148:                return append(property, false);
149:            }
150:
151:            /**
152:             * Appends an index to this configuration key.
153:             *
154:             * @param index the index to be appended
155:             * @return a reference to this object
156:             */
157:            public DefaultConfigurationKey appendIndex(int index) {
158:                keyBuffer.append(getExpressionEngine().getIndexStart());
159:                keyBuffer.append(index);
160:                keyBuffer.append(getExpressionEngine().getIndexEnd());
161:                return this ;
162:            }
163:
164:            /**
165:             * Appends an attribute to this configuration key.
166:             *
167:             * @param attr the name of the attribute to be appended
168:             * @return a reference to this object
169:             */
170:            public DefaultConfigurationKey appendAttribute(String attr) {
171:                keyBuffer.append(constructAttributeKey(attr));
172:                return this ;
173:            }
174:
175:            /**
176:             * Returns the actual length of this configuration key.
177:             *
178:             * @return the length of this key
179:             */
180:            public int length() {
181:                return keyBuffer.length();
182:            }
183:
184:            /**
185:             * Sets the new length of this configuration key. With this method it is
186:             * possible to truncate the key, e.g. to return to a state prior calling
187:             * some <code>append()</code> methods. The semantic is the same as the
188:             * <code>setLength()</code> method of <code>StringBuffer</code>.
189:             *
190:             * @param len the new length of the key
191:             */
192:            public void setLength(int len) {
193:                keyBuffer.setLength(len);
194:            }
195:
196:            /**
197:             * Checks if two <code>ConfigurationKey</code> objects are equal. The
198:             * method can be called with strings or other objects, too.
199:             *
200:             * @param c the object to compare
201:             * @return a flag if both objects are equal
202:             */
203:            public boolean equals(Object c) {
204:                if (c == null) {
205:                    return false;
206:                }
207:
208:                return keyBuffer.toString().equals(c.toString());
209:            }
210:
211:            /**
212:             * Returns the hash code for this object.
213:             *
214:             * @return the hash code
215:             */
216:            public int hashCode() {
217:                return String.valueOf(keyBuffer).hashCode();
218:            }
219:
220:            /**
221:             * Returns a string representation of this object. This is the configuration
222:             * key as a plain string.
223:             *
224:             * @return a string for this object
225:             */
226:            public String toString() {
227:                return keyBuffer.toString();
228:            }
229:
230:            /**
231:             * Tests if the specified key represents an attribute according to the
232:             * current expression engine.
233:             *
234:             * @param key the key to be checked
235:             * @return <b>true</b> if this is an attribute key, <b>false</b> otherwise
236:             */
237:            public boolean isAttributeKey(String key) {
238:                if (key == null) {
239:                    return false;
240:                }
241:
242:                return key
243:                        .startsWith(getExpressionEngine().getAttributeStart())
244:                        && (getExpressionEngine().getAttributeEnd() == null || key
245:                                .endsWith(getExpressionEngine()
246:                                        .getAttributeEnd()));
247:            }
248:
249:            /**
250:             * Decorates the given key so that it represents an attribute. Adds special
251:             * start and end markers. The passed in string will be modified only if does
252:             * not already represent an attribute.
253:             *
254:             * @param key the key to be decorated
255:             * @return the decorated attribute key
256:             */
257:            public String constructAttributeKey(String key) {
258:                if (key == null) {
259:                    return StringUtils.EMPTY;
260:                }
261:                if (isAttributeKey(key)) {
262:                    return key;
263:                } else {
264:                    StringBuffer buf = new StringBuffer();
265:                    buf.append(getExpressionEngine().getAttributeStart())
266:                            .append(key);
267:                    if (getExpressionEngine().getAttributeEnd() != null) {
268:                        buf.append(getExpressionEngine().getAttributeEnd());
269:                    }
270:                    return buf.toString();
271:                }
272:            }
273:
274:            /**
275:             * Extracts the name of the attribute from the given attribute key. This
276:             * method removes the attribute markers - if any - from the specified key.
277:             *
278:             * @param key the attribute key
279:             * @return the name of the corresponding attribute
280:             */
281:            public String attributeName(String key) {
282:                return isAttributeKey(key) ? removeAttributeMarkers(key) : key;
283:            }
284:
285:            /**
286:             * Removes leading property delimiters from the specified key.
287:             *
288:             * @param key the key
289:             * @return the key with removed leading property delimiters
290:             */
291:            public String trimLeft(String key) {
292:                if (key == null) {
293:                    return StringUtils.EMPTY;
294:                } else {
295:                    String result = key;
296:                    while (hasLeadingDelimiter(result)) {
297:                        result = result.substring(getExpressionEngine()
298:                                .getPropertyDelimiter().length());
299:                    }
300:                    return result;
301:                }
302:            }
303:
304:            /**
305:             * Removes trailing property delimiters from the specified key.
306:             *
307:             * @param key the key
308:             * @return the key with removed trailing property delimiters
309:             */
310:            public String trimRight(String key) {
311:                if (key == null) {
312:                    return StringUtils.EMPTY;
313:                } else {
314:                    String result = key;
315:                    while (hasTrailingDelimiter(result)) {
316:                        result = result.substring(0, result.length()
317:                                - getExpressionEngine().getPropertyDelimiter()
318:                                        .length());
319:                    }
320:                    return result;
321:                }
322:            }
323:
324:            /**
325:             * Removes delimiters at the beginning and the end of the specified key.
326:             *
327:             * @param key the key
328:             * @return the key with removed property delimiters
329:             */
330:            public String trim(String key) {
331:                return trimRight(trimLeft(key));
332:            }
333:
334:            /**
335:             * Returns an iterator for iterating over the single components of this
336:             * configuration key.
337:             *
338:             * @return an iterator for this key
339:             */
340:            public KeyIterator iterator() {
341:                return new KeyIterator();
342:            }
343:
344:            /**
345:             * Helper method that checks if the specified key ends with a property
346:             * delimiter.
347:             *
348:             * @param key the key to check
349:             * @return a flag if there is a trailing delimiter
350:             */
351:            private boolean hasTrailingDelimiter(String key) {
352:                return key.endsWith(getExpressionEngine()
353:                        .getPropertyDelimiter())
354:                        && (getExpressionEngine().getEscapedDelimiter() == null || !key
355:                                .endsWith(getExpressionEngine()
356:                                        .getEscapedDelimiter()));
357:            }
358:
359:            /**
360:             * Helper method that checks if the specified key starts with a property
361:             * delimiter.
362:             *
363:             * @param key the key to check
364:             * @return a flag if there is a leading delimiter
365:             */
366:            private boolean hasLeadingDelimiter(String key) {
367:                return key.startsWith(getExpressionEngine()
368:                        .getPropertyDelimiter())
369:                        && (getExpressionEngine().getEscapedDelimiter() == null || !key
370:                                .startsWith(getExpressionEngine()
371:                                        .getEscapedDelimiter()));
372:            }
373:
374:            /**
375:             * Helper method for removing attribute markers from a key.
376:             *
377:             * @param key the key
378:             * @return the key with removed attribute markers
379:             */
380:            private String removeAttributeMarkers(String key) {
381:                return key
382:                        .substring(
383:                                getExpressionEngine().getAttributeStart()
384:                                        .length(),
385:                                key.length()
386:                                        - ((getExpressionEngine()
387:                                                .getAttributeEnd() != null) ? getExpressionEngine()
388:                                                .getAttributeEnd().length()
389:                                                : 0));
390:            }
391:
392:            /**
393:             * Unescapes the delimiters in the specified string.
394:             *
395:             * @param key the key to be unescaped
396:             * @return the unescaped key
397:             */
398:            private String unescapeDelimiters(String key) {
399:                return (getExpressionEngine().getEscapedDelimiter() == null) ? key
400:                        : StringUtils.replace(key, getExpressionEngine()
401:                                .getEscapedDelimiter(), getExpressionEngine()
402:                                .getPropertyDelimiter());
403:            }
404:
405:            /**
406:             * Escapes the delimiters in the specified string.
407:             *
408:             * @param key the key to be escaped
409:             * @return the escaped key
410:             */
411:            private String escapeDelimiters(String key) {
412:                return (getExpressionEngine().getEscapedDelimiter() == null || key
413:                        .indexOf(getExpressionEngine().getPropertyDelimiter()) < 0) ? key
414:                        : StringUtils.replace(key, getExpressionEngine()
415:                                .getPropertyDelimiter(), getExpressionEngine()
416:                                .getEscapedDelimiter());
417:            }
418:
419:            /**
420:             * A specialized iterator class for tokenizing a configuration key. This
421:             * class implements the normal iterator interface. In addition it provides
422:             * some specific methods for configuration keys.
423:             */
424:            public class KeyIterator implements  Iterator, Cloneable {
425:                /** Stores the current key name. */
426:                private String current;
427:
428:                /** Stores the start index of the actual token. */
429:                private int startIndex;
430:
431:                /** Stores the end index of the actual token. */
432:                private int endIndex;
433:
434:                /** Stores the index of the actual property if there is one. */
435:                private int indexValue;
436:
437:                /** Stores a flag if the actual property has an index. */
438:                private boolean hasIndex;
439:
440:                /** Stores a flag if the actual property is an attribute. */
441:                private boolean attribute;
442:
443:                /**
444:                 * Returns the next key part of this configuration key. This is a short
445:                 * form of <code>nextKey(false)</code>.
446:                 *
447:                 * @return the next key part
448:                 */
449:                public String nextKey() {
450:                    return nextKey(false);
451:                }
452:
453:                /**
454:                 * Returns the next key part of this configuration key. The boolean
455:                 * parameter indicates wheter a decorated key should be returned. This
456:                 * affects only attribute keys: if the parameter is <b>false</b>, the
457:                 * attribute markers are stripped from the key; if it is <b>true</b>,
458:                 * they remain.
459:                 *
460:                 * @param decorated a flag if the decorated key is to be returned
461:                 * @return the next key part
462:                 */
463:                public String nextKey(boolean decorated) {
464:                    if (!hasNext()) {
465:                        throw new NoSuchElementException("No more key parts!");
466:                    }
467:
468:                    hasIndex = false;
469:                    indexValue = -1;
470:                    String key = findNextIndices();
471:
472:                    current = key;
473:                    hasIndex = checkIndex(key);
474:                    attribute = checkAttribute(current);
475:
476:                    return currentKey(decorated);
477:                }
478:
479:                /**
480:                 * Checks if there is a next element.
481:                 *
482:                 * @return a flag if there is a next element
483:                 */
484:                public boolean hasNext() {
485:                    return endIndex < keyBuffer.length();
486:                }
487:
488:                /**
489:                 * Returns the next object in the iteration.
490:                 *
491:                 * @return the next object
492:                 */
493:                public Object next() {
494:                    return nextKey();
495:                }
496:
497:                /**
498:                 * Removes the current object in the iteration. This method is not
499:                 * supported by this iterator type, so an exception is thrown.
500:                 */
501:                public void remove() {
502:                    throw new UnsupportedOperationException(
503:                            "Remove not supported!");
504:                }
505:
506:                /**
507:                 * Returns the current key of the iteration (without skipping to the
508:                 * next element). This is the same key the previous <code>next()</code>
509:                 * call had returned. (Short form of <code>currentKey(false)</code>.
510:                 *
511:                 * @return the current key
512:                 */
513:                public String currentKey() {
514:                    return currentKey(false);
515:                }
516:
517:                /**
518:                 * Returns the current key of the iteration (without skipping to the
519:                 * next element). The boolean parameter indicates wheter a decorated key
520:                 * should be returned. This affects only attribute keys: if the
521:                 * parameter is <b>false</b>, the attribute markers are stripped from
522:                 * the key; if it is <b>true</b>, they remain.
523:                 *
524:                 * @param decorated a flag if the decorated key is to be returned
525:                 * @return the current key
526:                 */
527:                public String currentKey(boolean decorated) {
528:                    return (decorated && !isPropertyKey()) ? constructAttributeKey(current)
529:                            : current;
530:                }
531:
532:                /**
533:                 * Returns a flag if the current key is an attribute. This method can be
534:                 * called after <code>next()</code>.
535:                 *
536:                 * @return a flag if the current key is an attribute
537:                 */
538:                public boolean isAttribute() {
539:                    // if attribute emulation mode is active, the last part of a key is
540:                    // always an attribute key, too
541:                    return attribute
542:                            || (isAttributeEmulatingMode() && !hasNext());
543:                }
544:
545:                /**
546:                 * Returns a flag whether the current key refers to a property (i.e. is
547:                 * no special attribute key). Usually this method will return the
548:                 * opposite of <code>isAttribute()</code>, but if the delimiters for
549:                 * normal properties and attributes are set to the same string, it is
550:                 * possible that both methods return <b>true</b>.
551:                 *
552:                 * @return a flag if the current key is a property key
553:                 * @see #isAttribute()
554:                 */
555:                public boolean isPropertyKey() {
556:                    return !attribute;
557:                }
558:
559:                /**
560:                 * Returns the index value of the current key. If the current key does
561:                 * not have an index, return value is -1. This method can be called
562:                 * after <code>next()</code>.
563:                 *
564:                 * @return the index value of the current key
565:                 */
566:                public int getIndex() {
567:                    return indexValue;
568:                }
569:
570:                /**
571:                 * Returns a flag if the current key has an associated index. This
572:                 * method can be called after <code>next()</code>.
573:                 *
574:                 * @return a flag if the current key has an index
575:                 */
576:                public boolean hasIndex() {
577:                    return hasIndex;
578:                }
579:
580:                /**
581:                 * Creates a clone of this object.
582:                 *
583:                 * @return a clone of this object
584:                 */
585:                public Object clone() {
586:                    try {
587:                        return super .clone();
588:                    } catch (CloneNotSupportedException cex) {
589:                        // should not happen
590:                        return null;
591:                    }
592:                }
593:
594:                /**
595:                 * Helper method for determining the next indices.
596:                 *
597:                 * @return the next key part
598:                 */
599:                private String findNextIndices() {
600:                    startIndex = endIndex;
601:                    // skip empty names
602:                    while (startIndex < length()
603:                            && hasLeadingDelimiter(keyBuffer
604:                                    .substring(startIndex))) {
605:                        startIndex += getExpressionEngine()
606:                                .getPropertyDelimiter().length();
607:                    }
608:
609:                    // Key ends with a delimiter?
610:                    if (startIndex >= length()) {
611:                        endIndex = length();
612:                        startIndex = endIndex - 1;
613:                        return keyBuffer.substring(startIndex, endIndex);
614:                    } else {
615:                        return nextKeyPart();
616:                    }
617:                }
618:
619:                /**
620:                 * Helper method for extracting the next key part. Takes escaping of
621:                 * delimiter characters into account.
622:                 *
623:                 * @return the next key part
624:                 */
625:                private String nextKeyPart() {
626:                    int attrIdx = keyBuffer.toString().indexOf(
627:                            getExpressionEngine().getAttributeStart(),
628:                            startIndex);
629:                    if (attrIdx < 0 || attrIdx == startIndex) {
630:                        attrIdx = length();
631:                    }
632:
633:                    int delIdx = nextDelimiterPos(keyBuffer.toString(),
634:                            startIndex, attrIdx);
635:                    if (delIdx < 0) {
636:                        delIdx = attrIdx;
637:                    }
638:
639:                    endIndex = Math.min(attrIdx, delIdx);
640:                    return unescapeDelimiters(keyBuffer.substring(startIndex,
641:                            endIndex));
642:                }
643:
644:                /**
645:                 * Searches the next unescaped delimiter from the given position.
646:                 *
647:                 * @param key the key
648:                 * @param pos the start position
649:                 * @param endPos the end position
650:                 * @return the position of the next delimiter or -1 if there is none
651:                 */
652:                private int nextDelimiterPos(String key, int pos, int endPos) {
653:                    int delimiterPos = pos;
654:                    boolean found = false;
655:
656:                    do {
657:                        delimiterPos = key.indexOf(getExpressionEngine()
658:                                .getPropertyDelimiter(), delimiterPos);
659:                        if (delimiterPos < 0 || delimiterPos >= endPos) {
660:                            return -1;
661:                        }
662:                        int escapePos = escapedPosition(key, delimiterPos);
663:                        if (escapePos < 0) {
664:                            found = true;
665:                        } else {
666:                            delimiterPos = escapePos;
667:                        }
668:                    } while (!found);
669:
670:                    return delimiterPos;
671:                }
672:
673:                /**
674:                 * Checks if a delimiter at the specified position is escaped. If this
675:                 * is the case, the next valid search position will be returned.
676:                 * Otherwise the return value is -1.
677:                 *
678:                 * @param key the key to check
679:                 * @param pos the position where a delimiter was found
680:                 * @return information about escaped delimiters
681:                 */
682:                private int escapedPosition(String key, int pos) {
683:                    if (getExpressionEngine().getEscapedDelimiter() == null) {
684:                        // nothing to escape
685:                        return -1;
686:                    }
687:                    int escapeOffset = escapeOffset();
688:                    if (escapeOffset < 0 || escapeOffset > pos) {
689:                        // No escaping possible at this position
690:                        return -1;
691:                    }
692:
693:                    int escapePos = key.indexOf(getExpressionEngine()
694:                            .getEscapedDelimiter(), pos - escapeOffset);
695:                    if (escapePos <= pos && escapePos >= 0) {
696:                        // The found delimiter is escaped. Next valid search position
697:                        // is behind the escaped delimiter.
698:                        return escapePos
699:                                + getExpressionEngine().getEscapedDelimiter()
700:                                        .length();
701:                    } else {
702:                        return -1;
703:                    }
704:                }
705:
706:                /**
707:                 * Determines the relative offset of an escaped delimiter in relation to
708:                 * a delimiter. Depending on the used delimiter and escaped delimiter
709:                 * tokens the position where to search for an escaped delimiter is
710:                 * different. If, for instance, the dot character (&quot;.&quot;) is
711:                 * used as delimiter, and a doubled dot (&quot;..&quot;) as escaped
712:                 * delimiter, the escaped delimiter starts at the same position as the
713:                 * delimiter. If the token &quot;\.&quot; was used, it would start one
714:                 * character before the delimiter because the delimiter character
715:                 * &quot;.&quot; is the second character in the escaped delimiter
716:                 * string. This relation will be determined by this method. For this to
717:                 * work the delimiter string must be contained in the escaped delimiter
718:                 * string.
719:                 *
720:                 * @return the relative offset of the escaped delimiter in relation to a
721:                 * delimiter
722:                 */
723:                private int escapeOffset() {
724:                    return getExpressionEngine().getEscapedDelimiter().indexOf(
725:                            getExpressionEngine().getPropertyDelimiter());
726:                }
727:
728:                /**
729:                 * Helper method for checking if the passed key is an attribute. If this
730:                 * is the case, the internal fields will be set.
731:                 *
732:                 * @param key the key to be checked
733:                 * @return a flag if the key is an attribute
734:                 */
735:                private boolean checkAttribute(String key) {
736:                    if (isAttributeKey(key)) {
737:                        current = removeAttributeMarkers(key);
738:                        return true;
739:                    } else {
740:                        return false;
741:                    }
742:                }
743:
744:                /**
745:                 * Helper method for checking if the passed key contains an index. If
746:                 * this is the case, internal fields will be set.
747:                 *
748:                 * @param key the key to be checked
749:                 * @return a flag if an index is defined
750:                 */
751:                private boolean checkIndex(String key) {
752:                    boolean result = false;
753:
754:                    int idx = key.lastIndexOf(getExpressionEngine()
755:                            .getIndexStart());
756:                    if (idx > 0) {
757:                        int endidx = key.indexOf(getExpressionEngine()
758:                                .getIndexEnd(), idx);
759:
760:                        if (endidx > idx + 1) {
761:                            indexValue = Integer.parseInt(key.substring(
762:                                    idx + 1, endidx));
763:                            current = key.substring(0, idx);
764:                            result = true;
765:                        }
766:                    }
767:
768:                    return result;
769:                }
770:
771:                /**
772:                 * Returns a flag whether attributes are marked the same way as normal
773:                 * property keys. We call this the &quot;attribute emulating mode&quot;.
774:                 * When navigating through node hierarchies it might be convenient to
775:                 * treat attributes the same way than other child nodes, so an
776:                 * expression engine supports to set the attribute markers to the same
777:                 * value than the property delimiter. If this is the case, some special
778:                 * checks have to be performed.
779:                 *
780:                 * @return a flag if attributes and normal property keys are treated the
781:                 * same way
782:                 */
783:                private boolean isAttributeEmulatingMode() {
784:                    return getExpressionEngine().getAttributeEnd() == null
785:                            && StringUtils.equals(getExpressionEngine()
786:                                    .getPropertyDelimiter(),
787:                                    getExpressionEngine().getAttributeStart());
788:                }
789:            }
790:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.