Clover Coverage Report - Pebble 2.5-SNAPSHOT
Coverage timestamp: Sat Jun 12 2010 09:39:29 EST
../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
248   910   120   4,35
110   457   0,48   57
57     2,11  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  BlogEntry       Line # 50 248 0% 120 36 91,3% 0.913253
 
  (396)
 
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.comparator.ResponseByDateComparator;
38    import net.sourceforge.pebble.web.validation.ValidationContext;
39    import net.sourceforge.pebble.trackback.TrackBackTokenManager;
40    import org.apache.commons.logging.Log;
41    import org.apache.commons.logging.LogFactory;
42   
43    import java.util.*;
44   
45    /**
46    * Represents a blog entry.
47    *
48    * @author Simon Brown
49    */
 
50    public class BlogEntry extends PageBasedContent {
51   
52    /**
53    * the log used by this class
54    */
55    private static Log log = LogFactory.getLog(BlogEntry.class);
56   
57    public static final String EXCERPT_PROPERTY = "excerpt";
58    public static final String COMMENTS_ENABLED_PROPERTY = "commentsEnabed";
59    public static final String TRACKBACKS_ENABLED_PROPERTY = "trackBacksEnabled";
60    public static final String ATTACHMENT_PROPERTY = "attachment";
61    public static final String CATEGORIES_PROPERTY = "categories";
62   
63    /** the permalink */
64    private String permalink;
65   
66    /**
67    * the category that the blog entry falls into
68    */
69    private Set categories = new HashSet();
70   
71    /**
72    * the excerpt of the blog entry
73    */
74    private String excerpt = "";
75   
76    /**
77    * a flag to indicate whether comments are enabled for this entry
78    */
79    private boolean commentsEnabled = true;
80   
81    /**
82    * a flag to indicate whether TrackBacks are enabled for this entry
83    */
84    private boolean trackBacksEnabled = true;
85   
86    /**
87    * the collection of comments for the blog entry
88    */
89    private List comments = new ArrayList();
90   
91    /**
92    * the collection of trackbacks for the blog entry
93    */
94    private List trackBacks = new ArrayList();
95   
96    /** the attachment for this blog entry, if applicable */
97    private Attachment attachment;
98   
99    /** the timezone that this entry was posted in */
100    private String timeZoneId;
101   
102    /**
103    * Creates a new blog entry.
104    *
105    * @param blog the owning Blog
106    */
 
107  1254 toggle public BlogEntry(Blog blog) {
108  1254 super(blog);
109  1254 setPublished(false);
110    }
111   
112    /**
113    * Sets the title of this blog entry.
114    *
115    * @param newTitle the title as a String
116    */
 
117  932 toggle public void setTitle(String newTitle) {
118  932 super.setTitle(newTitle);
119   
120    // and cause the permalink to be re-generated
121  932 this.permalink = null;
122    }
123   
124    /**
125    * Gets the category of this blog entry.
126    *
127    * @return the category as a String
128    */
 
129  1242 toggle public Set<Category> getCategories() {
130  1242 return new HashSet<Category>(categories);
131    }
132   
133    /**
134    * Gets a list of all tags.
135    *
136    * @return a List of tags
137    */
 
138  848 toggle public List<Tag> getAllTags() {
139  848 List<Tag> list = new ArrayList<Tag>();
140   
141  848 if (getCategories().size() > 0) {
142  124 Iterator it = getCategories().iterator();
143  268 while (it.hasNext()) {
144  144 Category category = (Category)it.next();
145  144 List tagsForCategory = category.getAllTags();
146  144 Collections.reverse(tagsForCategory);
147  144 Iterator jt = tagsForCategory.iterator();
148  196 while (jt.hasNext()) {
149  52 Tag tag = (Tag)jt.next();
150  52 if (!list.contains(tag)) {
151  46 list.add(tag);
152    }
153    }
154    }
155    } else {
156  724 List tagsForCategory = getBlog().getRootCategory().getAllTags();
157  724 Iterator it = tagsForCategory.iterator();
158  726 while (it.hasNext()) {
159  2 Tag tag = (Tag)it.next();
160  2 if (!list.contains(tag)) {
161  2 list.add(tag);
162    }
163    }
164    }
165   
166  848 Iterator it = getTagsAsList().iterator();
167  1382 while (it.hasNext()) {
168  534 Tag tag = (Tag)it.next();
169  534 if (!list.contains(tag)) {
170  534 list.add(tag);
171    }
172    }
173   
174  848 Collections.sort(list);
175  848 return list;
176    }
177   
178    /**
179    * Sets the category of this blog entry.
180    *
181    * @param category the category as a String
182    */
 
183  200 toggle public synchronized void addCategory(Category category) {
184  200 if (category != null && !categories.contains(category)) {
185  152 Set oldCategories = new HashSet(categories);
186  152 categories.add(category);
187  152 Set newCategories = new HashSet(categories);
188  152 propertyChangeSupport.firePropertyChange(CATEGORIES_PROPERTY, oldCategories, newCategories);
189    }
190    }
191   
192    /**
193    * Removes all categories from this blog entry.
194    */
 
195  8 toggle public synchronized void removeAllCategories() {
196  8 propertyChangeSupport.firePropertyChange(CATEGORIES_PROPERTY, new HashSet(categories), new HashSet());
197  8 categories.clear();
198    }
199   
200    /**
201    * Sets the categories for this blog entry.
202    *
203    * @param newCategories a Collection of Category instances
204    */
 
205  4 toggle public synchronized void setCategories(Collection newCategories) {
206  4 if (newCategories != null) {
207  4 Set oldCategories = new HashSet(categories);
208  4 categories.clear();
209  4 Iterator it = newCategories.iterator();
210  10 while (it.hasNext()) {
211  6 categories.add(it.next());
212    }
213  4 propertyChangeSupport.firePropertyChange(CATEGORIES_PROPERTY, oldCategories, new HashSet(newCategories));
214    }
215    }
216   
217    /**
218    * Determines whether this blog entry is in the specified category.
219    *
220    * @param category a Category instance
221    * @return true if this entry is in the specified category,
222    * false otherwise
223    */
 
224  52 toggle public boolean inCategory(Category category) {
225  52 if (category != null) {
226  26 Iterator it = categories.iterator();
227  36 while (it.hasNext()) {
228  32 Category c = (Category)it.next();
229  32 if (c.equals(category) || c.hasParent(category)) {
230  22 return true;
231    }
232    }
233   
234  4 return false;
235    } else {
236  26 return true;
237    }
238    }
239   
240    /**
241    * Determines whether this blog entry has the specified tag.
242    *
243    * @param s a String
244    * @return true if this entry has the specified tag,
245    * false otherwise
246    */
 
247  36 toggle public boolean hasTag(String s) {
248  36 if (s != null) {
249  34 return getAllTags().contains(new Tag(s, getBlog()));
250    } else {
251  2 return false;
252    }
253    }
254   
255    /**
256    * Gets the content of this response.
257    *
258    * @return a String
259    */
 
260  76 toggle public String getContent() {
261  76 if (excerpt != null && excerpt.length() > 0) {
262  38 return excerpt;
263    } else {
264  38 return getBody();
265    }
266    }
267   
268    /**
269    * Gets the excerpt of this blog entry.
270    *
271    * @return the excerpt as a String
272    */
 
273  876 toggle public String getExcerpt() {
274  876 return excerpt;
275    }
276   
277    /**
278    * Sets the excerpt of this blog entry.
279    *
280    * @param newExcerpt the excerpt as a String
281    */
 
282  910 toggle public void setExcerpt(String newExcerpt) {
283  910 if (newExcerpt != null) {
284  906 newExcerpt = newExcerpt.trim();
285    }
286  910 propertyChangeSupport.firePropertyChange(EXCERPT_PROPERTY, excerpt, newExcerpt);
287  910 this.excerpt = newExcerpt;
288    }
289   
290    /**
291    * Gets the date that this blog entry was last updated.
292    *
293    * @return a Date instance representing the time of the last comment/TrackBack
294    */
 
295  4 toggle public Date getLastModified() {
296  4 Date date = getDate();
297   
298  4 Iterator it = comments.iterator();
299  16 while (it.hasNext()) {
300  12 Comment comment = (Comment)it.next();
301  12 if (comment.getDate().after(date)) {
302  12 date = comment.getDate();
303    }
304    }
305   
306  4 it = trackBacks.iterator();
307  10 while (it.hasNext()) {
308  6 TrackBack trackBack = (TrackBack)it.next();
309  6 if (trackBack.getDate().after(date)) {
310  2 date = trackBack.getDate();
311    }
312    }
313   
314  4 return date;
315    }
316   
317    /**
318    * Sets the date that this blog entry was created.
319    *
320    * @param newDate a java.util.Date instance
321    */
 
322  2146 toggle public void setDate(Date newDate) {
323  2146 super.setDate(newDate);
324   
325    // and cause the permalink to be re-generated
326  2146 this.permalink = null;
327    }
328   
329    /**
330    * Gets a permalink for this blog entry that is local to the blog. In other
331    * words, it doesn't take into account the original permalink for
332    * aggregated content.
333    *
334    * @return an absolute URL as a String
335    */
 
336  158 toggle public String getLocalPermalink() {
337  158 if (this.permalink == null) {
338  126 String s = getBlog().getPermalinkProvider().getPermalink(this);
339  126 if (s != null && s.length() > 0) {
340  126 this.permalink = getBlog().getUrl() + s.substring(1);
341    }
342    }
343   
344  158 return permalink;
345    }
346   
347    /**
348    * Gets the attachment associated with this blog entry.
349    *
350    * @return an Attachment instance, or null if one doesn't exist
351    */
 
352  106 toggle public Attachment getAttachment() {
353  106 return attachment;
354    }
355   
356    /**
357    * Sets the attachment associated with thie blog entry.
358    *
359    * @param newAttachment an Attachment instance
360    */
 
361  16 toggle public void setAttachment(Attachment newAttachment) {
362  16 propertyChangeSupport.firePropertyChange(ATTACHMENT_PROPERTY, attachment, newAttachment);
363  16 this.attachment = newAttachment;
364    }
365   
366    /**
367    * Determines whether comments are enabled for this blog entry.
368    *
369    * @return true if comments are enabled, false otherwise
370    */
 
371  90 toggle public boolean isCommentsEnabled() {
372  90 return this.commentsEnabled;
373    }
374   
375    /**
376    * Sets whether comments are enabled for this blog entry.
377    *
378    * @param newCommentsEnabled true if comments should be enabled,
379    * false otherwise
380    */
 
381  592 toggle public void setCommentsEnabled(boolean newCommentsEnabled) {
382  592 propertyChangeSupport.firePropertyChange(COMMENTS_ENABLED_PROPERTY, commentsEnabled, newCommentsEnabled);
383  592 this.commentsEnabled = newCommentsEnabled;
384    }
385   
386    /**
387    * Gets a link to the comments for this blog entry.
388    *
389    * @return an absolute URL as a String
390    */
 
391  2 toggle public String getCommentsLink() {
392  2 return getLocalPermalink() + "#comments";
393    }
394   
395    /**
396    * Determines whether TrackBacks are enabled for this blog entry.
397    *
398    * @return true if TrackBacks are enabled, false otherwise
399    */
 
400  74 toggle public boolean isTrackBacksEnabled() {
401  74 return this.trackBacksEnabled;
402    }
403   
404    /**
405    * Sets whether TrackBacks are enabled for this blog entry.
406    *
407    * @param newTrackBacksEnabled true if TrackBacks should be enabled,
408    * false otherwise
409    */
 
410  588 toggle public void setTrackBacksEnabled(boolean newTrackBacksEnabled) {
411  588 propertyChangeSupport.firePropertyChange(TRACKBACKS_ENABLED_PROPERTY, trackBacksEnabled, newTrackBacksEnabled);
412  588 this.trackBacksEnabled = newTrackBacksEnabled;
413    }
414   
415    /**
416    * Gets a link to the trackbacks for this blog entry.
417    *
418    * @return an absolute URL as a String
419    */
 
420  2 toggle public String getTrackBacksLink() {
421  2 return getLocalPermalink() + "#trackbacks";
422    }
423   
424    /**
425    * Gets the link that blogs can send TrackBacks too.
426    */
 
427  2 toggle public String getTrackBackLink() {
428  2 StringBuffer link = new StringBuffer();
429  2 link.append(getBlog().getUrl());
430  2 link.append("addTrackBack.action?entry=");
431  2 link.append(getId());
432  2 link.append("&token=");
433  2 link.append(TrackBackTokenManager.getInstance().generateToken());
434   
435  2 return link.toString();
436    }
437   
438    /**
439    * Gets a list of all comments and TrackBacks.
440    *
441    * @return a List of all Response instances
442    */
 
443  2074 toggle public List<Response> getResponses() {
444  2074 List<Response> responses = new ArrayList();
445  2074 responses.addAll(getComments());
446  2074 responses.addAll(getTrackBacks());
447  2074 Collections.sort(responses, new ResponseByDateComparator());
448  2074 return responses;
449    }
450   
451    /**
452    * Gets a collection of all comments.
453    *
454    * @return a List of Comment instances
455    */
 
456  3652 toggle public List<Comment> getComments() {
457  3652 List<Comment> allComments = new ArrayList();
458  3652 Iterator it = comments.iterator();
459  6825 while (it.hasNext()) {
460  3173 allComments.addAll(getComments((Comment)it.next()));
461    }
462   
463  3652 return allComments;
464    }
465   
 
466  3261 toggle private List<Comment> getComments(Comment comment) {
467  3261 List<Comment> allComments = new ArrayList();
468  3261 allComments.add(comment);
469  3261 Iterator it = comment.getComments().iterator();
470  3349 while (it.hasNext()) {
471  88 allComments.addAll(getComments((Comment)it.next()));
472    }
473   
474  3261 return allComments;
475    }
476   
477    /**
478    * Gets the number of comments that have been left for this blog entry.
479    *
480    * @return the number of comments as a int
481    */
 
482  30 toggle public int getNumberOfComments() {
483  30 return getComments().size();
484    }
485   
486    /**
487    * Gets a collection of all trackbacks.
488    *
489    * @return a List of TrackBack instances
490    */
 
491  3032 toggle public List<TrackBack> getTrackBacks() {
492  3032 return new ArrayList<TrackBack>(trackBacks);
493    }
494   
495    /**
496    * Gets the number of trackbacks that have been left for this blog entry.
497    *
498    * @return the number of trackbacks as a int
499    */
 
500  6 toggle public int getNumberOfTrackBacks() {
501  6 return trackBacks.size();
502    }
503   
504    /**
505    * Gets the number of responses that have been left for this blog entry.
506    *
507    * @return the number of responses as a int
508    */
 
509  0 toggle public int getNumberOfResponses() {
510  0 return getResponses().size();
511    }
512   
513    /**
514    * Creates a new comment for this blog entry. This method doesn't actually
515    * <b>add</b> the comment too.
516    *
517    * @param title the title of the comment
518    * @param body the body of the comment
519    * @param author the author of the comment
520    * @param email the author's e-mail address
521    * @param website the author's website
522    * @param ipAddress the IP address of the author
523    * @param date the date that the comment was created
524    * @param state the state of the comment
525    * @return a new Comment instance with the specified properties
526    */
 
527  298 toggle public Comment createComment(String title, String body, String author, String email, String website, String ipAddress, Date date, State state) {
528  298 return new Comment(title, body, author, email, website, ipAddress, date, state, this);
529    }
530   
531    /**
532    * Creates a new comment for this blog entry, with a creation date of now.
533    * This method doesn't actually <b>add</b> the comment too.
534    *
535    * @param title the title of the comment
536    * @param body the body of the comment
537    * @param author the author of the comment
538    * @param email the author's e-mail address
539    * @param website the author's website
540    * @param ipAddress the IP address of the author
541    * @return a new Comment instance with the specified properties
542    */
 
543  246 toggle public Comment createComment(String title, String body, String author, String email, String website, String ipAddress) {
544  246 Calendar cal = getBlog().getCalendar();
545  246 return createComment(title, body, author, email, website, ipAddress, cal.getTime(), State.APPROVED);
546    }
547   
548    /**
549    * Adds the specified comment.
550    *
551    * @param comment a Comment instance
552    */
 
553  448 toggle public synchronized void addComment(Comment comment) {
554  448 if (comment == null) {
555  0 return;
556    }
557   
558  448 Comment existingComment = getComment(comment.getId());
559  448 if (existingComment != null && existingComment != comment) {
560    // there is an existing comment with the same ID, but it's
561    // not the same instance
562  172 comment.setDate(new Date(comment.getDate().getTime() + 1));
563  172 addComment(comment);
564  276 } else if (existingComment != null) {
565  2 return;
566    } else {
567  274 if (comment.getParent() != null) {
568  34 Comment parent = getComment(comment.getParent().getId());
569  34 if (parent != null) {
570  34 parent.addComment(comment);
571    } else {
572  0 comments.add(comment);
573    }
574    } else {
575  240 comments.add(comment);
576    }
577  274 comment.setBlogEntry(this);
578   
579  274 if (areEventsEnabled()) {
580  106 addEvent(new CommentEvent(comment, CommentEvent.COMMENT_ADDED));
581  106 comment.setEventsEnabled(true);
582    }
583    }
584    }
585   
586    /**
587    * Creates a new trackback for this blog entry. This method doesn't actually
588    * <b>add</b> the trackback too.
589    *
590    * @param title the title of the entry
591    * @param excerpt the excerpt of the entry
592    * @param url the url (permalink) of the entry
593    * @param blogName the name of the blog
594    * @param ipAddress the IP address of the author
595    * @param date the date the trackback was received
596    * @return a new TrackBack instance with the specified properties
597    */
 
598  144 toggle public TrackBack createTrackBack(String title, String excerpt, String url, String blogName, String ipAddress, Date date, State state) {
599  144 return new TrackBack(title, excerpt, url, blogName, ipAddress, date, state, this);
600    }
601   
602    /**
603    * Creates a new trackback for this blog entry with a date of now.
604    * This method doesn't actually <b>add</b> the trackback too.
605    *
606    * @param title the title of the entry
607    * @param excerpt the excerpt of the entry
608    * @param url the url (permalink) of the entry
609    * @param blogName the name of the blog
610    * @param ipAddress the IP address of the author
611    * @return a new Comment instance with the specified properties
612    */
 
613  132 toggle public TrackBack createTrackBack(String title, String excerpt, String url, String blogName, String ipAddress) {
614  132 Calendar cal = getBlog().getCalendar();
615  132 return createTrackBack(title, excerpt, url, blogName, ipAddress, cal.getTime(), State.APPROVED);
616    }
617   
618    /**
619    * Adds the specified trackback.
620    *
621    * @param trackBack a TrackBack instance
622    */
 
623  48 toggle public synchronized void addTrackBack(TrackBack trackBack) {
624  48 if (trackBack == null || trackBacks.contains(trackBack)) {
625  0 return;
626    }
627   
628  48 trackBacks.add(trackBack);
629   
630  48 if (areEventsEnabled()) {
631  10 addEvent(new TrackBackEvent(trackBack, TrackBackEvent.TRACKBACK_ADDED));
632  10 trackBack.setEventsEnabled(true);
633    }
634    }
635   
636    /**
637    * Removes the specified comment.
638    *
639    * @param id the id of the comment to be removed
640    */
 
641  24 toggle public synchronized void removeComment(long id) {
642  24 Comment comment = getComment(id);
643  24 if (comment != null) {
644   
645    // get all children and delete them
646  24 for (Comment child : comment.getComments()) {
647  6 comment.removeComment(child);
648    }
649   
650  24 if (comment.getParent() != null) {
651  4 comment.getParent().removeComment(comment);
652    } else {
653  20 comments.remove(comment);
654    }
655   
656  24 if (areEventsEnabled()) {
657  14 addEvent(new CommentEvent(comment, CommentEvent.COMMENT_REMOVED));
658    }
659    } else {
660  0 log.warn("A comment with id=" + id + " could not be found - " +
661    "perhaps it has been removed already.");
662    }
663    }
664   
665    /**
666    * Gets the specified comment.
667    *
668    * @param id the id of the comment
669    */
 
670  516 toggle public Comment getComment(long id) {
671  516 Iterator it = getComments().iterator();
672  2416 while (it.hasNext()) {
673  2138 Comment comment = (Comment) it.next();
674  2138 if (comment.getId() == id) {
675  238 return comment;
676    }
677    }
678   
679  278 return null;
680    }
681   
682    /**
683    * Gets the specified TrackBack.
684    *
685    * @param id the id of the TrackBack
686    */
 
687  12 toggle public TrackBack getTrackBack(long id) {
688  12 Iterator it = getTrackBacks().iterator();
689  12 while (it.hasNext()) {
690  12 TrackBack trackBack = (TrackBack)it.next();
691  12 if (trackBack.getId() == id) {
692  12 return trackBack;
693    }
694    }
695   
696  0 return null;
697    }
698   
699    /**
700    * Gets the response specified by the guid.
701    *
702    * @param guid the response guid
703    * @return a Response object, or null if no response exists
704    */
 
705  0 toggle public Response getResponse(String guid) {
706  0 long id = Long.parseLong(guid.substring(guid.lastIndexOf("/")+1));
707  0 if (guid.startsWith("c")) {
708  0 return getComment(id);
709    } else {
710  0 return getTrackBack(id);
711    }
712    }
713   
714    /**
715    * Removes the specified TrackBack.
716    *
717    * @param id the id of the TrackBack to be removed
718    */
 
719  12 toggle public synchronized void removeTrackBack(long id) {
720  12 TrackBack trackBack = getTrackBack(id);
721  12 if (trackBack != null) {
722  12 trackBacks.remove(trackBack);
723   
724  12 if (areEventsEnabled()) {
725  4 addEvent(new TrackBackEvent(trackBack, TrackBackEvent.TRACKBACK_REMOVED));
726    }
727    } else {
728  0 log.warn("A TrackBack with id=" + id + " could not be found - " +
729    "perhaps it has been removed already.");
730    }
731    }
732   
733    /**
734    * Removes the specified comment or TrackBack.
735    *
736    * @param response the Response to be removed
737    */
 
738  8 toggle public void removeResponse(Response response) {
739  8 if (response instanceof Comment) {
740  4 removeComment(response.getId());
741  4 } else if (response instanceof TrackBack) {
742  4 removeTrackBack(response.getId());
743    }
744    }
745   
746    /**
747    * Returns the blog entry that was posted before this one.
748    *
749    * @return a BlogEntry instance, or null if this is the first entry
750    */
 
751  6 toggle public BlogEntry getPreviousBlogEntry() {
752  6 return getBlog().getPreviousBlogEntry(this);
753    }
754   
755    /**
756    * Returns the blog entry that was posted after this one.
757    *
758    * @return a BlogEntry instance, or null is this is the last entry
759    */
 
760  6 toggle public BlogEntry getNextBlogEntry() {
761  6 return getBlog().getNextBlogEntry(this);
762    }
763   
 
764  0 toggle public void validate(ValidationContext context) {
765    }
766   
767    /**
768    * Indicates whether some other object is "equal to" this one.
769    *
770    * @param o the reference object with which to compare.
771    * @return <code>true</code> if this object is the same as the obj
772    * argument; <code>false</code> otherwise.
773    * @see #hashCode()
774    * @see java.util.Hashtable
775    */
 
776  74 toggle public boolean equals(Object o) {
777  74 if (this == o) {
778  40 return true;
779    }
780   
781  34 if (!(o instanceof BlogEntry)) {
782  0 return false;
783    }
784   
785  34 BlogEntry blogEntry = (BlogEntry)o;
786  34 return getGuid().equals(blogEntry.getGuid());
787    }
788   
 
789  408 toggle public String getGuid() {
790  408 return "blogEntry/" + getBlog().getId() + "/" + getId();
791    }
792   
 
793  16 toggle public int hashCode() {
794  16 return getGuid().hashCode();
795    }
796   
797    /**
798    * Creates and returns a copy of this object.
799    *
800    * @return a clone of this instance.
801    * @see Cloneable
802    */
 
803  504 toggle public Object clone() {
804  504 BlogEntry entry = new BlogEntry(getBlog());
805  504 entry.setEventsEnabled(false);
806  504 entry.setPersistent(isPersistent());
807  504 entry.setPublished(isPublished());
808  504 entry.setTitle(getTitle());
809  504 entry.setSubtitle(getSubtitle());
810  504 entry.setExcerpt(getExcerpt());
811  504 entry.setBody(getBody());
812  504 entry.setDate(getDate());
813  504 entry.setTimeZoneId(timeZoneId);
814  504 entry.setState(getState());
815  504 entry.setAuthor(getAuthor());
816  504 entry.setOriginalPermalink(getOriginalPermalink());
817  504 entry.setCommentsEnabled(commentsEnabled);
818  504 entry.setTrackBacksEnabled(trackBacksEnabled);
819   
820  504 if (attachment != null) {
821  2 entry.setAttachment((Attachment)attachment.clone());
822    }
823   
824    // copy the categories
825  504 Iterator it = categories.iterator();
826  554 while (it.hasNext()) {
827  50 entry.addCategory((Category)it.next());
828    }
829   
830  504 entry.setTags(getTags());
831   
832    // also copy the comments
833  504 it = getComments().iterator();
834  624 while (it.hasNext()) {
835  120 Comment comment = (Comment)it.next();
836  120 Comment clonedComment = (Comment)comment.clone();
837  120 entry.addComment(clonedComment);
838    }
839   
840    // and TrackBacks
841  504 it = getTrackBacks().iterator();
842  510 while (it.hasNext()) {
843  6 TrackBack trackBack = (TrackBack)it.next();
844  6 TrackBack clonedTrackBack = (TrackBack)trackBack.clone();
845  6 clonedTrackBack.setBlogEntry(entry);
846  6 entry.addTrackBack(clonedTrackBack);
847    }
848   
849  504 return entry;
850    }
851   
852    /**
853    * Sets whether events are enabled.
854    *
855    * @param b true to enable events, false otherwise
856    */
 
857  1570 toggle void setEventsEnabled(boolean b) {
858  1570 super.setEventsEnabled(b);
859   
860    // and cascade
861  1570 for (Response response : getResponses()) {
862  262 response.setEventsEnabled(b);
863    }
864    }
865   
 
866  486 toggle public void clearEvents() {
867  486 super.clearEvents();
868   
869  486 for (Response response : getResponses()) {
870  150 response.clearEvents();
871    }
872    }
873   
874    /**
875    * Sets the state of this blog entry.
876    */
 
877  2468 toggle void setState(State state) {
878  2468 State previousState = getState();
879  2468 super.setState(state);
880   
881  2468 if (areEventsEnabled()) {
882  18 if (isPublished() && previousState == State.UNPUBLISHED) {
883  14 addEvent(new BlogEntryEvent(this, BlogEntryEvent.BLOG_ENTRY_PUBLISHED));
884  4 } else if (isUnpublished() && previousState == State.PUBLISHED) {
885  4 addEvent(new BlogEntryEvent(this, BlogEntryEvent.BLOG_ENTRY_UNPUBLISHED));
886    }
887    }
888    }
889   
 
890  0 toggle public String toString() {
891  0 return getGuid() + ":" + super.hashCode();
892    }
893   
 
894  0 toggle public TimeZone getTimeZone() {
895  0 return TimeZone.getTimeZone(getTimeZoneId());
896    }
897   
 
898  70 toggle public String getTimeZoneId() {
899  70 if (this.timeZoneId != null) {
900  6 return timeZoneId;
901    } else {
902  64 return getBlog().getTimeZoneId();
903    }
904    }
905   
 
906  558 toggle public void setTimeZoneId(String timeZoneId) {
907  558 this.timeZoneId = timeZoneId;
908    }
909   
910    }