Coverage Report - palmed.edit.selection.AbstractAction

Classes in this Package Line Coverage Branch Coverage Complexity
AbstractAction
81% 
100% 
1,923

 1  
 /**
 2  
  * Redistribution  and use  in source  and binary  forms, with  or without
 3  
  * modification, are permitted provided  that the following conditions are
 4  
  * met :
 5  
  *
 6  
  * . Redistributions  of  source  code  must  retain  the  above copyright
 7  
  *   notice, this list of conditions and the following disclaimer.
 8  
  *
 9  
  * . Redistributions in  binary form  must reproduce  the above  copyright
 10  
  *   notice, this list of conditions  and the following disclaimer in  the
 11  
  *   documentation and/or other materials provided with the distribution.
 12  
  *
 13  
  * . The name of the author may not be used to endorse or promote products
 14  
  *   derived from this software without specific prior written permission.
 15  
  *
 16  
  * THIS SOFTWARE IS  PROVIDED BY THE  AUTHOR ``AS IS''  AND ANY EXPRESS  OR
 17  
  * IMPLIED  WARRANTIES,  INCLUDING,  BUT   NOT  LIMITED  TO,  THE   IMPLIED
 18  
  * WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE ARE
 19  
  * DISCLAIMED.  IN NO  EVENT SHALL  THE AUTHOR  BE LIABLE  FOR ANY  DIRECT,
 20  
  * INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL  DAMAGES
 21  
  * (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT OF  SUBSTITUTE  GOODS OR
 22  
  * SERVICES;  LOSS  OF USE,  DATA,  OR PROFITS;  OR  BUSINESS INTERRUPTION)
 23  
  * HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN  CONTRACT,
 24  
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 25  
  * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE, EVEN  IF  ADVISED OF  THE
 26  
  * POSSIBILITY OF SUCH DAMAGE.
 27  
  *
 28  
  * $Id$
 29  
  */
 30  
 
 31  
 package palmed.edit.selection;
 32  
 
 33  
 import java.io.ByteArrayInputStream;
 34  
 import java.io.ByteArrayOutputStream;
 35  
 import java.io.IOException;
 36  
 import palmed.util.ChainedException;
 37  
 
 38  
 /**
 39  
  * This class factorizes behaviours common to all actions.
 40  
  *
 41  
  * @author Mathieu Champlon
 42  
  * @version $Revision$ $Date$
 43  
  */
 44  
 public abstract class AbstractAction implements IAction
 45  
 {
 46  
     /**
 47  
      * The selection.
 48  
      */
 49  
     private final ISelection selection_;
 50  
     /**
 51  
      * A backup of the initial selection state.
 52  
      */
 53  
     private byte[] initial_;
 54  
     /**
 55  
      * A backup of the final selection state.
 56  
      */
 57  
     private byte[] final_;
 58  
     /**
 59  
      * A backup of the removed data.
 60  
      */
 61  
     private byte[] data_;
 62  
 
 63  
     /**
 64  
      * Create an abstract action.
 65  
      *
 66  
      * @param selection the selection
 67  
      */
 68  
     protected AbstractAction( final ISelection selection )
 69  540
     {
 70  540
         if( selection == null )
 71  0
             throw new IllegalArgumentException( "parameter 'selection' is null" );
 72  540
         selection_ = selection;
 73  540
     }
 74  
 
 75  
     /**
 76  
      * {@inheritDoc}
 77  
      */
 78  
     public final void perform()
 79  
     {
 80  540
         initial_ = backupState();
 81  540
         onPerform();
 82  540
         final_ = backupState();
 83  540
     }
 84  
 
 85  
     /**
 86  
      * {@inheritDoc}
 87  
      */
 88  
     public final void undo()
 89  
     {
 90  110
         restoreState( final_ );
 91  110
         if( onUndo() )
 92  60
             restoreState( initial_ );
 93  110
     }
 94  
 
 95  
     /**
 96  
      * {@inheritDoc}
 97  
      */
 98  
     public final void redo()
 99  
     {
 100  50
         restoreState( initial_ );
 101  50
         if( onRedo() )
 102  10
             restoreState( final_ );
 103  50
     }
 104  
 
 105  
     /**
 106  
      * Perform the action.
 107  
      */
 108  
     protected abstract void onPerform();
 109  
 
 110  
     /**
 111  
      * Undo the action.
 112  
      *
 113  
      * @return Whether the initial state must be restored or not
 114  
      */
 115  
     protected abstract boolean onUndo();
 116  
 
 117  
     /**
 118  
      * Redo the action.
 119  
      *
 120  
      * @return Whether the final state must be restored or not
 121  
      */
 122  
     protected abstract boolean onRedo();
 123  
 
 124  
     /**
 125  
      * Overwrite the current final state with the one of another action.
 126  
      *
 127  
      * @param action the action
 128  
      */
 129  
     protected final void overwriteFinalState( final AbstractAction action ) // FIXME dirty
 130  
     {
 131  260
         final_ = action.final_;
 132  260
     }
 133  
 
 134  
     /**
 135  
      * Prepend the current backup data with the data from another action.
 136  
      *
 137  
      * @param action the action
 138  
      */
 139  
     protected final void prependData( final AbstractAction action ) // FIXME dirty
 140  
     {
 141  15
         final byte[] data = new byte[data_.length + action.data_.length];
 142  15
         System.arraycopy( action.data_, 0, data, 0, action.data_.length );
 143  15
         System.arraycopy( data_, 0, data, action.data_.length, data_.length );
 144  15
         data_ = data;
 145  15
     }
 146  
 
 147  
     private byte[] backupState()
 148  
     {
 149  1080
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();
 150  
         try
 151  
         {
 152  1080
             selection_.marshall( stream );
 153  
         }
 154  0
         catch( IOException e )
 155  
         {
 156  0
             throw new ChainedException( e ); // FIXME custom exception
 157  1080
         }
 158  1080
         return stream.toByteArray();
 159  
     }
 160  
 
 161  
     private void restoreState( final byte[] state )
 162  
     {
 163  
         try
 164  
         {
 165  230
             selection_.unmarshall( new ByteArrayInputStream( state ) );
 166  
         }
 167  0
         catch( IOException e )
 168  
         {
 169  0
             throw new ChainedException( e ); // FIXME custom exception
 170  230
         }
 171  230
     }
 172  
 
 173  
     /**
 174  
      * Backup the selected text.
 175  
      */
 176  
     protected final void backupData()
 177  
     {
 178  180
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();
 179  
         try
 180  
         {
 181  180
             selection_.write( stream );
 182  
         }
 183  0
         catch( IOException e )
 184  
         {
 185  0
             throw new ChainedException( e ); // FIXME custom exception
 186  180
         }
 187  180
         data_ = stream.toByteArray();
 188  180
     }
 189  
 
 190  
     /**
 191  
      * Remove the selected text and restore backup.
 192  
      */
 193  
     protected final void restoreData()
 194  
     {
 195  
         try
 196  
         {
 197  95
             selection_.read( new ByteArrayInputStream( data_ ) );
 198  
         }
 199  0
         catch( IOException e )
 200  
         {
 201  0
             throw new ChainedException( e ); // FIXME custom exception
 202  95
         }
 203  95
     }
 204  
 }