Clover Coverage Report - Pebble 2.5-SNAPSHOT
Coverage timestamp: Sat Jun 12 2010 09:39:29 EST
../../../../img/srcFileCovDistChart8.png 29% of files have more coverage
73   245   24   6,64
20   132   0,33   11
11     2,18  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  TagIndex       Line # 48 73 0% 24 28 73,1% 0.7307692
 
  (82)
 
1    /*
2    * Copyright (c) 2003-2006, 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.index;
33   
34    import net.sourceforge.pebble.domain.Blog;
35    import net.sourceforge.pebble.domain.BlogEntry;
36    import net.sourceforge.pebble.domain.Tag;
37    import org.apache.commons.logging.Log;
38    import org.apache.commons.logging.LogFactory;
39   
40    import java.io.*;
41    import java.util.*;
42   
43    /**
44    * Represents the tag index for a blog.
45    *
46    * @author Simon Brown
47    */
 
48    public class TagIndex {
49   
50    private static final Log log = LogFactory.getLog(TagIndex.class);
51   
52    private Blog blog;
53   
54    /** the map containing the tags */
55    private Map<String,IndexedTag> tags = new HashMap<String,IndexedTag>();
56   
57    /** a view onto the map, ordered by tag name */
58    private List<Tag> orderedTags = new ArrayList<Tag>();
59   
 
60  1338 toggle public TagIndex(Blog blog) {
61  1338 this.blog = blog;
62   
63  1338 readIndex();
64  1338 recalculateTagRankings();
65    }
66   
67    /**
68    * Clears the index.
69    */
 
70  18 toggle public void clear() {
71  18 tags = new HashMap<String,IndexedTag>();
72  18 writeIndex();
73    }
74   
75    /**
76    * Indexes one or more blog entries.
77    *
78    * @param blogEntries a List of BlogEntry instances
79    */
 
80  18 toggle public synchronized void index(Collection<BlogEntry> blogEntries) {
81  18 for (BlogEntry blogEntry : blogEntries) {
82  18 if (blogEntry.isPublished()) {
83  18 for (Tag tag : blogEntry.getAllTags()) {
84  0 IndexedTag t = getTag(tag.getName());
85  0 t.addBlogEntry(blogEntry.getId());
86    }
87    }
88    }
89   
90  18 writeIndex();
91  18 recalculateTagRankings();
92    }
93   
94    /**
95    * Indexes a single blog entry.
96    *
97    * @param blogEntry a BlogEntry instance
98    */
 
99  100 toggle public synchronized void index(BlogEntry blogEntry) {
100  100 if (blogEntry.isPublished()) {
101  98 for (Tag tag : blogEntry.getAllTags()) {
102  2 IndexedTag t = getTag(tag.getName());
103  2 t.addBlogEntry(blogEntry.getId());
104    }
105   
106  98 writeIndex();
107  98 recalculateTagRankings();
108    }
109    }
110   
111    /**
112    * Unindexes a single blog entry.
113    *
114    * @param blogEntry a BlogEntry instance
115    */
 
116  28 toggle public synchronized void unindex(BlogEntry blogEntry) {
117  28 for (Tag tag : tags.values()) {
118  0 IndexedTag t = getTag(tag.getName());
119  0 t.removeBlogEntry(blogEntry.getId());
120    }
121   
122  28 writeIndex();
123  28 recalculateTagRankings();
124    }
125   
126    /**
127    * Helper method to load the index.
128    */
 
129  1338 toggle private void readIndex() {
130  1338 File indexFile = new File(blog.getIndexesDirectory(), "tags.index");
131  1338 if (indexFile.exists()) {
132  0 try {
133  0 BufferedReader reader = new BufferedReader(new FileReader(indexFile));
134  0 String indexEntry = reader.readLine();
135  0 while (indexEntry != null) {
136  0 String[] tuple = indexEntry.split("=");
137  0 IndexedTag tag = getTag(tuple[0]);
138   
139  0 if (tuple.length > 1 && tuple[1] != null) {
140  0 String[] blogEntries = tuple[1].split(",");
141  0 for (String blogEntry : blogEntries) {
142  0 tag.addBlogEntry(blogEntry);
143    }
144    }
145   
146  0 indexEntry = reader.readLine();
147    }
148   
149  0 reader.close();
150    } catch (Exception e) {
151  0 log.error("Error while reading index", e);
152    }
153    }
154    }
155   
156    /**
157    * Helper method to write out the index to disk.
158    */
 
159  162 toggle private void writeIndex() {
160  162 try {
161  162 File indexFile = new File(blog.getIndexesDirectory(), "tags.index");
162  162 BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile));
163   
164  162 for (IndexedTag tag : tags.values()) {
165  2 writer.write(tag.getName());
166  2 writer.write("=");
167  2 for (String blogEntry : tag.getBlogEntries()) {
168  2 writer.write(blogEntry);
169  2 writer.write(",");
170    }
171  2 writer.newLine();
172    }
173   
174  162 writer.flush();
175  162 writer.close();
176    } catch (Exception e) {
177  0 log.error("Error while writing index", e);
178    }
179    }
180   
181    /**
182    * Gets a tag from the index, creating it if necessary.
183    *
184    * @param name the tag as a String
185    * @return a Tag instance
186    */
 
187  6 toggle synchronized IndexedTag getTag(String name) {
188  6 String encodedName = Tag.encode(name);
189  6 IndexedTag tag = tags.get(encodedName);
190  6 if (tag == null) {
191  4 tag = new IndexedTag(name, blog);
192  4 tags.put(encodedName, tag);
193    }
194  6 return tag;
195    }
196   
 
197  1482 toggle private synchronized void recalculateTagRankings() {
198  1482 if (tags.size() > 0) {
199    // find the maximum
200  2 int maxBlogEntries = 0;
201  2 for (IndexedTag tag : tags.values()) {
202  2 if (tag.getNumberOfBlogEntries() > maxBlogEntries) {
203  2 maxBlogEntries = tag.getNumberOfBlogEntries();
204    }
205    }
206   
207  2 int[] thresholds = new int[10];
208  22 for (int i = 0; i < 10; i++) {
209  20 thresholds[i] = (int)Math.round((maxBlogEntries/10.0) * (i+1));
210    }
211   
212  2 orderedTags = new ArrayList<Tag>();
213   
214    // now rank the tags
215  2 for (IndexedTag tag : tags.values()) {
216  2 tag.calculateRank(thresholds);
217   
218  2 if (tag.getNumberOfBlogEntries() > 0) {
219  2 orderedTags.add(tag);
220    }
221    }
222   
223  2 Collections.sort(orderedTags);
224    }
225   
226    }
227   
228    /**
229    * Gets the list of tags associated with this blog.
230    */
 
231  6 toggle public List<Tag> getTags() {
232  6 return new ArrayList<Tag>(orderedTags);
233    }
234   
235    /**
236    * Gets the blog entries for a given tag.
237    *
238    * @param tag a tag
239    * @return a List of blog entry IDs
240    */
 
241  0 toggle public List<String> getRecentBlogEntries(Tag tag) {
242  0 return new ArrayList<String>(getTag(tag.getName()).getBlogEntries());
243    }
244   
245    }