View Javadoc

1   /*
2    *   Copyright (C) Christian Schulte, 2005-206
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: LineEditor.java 3875 2011-10-19 09:17:25Z schulte2005 $
29   *
30   */
31  package org.jomc.util;
32  
33  import java.io.BufferedReader;
34  import java.io.IOException;
35  import java.io.StringReader;
36  
37  /**
38   * Interface to line based editing.
39   *
40   * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
41   * @version $JOMC: LineEditor.java 3875 2011-10-19 09:17:25Z schulte2005 $
42   *
43   * @see #edit(java.lang.String)
44   */
45  public class LineEditor
46  {
47  
48      /** Editor to chain. */
49      private LineEditor editor;
50  
51      /** Line separator. */
52      private String lineSeparator;
53  
54      /**
55       * Current line number.
56       * @since 1.2
57       */
58      private long lineNumber;
59  
60      /** Creates a new {@code LineEditor} instance. */
61      public LineEditor()
62      {
63          this( null, null );
64      }
65  
66      /**
67       * Creates a new {@code LineEditor} instance taking a string to use for separating lines.
68       *
69       * @param lineSeparator String to use for separating lines.
70       */
71      public LineEditor( final String lineSeparator )
72      {
73          this( null, lineSeparator );
74      }
75  
76      /**
77       * Creates a new {@code LineEditor} instance taking an editor to chain.
78       *
79       * @param editor The editor to chain.
80       */
81      public LineEditor( final LineEditor editor )
82      {
83          this( editor, null );
84      }
85  
86      /**
87       * Creates a new {@code LineEditor} instance taking an editor to chain and a string to use for separating lines.
88       *
89       * @param editor The editor to chain.
90       * @param lineSeparator String to use for separating lines.
91       */
92      public LineEditor( final LineEditor editor, final String lineSeparator )
93      {
94          super();
95          this.editor = editor;
96          this.lineSeparator = lineSeparator;
97          this.lineNumber = 0L;
98      }
99  
100     /**
101      * Gets the line separator of the editor.
102      *
103      * @return The line separator of the editor.
104      */
105     public final String getLineSeparator()
106     {
107         if ( this.lineSeparator == null )
108         {
109             this.lineSeparator = System.getProperty( "line.separator", "\n" );
110         }
111 
112         return this.lineSeparator;
113     }
114 
115     /**
116      * Gets the current line number.
117      *
118      * @return The current line number.
119      *
120      * @since 1.2
121      */
122     public final long getLineNumber()
123     {
124         return this.lineNumber;
125     }
126 
127     /**
128      * Edits text.
129      * <p>This method splits the given string into lines and passes every line to method {@code editLine} in order of
130      * occurrence. On end of input, method {@code editLine} is called with a {@code null} argument.</p>
131      *
132      * @param text The text to edit or {@code null}.
133      *
134      * @return The edited text or {@code null}.
135      *
136      * @throws IOException if editing fails.
137      */
138     public final String edit( final String text ) throws IOException
139     {
140         String edited = text;
141         this.lineNumber = 0L;
142         BufferedReader reader = null;
143         boolean suppressExceptionOnClose = true;
144 
145         try
146         {
147             if ( edited != null )
148             {
149                 final StringBuilder buf = new StringBuilder( edited.length() + 16 );
150                 boolean appended = false;
151 
152                 if ( edited.length() > 0 )
153                 {
154                     reader = new BufferedReader( new StringReader( edited ) );
155 
156                     String line = null;
157                     while ( ( line = reader.readLine() ) != null )
158                     {
159                         this.lineNumber++;
160                         final String replacement = this.editLine( line );
161                         if ( replacement != null )
162                         {
163                             buf.append( replacement ).append( this.getLineSeparator() );
164                             appended = true;
165                         }
166                     }
167                 }
168                 else
169                 {
170                     this.lineNumber++;
171                     final String replacement = this.editLine( edited );
172                     if ( replacement != null )
173                     {
174                         buf.append( replacement ).append( this.getLineSeparator() );
175                         appended = true;
176                     }
177                 }
178 
179                 final String replacement = this.editLine( null );
180                 if ( replacement != null )
181                 {
182                     buf.append( replacement );
183                     appended = true;
184                 }
185 
186                 edited = appended ? buf.toString() : null;
187             }
188 
189             if ( this.editor != null )
190             {
191                 edited = this.editor.edit( edited );
192             }
193 
194             suppressExceptionOnClose = false;
195             return edited;
196         }
197         finally
198         {
199             try
200             {
201                 if ( reader != null )
202                 {
203                     reader.close();
204                 }
205             }
206             catch ( final IOException e )
207             {
208                 if ( !suppressExceptionOnClose )
209                 {
210                     throw e;
211                 }
212             }
213         }
214     }
215 
216     /**
217      * Edits a line.
218      *
219      * @param line The line to edit or {@code null}, indicating the end of input.
220      *
221      * @return The string to replace {@code line} with or {@code null}, to replace {@code line} with nothing.
222      *
223      * @throws IOException if editing fails.
224      */
225     protected String editLine( final String line ) throws IOException
226     {
227         return line;
228     }
229 
230 }