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 }