001package org.apache.maven.doxia.index;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.Stack;
023
024import org.apache.maven.doxia.util.HtmlTools;
025import org.apache.maven.doxia.sink.SinkAdapter;
026
027/**
028 * A sink implementation for index.
029 *
030 * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
031 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
032 * @version $Id: IndexingSink.html 905940 2014-04-12 16:27:29Z hboutemy $
033 */
034public class IndexingSink
035    extends SinkAdapter
036{
037    /** Section 1. */
038    private static final int TYPE_SECTION_1 = 1;
039
040    /** Section 2. */
041    private static final int TYPE_SECTION_2 = 2;
042
043    /** Section 3. */
044    private static final int TYPE_SECTION_3 = 3;
045
046    /** Section 4. */
047    private static final int TYPE_SECTION_4 = 4;
048
049    /** Section 5. */
050    private static final int TYPE_SECTION_5 = 5;
051
052    /** Defined term. */
053    private static final int TYPE_DEFINED_TERM = 6;
054
055    /** Figure. */
056    private static final int TYPE_FIGURE = 7;
057
058    /** Table. */
059    private static final int TYPE_TABLE = 8;
060
061    /** Title. */
062    private static final int TITLE = 9;
063
064    /** The current type. */
065    private int type;
066
067    /** The current title. */
068    private String title;
069
070    /** The stack. */
071    private final Stack<IndexEntry> stack;
072
073    /** The current type. */
074    private IndexEntry currentEntry;
075
076    /**
077     * Default constructor.
078     *
079     * @param sectionEntry The first index entry.
080     */
081    public IndexingSink( IndexEntry sectionEntry )
082    {
083        stack = new Stack<IndexEntry>();
084        stack.push( sectionEntry );
085
086        init();
087    }
088
089    /**
090     * <p>Getter for the field <code>title</code>.</p>
091     *
092     * @return the title
093     */
094    public String getTitle()
095    {
096        return title;
097    }
098
099    // ----------------------------------------------------------------------
100    // Sink Overrides
101    // ----------------------------------------------------------------------
102
103    /** {@inheritDoc} */
104    public void title()
105    {
106        this.type = TITLE;
107    }
108
109    /** {@inheritDoc} */
110    public void sectionTitle1()
111    {
112        this.currentEntry = null;
113        this.type = TYPE_SECTION_1;
114    }
115
116    /** {@inheritDoc} */
117    public void title_()
118    {
119        this.type = 0;
120    }
121
122    public void sectionTitle1_()
123    {
124        this.type = 0;
125    }
126
127    /** {@inheritDoc} */
128    public void section1_()
129    {
130        pop();
131    }
132
133    /** {@inheritDoc} */
134    public void sectionTitle2()
135    {
136        this.currentEntry = null;
137        this.type = TYPE_SECTION_2;
138    }
139
140    public void sectionTitle2_()
141    {
142        this.type = 0;
143    }
144
145    /** {@inheritDoc} */
146    public void section2_()
147    {
148        pop();
149    }
150
151    /** {@inheritDoc} */
152    public void sectionTitle3()
153    {
154        this.currentEntry = null;
155        this.type = TYPE_SECTION_3;
156    }
157
158    public void sectionTitle3_()
159    {
160        this.type = 0;
161    }
162
163    /** {@inheritDoc} */
164    public void section3_()
165    {
166        pop();
167    }
168
169    /** {@inheritDoc} */
170    public void sectionTitle4()
171    {
172        this.currentEntry = null;
173        this.type = TYPE_SECTION_4;
174    }
175
176    public void sectionTitle4_()
177    {
178        this.type = 0;
179    }
180
181    /** {@inheritDoc} */
182    public void section4_()
183    {
184        pop();
185    }
186
187    /** {@inheritDoc} */
188    public void sectionTitle5()
189    {
190        this.currentEntry = null;
191        this.type = TYPE_SECTION_5;
192    }
193
194    public void sectionTitle5_()
195    {
196        this.type = 0;
197    }
198
199    /** {@inheritDoc} */
200    public void section5_()
201    {
202        pop();
203    }
204
205    // public void definedTerm()
206    // {
207    // type = TYPE_DEFINED_TERM;
208    // }
209    //
210    // public void figureCaption()
211    // {
212    // type = TYPE_FIGURE;
213    // }
214    //
215    // public void tableCaption()
216    // {
217    // type = TYPE_TABLE;
218    // }
219
220    /** {@inheritDoc} */
221    public void text( String text )
222    {
223        switch ( this.type )
224        {
225            case TITLE:
226                this.title = text;
227                break;
228            case TYPE_SECTION_1:
229            case TYPE_SECTION_2:
230            case TYPE_SECTION_3:
231            case TYPE_SECTION_4:
232            case TYPE_SECTION_5:
233                // -----------------------------------------------------------------------
234                // Sanitize the id. The most important step is to remove any blanks
235                // -----------------------------------------------------------------------
236
237                if ( this.currentEntry == null )
238                {
239                    this.currentEntry = new IndexEntry( peek(), HtmlTools.encodeId( text ) );
240
241                    this.currentEntry.setTitle( text );
242
243                    push( currentEntry );
244                }
245                else
246                {
247                    IndexEntry entry = (IndexEntry) stack.lastElement();
248
249                    String title = currentEntry.getTitle() + text;
250                    title = title.replaceAll( "[\\r\\n]+", "" );
251
252                    entry.setId( HtmlTools.encodeId( title ) );
253
254                    entry.setTitle( title );
255                }
256
257                break;
258            // Dunno how to handle these yet
259            case TYPE_DEFINED_TERM:
260            case TYPE_FIGURE:
261            case TYPE_TABLE:
262            default:
263                break;
264        }
265    }
266
267    /**
268     * Pushes an IndexEntry onto the top of this stack.
269     *
270     * @param entry to put.
271     */
272    public void push( IndexEntry entry )
273    {
274        stack.push( entry );
275    }
276
277    /**
278     * Removes the IndexEntry at the top of this stack.
279     */
280    public void pop()
281    {
282        stack.pop();
283    }
284
285    /**
286     * <p>peek.</p>
287     *
288     * @return Looks at the IndexEntry at the top of this stack.
289     */
290    public IndexEntry peek()
291    {
292        return stack.peek();
293    }
294
295    /** {@inheritDoc} */
296    public void close()
297    {
298        super.close();
299
300        init();
301    }
302
303    /** {@inheritDoc} */
304    protected void init()
305    {
306        this.type = 0;
307        this.title = null;
308    }
309}