LineEditor.java

  1. /*
  2.  *   Copyright (C) Christian Schulte <cs@schulte.it>, 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 5043 2015-05-27 07:03:39Z schulte $
  29.  *
  30.  */
  31. package org.jomc.util;

  32. import java.io.BufferedReader;
  33. import java.io.IOException;
  34. import java.io.StringReader;

  35. /**
  36.  * Interface to line based editing.
  37.  *
  38.  * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
  39.  * @version $JOMC: LineEditor.java 5043 2015-05-27 07:03:39Z schulte $
  40.  *
  41.  * @see #edit(java.lang.String)
  42.  */
  43. public class LineEditor
  44. {

  45.     /**
  46.      * Editor to chain.
  47.      */
  48.     private LineEditor editor;

  49.     /**
  50.      * Line separator.
  51.      */
  52.     private String lineSeparator;

  53.     /**
  54.      * Current line number.
  55.      *
  56.      * @since 1.2
  57.      */
  58.     private long lineNumber;

  59.     /**
  60.      * Creates a new {@code LineEditor} instance.
  61.      */
  62.     public LineEditor()
  63.     {
  64.         this( null, null );
  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.      * Creates a new {@code LineEditor} instance taking an editor to chain.
  77.      *
  78.      * @param editor The editor to chain.
  79.      */
  80.     public LineEditor( final LineEditor editor )
  81.     {
  82.         this( editor, null );
  83.     }

  84.     /**
  85.      * Creates a new {@code LineEditor} instance taking an editor to chain and a string to use for separating lines.
  86.      *
  87.      * @param editor The editor to chain.
  88.      * @param lineSeparator String to use for separating lines.
  89.      */
  90.     public LineEditor( final LineEditor editor, final String lineSeparator )
  91.     {
  92.         super();
  93.         this.editor = editor;
  94.         this.lineSeparator = lineSeparator;
  95.         this.lineNumber = 0L;
  96.     }

  97.     /**
  98.      * Gets the line separator of the editor.
  99.      *
  100.      * @return The line separator of the editor.
  101.      */
  102.     public final String getLineSeparator()
  103.     {
  104.         if ( this.lineSeparator == null )
  105.         {
  106.             this.lineSeparator = System.getProperty( "line.separator", "\n" );
  107.         }

  108.         return this.lineSeparator;
  109.     }

  110.     /**
  111.      * Gets the current line number.
  112.      *
  113.      * @return The current line number.
  114.      *
  115.      * @since 1.2
  116.      */
  117.     public final long getLineNumber()
  118.     {
  119.         return this.lineNumber;
  120.     }

  121.     /**
  122.      * Edits text.
  123.      * <p>
  124.      * This method splits the given string into lines and passes every line to method {@code editLine} in order of
  125.      * occurrence. On end of input, method {@code editLine} is called with a {@code null} argument.
  126.      * </p>
  127.      *
  128.      * @param text The text to edit or {@code null}.
  129.      *
  130.      * @return The edited text or {@code null}.
  131.      *
  132.      * @throws IOException if editing fails.
  133.      */
  134.     public final String edit( final String text ) throws IOException
  135.     {
  136.         String edited = text;
  137.         this.lineNumber = 0L;
  138.         BufferedReader reader = null;
  139.         boolean suppressExceptionOnClose = true;

  140.         try
  141.         {
  142.             if ( edited != null )
  143.             {
  144.                 final StringBuilder buf = new StringBuilder( edited.length() + 16 );
  145.                 boolean appended = false;

  146.                 if ( edited.length() > 0 )
  147.                 {
  148.                     reader = new BufferedReader( new StringReader( edited ) );

  149.                     String line = null;
  150.                     while ( ( line = reader.readLine() ) != null )
  151.                     {
  152.                         this.lineNumber++;
  153.                         final String replacement = this.editLine( line );
  154.                         if ( replacement != null )
  155.                         {
  156.                             buf.append( replacement ).append( this.getLineSeparator() );
  157.                             appended = true;
  158.                         }
  159.                     }
  160.                 }
  161.                 else
  162.                 {
  163.                     this.lineNumber++;
  164.                     final String replacement = this.editLine( edited );
  165.                     if ( replacement != null )
  166.                     {
  167.                         buf.append( replacement ).append( this.getLineSeparator() );
  168.                         appended = true;
  169.                     }
  170.                 }

  171.                 final String replacement = this.editLine( null );
  172.                 if ( replacement != null )
  173.                 {
  174.                     buf.append( replacement );
  175.                     appended = true;
  176.                 }

  177.                 edited = appended ? buf.toString() : null;
  178.             }

  179.             if ( this.editor != null )
  180.             {
  181.                 edited = this.editor.edit( edited );
  182.             }

  183.             suppressExceptionOnClose = false;
  184.             return edited;
  185.         }
  186.         finally
  187.         {
  188.             try
  189.             {
  190.                 if ( reader != null )
  191.                 {
  192.                     reader.close();
  193.                 }
  194.             }
  195.             catch ( final IOException e )
  196.             {
  197.                 if ( !suppressExceptionOnClose )
  198.                 {
  199.                     throw e;
  200.                 }
  201.             }
  202.         }
  203.     }

  204.     /**
  205.      * Edits a line.
  206.      *
  207.      * @param line The line to edit or {@code null}, indicating the end of input.
  208.      *
  209.      * @return The string to replace {@code line} with or {@code null}, to replace {@code line} with nothing.
  210.      *
  211.      * @throws IOException if editing fails.
  212.      */
  213.     protected String editLine( final String line ) throws IOException
  214.     {
  215.         return line;
  216.     }

  217. }