Coverage Report - com.healthmarketscience.jackcess.CursorBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
CursorBuilder
100%
68/68
88%
21/24
0
 
 1  
 /*
 2  
 Copyright (c) 2007 Health Market Science, Inc.
 3  
 
 4  
 This library is free software; you can redistribute it and/or
 5  
 modify it under the terms of the GNU Lesser General Public
 6  
 License as published by the Free Software Foundation; either
 7  
 version 2.1 of the License, or (at your option) any later version.
 8  
 
 9  
 This library is distributed in the hope that it will be useful,
 10  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  
 Lesser General Public License for more details.
 13  
 
 14  
 You should have received a copy of the GNU Lesser General Public
 15  
 License along with this library; if not, write to the Free Software
 16  
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 17  
 USA
 18  
 
 19  
 You can contact Health Market Science at info@healthmarketscience.com
 20  
 or at the following address:
 21  
 
 22  
 Health Market Science
 23  
 2700 Horizon Drive
 24  
 Suite 200
 25  
 King of Prussia, PA 19406
 26  
 */
 27  
 
 28  
 package com.healthmarketscience.jackcess;
 29  
 
 30  
 import java.io.IOException;
 31  
 import java.util.Arrays;
 32  
 import java.util.Collection;
 33  
 import java.util.Iterator;
 34  
 import java.util.List;
 35  
 
 36  
 import org.apache.commons.lang.ObjectUtils;
 37  
 
 38  
 /**
 39  
  * Builder style class for constructing a Cursor.  By default, a cursor is
 40  
  * created at the beginning of the table, and any start/end rows are
 41  
  * inclusive.
 42  
  *
 43  
  * @author James Ahlborn
 44  
  */
 45  
 public class CursorBuilder {
 46  
   /** the table which the cursor will traverse */
 47  
   private final Table _table;
 48  
   /** optional index to use in traversal */
 49  
   private Index _index;
 50  
   /** optional start row for an index cursor */
 51  
   private Object[] _startRow;
 52  
   /** whether or not start row for an index cursor is inclusive */
 53  70
   private boolean _startRowInclusive = true;
 54  
   /** optional end row for an index cursor */
 55  
   private Object[] _endRow;
 56  
   /** whether or not end row for an index cursor is inclusive */
 57  70
   private boolean _endRowInclusive = true;
 58  
   /** whether to start at beginning or end of cursor */
 59  70
   private boolean _beforeFirst = true;
 60  
   /** optional save point to restore to the cursor */
 61  
   private Cursor.Savepoint _savepoint;
 62  
 
 63  70
   public CursorBuilder(Table table) {
 64  70
     _table = table;
 65  70
   }
 66  
 
 67  
   /**
 68  
    * Sets the cursor so that it will start at the beginning (unless a
 69  
    * savepoint is given).
 70  
    */
 71  
   public CursorBuilder beforeFirst() {
 72  2
     _beforeFirst = true;
 73  2
     return this;
 74  
   }
 75  
   
 76  
   /**
 77  
    * Sets the cursor so that it will start at the end (unless a savepoint is
 78  
    * given).
 79  
    */
 80  
   public CursorBuilder afterLast() {
 81  2
     _beforeFirst = false;
 82  2
     return this;
 83  
   }
 84  
 
 85  
   /**
 86  
    * Sets a savepoint to restore for the initial position of the cursor.
 87  
    */
 88  
   public CursorBuilder restoreSavepoint(Cursor.Savepoint savepoint) {
 89  2
     _savepoint = savepoint;
 90  2
     return this;
 91  
   }
 92  
 
 93  
   /**
 94  
    * Sets an index to use for the cursor.
 95  
    */
 96  
   public CursorBuilder setIndex(Index index) {
 97  25
     _index = index;
 98  25
     return this;
 99  
   }
 100  
 
 101  
   /**
 102  
    * Sets an index to use for the cursor by searching the table for an index
 103  
    * with the given name.
 104  
    * @throws IllegalArgumentException if no index can be found on the table
 105  
    *         with the given name
 106  
    */
 107  
   public CursorBuilder setIndexByName(String indexName) {
 108  2
     return setIndex(_table.getIndex(indexName));
 109  
   }
 110  
 
 111  
   /**
 112  
    * Sets an index to use for the cursor by searching the table for an index
 113  
    * with exactly the given columns.
 114  
    * @throws IllegalArgumentException if no index can be found on the table
 115  
    *         with the given name
 116  
    */
 117  
   public CursorBuilder setIndexByColumns(Column... columns) {
 118  40
     List<Column> searchColumns = Arrays.asList(columns);
 119  40
     boolean found = false;
 120  40
     for(Index index : _table.getIndexes()) {
 121  
       
 122  61
       Collection<Index.ColumnDescriptor> indexColumns = index.getColumns();
 123  61
       if(indexColumns.size() != searchColumns.size()) {
 124  1
         continue;
 125  
       }
 126  60
       Iterator<Column> sIter = searchColumns.iterator();
 127  60
       Iterator<Index.ColumnDescriptor> iIter = indexColumns.iterator();
 128  60
       boolean matches = true;
 129  98
       while(sIter.hasNext()) {
 130  60
         Column sCol = sIter.next();
 131  60
         Index.ColumnDescriptor iCol = iIter.next();
 132  60
         if(!ObjectUtils.equals(sCol.getName(), iCol.getName())) {
 133  22
           matches = false;
 134  22
           break;
 135  
         }
 136  38
       }
 137  
 
 138  60
       if(matches) {
 139  38
         _index = index;
 140  38
         found = true;
 141  38
         break;
 142  
       }
 143  22
     }
 144  40
     if(!found) {
 145  2
       throw new IllegalArgumentException("Index with columns " +
 146  
                                          searchColumns +
 147  
                                          " does not exist in table " + _table);
 148  
     }
 149  38
     return this;
 150  
   }
 151  
 
 152  
   /**
 153  
    * Sets the starting and ending row for a range based index cursor.
 154  
    * <p>
 155  
    * A valid index must be specified before calling this method.
 156  
    */
 157  
   public CursorBuilder setSpecificRow(Object[] specificRow) {
 158  37
     setStartRow(specificRow);
 159  37
     setEndRow(specificRow);
 160  37
     return this;
 161  
   }
 162  
   
 163  
   /**
 164  
    * Sets the starting and ending row for a range based index cursor to the
 165  
    * given entry (where the given values correspond to the index's columns).
 166  
    * <p>
 167  
    * A valid index must be specified before calling this method.
 168  
    */
 169  
   public CursorBuilder setSpecificEntry(Object... specificEntry) {
 170  37
     if(specificEntry != null) {
 171  37
       setSpecificRow(_index.constructIndexRowFromEntry(specificEntry));
 172  
     }
 173  37
     return this;
 174  
   }
 175  
 
 176  
   
 177  
   /**
 178  
    * Sets the starting row for a range based index cursor.
 179  
    * <p>
 180  
    * A valid index must be specified before calling this method.
 181  
    */
 182  
   public CursorBuilder setStartRow(Object[] startRow) {
 183  59
     _startRow = startRow;
 184  59
     return this;
 185  
   }
 186  
   
 187  
   /**
 188  
    * Sets the starting row for a range based index cursor to the given entry
 189  
    * (where the given values correspond to the index's columns).
 190  
    * <p>
 191  
    * A valid index must be specified before calling this method.
 192  
    */
 193  
   public CursorBuilder setStartEntry(Object... startEntry) {
 194  22
     if(startEntry != null) {
 195  22
       setStartRow(_index.constructIndexRowFromEntry(startEntry));
 196  
     }
 197  22
     return this;
 198  
   }
 199  
 
 200  
   /**
 201  
    * Sets whether the starting row for a range based index cursor is inclusive
 202  
    * or exclusive.
 203  
    */
 204  
   public CursorBuilder setStartRowInclusive(boolean inclusive) {
 205  21
     _startRowInclusive = inclusive;
 206  21
     return this;
 207  
   }
 208  
 
 209  
   /**
 210  
    * Sets the ending row for a range based index cursor.
 211  
    * <p>
 212  
    * A valid index must be specified before calling this method.
 213  
    */
 214  
   public CursorBuilder setEndRow(Object[] endRow) {
 215  58
     _endRow = endRow;
 216  58
     return this;
 217  
   }
 218  
   
 219  
   /**
 220  
    * Sets the ending row for a range based index cursor to the given entry
 221  
    * (where the given values correspond to the index's columns).
 222  
    * <p>
 223  
    * A valid index must be specified before calling this method.
 224  
    */
 225  
   public CursorBuilder setEndEntry(Object... endEntry) {
 226  21
     if(endEntry != null) {
 227  21
       setEndRow(_index.constructIndexRowFromEntry(endEntry));
 228  
     }
 229  21
     return this;
 230  
   }
 231  
 
 232  
   /**
 233  
    * Sets whether the ending row for a range based index cursor is inclusive
 234  
    * or exclusive.
 235  
    */
 236  
   public CursorBuilder setEndRowInclusive(boolean inclusive) {
 237  21
     _endRowInclusive = inclusive;
 238  21
     return this;
 239  
   }
 240  
 
 241  
   /**
 242  
    * Returns a new cursor for the table, constructed to the given
 243  
    * specifications.
 244  
    */
 245  
   public Cursor toCursor()
 246  
     throws IOException
 247  
   {
 248  67
     Cursor cursor = null;
 249  67
     if(_index == null) {
 250  4
       cursor = Cursor.createCursor(_table);
 251  
     } else {
 252  63
       cursor = Cursor.createIndexCursor(_table, _index,
 253  
                                         _startRow, _startRowInclusive,
 254  
                                         _endRow, _endRowInclusive);
 255  
     }
 256  67
     if(_savepoint == null) {
 257  65
       if(!_beforeFirst) {
 258  1
         cursor.afterLast();
 259  
       }
 260  
     } else {
 261  2
       cursor.restoreSavepoint(_savepoint);
 262  
     }
 263  67
     return cursor;
 264  
   }
 265  
   
 266  
 }