Source Code Cross Referenced for PropertiesConfigurationLayout.java in  » Library » Apache-commons-configuration-1.4-src » org » apache » commons » configuration » 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 
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;
018:
019:        import java.io.IOException;
020:        import java.io.Reader;
021:        import java.io.Writer;
022:        import java.util.Iterator;
023:        import java.util.List;
024:        import java.util.Map;
025:        import java.util.Set;
026:
027:        import org.apache.commons.collections.map.LinkedMap;
028:        import org.apache.commons.configuration.event.ConfigurationEvent;
029:        import org.apache.commons.configuration.event.ConfigurationListener;
030:        import org.apache.commons.lang.StringUtils;
031:
032:        /**
033:         * <p>
034:         * A helper class used by <code>{@link PropertiesConfiguration}</code> to keep
035:         * the layout of a properties file.
036:         * </p>
037:         * <p>
038:         * Instances of this class are associated with a
039:         * <code>PropertiesConfiguration</code> object. They are responsible for
040:         * analyzing properties files and for extracting as much information about the
041:         * file layout (e.g. empty lines, comments) as possible. When the properties
042:         * file is written back again it should be close to the original.
043:         * </p>
044:         * <p>
045:         * The <code>PropertiesConfigurationLayout</code> object associated with a
046:         * <code>PropertiesConfiguration</code> object can be obtained using the
047:         * <code>getLayout()</code> method of the configuration. Then the methods
048:         * provided by this class can be used to alter the properties file's layout.
049:         * </p>
050:         * <p>
051:         * Implementation note: This is a very simple implementation, which is far away
052:         * from being perfect, i.e. the original layout of a properties file won't be
053:         * reproduced in all cases. One limitation is that comments for multi-valued
054:         * property keys are concatenated. Maybe this implementation can later be
055:         * improved.
056:         * </p>
057:         * <p>
058:         * To get an impression how this class works consider the following properties
059:         * file:
060:         * </p>
061:         * <p>
062:         *
063:         * <pre>
064:         * # A demo configuration file
065:         * # for Demo App 1.42
066:         *
067:         * # Application name
068:         * AppName=Demo App
069:         *
070:         * # Application vendor
071:         * AppVendor=DemoSoft
072:         *
073:         *
074:         * # GUI properties
075:         * # Window Color
076:         * windowColors=0xFFFFFF,0x000000
077:         *
078:         * # Include some setting
079:         * include=settings.properties
080:         * # Another vendor
081:         * AppVendor=TestSoft
082:         * </pre>
083:         *
084:         * </p>
085:         * <p>
086:         * For this example the following points are relevant:
087:         * </p>
088:         * <p>
089:         * <ul>
090:         * <li>The first two lines are set as header comment. The header comment is
091:         * determined by the last blanc line before the first property definition.</li>
092:         * <li>For the property <code>AppName</code> one comment line and one
093:         * leading blanc line is stored.</li>
094:         * <li>For the property <code>windowColors</code> two comment lines and two
095:         * leading blanc lines are stored.</li>
096:         * <li>Include files is something this class cannot deal with well. When saving
097:         * the properties configuration back, the included properties are simply
098:         * contained in the original file. The comment before the include property is
099:         * skipped.</li>
100:         * <li>For all properties except for <code>AppVendor</code> the &quot;single
101:         * line&quot; flag is set. This is relevant only for <code>windowColors</code>,
102:         * which has multiple values defined in one line using the separator character.</li>
103:         * <li>The <code>AppVendor</code> property appears twice. The comment lines
104:         * are concatenated, so that <code>layout.getComment("AppVendor");</code> will
105:         * result in <code>Application vendor&lt;CR&gt;Another vendor</code>, whith
106:         * <code>&lt;CR&gt;</code> meaning the line separator. In addition the
107:         * &quot;single line&quot; flag is set to <b>false</b> for this property. When
108:         * the file is saved, two property definitions will be written (in series).</li>
109:         * </ul>
110:         * </p>
111:         *
112:         * @author <a
113:         * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons
114:         * Configuration team</a>
115:         * @version $Id: PropertiesConfigurationLayout.java 439648 2006-09-02 20:42:10Z oheger $
116:         * @since 1.3
117:         */
118:        public class PropertiesConfigurationLayout implements 
119:                ConfigurationListener {
120:            /** Constant for the line break character. */
121:            private static final String CR = System
122:                    .getProperty("line.separator");
123:
124:            /** Constant for the default comment prefix. */
125:            private static final String COMMENT_PREFIX = "# ";
126:
127:            /** Stores the associated configuration object. */
128:            private PropertiesConfiguration configuration;
129:
130:            /** Stores a map with the contained layout information. */
131:            private Map layoutData;
132:
133:            /** Stores the header comment. */
134:            private String headerComment;
135:
136:            /** A counter for determining nested load calls. */
137:            private int loadCounter;
138:
139:            /** Stores the force single line flag. */
140:            private boolean forceSingleLine;
141:
142:            /**
143:             * Creates a new instance of <code>PropertiesConfigurationLayout</code>
144:             * and initializes it with the associated configuration object.
145:             *
146:             * @param config the configuration (must not be <b>null</b>)
147:             */
148:            public PropertiesConfigurationLayout(PropertiesConfiguration config) {
149:                this (config, null);
150:            }
151:
152:            /**
153:             * Creates a new instance of <code>PropertiesConfigurationLayout</code>
154:             * and initializes it with the given configuration object. The data of the
155:             * specified layout object is copied.
156:             *
157:             * @param config the configuration (must not be <b>null</b>)
158:             * @param c the layout object to be copied
159:             */
160:            public PropertiesConfigurationLayout(
161:                    PropertiesConfiguration config,
162:                    PropertiesConfigurationLayout c) {
163:                if (config == null) {
164:                    throw new IllegalArgumentException(
165:                            "Configuration must not be null!");
166:                }
167:                configuration = config;
168:                layoutData = new LinkedMap();
169:                config.addConfigurationListener(this );
170:
171:                if (c != null) {
172:                    copyFrom(c);
173:                }
174:            }
175:
176:            /**
177:             * Returns the associated configuration object.
178:             *
179:             * @return the associated configuration
180:             */
181:            public PropertiesConfiguration getConfiguration() {
182:                return configuration;
183:            }
184:
185:            /**
186:             * Returns the comment for the specified property key in a cononical form.
187:             * &quot;Canonical&quot; means that either all lines start with a comment
188:             * character or none. The <code>commentChar</code> parameter is <b>false</b>,
189:             * all comment characters are removed, so that the result is only the plain
190:             * text of the comment. Otherwise it is ensured that each line of the
191:             * comment starts with a comment character.
192:             *
193:             * @param key the key of the property
194:             * @param commentChar determines whether all lines should start with comment
195:             * characters or not
196:             * @return the canonical comment for this key (can be <b>null</b>)
197:             */
198:            public String getCanonicalComment(String key, boolean commentChar) {
199:                String comment = getComment(key);
200:                if (comment == null) {
201:                    return null;
202:                } else {
203:                    return trimComment(comment, commentChar);
204:                }
205:            }
206:
207:            /**
208:             * Returns the comment for the specified property key. The comment is
209:             * returned as it was set (either manually by calling
210:             * <code>setComment()</code> or when it was loaded from a properties
211:             * file). No modifications are performed.
212:             *
213:             * @param key the key of the property
214:             * @return the comment for this key (can be <b>null</b>)
215:             */
216:            public String getComment(String key) {
217:                return fetchLayoutData(key).getComment();
218:            }
219:
220:            /**
221:             * Sets the comment for the specified property key. The comment (or its
222:             * single lines if it is a multi-line comment) can start with a comment
223:             * character. If this is the case, it will be written without changes.
224:             * Otherwise a default comment character is added automatically.
225:             *
226:             * @param key the key of the property
227:             * @param comment the comment for this key (can be <b>null</b>, then the
228:             * comment will be removed)
229:             */
230:            public void setComment(String key, String comment) {
231:                fetchLayoutData(key).setComment(comment);
232:            }
233:
234:            /**
235:             * Returns the number of blanc lines before this property key. If this key
236:             * does not exist, 0 will be returned.
237:             *
238:             * @param key the property key
239:             * @return the number of blanc lines before the property definition for this
240:             * key
241:             */
242:            public int getBlancLinesBefore(String key) {
243:                return fetchLayoutData(key).getBlancLines();
244:            }
245:
246:            /**
247:             * Sets the number of blanc lines before the given property key. This can be
248:             * used for a logical grouping of properties.
249:             *
250:             * @param key the property key
251:             * @param number the number of blanc lines to add before this property
252:             * definition
253:             */
254:            public void setBlancLinesBefore(String key, int number) {
255:                fetchLayoutData(key).setBlancLines(number);
256:            }
257:
258:            /**
259:             * Returns the header comment of the represented properties file in a
260:             * canonical form. With the <code>commentChar</code> parameter it can be
261:             * specified whether comment characters should be stripped or be always
262:             * present.
263:             *
264:             * @param commentChar determines the presence of comment characters
265:             * @return the header comment (can be <b>null</b>)
266:             */
267:            public String getCanonicalHeaderComment(boolean commentChar) {
268:                return (getHeaderComment() == null) ? null : trimComment(
269:                        getHeaderComment(), commentChar);
270:            }
271:
272:            /**
273:             * Returns the header comment of the represented properties file. This
274:             * method returns the header comment exactly as it was set using
275:             * <code>setHeaderComment()</code> or extracted from the loaded properties
276:             * file.
277:             *
278:             * @return the header comment (can be <b>null</b>)
279:             */
280:            public String getHeaderComment() {
281:                return headerComment;
282:            }
283:
284:            /**
285:             * Sets the header comment for the represented properties file. This comment
286:             * will be output on top of the file.
287:             *
288:             * @param comment the comment
289:             */
290:            public void setHeaderComment(String comment) {
291:                headerComment = comment;
292:            }
293:
294:            /**
295:             * Returns a flag whether the specified property is defined on a single
296:             * line. This is meaningful only if this property has multiple values.
297:             *
298:             * @param key the property key
299:             * @return a flag if this property is defined on a single line
300:             */
301:            public boolean isSingleLine(String key) {
302:                return fetchLayoutData(key).isSingleLine();
303:            }
304:
305:            /**
306:             * Sets the &quot;single line flag&quot; for the specified property key.
307:             * This flag is evaluated if the property has multiple values (i.e. if it is
308:             * a list property). In this case, if the flag is set, all values will be
309:             * written in a single property definition using the list delimiter as
310:             * separator. Otherwise multiple lines will be written for this property,
311:             * each line containing one property value.
312:             *
313:             * @param key the property key
314:             * @param f the single line flag
315:             */
316:            public void setSingleLine(String key, boolean f) {
317:                fetchLayoutData(key).setSingleLine(f);
318:            }
319:
320:            /**
321:             * Returns the &quot;force single line&quot; flag.
322:             *
323:             * @return the force single line flag
324:             * @see #setForceSingleLine(boolean)
325:             */
326:            public boolean isForceSingleLine() {
327:                return forceSingleLine;
328:            }
329:
330:            /**
331:             * Sets the &quot;force single line&quot; flag. If this flag is set, all
332:             * properties with multiple values are written on single lines. This mode
333:             * provides more compatibility with <code>java.lang.Properties</code>,
334:             * which cannot deal with multiple definitions of a single property.
335:             *
336:             * @param f the force single line flag
337:             */
338:            public void setForceSingleLine(boolean f) {
339:                forceSingleLine = f;
340:            }
341:
342:            /**
343:             * Returns a set with all property keys managed by this object.
344:             *
345:             * @return a set with all contained property keys
346:             */
347:            public Set getKeys() {
348:                return layoutData.keySet();
349:            }
350:
351:            /**
352:             * Reads a properties file and stores its internal structure. The found
353:             * properties will be added to the associated configuration object.
354:             *
355:             * @param in the reader to the properties file
356:             * @throws ConfigurationException if an error occurs
357:             */
358:            public void load(Reader in) throws ConfigurationException {
359:                if (++loadCounter == 1) {
360:                    getConfiguration().removeConfigurationListener(this );
361:                }
362:                PropertiesConfiguration.PropertiesReader reader = new PropertiesConfiguration.PropertiesReader(
363:                        in, getConfiguration().getListDelimiter());
364:
365:                try {
366:                    while (reader.nextProperty()) {
367:                        if (getConfiguration().propertyLoaded(
368:                                reader.getPropertyName(),
369:                                reader.getPropertyValue())) {
370:                            boolean contained = layoutData.containsKey(reader
371:                                    .getPropertyName());
372:                            int blancLines = 0;
373:                            int idx = checkHeaderComment(reader
374:                                    .getCommentLines());
375:                            while (idx < reader.getCommentLines().size()
376:                                    && ((String) reader.getCommentLines().get(
377:                                            idx)).length() < 1) {
378:                                idx++;
379:                                blancLines++;
380:                            }
381:                            String comment = extractComment(reader
382:                                    .getCommentLines(), idx, reader
383:                                    .getCommentLines().size() - 1);
384:                            PropertyLayoutData data = fetchLayoutData(reader
385:                                    .getPropertyName());
386:                            if (contained) {
387:                                data.addComment(comment);
388:                                data.setSingleLine(false);
389:                            } else {
390:                                data.setComment(comment);
391:                                data.setBlancLines(blancLines);
392:                            }
393:                        }
394:                    }
395:                } catch (IOException ioex) {
396:                    throw new ConfigurationException(ioex);
397:                } finally {
398:                    if (--loadCounter == 0) {
399:                        getConfiguration().addConfigurationListener(this );
400:                    }
401:                }
402:            }
403:
404:            /**
405:             * Writes the properties file to the given writer, preserving as much of its
406:             * structure as possible.
407:             *
408:             * @param out the writer
409:             * @throws ConfigurationException if an error occurs
410:             */
411:            public void save(Writer out) throws ConfigurationException {
412:                try {
413:                    PropertiesConfiguration.PropertiesWriter writer = new PropertiesConfiguration.PropertiesWriter(
414:                            out, getConfiguration().getListDelimiter());
415:                    if (headerComment != null) {
416:                        writer.writeln(getCanonicalHeaderComment(true));
417:                        writer.writeln(null);
418:                    }
419:
420:                    for (Iterator it = layoutData.keySet().iterator(); it
421:                            .hasNext();) {
422:                        String key = (String) it.next();
423:                        if (getConfiguration().containsKey(key)) {
424:
425:                            // Output blanc lines before property
426:                            for (int i = 0; i < getBlancLinesBefore(key); i++) {
427:                                writer.writeln(null);
428:                            }
429:
430:                            // Output the comment
431:                            if (getComment(key) != null) {
432:                                writer.writeln(getCanonicalComment(key, true));
433:                            }
434:
435:                            // Output the property and its value
436:                            writer.writeProperty(key, getConfiguration()
437:                                    .getProperty(key), isForceSingleLine()
438:                                    || isSingleLine(key));
439:                        }
440:                    }
441:                    writer.flush();
442:                } catch (IOException ioex) {
443:                    throw new ConfigurationException(ioex);
444:                }
445:            }
446:
447:            /**
448:             * The event listener callback. Here event notifications of the
449:             * configuration object are processed to update the layout object properly.
450:             *
451:             * @param event the event object
452:             */
453:            public void configurationChanged(ConfigurationEvent event) {
454:                if (event.isBeforeUpdate()) {
455:                    if (AbstractFileConfiguration.EVENT_RELOAD == event
456:                            .getType()) {
457:                        clear();
458:                    }
459:                }
460:
461:                else {
462:                    switch (event.getType()) {
463:                    case AbstractConfiguration.EVENT_ADD_PROPERTY:
464:                        boolean contained = layoutData.containsKey(event
465:                                .getPropertyName());
466:                        PropertyLayoutData data = fetchLayoutData(event
467:                                .getPropertyName());
468:                        data.setSingleLine(!contained);
469:                        break;
470:                    case AbstractConfiguration.EVENT_CLEAR_PROPERTY:
471:                        layoutData.remove(event.getPropertyName());
472:                        break;
473:                    case AbstractConfiguration.EVENT_CLEAR:
474:                        clear();
475:                        break;
476:                    case AbstractConfiguration.EVENT_SET_PROPERTY:
477:                        fetchLayoutData(event.getPropertyName());
478:                        break;
479:                    }
480:                }
481:            }
482:
483:            /**
484:             * Returns a layout data object for the specified key. If this is a new key,
485:             * a new object is created and initialized with default values.
486:             *
487:             * @param key the key
488:             * @return the corresponding layout data object
489:             */
490:            private PropertyLayoutData fetchLayoutData(String key) {
491:                if (key == null) {
492:                    throw new IllegalArgumentException(
493:                            "Property key must not be null!");
494:                }
495:
496:                PropertyLayoutData data = (PropertyLayoutData) layoutData
497:                        .get(key);
498:                if (data == null) {
499:                    data = new PropertyLayoutData();
500:                    data.setSingleLine(true);
501:                    layoutData.put(key, data);
502:                }
503:
504:                return data;
505:            }
506:
507:            /**
508:             * Removes all content from this layout object.
509:             */
510:            private void clear() {
511:                layoutData.clear();
512:                setHeaderComment(null);
513:            }
514:
515:            /**
516:             * Tests whether a line is a comment, i.e. whether it starts with a comment
517:             * character.
518:             *
519:             * @param line the line
520:             * @return a flag if this is a comment line
521:             */
522:            static boolean isCommentLine(String line) {
523:                return PropertiesConfiguration.isCommentLine(line);
524:            }
525:
526:            /**
527:             * Trims a comment. This method either removes all comment characters from
528:             * the given string, leaving only the plain comment text or ensures that
529:             * every line starts with a valid comment character.
530:             *
531:             * @param s the string to be processed
532:             * @param comment if <b>true</b>, a comment character will always be
533:             * enforced; if <b>false</b>, it will be removed
534:             * @return the trimmed comment
535:             */
536:            static String trimComment(String s, boolean comment) {
537:                StringBuffer buf = new StringBuffer(s.length());
538:                int lastPos = 0;
539:                int pos;
540:
541:                do {
542:                    pos = s.indexOf(CR, lastPos);
543:                    if (pos >= 0) {
544:                        String line = s.substring(lastPos, pos);
545:                        buf.append(stripCommentChar(line, comment)).append(CR);
546:                        lastPos = pos + CR.length();
547:                    }
548:                } while (pos >= 0);
549:
550:                if (lastPos < s.length()) {
551:                    buf.append(stripCommentChar(s.substring(lastPos), comment));
552:                }
553:                return buf.toString();
554:            }
555:
556:            /**
557:             * Either removes the comment character from the given comment line or
558:             * ensures that the line starts with a comment character.
559:             *
560:             * @param s the comment line
561:             * @param comment if <b>true</b>, a comment character will always be
562:             * enforced; if <b>false</b>, it will be removed
563:             * @return the line without comment character
564:             */
565:            static String stripCommentChar(String s, boolean comment) {
566:                if (s.length() < 1 || (isCommentLine(s) == comment)) {
567:                    return s;
568:                }
569:
570:                else {
571:                    if (!comment) {
572:                        int pos = 0;
573:                        // find first comment character
574:                        while (PropertiesConfiguration.COMMENT_CHARS.indexOf(s
575:                                .charAt(pos)) < 0) {
576:                            pos++;
577:                        }
578:
579:                        // Remove leading spaces
580:                        pos++;
581:                        while (pos < s.length()
582:                                && Character.isWhitespace(s.charAt(pos))) {
583:                            pos++;
584:                        }
585:
586:                        return (pos < s.length()) ? s.substring(pos)
587:                                : StringUtils.EMPTY;
588:                    } else {
589:                        return COMMENT_PREFIX + s;
590:                    }
591:                }
592:            }
593:
594:            /**
595:             * Extracts a comment string from the given range of the specified comment
596:             * lines. The single lines are added using a line feed as separator.
597:             *
598:             * @param commentLines a list with comment lines
599:             * @param from the start index
600:             * @param to the end index (inclusive)
601:             * @return the comment string (<b>null</b> if it is undefined)
602:             */
603:            private String extractComment(List commentLines, int from, int to) {
604:                if (to < from) {
605:                    return null;
606:                }
607:
608:                else {
609:                    StringBuffer buf = new StringBuffer((String) commentLines
610:                            .get(from));
611:                    for (int i = from + 1; i <= to; i++) {
612:                        buf.append(CR);
613:                        buf.append(commentLines.get(i));
614:                    }
615:                    return buf.toString();
616:                }
617:            }
618:
619:            /**
620:             * Checks if parts of the passed in comment can be used as header comment.
621:             * This method checks whether a header comment can be defined (i.e. whether
622:             * this is the first comment in the loaded file). If this is the case, it is
623:             * searched for the lates blanc line. This line will mark the end of the
624:             * header comment. The return value is the index of the first line in the
625:             * passed in list, which does not belong to the header comment.
626:             *
627:             * @param commentLines the comment lines
628:             * @return the index of the next line after the header comment
629:             */
630:            private int checkHeaderComment(List commentLines) {
631:                if (loadCounter == 1 && getHeaderComment() == null
632:                        && layoutData.isEmpty()) {
633:                    // This is the first comment. Search for blanc lines.
634:                    int index = commentLines.size() - 1;
635:                    while (index >= 0
636:                            && ((String) commentLines.get(index)).length() > 0) {
637:                        index--;
638:                    }
639:                    setHeaderComment(extractComment(commentLines, 0, index - 1));
640:                    return index + 1;
641:                } else {
642:                    return 0;
643:                }
644:            }
645:
646:            /**
647:             * Copies the data from the given layout object.
648:             *
649:             * @param c the layout object to copy
650:             */
651:            private void copyFrom(PropertiesConfigurationLayout c) {
652:                for (Iterator it = c.getKeys().iterator(); it.hasNext();) {
653:                    String key = (String) it.next();
654:                    PropertyLayoutData data = (PropertyLayoutData) c.layoutData
655:                            .get(key);
656:                    layoutData.put(key, data.clone());
657:                }
658:            }
659:
660:            /**
661:             * A helper class for storing all layout related information for a
662:             * configuration property.
663:             */
664:            static class PropertyLayoutData implements  Cloneable {
665:                /** Stores the comment for the property. */
666:                private StringBuffer comment;
667:
668:                /** Stores the number of blanc lines before this property. */
669:                private int blancLines;
670:
671:                /** Stores the single line property. */
672:                private boolean singleLine;
673:
674:                /**
675:                 * Creates a new instance of <code>PropertyLayoutData</code>.
676:                 */
677:                public PropertyLayoutData() {
678:                    singleLine = true;
679:                }
680:
681:                /**
682:                 * Returns the number of blanc lines before this property.
683:                 *
684:                 * @return the number of blanc lines before this property
685:                 */
686:                public int getBlancLines() {
687:                    return blancLines;
688:                }
689:
690:                /**
691:                 * Sets the number of properties before this property.
692:                 *
693:                 * @param blancLines the number of properties before this property
694:                 */
695:                public void setBlancLines(int blancLines) {
696:                    this .blancLines = blancLines;
697:                }
698:
699:                /**
700:                 * Returns the single line flag.
701:                 *
702:                 * @return the single line flag
703:                 */
704:                public boolean isSingleLine() {
705:                    return singleLine;
706:                }
707:
708:                /**
709:                 * Sets the single line flag.
710:                 *
711:                 * @param singleLine the single line flag
712:                 */
713:                public void setSingleLine(boolean singleLine) {
714:                    this .singleLine = singleLine;
715:                }
716:
717:                /**
718:                 * Adds a comment for this property. If already a comment exists, the
719:                 * new comment is added (separated by a newline).
720:                 *
721:                 * @param s the comment to add
722:                 */
723:                public void addComment(String s) {
724:                    if (s != null) {
725:                        if (comment == null) {
726:                            comment = new StringBuffer(s);
727:                        } else {
728:                            comment.append(CR).append(s);
729:                        }
730:                    }
731:                }
732:
733:                /**
734:                 * Sets the comment for this property.
735:                 *
736:                 * @param s the new comment (can be <b>null</b>)
737:                 */
738:                public void setComment(String s) {
739:                    if (s == null) {
740:                        comment = null;
741:                    } else {
742:                        comment = new StringBuffer(s);
743:                    }
744:                }
745:
746:                /**
747:                 * Returns the comment for this property. The comment is returned as it
748:                 * is, without processing of comment characters.
749:                 *
750:                 * @return the comment (can be <b>null</b>)
751:                 */
752:                public String getComment() {
753:                    return (comment == null) ? null : comment.toString();
754:                }
755:
756:                /**
757:                 * Creates a copy of this object.
758:                 *
759:                 * @return the copy
760:                 */
761:                public Object clone() {
762:                    try {
763:                        PropertyLayoutData copy = (PropertyLayoutData) super 
764:                                .clone();
765:                        if (comment != null) {
766:                            // must copy string buffer, too
767:                            copy.comment = new StringBuffer(getComment());
768:                        }
769:                        return copy;
770:                    } catch (CloneNotSupportedException cnex) {
771:                        // This cannot happen!
772:                        throw new ConfigurationRuntimeException(cnex);
773:                    }
774:                }
775:            }
776:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.