Coverage Report - net.sourceforge.pebble.index.ResponseIndex
 
Classes in this File Line Coverage Branch Coverage Complexity
ResponseIndex
76%
83/109
64%
27/42
2.5
 
 1  
 /*
 2  
  * Copyright (c) 2003-2011, Simon Brown
 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 are met:
 7  
  *
 8  
  *   - Redistributions of source code must retain the above copyright
 9  
  *     notice, this list of conditions and the following disclaimer.
 10  
  *
 11  
  *   - Redistributions in binary form must reproduce the above copyright
 12  
  *     notice, this list of conditions and the following disclaimer in
 13  
  *     the documentation and/or other materials provided with the
 14  
  *     distribution.
 15  
  *
 16  
  *   - Neither the name of Pebble nor the names of its contributors may
 17  
  *     be used to endorse or promote products derived from this software
 18  
  *     without specific prior written permission.
 19  
  *
 20  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 21  
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22  
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23  
  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 24  
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 25  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 26  
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 27  
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 28  
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 29  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 30  
  * POSSIBILITY OF SUCH DAMAGE.
 31  
  */
 32  
 
 33  
 package net.sourceforge.pebble.index;
 34  
 
 35  
 import net.sourceforge.pebble.comparator.ReverseResponseIdComparator;
 36  
 import net.sourceforge.pebble.domain.Blog;
 37  
 import net.sourceforge.pebble.domain.BlogEntry;
 38  
 import net.sourceforge.pebble.domain.Response;
 39  
 import net.sourceforge.pebble.domain.State;
 40  
 import org.apache.commons.logging.Log;
 41  
 import org.apache.commons.logging.LogFactory;
 42  
 
 43  
 import java.io.*;
 44  
 import java.util.ArrayList;
 45  
 import java.util.Collections;
 46  
 import java.util.List;
 47  
 import java.util.Collection;
 48  
 
 49  
 /**
 50  
  * Keeps an index of all responses.
 51  
  *
 52  
  * @author    Simon Brown
 53  
  */
 54  
 public class ResponseIndex {
 55  
 
 56  4
   private static final Log log = LogFactory.getLog(ResponseIndex.class);
 57  
 
 58  
   private Blog blog;
 59  
 
 60  2720
   private List<String> approvedResponses = new ArrayList<String>();
 61  2720
   private List<String> pendingResponses = new ArrayList<String>();
 62  2720
   private List<String> rejectedResponses = new ArrayList<String>();
 63  
 
 64  2720
   public ResponseIndex(Blog blog) {
 65  2720
     this.blog = blog;
 66  
 
 67  2720
     approvedResponses = readIndex(State.APPROVED);
 68  2720
     pendingResponses = readIndex(State.PENDING);
 69  2720
     rejectedResponses = readIndex(State.REJECTED);
 70  2720
   }
 71  
 
 72  
   /**
 73  
    * Clears the index.
 74  
    */
 75  
   public void clear() {
 76  36
     approvedResponses = new ArrayList<String>();
 77  36
     writeIndex(State.APPROVED);
 78  
 
 79  36
     pendingResponses = new ArrayList<String>();
 80  36
     writeIndex(State.PENDING);
 81  
 
 82  36
     rejectedResponses = new ArrayList<String>();
 83  36
     writeIndex(State.REJECTED);
 84  36
   }
 85  
 
 86  
   /**
 87  
    * Indexes one or more blog entries.
 88  
    *
 89  
    * @param blogEntries   a List of BlogEntry instances
 90  
    */
 91  
   public synchronized void index(Collection<BlogEntry> blogEntries) {
 92  36
     for (BlogEntry blogEntry : blogEntries) {
 93  36
       for (Response response : blogEntry.getResponses()) {
 94  12
         if (response.isApproved()) {
 95  0
           approvedResponses.add(response.getGuid());
 96  12
         } else if (response.isPending()) {
 97  12
           pendingResponses.add(response.getGuid());
 98  0
         } else if (response.isRejected()) {
 99  0
           rejectedResponses.add(response.getGuid());
 100  
         }
 101  
       }
 102  
     }
 103  
 
 104  36
     Collections.sort(approvedResponses, new ReverseResponseIdComparator());
 105  36
     Collections.sort(pendingResponses, new ReverseResponseIdComparator());
 106  36
     Collections.sort(rejectedResponses, new ReverseResponseIdComparator());
 107  36
     writeIndex(State.APPROVED);
 108  36
     writeIndex(State.PENDING);
 109  36
     writeIndex(State.REJECTED);
 110  36
   }
 111  
 
 112  
   /**
 113  
    * Indexes a single response.
 114  
    *
 115  
    * @param response    a Response instance
 116  
    */
 117  
   public synchronized void index(Response response) {
 118  288
     if (response.isApproved()) {
 119  120
       approvedResponses.add(response.getGuid());
 120  120
       Collections.sort(approvedResponses, new ReverseResponseIdComparator());
 121  120
       writeIndex(State.APPROVED);
 122  168
     } else if (response.isPending()) {
 123  160
       pendingResponses.add(response.getGuid());
 124  160
       Collections.sort(pendingResponses, new ReverseResponseIdComparator());
 125  160
       writeIndex(State.PENDING);
 126  8
     } else if (response.isRejected()) {
 127  8
       rejectedResponses.add(response.getGuid());
 128  8
       Collections.sort(rejectedResponses, new ReverseResponseIdComparator());
 129  8
       writeIndex(State.REJECTED);
 130  
     }
 131  288
   }
 132  
 
 133  
   /**
 134  
    * Unindexes a single response.
 135  
    *
 136  
    * @param response    a Response instance
 137  
    */
 138  
   public synchronized void unindex(Response response) {
 139  152
     if (approvedResponses.contains(response.getGuid())) {
 140  16
       approvedResponses.remove(response.getGuid());
 141  16
       writeIndex(State.APPROVED);
 142  136
     } else if (pendingResponses.contains(response.getGuid())) {
 143  136
       pendingResponses.remove(response.getGuid());
 144  136
       writeIndex(State.PENDING);
 145  0
     } else if (rejectedResponses.contains(response.getGuid())) {
 146  0
       rejectedResponses.remove(response.getGuid());
 147  0
       writeIndex(State.REJECTED);
 148  
     }
 149  152
   }
 150  
 
 151  
   /**
 152  
    * Helper method to load the index.
 153  
    */
 154  
   private List<String> readIndex(State state) {
 155  8160
     String filename = null;
 156  8160
     List<String> responses = new ArrayList<String>();
 157  8160
     if (state == State.APPROVED) {
 158  2720
         filename = "responses-approved.index";
 159  5440
     } else if (state == State.PENDING) {
 160  2720
       filename = "responses-pending.index";
 161  2720
     } else if (state == State.REJECTED) {
 162  2720
       filename = "responses-rejected.index";
 163  
     }
 164  
 
 165  8160
     File indexFile = new File(blog.getIndexesDirectory(), filename);
 166  8160
     if (indexFile.exists()) {
 167  
       try {
 168  0
         BufferedReader reader = new BufferedReader(new FileReader(indexFile));
 169  0
         String response = reader.readLine();
 170  0
         while (response != null) {
 171  0
           responses.add(response);
 172  0
           response = reader.readLine();
 173  
         }
 174  
 
 175  0
         reader.close();
 176  0
       } catch (Exception e) {
 177  0
         log.error("Error while reading index", e);
 178  0
       }
 179  
     }
 180  
 
 181  8160
     Collections.sort(responses, new ReverseResponseIdComparator());
 182  
 
 183  8160
     return responses;
 184  
   }
 185  
 
 186  
   /**
 187  
    * Helper method to write out the index to disk.
 188  
    */
 189  
   private void writeIndex(State state) {
 190  656
     String filename = null;
 191  656
     List<String> responses = null;
 192  656
     if (state == State.APPROVED) {
 193  208
         filename = "responses-approved.index";
 194  208
         responses = approvedResponses;
 195  448
     } else if (state == State.PENDING) {
 196  368
       filename = "responses-pending.index";
 197  368
       responses = pendingResponses;
 198  80
     } else if (state == State.REJECTED) {
 199  80
       filename = "responses-rejected.index";
 200  80
       responses = rejectedResponses;
 201  
     }
 202  
 
 203  
     try {
 204  656
       File indexFile = new File(blog.getIndexesDirectory(), filename);
 205  656
       BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile));
 206  
 
 207  656
       for (String response : responses) {
 208  2424
         writer.write(response);
 209  2424
         writer.newLine();
 210  
       }
 211  
 
 212  656
       writer.flush();
 213  656
       writer.close();
 214  0
     } catch (Exception e) {
 215  0
       log.error("Error while writing index", e);
 216  656
     }
 217  656
   }
 218  
 
 219  
   /**
 220  
    * Gets the number of approved responses for this blog.
 221  
    *
 222  
    * @return  an int
 223  
    */
 224  
   public int getNumberOfApprovedResponses() {
 225  0
     return approvedResponses.size();
 226  
   }
 227  
 
 228  
   /**
 229  
    * Gets the number of pending responses for this blog.
 230  
    *
 231  
    * @return  an int
 232  
    */
 233  
   public int getNumberOfPendingResponses() {
 234  0
     return pendingResponses.size();
 235  
   }
 236  
 
 237  
   /**
 238  
    * Gets the number of rejected responses for this blog.
 239  
    *
 240  
    * @return  an int
 241  
    */
 242  
   public int getNumberOfRejectedResponses() {
 243  0
     return rejectedResponses.size();
 244  
   }
 245  
 
 246  
   /**
 247  
    * Gets the number of responses for this blog.
 248  
    *
 249  
    * @return  an int
 250  
    */
 251  
   public int getNumberOfResponses() {
 252  0
     return getNumberOfApprovedResponses() + getNumberOfPendingResponses() + getNumberOfRejectedResponses();
 253  
   }
 254  
 
 255  
   /**
 256  
    * Gets the most recent N approved responses.
 257  
    *
 258  
    * @return  a List of response IDs
 259  
    */
 260  
   public List<String> getRecentResponses(int number) {
 261  0
     return getRecentApprovedResponses(number);
 262  
   }
 263  
 
 264  
   /**
 265  
    * Gets the most recent N approved responses.
 266  
    *
 267  
    * @return  a List of response IDs
 268  
    */
 269  
   public List<String> getRecentApprovedResponses(int number) {
 270  0
     if (approvedResponses.size() >= number) {
 271  0
       return approvedResponses.subList(0, number);
 272  
     } else {
 273  0
       return approvedResponses;
 274  
     }
 275  
   }
 276  
 
 277  
   /**
 278  
    * Gets the list of approved responses.
 279  
    *
 280  
    * @return  a List of response IDs
 281  
    */
 282  
   public List<String> getApprovedResponses() {
 283  32
     return new ArrayList<String>(approvedResponses);
 284  
   }
 285  
 
 286  
   /**
 287  
    * Gets the list of pending responses.
 288  
    *
 289  
    * @return  a List of response IDs
 290  
    */
 291  
   public List<String> getPendingResponses() {
 292  24
     return new ArrayList<String>(pendingResponses);
 293  
   }
 294  
 
 295  
   /**
 296  
    * Gets the list of rejected responses.
 297  
    *
 298  
    * @return  a List of response IDs
 299  
    */
 300  
   public List<String> getRejectedResponses() {
 301  0
     return new ArrayList<String>(rejectedResponses);
 302  
   }
 303  
 
 304  
 }