File Source: blogservice.java
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.domain;
33
34 import net.sourceforge.pebble.api.event.blogentry.BlogEntryEvent;
35 import net.sourceforge.pebble.api.event.comment.CommentEvent;
36 import net.sourceforge.pebble.api.event.trackback.TrackBackEvent;
37 import net.sourceforge.pebble.dao.BlogEntryDAO;
38 import net.sourceforge.pebble.dao.DAOFactory;
39 import net.sourceforge.pebble.dao.PersistenceException;
40 import net.sourceforge.pebble.ContentCache;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43
44 import java.util.ArrayList;
45 import java.util.Date;
46 import java.util.List;
47 import java.util.Collection;
48
49 /**
50 * Service that encompasses all functionality related to getting, putting
51 * and removing blog entries.
52 *
53 * @author Simon Brown
54 */
/*
P/P * Method: void net.sourceforge.pebble.domain.BlogService()
*/
55 public class BlogService {
56
/*
P/P * Method: net.sourceforge.pebble.domain.BlogService__static_init
*
* Postconditions:
* init'ed(log)
*/
57 private static final Log log = LogFactory.getLog(BlogService.class);
58
59 /**
60 * Gets the blog entry with the specified id.
61 *
62 * @param blogEntryId the id of the blog entry
63 * @return a BlogEntry instance, or null if the entry couldn't be found
64 */
65 public BlogEntry getBlogEntry(Blog blog, String blogEntryId) throws BlogServiceException {
/*
P/P * Method: BlogEntry getBlogEntry(Blog, String)
*
* Preconditions:
* blog != null
* (soft) net/sourceforge/pebble/dao/file/FileBlogEntryDAO.log != null
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@57 != null
*
* Postconditions:
* new BlogEntry(loadBlogEntry#2*) num objects <= 1
* init'ed(new BlogEntry(loadBlogEntry#2*).attachment)
* init'ed(new BlogEntry(loadBlogEntry#2*).date)
* init'ed(new BlogEntry(loadBlogEntry#2*).eventsEnabled)
* possibly_updated(new BlogEntry(loadBlogEntry#2*).id)
* init'ed(new BlogEntry(loadBlogEntry#2*).lockedBy)
* init'ed(new BlogEntry(loadBlogEntry#2*).originalPermalink)
* init'ed(new BlogEntry(loadBlogEntry#2*).permalink)
* init'ed(new BlogEntry(loadBlogEntry#2*).persistent)
* init'ed(new BlogEntry(loadBlogEntry#2*).timeZoneId)
*
* Preconditions:
* init'ed(blog.id)
* net.sourceforge.pebble.ContentCache__static_init.new ContentCache(ContentCache__static_init#1).cache != null
* (soft) net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#4).name != null
* (soft) net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#5).name != null
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory.blogEntryDAO != null
*
* Presumptions:
* blogEntry.blog@77 != null
* blogEntry.categories@70 != null
* blogEntry.categories@77 != null
* blogEntry.categories@81 != null
* blogEntry.comments@70 != null
* ...
*
* Postconditions:
* return_value in Addr_Set{null,&new BlogEntry(clone#1)}
* new ArrayList(BlogEntry#2) num objects == One-of{0, 1, new ArrayList(BlogEntry#2) num objects + 1}
* new ArrayList(BlogEntry#2) num objects <= 2
* new ArrayList(BlogEntry#3) num objects == One-of{0, 1, new ArrayList(BlogEntry#3) num objects + 1}
* new ArrayList(BlogEntry#3) num objects <= 2
* init'ed(new ArrayList(Content#1) num objects)
* init'ed(new ArrayList(Content#3) num objects)
* new ArrayList(parse#1) num objects <= 1
* new Attachment(clone#1*) num objects <= 1
* init'ed(new Attachment(clone#1*).size)
* ...
*/
66 BlogEntry blogEntry = null;
67 ContentCache cache = ContentCache.getInstance();
68
69 // is the blog entry already in the cache?
70 blogEntry = cache.getBlogEntry(blog, blogEntryId);
71 if (blogEntry != null) {
72 log.debug("Got blog entry " + blogEntryId + " from cache");
73 } else {
74 log.debug("Loading blog entry " + blogEntryId + " from disk");
75 BlogEntryDAO dao = DAOFactory.getConfiguredFactory().getBlogEntryDAO();
76 try {
77 blogEntry = dao.loadBlogEntry(blog, blogEntryId);
78
79 if (blogEntry != null) {
80 // place in the cache for faster lookup next time
81 cache.putBlogEntry(blogEntry);
82 }
83 } catch (PersistenceException pe) {
84 throw new BlogServiceException(blog, pe);
85 }
86 }
87
88 if (blogEntry != null) {
89 blogEntry = (BlogEntry)blogEntry.clone();
90 blogEntry.setEventsEnabled(true);
91 blogEntry.setPersistent(true);
92 }
93
94 return blogEntry;
95 }
96
97 public List<BlogEntry> getBlogEntries(Blog blog, int year, int month, int day) throws BlogServiceException {
/*
P/P * Method: List getBlogEntries(Blog, int, int, int)
*
* Preconditions:
* blog != null
*
* Postconditions:
* return_value == &new ArrayList(getBlogEntries#1*)
* new ArrayList(getBlogEntries#1*) num objects == 1
*
* Preconditions:
* blog.years != null
* day >= 1
* month in 1..12
*/
98 Day d = blog.getBlogForDay(year, month, day);
+ 99 List<String> blogEntryIds = d.getBlogEntries();
100 return getBlogEntries(blog, blogEntryIds);
101 }
102
103 public List<BlogEntry> getBlogEntries(Blog blog, int year, int month) throws BlogServiceException {
/*
P/P * Method: List getBlogEntries(Blog, int, int)
*
* Preconditions:
* blog != null
*
* Postconditions:
* return_value == &new ArrayList(getBlogEntries#1*)
* new ArrayList(getBlogEntries#1*) num objects == 1
*
* Preconditions:
* blog.years != null
* month in 1..12
*
* Presumptions:
* m.dailyBlogs.length@104 <= 232-1
* m.dailyBlogs@104 != null
*/
104 Month m = blog.getBlogForMonth(year, month);
+ 105 List<String> blogEntryIds = m.getBlogEntries();
106 return getBlogEntries(blog, blogEntryIds);
107 }
108
109 /**
110 * Gets all blog entries for the specified blog.
111 *
112 * @return a List of BlogEntry objects
113 */
114 public Collection<BlogEntry> getBlogEntries(Blog blog) throws BlogServiceException {
/*
P/P * Method: Collection getBlogEntries(Blog)
*
* Preconditions:
* blog != null
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory.blogEntryDAO != null
* (soft) net/sourceforge/pebble/dao/file/FileBlogEntryDAO.log != null
*
* Presumptions:
* java.util.Iterator:next(...)@119 != null
*
* Postconditions:
* new ArrayList(loadBlogEntries#1) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@119: {1}, {0}
*
* Postconditions:
* (soft) return_value == &new ArrayList(loadBlogEntries#1)
*/
115 BlogEntryDAO dao = DAOFactory.getConfiguredFactory().getBlogEntryDAO();
116 Collection<BlogEntry> blogEntries;
117 try {
118 blogEntries = dao.loadBlogEntries(blog);
119 for (BlogEntry blogEntry : blogEntries) {
120 blogEntry.setPersistent(true);
121 }
122
123 } catch (PersistenceException pe) {
124 throw new BlogServiceException(blog, pe);
125 }
126
127 return blogEntries;
128 }
129
130 private List<BlogEntry> getBlogEntries(Blog blog, List<String> blogEntryIds) throws BlogServiceException {
/*
P/P * Method: List getBlogEntries(Blog, List)
*
* Preconditions:
* blogEntryIds != null
*
* Postconditions:
* return_value == &new ArrayList(getBlogEntries#1)
* new ArrayList(getBlogEntries#1) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@133: {1}, {0}
*/
131 List<BlogEntry> blogEntries = new ArrayList<BlogEntry>();
132
133 for (String blogEntryId : blogEntryIds) {
134 BlogEntry blogEntry = getBlogEntry(blog, blogEntryId);
135 blogEntries.add(blogEntry);
136 }
137
138 return blogEntries;
139 }
140
141 /**
142 * Puts the blog entry with the specified id.
143 */
144 public void putBlogEntry(BlogEntry blogEntry) throws BlogServiceException {
/*
P/P * Method: void putBlogEntry(BlogEntry)
*
* Preconditions:
* blogEntry != null
* blogEntry.blog != null
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
* init'ed(blogEntry.id)
* init'ed(blogEntry.persistent)
* (soft) init'ed(blogEntry.attachment)
* (soft) init'ed(blogEntry.attachment.size)
* (soft) init'ed(blogEntry.attachment.type)
* (soft) init'ed(blogEntry.attachment.url)
* (soft) init'ed(blogEntry.categories)
* ...
*
* Presumptions:
* blogEntry.comments@158 != null
* java.util.Date:getTime(...)@157 <= 264-2
* net/sourceforge/pebble/dao/file/FileBlogEntryDAO.log@152 != null
*
* Postconditions:
* init'ed(blogEntry.date)
* blogEntry.events != null
* blogEntry.eventsEnabled == 1
* init'ed(blogEntry.id)
* possibly_updated(blogEntry.permalink)
* blogEntry.persistent == 1
* blogEntry.propertyChangeEvents == &new ArrayList(clearPropertyChangeEvents#1)
* new ArrayList(clearEvents#1*) num objects >= 1
* new ArrayList(clearPropertyChangeEvents#1) num objects == 1
* new Date(putBlogEntry#1) num objects <= 1
*
* Preconditions:
* blogEntry.comments != null
* init'ed(blogEntry.trackBacks)
* (soft) init'ed(blogEntry.author)
* (soft) init'ed(blogEntry.body)
* (soft) init'ed(blogEntry.originalPermalink)
* (soft) blogEntry.state != null
* (soft) init'ed(blogEntry.state.name)
* (soft) init'ed(blogEntry.subtitle)
* (soft) init'ed(blogEntry.tags)
* (soft) init'ed(blogEntry.title)
* ...
*
* Presumptions:
* getBlog(...).eventDispatcher@152 != null
* getEventDispatcher(...).eventListenerList.blogEntryListeners@152 != null
* getEventDispatcher(...).eventListenerList.commentListeners@152 != null
* getEventDispatcher(...).eventListenerList.trackBackListeners@152 != null
* getEventDispatcher(...).eventListenerList@152 != null
*
* Test Vectors:
* blogEntry.persistent: {1}, {0}
* getBlogEntry(...)@152: Addr_Set{null}, Inverse{null}
* java.util.Iterator:hasNext(...)@164: {1}, {0}
*/
145 DAOFactory factory = DAOFactory.getConfiguredFactory();
146 BlogEntryDAO dao = factory.getBlogEntryDAO();
147 Blog blog = blogEntry.getBlog();
148 ContentCache cache = ContentCache.getInstance();
149
150 synchronized (blog) {
151 try {
152 BlogEntry be = getBlogEntry(blog, blogEntry.getId());
153
154 if (!blogEntry.isPersistent() && be != null) {
155 // the blog entry is new but one exists with the same ID already
156 // - increment the date/ID and try again
157 blogEntry.setDate(new Date(blogEntry.getDate().getTime() + 1));
158 putBlogEntry(blogEntry);
159 } else {
160 if (!blogEntry.isPersistent()) {
161 dao.storeBlogEntry(blogEntry);
162 blogEntry.insertEvent(new BlogEntryEvent(blogEntry, BlogEntryEvent.BLOG_ENTRY_ADDED));
163
164 for (Comment comment : blogEntry.getComments()) {
165 blogEntry.addEvent(new CommentEvent(comment, CommentEvent.COMMENT_ADDED));
166 }
167 for (TrackBack trackBack : blogEntry.getTrackBacks()) {
168 blogEntry.addEvent(new TrackBackEvent(trackBack, TrackBackEvent.TRACKBACK_ADDED));
169 }
170 } else {
171 dao.storeBlogEntry(blogEntry);
172 if (blogEntry.isDirty()) {
173 blogEntry.insertEvent(new BlogEntryEvent(blogEntry, blogEntry.getPropertyChangeEvents()));
174 }
175 }
176
177 blogEntry.getBlog().getEventDispatcher().fireEvents(blogEntry);
178
179 // and store the blog entry now that listeners have been fired
180 dao.storeBlogEntry(blogEntry);
181 cache.removeBlogEntry(blogEntry);
182 }
183
184 blogEntry.setPersistent(true);
185 } catch (PersistenceException pe) {
186 throw new BlogServiceException(blog, pe);
187 } finally {
188 blogEntry.clearPropertyChangeEvents();
189 blogEntry.clearEvents();
190 blogEntry.setEventsEnabled(true);
191 }
192 }
193 }
194
195 /**
196 * Removes this blog entry.
197 */
198 public void removeBlogEntry(BlogEntry blogEntry) throws BlogServiceException {
/*
P/P * Method: void removeBlogEntry(BlogEntry)
*
* Preconditions:
* blogEntry != null
* blogEntry.blog != null
* blogEntry.comments != null
* blogEntry.events != null
* init'ed(blogEntry.id)
* init'ed(blogEntry.trackBacks)
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory.blogEntryDAO != null
* net/sourceforge/pebble/dao/file/FileBlogEntryDAO.log != null
*
* Postconditions:
* blogEntry.persistent == 0
*
* Preconditions:
* blogEntry.blog.eventDispatcher != null
* init'ed(blogEntry.blog.id)
* net.sourceforge.pebble.ContentCache__static_init.new ContentCache(ContentCache__static_init#1).cache != null
* (soft) blogEntry.blog.eventDispatcher.eventListenerList != null
* (soft) blogEntry.blog.eventDispatcher.eventListenerList.blogEntryListeners != null
* (soft) blogEntry.blog.eventDispatcher.eventListenerList.commentListeners != null
* (soft) blogEntry.blog.eventDispatcher.eventListenerList.trackBackListeners != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@215: {1}, {0}
* java.util.Iterator:hasNext(...)@218: {1}, {0}
*/
199 Blog blog = blogEntry.getBlog();
200 ContentCache cache = ContentCache.getInstance();
201
202 try {
203 DAOFactory factory = DAOFactory.getConfiguredFactory();
204 BlogEntryDAO dao = factory.getBlogEntryDAO();
205 dao.removeBlogEntry(blogEntry);
206 blogEntry.setPersistent(false);
207
208 // remove from cache
209 cache.removeBlogEntry(blogEntry);
210
211 blogEntry.insertEvent(new BlogEntryEvent(blogEntry, BlogEntryEvent.BLOG_ENTRY_REMOVED));
212
213 // and remove all of the responses, so the appropriate events are raised
214 // and the responses get unindexed
215 for (Comment comment : blogEntry.getComments()) {
216 blogEntry.addEvent(new CommentEvent(comment, CommentEvent.COMMENT_REMOVED));
217 }
218 for (TrackBack trackBack : blogEntry.getTrackBacks()) {
219 blogEntry.addEvent(new TrackBackEvent(trackBack, TrackBackEvent.TRACKBACK_REMOVED));
220 }
221
222 blogEntry.getBlog().getEventDispatcher().fireEvents(blogEntry);
223 } catch (PersistenceException pe) {
224 throw new BlogServiceException(blogEntry.getBlog(), pe);
225 }
226 }
227
228 /**
229 * Gets the blog entry with the specified id.
230 *
231 * @param responseId the id of the response
232 * @return a response instance, or null if the entry couldn't be found
233 */
234 public Response getResponse(Blog blog, String responseId) throws BlogServiceException {
/*
P/P * Method: Response getResponse(Blog, String)
*
* Preconditions:
* responseId != null
*
* Presumptions:
* blogEntry.comments@236 != null
* java.lang.String:indexOf(...)@235 <= 232-2
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* getBlogEntry(...)@236: Addr_Set{null}, Inverse{null}
*/
235 String blogEntryId = responseId.substring(responseId.indexOf("/")+1, responseId.lastIndexOf("/"));
236 BlogEntry blogEntry = getBlogEntry(blog, blogEntryId);
237 if (blogEntry != null) {
238 return blogEntry.getResponse(responseId);
239 } else {
240 return null;
241 }
242 }
243
244 }
SofCheck Inspector Build Version : 2.22510
| blogservice.java |
2010-Jun-25 19:40:32 |
| blogservice.class |
2010-Jul-19 20:23:40 |