Coverage Report - org.crosswire.jsword.passage.DistinctPassage
 
Classes in this File Line Coverage Branch Coverage Complexity
DistinctPassage
0%
0/55
0%
0/16
1.692
 
 1  
 /**
 2  
  * Distribution License:
 3  
  * JSword is free software; you can redistribute it and/or modify it under
 4  
  * the terms of the GNU Lesser General Public License, version 2.1 or later
 5  
  * as published by the Free Software Foundation. This program is distributed
 6  
  * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 7  
  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 8  
  * See the GNU Lesser General Public License for more details.
 9  
  *
 10  
  * The License is available on the internet at:
 11  
  *      http://www.gnu.org/copyleft/lgpl.html
 12  
  * or by writing to:
 13  
  *      Free Software Foundation, Inc.
 14  
  *      59 Temple Place - Suite 330
 15  
  *      Boston, MA 02111-1307, USA
 16  
  *
 17  
  * © CrossWire Bible Society, 2005 - 2016
 18  
  *
 19  
  */
 20  
 package org.crosswire.jsword.passage;
 21  
 
 22  
 import java.io.IOException;
 23  
 import java.io.ObjectInputStream;
 24  
 import java.io.ObjectOutputStream;
 25  
 import java.util.Collections;
 26  
 import java.util.Iterator;
 27  
 import java.util.SortedSet;
 28  
 import java.util.TreeSet;
 29  
 
 30  
 import org.crosswire.jsword.versification.Versification;
 31  
 
 32  
 /**
 33  
  * A Passage that is implemented using a TreeSet of Verses. The attributes of
 34  
  * the style are:
 35  
  * <ul>
 36  
  * <li>Fairly fast manipulation
 37  
  * <li>Slow getName()
 38  
  * <li>Bloated for storing large numbers of Verses
 39  
  * </ul>
 40  
  * 
 41  
  * @see gnu.lgpl.License The GNU Lesser General Public License for details.
 42  
  * @author Joe Walker
 43  
  */
 44  0
 public class DistinctPassage extends AbstractPassage {
 45  
     /**
 46  
      * Create an empty DistinctPassage. There are no ctors from either Verse or
 47  
      * VerseRange so you need to do new <code>DistinctPassage().add(...);</code>
 48  
      * 
 49  
      * @param v11n
 50  
      *            The Versification to which this Passage belongs.
 51  
      */
 52  
     public DistinctPassage(Versification v11n) {
 53  0
         super(v11n);
 54  0
     }
 55  
 
 56  
     /**
 57  
      * Create a Verse from a human readable string. The opposite of toString(),
 58  
      * Given any DistinctPassage v1, and the following
 59  
      * <code>DistinctPassage v2 = new DistinctPassage(v1.toString());</code>
 60  
      * Then <code>v1.equals(v2);</code> Theoretically, since there are many ways
 61  
      * of representing a DistinctPassage as text string comparison along the
 62  
      * lines of: <code>v1.toString().equals(v2.toString())</code> could be
 63  
      * false. Practically since toString() is standardized this will be true
 64  
      * however. We don't need to worry about thread safety in a ctor since we
 65  
      * don't exist yet.
 66  
      * 
 67  
      * @param v11n
 68  
      *            The Versification to which this Passage belongs.
 69  
      * @param refs
 70  
      *            A String containing the text of the DistinctPassage
 71  
      * @param basis
 72  
      *           The basis by which to interpret refs
 73  
      * @throws NoSuchVerseException
 74  
      *             If the string is not valid
 75  
      */
 76  
     protected DistinctPassage(Versification v11n, String refs, Key basis) throws NoSuchVerseException {
 77  0
         super(v11n, refs);
 78  
 
 79  0
         store = Collections.synchronizedSortedSet(new TreeSet<Key>());
 80  0
         addVerses(refs, basis);
 81  0
     }
 82  
 
 83  
     protected DistinctPassage(Versification v11n, String refs) throws NoSuchVerseException {
 84  0
         this(v11n, refs, null);
 85  0
     }
 86  
 
 87  
     /**
 88  
      * Get a copy of ourselves. Points to note:
 89  
      * <ul>
 90  
      * <li>Call clone() not new() on member Objects, and on us.
 91  
      * <li>Do not use Copy Constructors! - they do not inherit well.
 92  
      * <li>Think about this needing to be synchronized
 93  
      * <li>If this is not cloneable then writing cloneable children is harder
 94  
      * </ul>
 95  
      * 
 96  
      * @return A complete copy of ourselves
 97  
      */
 98  
     @Override
 99  
     public DistinctPassage clone() {
 100  
         // This gets us a shallow copy
 101  0
         DistinctPassage copy = (DistinctPassage) super.clone();
 102  
 
 103  
         // I want to just do the following
 104  
         // copy.store = (SortedSet) store.clone();
 105  
         // However SortedSet is not Cloneable so I can't
 106  
         // Watch out for this, I'm not sure if it breaks anything.
 107  0
         copy.store = new TreeSet<Key>();
 108  0
         copy.store.addAll(store);
 109  
 
 110  0
         return copy;
 111  
     }
 112  
 
 113  
     /* (non-Javadoc)
 114  
      * @see java.lang.Iterable#iterator()
 115  
      */
 116  
     public Iterator<Key> iterator() {
 117  0
         return store.iterator();
 118  
     }
 119  
 
 120  
     @Override
 121  
     public boolean isEmpty() {
 122  0
         return store.isEmpty();
 123  
     }
 124  
 
 125  
     @Override
 126  
     public int countVerses() {
 127  0
         return store.size();
 128  
     }
 129  
 
 130  
     @Override
 131  
     public boolean contains(Key obj) {
 132  0
         for (Key aKey : obj) {
 133  0
             if (!store.contains(aKey)) {
 134  0
                 return false;
 135  
             }
 136  
         }
 137  
 
 138  0
         return true;
 139  
     }
 140  
 
 141  
     /* (non-Javadoc)
 142  
      * @see org.crosswire.jsword.passage.Passage#add(org.crosswire.jsword.passage.Key)
 143  
      */
 144  
     public void add(Key obj) {
 145  0
         optimizeWrites();
 146  
 
 147  0
         Verse firstVerse = null;
 148  0
         Verse lastVerse = null;
 149  0
         for (Key aKey : obj) {
 150  0
             lastVerse = (Verse) aKey;
 151  0
             if (firstVerse == null) {
 152  0
                 firstVerse = lastVerse;
 153  
             }
 154  0
             store.add(lastVerse);
 155  
         }
 156  
 
 157  
         // we do an extra check here because the cost of calculating the
 158  
         // params is non-zero an may be wasted
 159  0
         if (suppressEvents == 0) {
 160  0
             fireIntervalAdded(this, firstVerse, lastVerse);
 161  
         }
 162  0
     }
 163  
 
 164  
     /* (non-Javadoc)
 165  
      * @see org.crosswire.jsword.passage.Passage#remove(org.crosswire.jsword.passage.Key)
 166  
      */
 167  
     public void remove(Key obj) {
 168  0
         optimizeWrites();
 169  
 
 170  0
         Verse firstVerse = null;
 171  0
         Verse lastVerse = null;
 172  0
         for (Key aKey : obj) {
 173  0
             lastVerse = (Verse) aKey;
 174  0
             if (firstVerse == null) {
 175  0
                 firstVerse = lastVerse;
 176  
             }
 177  0
             store.remove(lastVerse);
 178  
         }
 179  
 
 180  
         // we do an extra check here because the cost of calculating the
 181  
         // params is non-zero an may be wasted
 182  0
         if (suppressEvents == 0) {
 183  0
             fireIntervalAdded(this, firstVerse, lastVerse);
 184  
         }
 185  0
     }
 186  
 
 187  
     @Override
 188  
     public void clear() {
 189  0
         optimizeWrites();
 190  
 
 191  0
         store.clear();
 192  0
         fireIntervalRemoved(this, null, null);
 193  0
     }
 194  
 
 195  
     /**
 196  
      * Call the support mechanism in AbstractPassage
 197  
      * 
 198  
      * @param out
 199  
      *            The stream to write our state to
 200  
      * @throws IOException
 201  
      *             if the read fails
 202  
      * @serialData Write the ordinal number of this verse
 203  
      * @see AbstractPassage#writeObjectSupport(ObjectOutputStream)
 204  
      */
 205  
     private void writeObject(ObjectOutputStream out) throws IOException {
 206  0
         out.defaultWriteObject();
 207  
 
 208  0
         writeObjectSupport(out);
 209  0
     }
 210  
 
 211  
     /**
 212  
      * Call the support mechanism in AbstractPassage
 213  
      * 
 214  
      * @param in
 215  
      *            The stream to read our state from
 216  
      * @throws IOException
 217  
      *             if the read fails
 218  
      * @throws ClassNotFoundException
 219  
      *             If the read data is incorrect
 220  
      * @serialData Write the ordinal number of this verse
 221  
      * @see AbstractPassage#readObjectSupport(ObjectInputStream)
 222  
      */
 223  
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
 224  0
         optimizeWrites();
 225  
 
 226  0
         store = new TreeSet<Key>();
 227  
 
 228  0
         in.defaultReadObject();
 229  
 
 230  0
         readObjectSupport(in);
 231  0
     }
 232  
 
 233  
     /**
 234  
      * To make serialization work across new versions
 235  
      */
 236  
     private static final long serialVersionUID = 817374460730441662L;
 237  
 
 238  
     /**
 239  
      * The place the real data is stored
 240  
      */
 241  0
     private transient SortedSet<Key> store = new TreeSet<Key>();
 242  
 }