View Javadoc
1   /*
2    *   Copyright (C) 2005 Christian Schulte <cs@schulte.it>
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: Section.java 5091 2016-04-04 15:40:17Z schulte $
29   *
30   */
31  package org.jomc.util;
32  
33  import java.util.ArrayList;
34  import java.util.List;
35  
36  /**
37   * Section of text.
38   *
39   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
40   * @version $JOMC: Section.java 5091 2016-04-04 15:40:17Z schulte $
41   */
42  public class Section
43  {
44  
45      /**
46       * Constant for the mode during parsing the head content of a section.
47       */
48      static final int MODE_HEAD = 1;
49  
50      /**
51       * Constant for the mode during parsing the tail content of a section.
52       */
53      static final int MODE_TAIL = 2;
54  
55      /**
56       * The current parsing mode.
57       */
58      private int mode = MODE_HEAD;
59  
60      /**
61       * The name of this section.
62       */
63      private String name;
64  
65      /**
66       * The parsed head content of this section.
67       */
68      private StringBuilder headContent;
69  
70      /**
71       * The parsed tail content of this section.
72       */
73      private StringBuilder tailContent;
74  
75      /**
76       * Line marking the start of this section.
77       */
78      private String startingLine;
79  
80      /**
81       * Line marking the end of this section.
82       */
83      private String endingLine;
84  
85      /**
86       * The child sections of this section.
87       */
88      private List<Section> sections;
89  
90      /**
91       * Creates a new {@code Section} instance.
92       */
93      public Section()
94      {
95          super();
96      }
97  
98      /**
99       * Gets the name of this section.
100      *
101      * @return The name of this section or {@code null}.
102      */
103     public String getName()
104     {
105         return this.name;
106     }
107 
108     /**
109      * Sets the name of this section.
110      *
111      * @param value The new name of this section or {@code null}.
112      */
113     public void setName( final String value )
114     {
115         this.name = value;
116     }
117 
118     /**
119      * Gets the line marking the start of this section.
120      *
121      * @return The line marking the start of this section.
122      */
123     public String getStartingLine()
124     {
125         return this.startingLine;
126     }
127 
128     /**
129      * Sets the line marking the start of this section.
130      *
131      * @param value The new line marking the start of this section.
132      */
133     public void setStartingLine( final String value )
134     {
135         this.startingLine = value;
136     }
137 
138     /**
139      * Gets the line marking the end of this section.
140      *
141      * @return The line marking the end of this section.
142      */
143     public String getEndingLine()
144     {
145         return this.endingLine;
146     }
147 
148     /**
149      * Sets the line marking the end of this section.
150      *
151      * @param value The new line marking the end of this section.
152      */
153     public void setEndingLine( final String value )
154     {
155         this.endingLine = value;
156     }
157 
158     /**
159      * Gets the content of this section preceding any child section content.
160      *
161      * @return The content of this section preceding any child section content.
162      */
163     public StringBuilder getHeadContent()
164     {
165         if ( this.headContent == null )
166         {
167             this.headContent = new StringBuilder( 512 );
168         }
169 
170         return this.headContent;
171     }
172 
173     /**
174      * Gets the content of this section succeeding any child section content.
175      *
176      * @return The content of this section succeeding any child section content.
177      */
178     public StringBuilder getTailContent()
179     {
180         if ( this.tailContent == null )
181         {
182             this.tailContent = new StringBuilder( 512 );
183         }
184 
185         return this.tailContent;
186     }
187 
188     /**
189      * Gets the child sections of this section.
190      * <p>
191      * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
192      * to the returned list will be present inside the object. This is why there is no {@code set} method for the
193      * sections property.
194      * </p>
195      *
196      * @return A list of child sections of this section.
197      */
198     public List<Section> getSections()
199     {
200         if ( this.sections == null )
201         {
202             this.sections = new ArrayList<Section>();
203         }
204 
205         return this.sections;
206     }
207 
208     /**
209      * Gets a child section matching a given name.
210      *
211      * @param sectionName The name of the section to return.
212      *
213      * @return The first child section matching {@code sectionName} or {@code null}, if no such section is found.
214      *
215      * @throws NullPointerException if {@code sectionName} is {@code null}.
216      */
217     public Section getSection( final String sectionName )
218     {
219         if ( sectionName == null )
220         {
221             throw new NullPointerException( "sectionName" );
222         }
223 
224         return this.getSection( this, sectionName );
225     }
226 
227     private Section getSection( final Section current, final String sectionName )
228     {
229         if ( sectionName.equals( current.getName() ) )
230         {
231             return current;
232         }
233 
234         for ( final Section child : current.getSections() )
235         {
236             if ( sectionName.equals( child.getName() ) )
237             {
238                 return child;
239             }
240 
241             if ( child.getName() == null )
242             {
243                 final Section section = child.getSection( sectionName );
244 
245                 if ( section != null )
246                 {
247                     return section;
248                 }
249             }
250         }
251 
252         return null;
253     }
254 
255     /**
256      * Gets the parsing mode of the instance.
257      *
258      * @return The parsing mode of the instance.
259      *
260      * @see #MODE_HEAD
261      * @see #MODE_TAIL
262      */
263     int getMode()
264     {
265         return this.mode;
266     }
267 
268     /**
269      * Sets the parsing mode of the instance.
270      *
271      * @param value The new parsing mode of the instance.
272      *
273      * @see #MODE_HEAD
274      * @see #MODE_TAIL
275      */
276     void setMode( final int value )
277     {
278         this.mode = value;
279     }
280 
281 }