001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.maven.doxia.sink.impl;
020
021import org.apache.maven.doxia.markup.Markup;
022import org.apache.maven.doxia.sink.EmptyLocator;
023import org.apache.maven.doxia.sink.Locator;
024import org.apache.maven.doxia.sink.Sink;
025import org.apache.maven.doxia.sink.SinkEventAttributes;
026
027/**
028 * An abstract base class that defines some convenience methods for sinks.
029 * Also acts as compatibility bridge for Doxia 1.0 methods which have overloaded variants in Doxia > 1.0 (taking an additional argument {@link SinkEventAttributes}).
030 * This implementation just delegates the former to the latter with argument {@link SinkEventAttributes} being {@code null}.
031 *
032 * @author ltheussl
033 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
034 * @since 1.1
035 */
036public abstract class AbstractSink implements Sink, Markup {
037
038    private Locator locator;
039
040    // -- start default implementation for legacy doxia 1.0 methods which have overridden variants in Doxia 1.1 or 2.0,
041    // all sink implementation derived from this must only override the Doxia > 1.0 variants
042    @Override
043    public final void head() {
044        head(null);
045    }
046
047    @Override
048    public final void title() {
049        title(null);
050    }
051
052    @Override
053    public final void author() {
054        author(null);
055    }
056
057    @Override
058    public final void date() {
059        date(null);
060    }
061
062    @Override
063    public final void body() {
064        body(null);
065    }
066
067    @Override
068    public final void article() {
069        article(null);
070    }
071
072    @Override
073    public final void navigation() {
074        navigation(null);
075    }
076
077    @Override
078    public final void sidebar() {
079        sidebar(null);
080    }
081
082    @Override
083    public final void sectionTitle() {
084        sectionTitle(0, null);
085    }
086
087    @Override
088    public final void section1() {
089        section(1, null);
090    }
091
092    @Override
093    public final void sectionTitle_() {
094        sectionTitle_(0);
095    }
096
097    @Override
098    public final void section1_() {
099        section_(1);
100    }
101
102    @Override
103    public final void sectionTitle1() {
104        sectionTitle(1, null);
105    }
106
107    @Override
108    public final void sectionTitle1_() {
109        sectionTitle_(1);
110    }
111
112    @Override
113    public final void section2() {
114        section(2, null);
115    }
116
117    @Override
118    public final void section2_() {
119        section_(2);
120    }
121
122    @Override
123    public final void sectionTitle2() {
124        sectionTitle(2, null);
125    }
126
127    @Override
128    public final void sectionTitle2_() {
129        sectionTitle_(2);
130    }
131
132    @Override
133    public final void section3() {
134        section(3, null);
135    }
136
137    @Override
138    public final void section3_() {
139        section_(3);
140    }
141
142    @Override
143    public final void sectionTitle3() {
144        sectionTitle(3, null);
145    }
146
147    @Override
148    public final void sectionTitle3_() {
149        sectionTitle_(3);
150    }
151
152    @Override
153    public final void section4() {
154        section(4, null);
155    }
156
157    @Override
158    public final void section4_() {
159        section_(4);
160    }
161
162    @Override
163    public final void sectionTitle4() {
164        sectionTitle(4, null);
165    }
166
167    @Override
168    public final void sectionTitle4_() {
169        sectionTitle_(4);
170    }
171
172    @Override
173    public final void section5() {
174        section(5, null);
175    }
176
177    @Override
178    public final void section5_() {
179        section_(5);
180    }
181
182    @Override
183    public final void sectionTitle5() {
184        sectionTitle(5, null);
185    }
186
187    @Override
188    public final void sectionTitle5_() {
189        sectionTitle_(5);
190    }
191
192    @Override
193    public final void section6() {
194        section(6, null);
195    }
196
197    @Override
198    public final void section6_() {
199        section_(6);
200    }
201
202    @Override
203    public final void sectionTitle6() {
204        sectionTitle(6, null);
205    }
206
207    @Override
208    public final void sectionTitle6_() {
209        sectionTitle_(6);
210    }
211
212    @Override
213    public final void header() {
214        header(null);
215    }
216
217    @Override
218    public final void content() {
219        content(null);
220    }
221
222    @Override
223    public final void footer() {
224        footer(null);
225    }
226
227    @Override
228    public final void list() {
229        list(null);
230    }
231
232    @Override
233    public final void listItem() {
234        listItem(null);
235    }
236
237    @Override
238    public final void numberedList(int numbering) {
239        numberedList(numbering, null);
240    }
241
242    @Override
243    public final void numberedListItem() {
244        numberedListItem(null);
245    }
246
247    @Override
248    public final void definitionList() {
249        definitionList(null);
250    }
251
252    @Override
253    public final void definitionListItem() {
254        definitionListItem(null);
255    }
256
257    @Override
258    public final void definition() {
259        definition(null);
260    }
261
262    @Override
263    public final void definedTerm() {
264        definedTerm(null);
265    }
266
267    @Override
268    public final void figure() {
269        figure(null);
270    }
271
272    @Override
273    public final void figureCaption() {
274        figureCaption(null);
275    }
276
277    @Override
278    public final void figureGraphics(String name) {
279        figureGraphics(name, null);
280    }
281
282    @Override
283    public final void table() {
284        table(null);
285    }
286
287    @Override
288    public final void tableRows() {
289        tableRows(null, false);
290    }
291
292    @Override
293    public final void tableRow() {
294        tableRow(null);
295    }
296
297    @Override
298    public final void tableCell() {
299        tableCell(null);
300    }
301
302    @Override
303    public final void tableHeaderCell() {
304        tableHeaderCell(null);
305    }
306
307    @Override
308    public final void tableCaption() {
309        tableCaption(null);
310    }
311
312    @Override
313    public final void paragraph() {
314        paragraph(null);
315    }
316
317    @Override
318    public final void data(String value) {
319        data(value, null);
320    }
321
322    @Override
323    public final void time(String datetime) {
324        time(datetime, null);
325    }
326
327    @Override
328    public final void address() {
329        address(null);
330    }
331
332    @Override
333    public final void blockquote() {
334        blockquote(null);
335    }
336
337    @Override
338    public final void division() {
339        division(null);
340    }
341
342    @Override
343    public final void verbatim() {
344        verbatim(null);
345    }
346
347    @Override
348    public final void horizontalRule() {
349        horizontalRule(null);
350    }
351
352    @Override
353    public final void anchor(String name) {
354        anchor(name, null);
355    }
356
357    @Override
358    public final void link(String name) {
359        link(name, null);
360    }
361
362    @Override
363    public final void inline() {
364        inline(null);
365    }
366
367    @Override
368    public final void lineBreak() {
369        lineBreak(null);
370    }
371
372    @Override
373    public final void lineBreakOpportunity() {
374        lineBreakOpportunity(null);
375    }
376
377    @Override
378    public final void text(String text) {
379        text(text, null);
380    }
381    // -- end default implementation for legacy doxia 1.0 methods which have overridden variants in Doxia 1.1 or 2.0
382
383    /**
384     * Parses the given String and replaces all occurrences of
385     * '\n', '\r' and '\r\n' with the system EOL. All Sinks should
386     * make sure that text output is filtered through this method.
387     *
388     * @param text the text to scan.
389     *      May be null in which case null is returned.
390     * @return a String that contains only System EOLs.
391     */
392    protected static String unifyEOLs(String text) {
393        if (text == null) {
394            return null;
395        }
396
397        int length = text.length();
398
399        StringBuilder buffer = new StringBuilder(length);
400
401        for (int i = 0; i < length; i++) {
402            if (text.charAt(i) == '\r') {
403                if ((i + 1) < length && text.charAt(i + 1) == '\n') {
404                    i++;
405                }
406
407                buffer.append(EOL);
408            } else if (text.charAt(i) == '\n') {
409                buffer.append(EOL);
410            } else {
411                buffer.append(text.charAt(i));
412            }
413        }
414
415        return buffer.toString();
416    }
417
418    /**
419     * This is called in {@link #head()} or in {@link #close()}, and can be used
420     * to set the sink into a clear state so it can be re-used.
421     *
422     * @since 1.1.2
423     */
424    protected void init() {
425        // nop
426    }
427
428    @Override
429    public void setDocumentLocator(Locator locator) {
430        this.locator = locator;
431    }
432
433    @Override
434    public Locator getDocumentLocator() {
435        if (locator == null) {
436            return EmptyLocator.INSTANCE;
437        }
438        return locator;
439    }
440
441    protected String getLocationLogPrefix() {
442        return formatLocation(getDocumentLocator());
443    }
444
445    /**
446     * Creates a string with line/column information. Inspired by
447     * {@code o.a.m.model.building.ModelProblemUtils.formatLocation(...)}.
448     *
449     * @param locator The locator must not be {@code null}.
450     * @return The formatted location or an empty string if unknown, never {@code null}.
451     */
452    public static String formatLocation(Locator locator) {
453        StringBuilder buffer = new StringBuilder();
454
455        if (locator.getReference() != null) {
456            buffer.append(locator.getReference());
457        } else {
458            buffer.append("Unknown source");
459        }
460        if (locator.getLineNumber() > 0) {
461            buffer.append(", line ").append(locator.getLineNumber());
462        }
463        if (locator.getColumnNumber() > 0) {
464            buffer.append(", column ").append(locator.getColumnNumber());
465        }
466        if (buffer.length() > 0) {
467            buffer.append(": ");
468        }
469        return buffer.toString();
470    }
471}