001package org.apache.maven.doxia.util;
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
022/*
023 * Originally from org.apache.doxia.module.apt.AptReaderSource. It was modified
024 * to get unget support
025 */
026
027import java.io.IOException;
028import java.io.LineNumberReader;
029import java.io.Reader;
030
031import org.apache.maven.doxia.parser.ParseException;
032import org.codehaus.plexus.util.IOUtil;
033
034/**
035 * {@link ByLineSource} default implementation
036 */
037public class ByLineReaderSource implements ByLineSource
038{
039    /**
040     * reader
041     */
042    private LineNumberReader reader;
043
044    /**
045     * current line number
046     */
047    private int lineNumber;
048
049    /**
050     * holds the last line returned by getNextLine()
051     */
052    private String lastLine;
053
054    /**
055     * <code>true</code> if ungetLine() was called and no getNextLine() was
056     * called
057     */
058    private boolean ungetted = false;
059    
060    private String name;
061
062    /**
063     * Creates the ByLineReaderSource.
064     *
065     * @param in real source :)
066     */
067    public ByLineReaderSource( final Reader in )
068    {
069        this( in, "" );
070    }
071    
072    /**
073     * <p>Constructor for ByLineReaderSource.</p>
074     *
075     * @param in a {@link java.io.Reader} object.
076     * @param name a {@link java.lang.String} object.
077     */
078    public ByLineReaderSource( final Reader in, final String name )
079    {
080        this.reader = new LineNumberReader( in );
081        
082        this.name = name;
083
084        this.lineNumber = -1;
085    }
086
087    /**
088     * {@inheritDoc}
089     *
090     * @return a {@link java.lang.String} object.
091     * @throws org.apache.maven.doxia.parser.ParseException if any.
092     */
093    public final String getNextLine() throws ParseException
094    {
095        if ( reader == null )
096        {
097            return null;
098        }
099
100        if ( ungetted )
101        {
102            ungetted = false;
103            return lastLine;
104        }
105
106        String line;
107
108        try
109        {
110            line = reader.readLine();
111            if ( line == null )
112            {
113                reader.close();
114                reader = null;
115            }
116            else
117            {
118                lineNumber = reader.getLineNumber();
119            }
120        }
121        catch ( IOException e )
122        {
123            throw new ParseException( e, lineNumber, 0 );
124        }
125
126        lastLine = line;
127
128        return line;
129    }
130
131    /**
132     * {@inheritDoc}
133     *
134     * @return a {@link java.lang.String} object.
135     */
136    public final String getName()
137    {
138        return name;
139    }
140
141    /**
142     * {@inheritDoc}
143     *
144     * @return a int.
145     */
146    public final int getLineNumber()
147    {
148        return lineNumber;
149    }
150
151    /**
152     * {@inheritDoc}
153     */
154    public final void close()
155    {
156        IOUtil.close( reader );
157        reader = null;
158    }
159
160    /**
161     * {@inheritDoc}
162     */
163    public final void ungetLine()
164    {
165        if ( ungetted )
166        {
167            throw new IllegalStateException( "we support only one level of ungetLine()" );
168        }
169        ungetted = true;
170    }
171
172    /** {@inheritDoc} */
173    public final void unget( final String s )
174    {
175        if ( s == null )
176        {
177            throw new IllegalArgumentException( "argument can't be null" );
178        }
179        if ( s.length() != 0 )
180        {
181            ungetLine();
182            lastLine = s;
183        }
184    }
185}