Coverage Report - net.sourceforge.pebble.domain.Category
 
Classes in this File Line Coverage Branch Coverage Complexity
Category
97%
87/89
84%
32/38
1.759
 
 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  
 package net.sourceforge.pebble.domain;
 33  
 
 34  
 import org.apache.commons.logging.Log;
 35  
 import org.apache.commons.logging.LogFactory;
 36  
 
 37  
 import java.io.Serializable;
 38  
 import java.util.*;
 39  
 
 40  
 import net.sourceforge.pebble.comparator.ReverseBlogEntryIdComparator;
 41  
 
 42  
 /**
 43  
  * Represents a blog category.
 44  
  *
 45  
  * @author    Simon Brown
 46  
  */
 47  
 public class Category implements Permalinkable, Comparable, Serializable {
 48  
 
 49  
   /** the log used by this class */
 50  4
   private static final Log log = LogFactory.getLog(Category.class);
 51  
 
 52  
   /** the root category identifier */
 53  
   private static final String ROOT_CATEGORY_IDENTIFIER = "/";
 54  
 
 55  
   /** the owning blog */
 56  
   private transient Blog blog;
 57  
 
 58  
   /** the id of the category */
 59  3208
   private String id = "";
 60  
 
 61  
   /** the name of the category */
 62  3208
   private String name = "";
 63  
 
 64  
   /** the parent category, if applicable */
 65  3208
   private Category parent = null;
 66  
 
 67  
   /** the set of tags for this category */
 68  3208
   private String tags = "";
 69  
 
 70  
   /** the list of tags for this category */
 71  3208
   private List tagsAsList = new ArrayList();
 72  
 
 73  
   /** the sub-categories */
 74  3208
   private List subCategories = new ArrayList();
 75  
 
 76  
   /** the blog entries associated with this category */
 77  3208
   private List<String> blogEntries = new ArrayList<String>();
 78  
 
 79  
   /**
 80  
    * Default, no args constructor.
 81  
    */
 82  12
   public Category() {
 83  12
   }
 84  
 
 85  
   /**
 86  
    * Creates a new category with the specified properties.
 87  
    *
 88  
    * @param id          the id
 89  
    * @param name          the name
 90  
    */
 91  3196
   public Category(String id, String name) {
 92  3196
     setId(id);
 93  
 
 94  3196
     this.name = name;
 95  3196
   }
 96  
 
 97  
   /**
 98  
    * Gets the id of this category.
 99  
    *
 100  
    * @return    the id as a String
 101  
    */
 102  
   public String getId() {
 103  1704
     return id;
 104  
   }
 105  
 
 106  
   /**
 107  
    * Sets the id of this category.
 108  
    *
 109  
    * @param id    the id as a String
 110  
    */
 111  
   public void setId(String id) {
 112  3196
     this.id = id;
 113  3196
     if (this.id == null || !this.id.startsWith("/")) {
 114  88
       this.id = "/" + this.id;
 115  
     }
 116  3196
   }
 117  
 
 118  
   /**
 119  
    * Gets the name of this category.
 120  
    *
 121  
    * @return    the name as a String
 122  
    */
 123  
   public String getName() {
 124  88
     return name;
 125  
   }
 126  
 
 127  
   /**
 128  
    * Sets the name of this category.
 129  
    *
 130  
    * @param name    the new category name
 131  
    */
 132  
   public void setName(String name) {
 133  0
     this.name = name;
 134  0
   }
 135  
 
 136  
   /**
 137  
    * Determines whether this category is a root category.
 138  
    *
 139  
    * @return  true if the ID is "/", false otherwise
 140  
    */
 141  
   public boolean isRootCategory() {
 142  3088
     return id.equals(ROOT_CATEGORY_IDENTIFIER);
 143  
   }
 144  
 
 145  
   /**
 146  
    * Gets the parent of thie category.
 147  
    *
 148  
    * @return  a Category instance, or null if this category has no parent
 149  
    */
 150  
   public Category getParent() {
 151  2872
     return this.parent;
 152  
   }
 153  
 
 154  
   /**
 155  
    * Determines whether this category has the specified parent.
 156  
    *
 157  
    * @param category    a Category to test for
 158  
    * @return  true if this category has the specified category as one of its
 159  
    *          parents, false otherwise
 160  
    */
 161  
   public boolean hasParent(Category category) {
 162  24
     Category parent = getParent();
 163  44
     while (parent != null) {
 164  28
       if (parent.equals(category)) {
 165  8
         return true;
 166  
       } else {
 167  20
         parent = parent.getParent();
 168  
       }
 169  
     }
 170  
 
 171  16
     return false;
 172  
   }
 173  
 
 174  
   /**
 175  
    * Sets the parent of this category.
 176  
    *
 177  
    * @param parent  a Category instance
 178  
    */
 179  
   public void setParent(Category parent) {
 180  264
     this.parent = parent;
 181  264
   }
 182  
 
 183  
   /**
 184  
    * Gets the number of parents that this category has.
 185  
    *
 186  
    * @return  the number of parents this category has, or 0 if it is
 187  
    *          the root category
 188  
    */
 189  
   public int getNumberOfParents() {
 190  12
     int parents = 0;
 191  12
     Category parent = getParent();
 192  24
     while (parent != null) {
 193  12
       parents++;
 194  12
       parent = parent.getParent();
 195  
     }
 196  
 
 197  12
     return parents;
 198  
   }
 199  
 
 200  
   /**
 201  
    * Adds a sub-category.
 202  
    *
 203  
    * @param category    a Category instance
 204  
    */
 205  
   public synchronized void addSubCategory(Category category) {
 206  260
     if (subCategories != null && !subCategories.contains(category)) {
 207  256
       subCategories.add(category);
 208  256
       category.setParent(this);
 209  
     }
 210  260
   }
 211  
 
 212  
   /**
 213  
    * Removes a sub-category.
 214  
    *
 215  
    * @param category    a Category instance
 216  
    */
 217  
   public synchronized void removeSubCategory(Category category) {
 218  12
     if (subCategories != null && subCategories.contains(category)) {
 219  8
       subCategories.remove(category);
 220  8
       category.setParent(null);
 221  
     }
 222  12
   }
 223  
 
 224  
   /**
 225  
    * Gets the list of sub-categories.
 226  
    *
 227  
    * @return  a List of Category instances
 228  
    */
 229  
   public List getSubCategories() {
 230  956
     return Collections.unmodifiableList(subCategories);
 231  
   }
 232  
 
 233  
   /**
 234  
    * Gets the tags associated with this category.
 235  
    *
 236  
    * @return  a list of tags
 237  
    */
 238  
   public String getTags() {
 239  104
     return this.tags;
 240  
   }
 241  
 
 242  
   /**
 243  
    * Gets the tags associated with this category, as a List.
 244  
    *
 245  
    * @return  a List of tags
 246  
    */
 247  
   public List getTagsAsList() {
 248  2656
     return this.tagsAsList;
 249  
   }
 250  
 
 251  
   /**
 252  
    * Gets the tags associated with this category and its parents.
 253  
    *
 254  
    * @return  a list of tags
 255  
    */
 256  
   public List getAllTags() {
 257  2284
     List l = new ArrayList();
 258  
 
 259  2284
     l.addAll(getTagsAsList());
 260  2284
     Category parent = getParent();
 261  2552
     while (parent != null) {
 262  268
       l.addAll(parent.getTagsAsList());
 263  268
       parent = parent.getParent();
 264  
     }
 265  
 
 266  2284
     return l;
 267  
   }
 268  
 
 269  
   /**
 270  
    * Sets the set of tags associated with this category.
 271  
    *
 272  
    * @param newTags    a set of tags
 273  
    */
 274  
   public void setTags(String newTags) {
 275  136
     if (newTags != null && newTags.indexOf(",") > -1) {
 276  
       // if the tags have been comma separated, convert them to
 277  
       // whitespace separated by
 278  
       // - remove whitespace
 279  
       // - convert commas to whitespace
 280  4
       newTags = newTags.replaceAll(" ", "").replaceAll(",", " ");
 281  
     }
 282  136
     this.tags = newTags;
 283  136
     this.tagsAsList = Tag.parse(blog, tags);
 284  136
   }
 285  
 
 286  
   /**
 287  
    * Sets the owning blog.
 288  
    *
 289  
    * @param blog    a Blog instance
 290  
    */
 291  
   public void setBlog(Blog blog) {
 292  3056
     this.blog = blog;
 293  3056
   }
 294  
 
 295  
   /**
 296  
    * Gets the permalink for this object.
 297  
    *
 298  
    * @return  a URL as a String
 299  
    */
 300  
   public String getPermalink() {
 301  40
     if (isRootCategory()) {
 302  4
       return blog.getUrl() + "categories/";
 303  
     } else {
 304  36
       return blog.getUrl() + "categories" + id + "/";
 305  
     }
 306  
   }
 307  
 
 308  
   /**
 309  
    * Gets the hashcode of this object.
 310  
    *
 311  
    * @return  the hashcode as an int
 312  
    */
 313  
   public int hashCode() {
 314  1988
     return id.hashCode();
 315  
   }
 316  
 
 317  
   /**
 318  
    * Determines whether the specified object is equal to this one.
 319  
    *
 320  
    * @param o   the object to compare against
 321  
    * @return    true if Object o represents the same category, false otherwise
 322  
    */
 323  
   public boolean equals(Object o) {
 324  268
     if (!(o instanceof Category)) {
 325  4
       return false;
 326  
     }
 327  
 
 328  264
     Category cat = (Category)o;
 329  264
     return (cat.getId().equals(id));
 330  
   }
 331  
 
 332  
   /**
 333  
    * Compares this object with the specified object for order.  Returns a
 334  
    * negative integer, zero, or a positive integer as this object is less
 335  
    * than, equal to, or greater than the specified object.<p>
 336  
    *
 337  
    * @param   o the Object to be compared.
 338  
    * @return  a negative integer, zero, or a positive integer as this object
 339  
    *                is less than, equal to, or greater than the specified object.
 340  
    *
 341  
    * @throws ClassCastException if the specified object's type prevents it
 342  
    *         from being compared to this Object.
 343  
    */
 344  
   public int compareTo(Object o) {
 345  116
     Category category = (Category)o;
 346  116
     return getId().compareTo(category.getId());
 347  
   }
 348  
 
 349  
   /**
 350  
    * Returns a String representation of this object.
 351  
    *
 352  
    * @return  a String
 353  
    */
 354  
   public String toString() {
 355  4
     return this.name;
 356  
   }
 357  
 
 358  
   /**
 359  
    * Gets the blog entries associated with this category.
 360  
    *
 361  
    * @return  a Collection of BlogEntry instances
 362  
    */
 363  
   public List<String> getBlogEntries() {
 364  364
     return new ArrayList<String>(blogEntries);
 365  
   }
 366  
 
 367  
   /**
 368  
    * Adds a blog entry to this category.
 369  
    *
 370  
    * @param blogEntry   a blog entry id
 371  
    */
 372  
   public synchronized void addBlogEntry(String blogEntry) {
 373  136
     if (blogEntry != null && !blogEntries.contains(blogEntry)) {
 374  128
       blogEntries.add(blogEntry);
 375  128
       Collections.sort(blogEntries, new ReverseBlogEntryIdComparator());
 376  
 
 377  128
       if (getParent() != null) {
 378  68
         getParent().addBlogEntry(blogEntry);
 379  
       }
 380  
     }
 381  136
   }
 382  
 
 383  
   /**
 384  
    * Removes a blog entry from this category.
 385  
    *
 386  
    * @param blogEntry   a blog entry id
 387  
    */
 388  
   public synchronized void removeBlogEntry(String blogEntry) {
 389  20
     if (blogEntry != null) {
 390  20
       blogEntries.remove(blogEntry);
 391  
 
 392  20
       if (getParent() != null) {
 393  4
         getParent().removeBlogEntry(blogEntry);
 394  
       }
 395  
     }
 396  20
   }
 397  
 
 398  
   /**
 399  
    * Removes all blog entries from this category.
 400  
    */
 401  
   public synchronized void removeAllBlogEntries() {
 402  36
     blogEntries = new ArrayList<String>();
 403  36
   }
 404  
 
 405  
   /**
 406  
    * Gets the number of blog entries associated with this category.
 407  
    *
 408  
    * @return  an int
 409  
    */
 410  
   public int getNumberOfBlogEntries() {
 411  8
     return this.blogEntries.size();
 412  
   }
 413  
 
 414  
 }