001    /*
002     *   Copyright (C) Christian Schulte, 2005-206
003     *   All rights reserved.
004     *
005     *   Redistribution and use in source and binary forms, with or without
006     *   modification, are permitted provided that the following conditions
007     *   are met:
008     *
009     *     o Redistributions of source code must retain the above copyright
010     *       notice, this list of conditions and the following disclaimer.
011     *
012     *     o Redistributions in binary form must reproduce the above copyright
013     *       notice, this list of conditions and the following disclaimer in
014     *       the documentation and/or other materials provided with the
015     *       distribution.
016     *
017     *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018     *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019     *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020     *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021     *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022     *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023     *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024     *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026     *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     *
028     *   $JOMC: Section.java 3838 2011-10-08 20:15:41Z schulte2005 $
029     *
030     */
031    package org.jomc.util;
032    
033    import java.util.ArrayList;
034    import java.util.List;
035    
036    /**
037     * Section of text.
038     *
039     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
040     * @version $JOMC: Section.java 3838 2011-10-08 20:15:41Z schulte2005 $
041     */
042    public class Section
043    {
044    
045        /** Constant for the mode during parsing the head content of a section. */
046        static final int MODE_HEAD = 1;
047    
048        /** Constant for the mode during parsing the tail content of a section. */
049        static final int MODE_TAIL = 2;
050    
051        /** The current parsing mode. */
052        private int mode = MODE_HEAD;
053    
054        /** The name of this section. */
055        private String name;
056    
057        /** The parsed head content of this section. */
058        private StringBuilder headContent;
059    
060        /** The parsed tail content of this section. */
061        private StringBuilder tailContent;
062    
063        /** Line marking the start of this section. */
064        private String startingLine;
065    
066        /** Line marking the end of this section. */
067        private String endingLine;
068    
069        /** The child sections of this section. */
070        private List<Section> sections;
071    
072        /** Creates a new {@code Section} instance. */
073        public Section()
074        {
075            super();
076        }
077    
078        /**
079         * Gets the name of this section.
080         *
081         * @return The name of this section or {@code null}.
082         */
083        public String getName()
084        {
085            return this.name;
086        }
087    
088        /**
089         * Sets the name of this section.
090         *
091         * @param value The new name of this section or {@code null}.
092         */
093        public void setName( final String value )
094        {
095            this.name = value;
096        }
097    
098        /**
099         * Gets the line marking the start of this section.
100         *
101         * @return The line marking the start of this section.
102         */
103        public String getStartingLine()
104        {
105            return this.startingLine;
106        }
107    
108        /**
109         * Sets the line marking the start of this section.
110         *
111         * @param value The new line marking the start of this section.
112         */
113        public void setStartingLine( final String value )
114        {
115            this.startingLine = value;
116        }
117    
118        /**
119         * Gets the line marking the end of this section.
120         *
121         * @return The line marking the end of this section.
122         */
123        public String getEndingLine()
124        {
125            return this.endingLine;
126        }
127    
128        /**
129         * Sets the line marking the end of this section.
130         *
131         * @param value The new line marking the end of this section.
132         */
133        public void setEndingLine( final String value )
134        {
135            this.endingLine = value;
136        }
137    
138        /**
139         * Gets the content of this section preceding any child section content.
140         *
141         * @return The content of this section preceding any child section content.
142         */
143        public StringBuilder getHeadContent()
144        {
145            if ( this.headContent == null )
146            {
147                this.headContent = new StringBuilder( 512 );
148            }
149    
150            return this.headContent;
151        }
152    
153        /**
154         * Gets the content of this section succeeding any child section content.
155         *
156         * @return The content of this section succeeding any child section content.
157         */
158        public StringBuilder getTailContent()
159        {
160            if ( this.tailContent == null )
161            {
162                this.tailContent = new StringBuilder( 512 );
163            }
164    
165            return this.tailContent;
166        }
167    
168        /**
169         * Gets the child sections of this section.
170         * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
171         * to the returned list will be present inside the object. This is why there is no {@code set} method for the
172         * sections property.</p>
173         *
174         * @return A list of child sections of this section.
175         */
176        public List<Section> getSections()
177        {
178            if ( this.sections == null )
179            {
180                this.sections = new ArrayList<Section>();
181            }
182    
183            return this.sections;
184        }
185    
186        /**
187         * Gets a child section matching a given name.
188         *
189         * @param sectionName The name of the section to return.
190         *
191         * @return The first child section matching {@code sectionName} or {@code null}, if no such section is found.
192         *
193         * @throws NullPointerException if {@code sectionName} is {@code null}.
194         */
195        public Section getSection( final String sectionName )
196        {
197            if ( sectionName == null )
198            {
199                throw new NullPointerException( "sectionName" );
200            }
201    
202            return this.getSection( this, sectionName );
203        }
204    
205        private Section getSection( final Section current, final String sectionName )
206        {
207            if ( sectionName.equals( current.getName() ) )
208            {
209                return current;
210            }
211    
212            for ( Section child : current.getSections() )
213            {
214                if ( sectionName.equals( child.getName() ) )
215                {
216                    return child;
217                }
218    
219                if ( child.getName() == null )
220                {
221                    final Section section = child.getSection( sectionName );
222    
223                    if ( section != null )
224                    {
225                        return section;
226                    }
227                }
228            }
229    
230            return null;
231        }
232    
233        /**
234         * Gets the parsing mode of the instance.
235         *
236         * @return The parsing mode of the instance.
237         *
238         * @see #MODE_HEAD
239         * @see #MODE_TAIL
240         */
241        int getMode()
242        {
243            return this.mode;
244        }
245    
246        /**
247         * Sets the parsing mode of the instance.
248         *
249         * @param value The new parsing mode of the instance.
250         *
251         * @see #MODE_HEAD
252         * @see #MODE_TAIL
253         */
254        void setMode( final int value )
255        {
256            this.mode = value;
257        }
258    
259    }