001 /*
002 * Copyright (c) 2009 The JOMC Project
003 * Copyright (c) 2005 Christian Schulte <cs@jomc.org>
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions
008 * are met:
009 *
010 * o Redistributions of source code must retain the above copyright
011 * notice, this list of conditions and the following disclaimer.
012 *
013 * o Redistributions in binary form must reproduce the above copyright
014 * notice, this list of conditions and the following disclaimer in
015 * the documentation and/or other materials provided with the
016 * distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
027 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
028 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 *
030 * $Id: Section.java 509 2009-09-21 13:54:49Z schulte2005 $
031 *
032 */
033 package org.jomc.util;
034
035 import java.util.HashMap;
036 import java.util.LinkedList;
037 import java.util.List;
038 import java.util.Map;
039
040 /**
041 * Section of text.
042 *
043 * @author <a href="mailto:cs@jomc.org">Christian Schulte</a>
044 * @version $Id: Section.java 509 2009-09-21 13:54:49Z schulte2005 $
045 */
046 public class Section
047 {
048
049 /** The name of this section. */
050 private String name;
051
052 /** The level of this section. */
053 private int level;
054
055 /** The parsed head content of this section. */
056 private Map<Integer, StringBuilder> headContent;
057
058 /** The parsed tail content of this section. */
059 private Map<Integer, StringBuilder> tailContent;
060
061 /** Line marking the start of this section. */
062 private Map<Integer, String> startingLine;
063
064 /** Line marking the end of this section. */
065 private Map<Integer, String> endingLine;
066
067 /** The child sections of this section. */
068 private Map<Integer, List<Section>> children;
069
070 /** Creates a new {@code Section} instance. */
071 public Section()
072 {
073 super();
074 }
075
076 /**
077 * Gets the name of this section.
078 *
079 * @return The name of this section.
080 */
081 public String getName()
082 {
083 return this.name;
084 }
085
086 /**
087 * Sets the name of this section.
088 *
089 * @param value The name of this section.
090 */
091 public void setName( final String value )
092 {
093 this.name = value;
094 }
095
096 /**
097 * Gets the line marking the start of this section.
098 *
099 * @return The line marking the start of this section.
100 */
101 public String getStartingLine()
102 {
103 if ( this.startingLine == null )
104 {
105 this.startingLine = new HashMap<Integer, String>();
106 }
107
108 return this.startingLine.get( this.level );
109 }
110
111 /**
112 * Sets the line marking the start of this section.
113 *
114 * @param value The line marking the start of this section.
115 */
116 public void setStartingLine( final String value )
117 {
118 if ( this.startingLine == null )
119 {
120 this.startingLine = new HashMap<Integer, String>();
121 }
122
123 this.startingLine.put( this.level, value );
124 }
125
126 /**
127 * Gets the line marking the end of this section.
128 *
129 * @return The line marking the end of this section.
130 */
131 public String getEndingLine()
132 {
133 if ( this.endingLine == null )
134 {
135 this.endingLine = new HashMap<Integer, String>();
136 }
137
138 return this.endingLine.get( this.level );
139 }
140
141 /**
142 * Sets the line marking the end of this section.
143 *
144 * @param value The line marking the end of this section.
145 */
146 public void setEndingLine( final String value )
147 {
148 if ( this.endingLine == null )
149 {
150 this.endingLine = new HashMap<Integer, String>();
151 }
152
153 this.endingLine.put( this.level, value );
154 }
155
156 /**
157 * Gets the parsed head content of this section.
158 *
159 * @return The parsed head content of this section.
160 */
161 public StringBuilder getHeadContent()
162 {
163 if ( this.headContent == null )
164 {
165 this.headContent = new HashMap<Integer, StringBuilder>();
166 }
167
168 StringBuilder b = this.headContent.get( this.level );
169 if ( b == null )
170 {
171 b = new StringBuilder();
172 this.headContent.put( this.level, b );
173 }
174
175 return b;
176 }
177
178 /**
179 * Gets the parsed tail content of this section.
180 *
181 * @return The parsed tail content of this section.
182 */
183 public StringBuilder getTailContent()
184 {
185 if ( this.tailContent == null )
186 {
187 this.tailContent = new HashMap<Integer, StringBuilder>();
188 }
189
190 StringBuilder b = this.tailContent.get( this.level );
191 if ( b == null )
192 {
193 b = new StringBuilder();
194 this.tailContent.put( this.level, b );
195 }
196
197 return b;
198 }
199
200 /**
201 * Gets all sections recursively.
202 *
203 * @return A list of all sections collected recursively.
204 */
205 public List<Section> getSections()
206 {
207 return collectSections( this, new LinkedList<Section>() );
208 }
209
210 /** Constant for the mode when parsing the head of a section. */
211 static final int MODE_HEAD = 1;
212
213 /** Constant for the mode when parsing the tail of a section. */
214 static final int MODE_TAIL = 2;
215
216 /** The current parsing mode. */
217 private int mode = MODE_HEAD;
218
219 /**
220 * Gets the level of the section.
221 *
222 * @return The level of the section.
223 */
224 int getLevel()
225 {
226 return this.level;
227 }
228
229 /**
230 * Sets the level of the section.
231 *
232 * @param value The new level of the section.
233 */
234 void setLevel( final int value )
235 {
236 this.level = value;
237 }
238
239 /**
240 * Gets the mode of the section.
241 *
242 * @return The mode of the section.
243 */
244 int getMode()
245 {
246 return this.mode;
247 }
248
249 /**
250 * Sets the mode of the section.
251 *
252 * @param value The new mode of the section.
253 */
254 void setMode( final int value )
255 {
256 this.mode = value;
257 }
258
259 /**
260 * Adds content to the section.
261 *
262 * @param content The content to add.
263 *
264 * @see #getMode()
265 * @see #getLevel()
266 */
267 void addContent( final String content )
268 {
269 if ( this.mode == MODE_HEAD )
270 {
271 this.getHeadContent().append( content );
272 }
273 else if ( this.mode == MODE_TAIL )
274 {
275 this.getTailContent().append( content );
276 }
277 }
278
279 /**
280 * Gets the child sections of this section.
281 *
282 * @return The child sections of this section.
283 */
284 List<Section> getChildren()
285 {
286 if ( this.children == null )
287 {
288 this.children = new HashMap<Integer, List<Section>>();
289 }
290
291 List<Section> c = this.children.get( this.level );
292 if ( c == null )
293 {
294 c = new LinkedList<Section>();
295 this.children.put( this.level, c );
296 }
297
298 return c;
299 }
300
301 /**
302 * Collects sections recursively.
303 *
304 * @param section A section to collect child sections of.
305 * @param sections A list to add any child sections to.
306 *
307 * @return {@code sections} with any child sections of {@code section} added.
308 */
309 private static List<Section> collectSections( final Section section, final List<Section> sections )
310 {
311 sections.add( section );
312 final int l = section.getLevel();
313 for ( int i = 0; i <= l; i++ )
314 {
315 section.setLevel( i );
316 for ( Section child : section.getChildren() )
317 {
318 collectSections( child, sections );
319 }
320 }
321 section.setLevel( l );
322 return sections;
323 }
324
325 }