[jboss-cvs] JBossBlog SVN: r271 - in trunk: resources/WEB-INF and 15 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Mar 25 09:24:53 EDT 2008


Author: adamw
Date: 2008-03-25 09:24:53 -0400 (Tue, 25 Mar 2008)
New Revision: 271

Added:
   trunk/src/action/org/jboss/blog/tools/
   trunk/src/action/org/jboss/blog/tools/PostFilterTools.java
   trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuException.java
Modified:
   trunk/docs/tutorial.html
   trunk/resources/WEB-INF/pages.xml
   trunk/src/action/org/jboss/blog/session/feed/mod/PropositionsListener.java
   trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java
   trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java
   trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java
   trunk/src/action/org/jboss/blog/session/update/UpdateHandler.java
   trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java
   trunk/src/model/org/jboss/blog/model/post/filter/AbstractRegexpFilter.java
   trunk/src/model/org/jboss/blog/model/post/filter/CategoryRegexpFilter.java
   trunk/src/shotoku/org/jboss/blog/session/feed/mod/ShotokuModBean.java
   trunk/src/shotoku/org/jboss/blog/session/feed/update/ShotokuFeedUpdate.java
   trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuFeedService.java
   trunk/src/shotoku/org/jboss/shotoku/web/ShotokuFilesystemResourceResolver.java
   trunk/view/manage/aggregated/filter_add.xhtml
   trunk/view/manage/feed_mod.xhtml
   trunk/view/manage/remote/remote_add.xhtml
   trunk/view/manage/remote/remote_mod.xhtml
   trunk/view/manage/remote/remote_propose.xhtml
Log:


Modified: trunk/docs/tutorial.html
===================================================================
--- trunk/docs/tutorial.html	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/docs/tutorial.html	2008-03-25 13:24:53 UTC (rev 271)
@@ -130,10 +130,32 @@
     <div class="titlepage">
         <div>
             <div>
-                <h2 class="title">4. Viewing</h2>
+                <h2 class="title">4. Archiving</h2>
             </div>
         </div>
     </div>
+    <p>All feeds are updated in regular intervals of time (by default, every 15 minutes). In case of a remote feed
+    it means that if there are new posts, they will get merged with the posts that are currently held in the database.
+    No posts are deleted during merging, so if a post disappears from a remote feed (because, for example, the
+    remote feed has only 10 newest posts), it won't disappear from the feeds system.</p>
+
+    <p>This has one drawback, though: if you are not entirely concious when you get home in the evening, and decide to
+    write a very sincere post, with a degree of sincerity which isn't normally viewed as good manners, and in the
+    morning realize that you should delete the post, you'll have to delete it from the feeds sytem manually.</p>
+
+    <p>If you change your post, for example alter the content, the change will be picked up and the post in the
+    database will also be updated. With one exception: when you change the published date. That will be seen as a new
+    post.</p>
+</div>
+
+<div class="sect1">
+    <div class="titlepage">
+        <div>
+            <div>
+                <h2 class="title">5. Viewing</h2>
+            </div>
+        </div>
+    </div>
     <p>Users can view the feeds and posts using the webpage, or using an ATOM feed. When viewing a post (either
     as part of a feed page, or as part of a post page), there is always a link back to the original post, so that
     users can, for example, add comments. The URL schemes are:</p>
@@ -180,7 +202,7 @@
     <div class="titlepage">
         <div>
             <div>
-                <h2 class="title">5. Community involvement</h2>
+                <h2 class="title">6. Community involvement</h2>
             </div>
         </div>
     </div>
@@ -200,7 +222,7 @@
     <div class="titlepage">
         <div>
             <div>
-                <h2 class="title">6. Permissions</h2>
+                <h2 class="title">7. Permissions</h2>
             </div>
         </div>
     </div>
@@ -221,7 +243,7 @@
     <div class="titlepage">
         <div>
             <div>
-                <h2 class="title">7. Administration</h2>
+                <h2 class="title">8. Administration</h2>
             </div>
         </div>
     </div>
@@ -260,7 +282,7 @@
     <div class="titlepage">
         <div>
             <div>
-                <h2 class="title">8. Feeds portlet</h2>
+                <h2 class="title">9. Feeds portlet</h2>
             </div>
         </div>
     </div>
@@ -293,7 +315,7 @@
     <div class="titlepage">
         <div>
             <div>
-                <h2 class="title">9. Future improvements</h2>
+                <h2 class="title">10. Future improvements</h2>
             </div>
         </div>
     </div>

Modified: trunk/resources/WEB-INF/pages.xml
===================================================================
--- trunk/resources/WEB-INF/pages.xml	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/resources/WEB-INF/pages.xml	2008-03-25 13:24:53 UTC (rev 271)
@@ -117,7 +117,7 @@
             <end-conversation />
             <redirect view-id="/manage/index.xhtml" />
         </navigation>
-        <navigation from-action="#{remoteFeedMod.saveOnlyPostAuthorType}">
+        <navigation from-action="#{remoteFeedMod.savePartial}">
             <end-conversation />
             <redirect view-id="/manage/index.xhtml" />
         </navigation>

Modified: trunk/src/action/org/jboss/blog/session/feed/mod/PropositionsListener.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/mod/PropositionsListener.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/action/org/jboss/blog/session/feed/mod/PropositionsListener.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -12,6 +12,7 @@
 import org.jboss.blog.session.security.FeedsIdentity;
 import org.jboss.blog.session.security.external.ExternalSecurityService;
 import org.jboss.blog.session.configuration.ConfigurationManager;
+import org.jboss.blog.tools.StringTools;
 
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
@@ -50,7 +51,7 @@
     }
 
     private void sendEmail(String email, String view) {
-        if (email != null) {
+        if (!StringTools.isEmpty(email)) {
             try {
                 currentEmail = email;
                 renderer.render(view);

Modified: trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -3,10 +3,14 @@
 import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.feed.RemoteFeed;
 import org.jboss.blog.model.feed.PostAuthorType;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.model.Category;
 import org.jboss.blog.session.feed.InvalidFeedTypeException;
 import org.jboss.blog.session.parser.ParserException;
 import org.jboss.blog.session.parser.ParserService;
 import org.jboss.blog.tools.StringTools;
+import org.jboss.blog.tools.PostFilterTools;
+import org.jboss.blog.tools.validator.Regexp;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.core.Events;
 import org.jboss.seam.annotations.In;
@@ -16,8 +20,14 @@
 import org.jboss.seam.faces.FacesMessages;
 
 import javax.faces.application.FacesMessage;
+import javax.faces.model.SelectItem;
 import javax.persistence.EntityManager;
 import java.io.Serializable;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.regex.Pattern;
 
 /**
  * @author <a href="mailto:adam at warski.org">Adam Warski</a>
@@ -40,6 +50,15 @@
     @In
     private PostsValidator postsValidator;
 
+    private List<SelectItem> includeCategories;
+
+    private String includeCategory;
+
+    @Regexp
+    private String includeOtherCategoryRegexp;
+
+    private List<Post> visiblePosts;
+
     private RemoteFeed remoteFeed;
 
     private Feed parsedFeed;
@@ -47,6 +66,9 @@
     private boolean parseOk;
     private Exception parseException;
 
+    private final static String ALL_CATEGORIES = "ALL";
+    private final static String OTHER_CATEGORY = "OTHER";
+
     public RemoteFeed getRemoteFeed() throws InvalidFeedTypeException {
         if (remoteFeed == null) {
             if (feedMod.getFeed() == null) {
@@ -59,6 +81,15 @@
             } else {
                 if (feedMod.getFeed() instanceof RemoteFeed) {
                     remoteFeed = (RemoteFeed) feedMod.getFeed();
+                    if (StringTools.isEmpty(remoteFeed.getIncludeCategoryRegexp())) {
+                        includeCategory = ALL_CATEGORIES;
+                    } else {
+                        includeCategory = OTHER_CATEGORY;
+                        includeOtherCategoryRegexp = remoteFeed.getIncludeCategoryRegexp();
+                    }
+
+                    initIncludeCategories();
+                    finishIncludeCategories();
                 } else {
                     throw new InvalidFeedTypeException();
                 }
@@ -84,10 +115,79 @@
         this.parseException = parseException;
     }
 
+    public List<SelectItem> getIncludeCategories() {
+        return includeCategories;
+    }
+
+    public String getIncludeCategory() {
+        return includeCategory;
+    }
+
+    public void setIncludeCategory(String includeCategory) throws InvalidFeedTypeException {
+        this.includeCategory = includeCategory;
+    }
+
+    public String getIncludeOtherCategoryRegexp() {
+        return includeOtherCategoryRegexp;
+    }
+
+    public void setIncludeOtherCategoryRegexp(String includeOtherCategoryRegexp) throws InvalidFeedTypeException {
+        this.includeOtherCategoryRegexp = includeOtherCategoryRegexp;
+    }
+
+    public List<Post> getVisiblePosts() {
+        return visiblePosts;
+    }
+
+    private void generateIncludedCategory() throws InvalidFeedTypeException {
+        if (ALL_CATEGORIES.equals(includeCategory)) {
+            getRemoteFeed().setIncludeCategoryRegexp(null);
+        } else if (OTHER_CATEGORY.equals(includeCategory)) {
+            getRemoteFeed().setIncludeCategoryRegexp(includeOtherCategoryRegexp);
+        } else {
+            getRemoteFeed().setIncludeCategoryRegexp(
+                    includeCategory == null ? null : Pattern.quote(includeCategory));
+        }
+    }
+
+    public void generateVisiblePosts() throws InvalidFeedTypeException {
+        generateIncludedCategory();
+
+        RemoteFeed remoteFeed = getRemoteFeed();        
+        visiblePosts = new ArrayList<Post>();
+
+        if (parsedFeed != null) {
+            for (Post post : parsedFeed.getPosts()) {
+                if (remoteFeed.getIncludeCategoryFilter().filter(post)) {
+                    visiblePosts.add(post);
+                }
+            }
+        }
+    }
+
     public void unsetAccepted() throws InvalidFeedTypeException {
         getRemoteFeed().setAccepted(false);
     }
 
+    private void initIncludeCategories() {
+        includeCategories = new ArrayList<SelectItem>();
+        includeCategories.add(new SelectItem(ALL_CATEGORIES, "All categories"));
+    }
+
+    private void finishIncludeCategories() {
+        includeCategories.add(new SelectItem(OTHER_CATEGORY, "Other (regular expression) ..."));
+    }
+
+    private Set<Category> getCategoriesOfPosts(Feed feed) {
+        Set<Category> categories = new HashSet<Category>();
+
+        for (Post post : feed.getPosts()) {
+            categories.addAll(post.getCategories());
+        }
+
+        return categories;
+    }
+
     public void parseFeed() throws InvalidFeedTypeException {
         try {
             parsedFeed = parserService.parse(getRemoteFeed().getRemoteLink());
@@ -95,7 +195,15 @@
             if (!postsValidator.validatePosts(parsedFeed.getPosts(), true, "link")) {
                throw new ParserException("Posts are missing some information.");
             }
-            
+
+            initIncludeCategories();
+            for (Category cat : getCategoriesOfPosts(parsedFeed)) {
+                includeCategories.add(new SelectItem(cat.getName(), cat.getName()));    
+            }
+            finishIncludeCategories();
+
+            generateVisiblePosts();
+
             setParseOk(true);
         } catch (ParserException e) {
             setParseException(e);
@@ -104,13 +212,17 @@
     }
 
     public void saveNew() throws InvalidFeedTypeException {
-        getRemoteFeed().setAuthor(parsedFeed.getAuthor());
-        getRemoteFeed().setDescription(parsedFeed.getDescription());
-        getRemoteFeed().setLink(parsedFeed.getLink());
-        getRemoteFeed().setTitle(parsedFeed.getTitle());
+        RemoteFeed remoteFeed = getRemoteFeed();
+        remoteFeed.setAuthor(parsedFeed.getAuthor());
+        remoteFeed.setDescription(parsedFeed.getDescription());
+        remoteFeed.setLink(parsedFeed.getLink());
+        remoteFeed.setTitle(parsedFeed.getTitle());
 
+        generateIncludedCategory();
+
         if (getRemoteFeed().isAccepted()) {
-            getRemoteFeed().setPosts(parsedFeed.getPosts());
+            remoteFeed.setPosts(PostFilterTools.filterPostList(parsedFeed.getPosts(),
+                    remoteFeed.getIncludeCategoryFilter()));
         }
     }
 
@@ -118,6 +230,8 @@
     public void saveExisting() throws InvalidFeedTypeException {
         getRemoteFeed().setLink(parsedFeed.getLink());
 
+        generateIncludedCategory();
+
         entityManager.flush();
 
         facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "blog.feed.remote.address.updated",
@@ -127,12 +241,13 @@
     }
 
     @Restrict("#{identity.hasPermission('feed', 'edit', feedMod.feed, feedMod.feed.group)}")
-    public void saveOnlyPostAuthorType() throws InvalidFeedTypeException {
+    public void savePartial() throws InvalidFeedTypeException {
         PostAuthorType newPostAuthorType = getRemoteFeed().getPostAuthorType();
 
         entityManager.refresh(getRemoteFeed());
 
         getRemoteFeed().setPostAuthorType(newPostAuthorType);
+        generateIncludedCategory();
 
         entityManager.flush();
 

Modified: trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -7,6 +7,7 @@
 import org.jboss.blog.service.FeedsService;
 import org.jboss.blog.service.GroupsService;
 import org.jboss.blog.tools.GeneralTools;
+import org.jboss.blog.tools.PostFilterTools;
 import org.jboss.blog.model.post.PostFilter;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.In;
@@ -30,14 +31,6 @@
     @In
     private AggregatedFeedStack aggregatedFeedStack;
 
-    private void filterPostList(List<? extends RestrictedPost> posts, PostFilter filter) {
-        for (Iterator<? extends RestrictedPost> iter = posts.iterator(); iter.hasNext();) {
-            if (!filter.filter(iter.next())) {
-                iter.remove();
-            }
-        }
-    }
-
     @SuppressWarnings("unchecked")
     public List<? extends RestrictedPost> getPosts(AggregatedFeed aggregatedFeed, int from, int to) {
         if (aggregatedFeedStack.contains(aggregatedFeed)) {
@@ -87,10 +80,10 @@
                 }
 
                 // Apply the local filters
-                filterPostList(feedPosts, feedsAndFilters.get(feed));
+                PostFilterTools.filterFromPostList(feedPosts, feedsAndFilters.get(feed));
 
                 // Apply the global filters
-                filterPostList(feedPosts, globalFilter);
+                PostFilterTools.filterFromPostList(feedPosts, globalFilter);
 
                 posts.addAll(feedPosts);
             }

Modified: trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -7,6 +7,7 @@
 import org.jboss.blog.session.merge.MergeServiceBean;
 import org.jboss.blog.session.update.UpdateException;
 import org.jboss.blog.session.feed.lock.FeedsLocksBean;
+import org.jboss.blog.tools.PostFilterTools;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
@@ -40,7 +41,8 @@
                 throw new UpdateException(e);
             }
 
-            mergeService.merge(feed, parsedFeed.getPosts());
+            mergeService.merge(feed, PostFilterTools.filterPostList(parsedFeed.getPosts(),
+                    feed.getIncludeCategoryFilter()));
         } finally {
             feedLock.unlock();
         }

Modified: trunk/src/action/org/jboss/blog/session/update/UpdateHandler.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/update/UpdateHandler.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/action/org/jboss/blog/session/update/UpdateHandler.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -5,7 +5,6 @@
 import org.jboss.blog.model.Group;
 import org.jboss.blog.service.GroupsService;
 import org.jboss.blog.session.feed.type.FeedTypes;
-import org.jboss.blog.session.feed.InvalidFeedTypeException;
 import org.jboss.seam.annotations.AutoCreate;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
@@ -43,7 +42,7 @@
             feedTypes.getFeedDao(feed).update();
         } catch (UpdateException e) {
             updateManager.addFeedUpdateException(feed.getName(), e);
-        } catch (InvalidFeedTypeException e) {
+        } catch (Exception e) {
             updateManager.addFeedUpdateException(feed.getName(), new UpdateException(e));
         }
     }

Added: trunk/src/action/org/jboss/blog/tools/PostFilterTools.java
===================================================================
--- trunk/src/action/org/jboss/blog/tools/PostFilterTools.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/tools/PostFilterTools.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -0,0 +1,33 @@
+package org.jboss.blog.tools;
+
+import org.jboss.blog.model.RestrictedPost;
+import org.jboss.blog.model.post.PostFilter;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class PostFilterTools {
+    public static void filterFromPostList(List<? extends RestrictedPost> posts, PostFilter filter) {
+        for (Iterator<? extends RestrictedPost> iter = posts.iterator(); iter.hasNext();) {
+            if (!filter.filter(iter.next())) {
+                iter.remove();
+            }
+        }
+    }
+
+    public static <T extends RestrictedPost> List<T> filterPostList(List<T> posts, PostFilter filter) {
+        List<T> filtered = new ArrayList<T>();
+
+        for (T post : posts) {
+            if (filter.filter(post)) {
+                filtered.add(post);
+            }
+        }
+
+        return filtered;
+    }
+}

Modified: trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -4,8 +4,15 @@
 import org.hibernate.validator.NotEmpty;
 import org.hibernate.annotations.Cache;
 import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.jboss.blog.tools.validator.Regexp;
+import org.jboss.blog.tools.StringTools;
+import org.jboss.blog.model.post.PostFilter;
+import org.jboss.blog.model.post.filter.CategoryRegexpFilter;
+import org.jboss.blog.model.post.filter.TotalFilter;
 
 import javax.persistence.Entity;
+import javax.persistence.Column;
+import javax.persistence.Transient;
 
 /**
  * @author <a href="mailto:adam at warski.org">Adam Warski</a>
@@ -17,6 +24,13 @@
     @Length(max = 512)
     private String remoteLink;
 
+    @Regexp
+    @Column
+    private String includeCategoryRegexp;
+
+    @Transient
+    private PostFilter includeCategoryFilter;
+
     public String getRemoteLink() {
         return remoteLink;
     }
@@ -24,4 +38,28 @@
     public void setRemoteLink(String remoteLink) {
         this.remoteLink = remoteLink;
     }
+
+    public String getIncludeCategoryRegexp() {
+        return includeCategoryRegexp;
+    }
+
+    public void setIncludeCategoryRegexp(String includeCategoryRegexp) {
+        this.includeCategoryRegexp = includeCategoryRegexp;
+
+        synchronized(this) {
+            includeCategoryFilter = null;
+        }
+    }
+
+    public synchronized PostFilter getIncludeCategoryFilter() {
+        if (includeCategoryFilter == null) {
+            if (StringTools.isEmpty(includeCategoryRegexp)) {
+                includeCategoryFilter = new TotalFilter();
+            } else {
+                includeCategoryFilter = new CategoryRegexpFilter(includeCategoryRegexp);
+            }
+        }
+        
+        return includeCategoryFilter;
+    }
 }

Modified: trunk/src/model/org/jboss/blog/model/post/filter/AbstractRegexpFilter.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/post/filter/AbstractRegexpFilter.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/model/org/jboss/blog/model/post/filter/AbstractRegexpFilter.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -14,6 +14,13 @@
 
     protected transient Pattern pattern;
 
+    protected AbstractRegexpFilter() {
+    }
+
+    protected AbstractRegexpFilter(String regexp) {
+        setRegexp(regexp);
+    }
+
     public String getRegexp() {
         return regexp;
     }

Modified: trunk/src/model/org/jboss/blog/model/post/filter/CategoryRegexpFilter.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/post/filter/CategoryRegexpFilter.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/model/org/jboss/blog/model/post/filter/CategoryRegexpFilter.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -11,6 +11,13 @@
 public class CategoryRegexpFilter extends AbstractRegexpFilter {
     private static final long serialVersionUID = 1209854919382113132L;
 
+    public CategoryRegexpFilter() {
+    }
+
+    public CategoryRegexpFilter(String regexp) {
+        super(regexp);
+    }
+
     public boolean filter(RestrictedPost post) {
         for (RestrictedCategory cat : post.getCategories()) {
             if (pattern.matcher(cat.getName()).matches()) {

Modified: trunk/src/shotoku/org/jboss/blog/session/feed/mod/ShotokuModBean.java
===================================================================
--- trunk/src/shotoku/org/jboss/blog/session/feed/mod/ShotokuModBean.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/shotoku/org/jboss/blog/session/feed/mod/ShotokuModBean.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -12,6 +12,7 @@
 import org.jboss.blog.session.feed.InvalidFeedTypeException;
 import org.jboss.blog.session.shotoku.ShotokuFeedService;
 import org.jboss.blog.session.shotoku.PostContentTooLargeException;
+import org.jboss.blog.session.shotoku.ShotokuException;
 import org.jboss.shotoku.exceptions.RepositoryException;
 
 import javax.persistence.EntityManager;
@@ -105,7 +106,7 @@
             }
 
             setPathOk(true);
-        } catch (RepositoryException e) {
+        } catch (ShotokuException e) {
             setPathOk(false);
             setPathException(e);
         } catch (PostContentTooLargeException e) {

Modified: trunk/src/shotoku/org/jboss/blog/session/feed/update/ShotokuFeedUpdate.java
===================================================================
--- trunk/src/shotoku/org/jboss/blog/session/feed/update/ShotokuFeedUpdate.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/shotoku/org/jboss/blog/session/feed/update/ShotokuFeedUpdate.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -7,11 +7,11 @@
 import org.jboss.blog.session.feed.lock.FeedsLocksBean;
 import org.jboss.blog.session.shotoku.ShotokuFeedService;
 import org.jboss.blog.session.shotoku.PostContentTooLargeException;
+import org.jboss.blog.session.shotoku.ShotokuException;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
 import org.jboss.seam.annotations.Scope;
-import org.jboss.shotoku.exceptions.RepositoryException;
 
 import java.util.concurrent.locks.Lock;
 import java.util.List;
@@ -39,7 +39,7 @@
 
             try {
                 posts = shotokuFeedService.getPosts(feed);
-            } catch (RepositoryException e) {
+            } catch (ShotokuException e) {
                 throw new UpdateException(e);
             } catch (PostContentTooLargeException e) {
                 throw new UpdateException(e);

Added: trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuException.java
===================================================================
--- trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuException.java	                        (rev 0)
+++ trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuException.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -0,0 +1,23 @@
+package org.jboss.blog.session.shotoku;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class ShotokuException extends Exception {
+    public ShotokuException() {
+    }
+
+    public ShotokuException(String message) {
+        super(message);
+    }
+
+    public ShotokuException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ShotokuException(Throwable cause) {
+        super(cause);
+    }
+}
+
+

Modified: trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuFeedService.java
===================================================================
--- trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuFeedService.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/shotoku/org/jboss/blog/session/shotoku/ShotokuFeedService.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -32,7 +32,7 @@
     private LinkService linkService;
 
     private void setEnclosureUrl(ShotokuFeed feed, Enclosure enclosure, String nodeName) {
-        enclosure.setUrl(linkService.getServerAddress() + '/' + feed.getPodcastPrefix() + '/' + nodeName);    
+        enclosure.setUrl(linkService.getServerAddress() + '/' + feed.getPodcastPrefix() + '/' + nodeName);
     }
 
     public void refreshEnclosureLinks(ShotokuFeed feed) {
@@ -49,56 +49,60 @@
         }
     }
 
-    public List<Post> getPosts(ShotokuFeed feed) throws RepositoryException, PostContentTooLargeException {
-        ContentManager cm = ContentManager.getContentManager(feed.getCmId(), feed.getCmPath());
+    public List<Post> getPosts(ShotokuFeed feed) throws ShotokuException, PostContentTooLargeException {
+        try {
+            ContentManager cm = ContentManager.getContentManager(feed.getCmId(), feed.getCmPath());
 
-        List<Post> posts = new ArrayList<Post>();
+            List<Post> posts = new ArrayList<Post>();
 
-        if (cm == null) {
-            throw new RepositoryException("Couldn't initialize the specified content manager.");
-        }
+            if (cm == null) {
+                throw new ShotokuException("Couldn't initialize the specified content manager.");
+            }
 
-        Directory rootDir = cm.getRootDirectory();
-        if (rootDir == null) {
-            throw new RepositoryException("Couldn't get the root directory in the specified content manager.");
-        }
+            Directory rootDir = cm.getRootDirectory();
+            if (rootDir == null) {
+                throw new ShotokuException("Couldn't get the root directory in the specified content manager.");
+            }
 
-        for (Node node : cm.getRootDirectory().getNodes()) {
-            Post post = new Post();
+            for (Node node : cm.getRootDirectory().getNodes()) {
+                Post post = new Post();
 
-            post.setAuthor(node.getProperty("author"));
-            post.setCategories(new ArrayList<Category>());
-            post.setEnclosures(new ArrayList<Enclosure>());
-            post.setImages(new ArrayList<Image>());
-            post.setModified(node.getLastModificationDate());
-            post.setPublished(node.getCreatedDate());
-            post.setTitle(node.getProperty("title"));
+                post.setAuthor(node.getProperty("author"));
+                post.setCategories(new ArrayList<Category>());
+                post.setEnclosures(new ArrayList<Enclosure>());
+                post.setImages(new ArrayList<Image>());
+                post.setModified(node.getLastModificationDate());
+                post.setPublished(node.getCreatedDate());
+                post.setTitle(node.getProperty("title"));
 
-            if (!StringTools.isEmpty(feed.getPodcastPrefix())) {
-                post.setContent(node.getProperty("description"));
+                if (!StringTools.isEmpty(feed.getPodcastPrefix())) {
+                    post.setContent(node.getProperty("description"));
 
-                Enclosure enclosure = new Enclosure(post, null, node.getLength(), node.getMimeType());
-                setEnclosureUrl(feed, enclosure, node.getName());
-                post.getEnclosures().add(enclosure);
+                    Enclosure enclosure = new Enclosure(post, null, node.getLength(), node.getMimeType());
+                    setEnclosureUrl(feed, enclosure, node.getName());
+                    post.getEnclosures().add(enclosure);
 
-                String thumbnail = node.getProperty("thumbnail");
-                if (!StringTools.isEmpty(thumbnail)) {
-                    post.getImages().add(new Image(post, linkService.getServerAddress() + '/' + thumbnail));
+                    String thumbnail = node.getProperty("thumbnail");
+                    if (!StringTools.isEmpty(thumbnail)) {
+                        post.getImages().add(new Image(post, linkService.getServerAddress() + '/' + thumbnail));
+                    }
+                } else {
+                    if (node.getLength() > 1000000) {
+                        throw new PostContentTooLargeException("The content for node: '" + node.getFullName() +
+                                "' is too large for a post.");
+                    }
+
+                    post.setContent(node.getContent());
                 }
-            } else {
-                if (node.getLength() > 1000000) {
-                    throw new PostContentTooLargeException("The content for node: '" + node.getFullName() +
-                        "' is too large for a post.");
-                }
 
-                post.setContent(node.getContent());    
+                posts.add(post);
             }
 
-            posts.add(post);
+            Collections.sort(posts);
+
+            return posts;
+        } catch (RepositoryException e) {
+            throw new ShotokuException(e);
         }
-
-        Collections.sort(posts);
-
-        return posts;
     }
 }

Modified: trunk/src/shotoku/org/jboss/shotoku/web/ShotokuFilesystemResourceResolver.java
===================================================================
--- trunk/src/shotoku/org/jboss/shotoku/web/ShotokuFilesystemResourceResolver.java	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/src/shotoku/org/jboss/shotoku/web/ShotokuFilesystemResourceResolver.java	2008-03-25 13:24:53 UTC (rev 271)
@@ -2,7 +2,6 @@
 
 import com.sun.facelets.impl.ResourceResolver;
 
-import javax.faces.context.FacesContext;
 import java.net.MalformedURLException;
 import java.net.URL;
 

Modified: trunk/view/manage/aggregated/filter_add.xhtml
===================================================================
--- trunk/view/manage/aggregated/filter_add.xhtml	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/view/manage/aggregated/filter_add.xhtml	2008-03-25 13:24:53 UTC (rev 271)
@@ -13,11 +13,12 @@
 </ui:define>
 
 <ui:define name="body">
-    <div class="QuickstartMargin" id="QuickStart">
+    <div class="TwoColumnBlogSubnav">
+        <h4>Tips</h4>
         <ul>
             <li>
                 An <a href="http://www.regular-expressions.info/javascriptexample.html" target="_blank">online regular
-                    expressions tester</a> in case you need help.
+                expressions tester</a> in case you need help.
             </li>
         </ul>
     </div>

Modified: trunk/view/manage/feed_mod.xhtml
===================================================================
--- trunk/view/manage/feed_mod.xhtml	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/view/manage/feed_mod.xhtml	2008-03-25 13:24:53 UTC (rev 271)
@@ -11,13 +11,9 @@
 <div class="TwoColumnBlogSubnav">
     <h4>Tips</h4>
     <ul>
-        <li>
+        <li class="last">
             Please fill in all the details that are necessary to handle your feed.
         </li>
-        <li class="last">
-            Also, choose an atom template that suites the type of your feed. Most of the time, 'standard' will
-                suffice, however if you have a podcast, choose 'podcast'.
-        </li>
     </ul>
 </div>
 
@@ -92,7 +88,9 @@
         <h:message for="group" styleClass="error" />
     </a:outputPanel>
 
-    <div><s:link value="Add new group" action="#{groupMod.add}" /></div><br />
+    <s:div rendered="#{identity.hasPermission('group', 'add')}">
+        <s:link value="Add new group" action="#{groupMod.add}" /><br />
+    </s:div>
 </h:panelGroup>
 
 <h:outputLabel for="maxPostsInFeed">

Modified: trunk/view/manage/remote/remote_add.xhtml
===================================================================
--- trunk/view/manage/remote/remote_add.xhtml	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/view/manage/remote/remote_add.xhtml	2008-03-25 13:24:53 UTC (rev 271)
@@ -27,7 +27,7 @@
 
         <ui:include src="remote_mod.xhtml">
             <ui:param name="new" value="true" />
-            <ui:param name="showCaptcha" value="false" /> 
+            <ui:param name="showCaptcha" value="false" />
             <ui:param name="backTo" value="/manage/index.html" />
         </ui:include>
     </ui:define>

Modified: trunk/view/manage/remote/remote_mod.xhtml
===================================================================
--- trunk/view/manage/remote/remote_mod.xhtml	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/view/manage/remote/remote_mod.xhtml	2008-03-25 13:24:53 UTC (rev 271)
@@ -7,93 +7,139 @@
                 xmlns:h="http://java.sun.com/jsf/html"
                 xmlns:rich="http://richfaces.org/rich"
                 xmlns:a="http://richfaces.org/a4j">
-    <div class="adminforms">
-        <h:form>
-            <h:panelGrid columns="2">
-                <h:panelGroup rendered="#{showCaptcha}">
-                    <span class="required">*</span>
-                    <h:graphicImage value="/seam/resource/captcha/#{captchaTools.id}" id="captchaGraphic"/>
-                </h:panelGroup>
-                <h:panelGroup rendered="#{showCaptcha}">
-                    <h:inputText id="verifyCaptcha" value="#{captcha.response}" required="true">
-                        <s:validate />
-                    </h:inputText>
-                    <a:outputPanel id="captchaMessage">
-                        <h:message for="verifyCaptcha" styleClass="error" />
-                    </a:outputPanel>
-                </h:panelGroup>
+<div class="adminforms">
+<h:form>
+<h:panelGrid columns="2">
+    <h:panelGroup rendered="#{showCaptcha}">
+        <span class="required">*</span>
+        <h:graphicImage value="/seam/resource/captcha/#{captchaTools.id}" id="captchaGraphic"/>
+    </h:panelGroup>
+    <h:panelGroup rendered="#{showCaptcha}">
+        <h:inputText id="verifyCaptcha" value="#{captcha.response}" required="true">
+            <s:validate />
+        </h:inputText>
+        <a:outputPanel id="captchaMessage">
+            <h:message for="verifyCaptcha" styleClass="error" />
+        </a:outputPanel>
+    </h:panelGroup>
 
-                <h:outputLabel><span class="required">*</span> Remote feed (atom/rss2) address:</h:outputLabel>
-                <h:panelGroup>
-                    <h:inputText id="link" value="#{remoteFeedMod.remoteFeed.remoteLink}" required="true" size="55"
-                                 maxlength="64">
-                        <s:validate />
-                    </h:inputText>
-                    <a:outputPanel id="linkMessage">
-                        <h:message for="link" styleClass="error" />
-                    </a:outputPanel>
-                </h:panelGroup>
+    <h:outputLabel><span class="required">*</span> Remote feed (atom/rss2) address:</h:outputLabel>
+    <h:panelGroup id="addressBody">
+        <h:inputText id="link" value="#{remoteFeedMod.remoteFeed.remoteLink}" required="true" size="55"
+                     maxlength="64" disabled="#{remoteFeedMod.parseOk}">
+            <s:validate />
+        </h:inputText>
+        <a:outputPanel id="linkMessage">
+            <h:message for="link" styleClass="error" />
+        </a:outputPanel>
+    </h:panelGroup>
 
-                <h:outputLabel for="postAuthorType"><span class="required">*</span> Post author:</h:outputLabel>
-                <h:panelGroup>
-                    <h:selectOneMenu id="postAuthorType" value="#{remoteFeedMod.remoteFeed.postAuthorType}"
-                                     required="true" styleClass="selectwide">
-                        <s:enumItem enumValue="BLOG_AUTHOR_IF_MISSING" label="Overwrite with blog author when post
+    <h:outputLabel for="postAuthorType"><span class="required">*</span> Post author:</h:outputLabel>
+    <h:panelGroup>
+        <h:selectOneMenu id="postAuthorType" value="#{remoteFeedMod.remoteFeed.postAuthorType}"
+                         required="true" styleClass="selectwide">
+            <s:enumItem enumValue="BLOG_AUTHOR_IF_MISSING" label="Overwrite with blog author when post
                             author is missing" />
-                        <s:enumItem enumValue="POST_AUTHOR" label="Always use original post author" />
-                        <s:enumItem enumValue="BLOG_AUTHOR" label="Always overwrite post author with blog author" />
-                        <s:convertEnum />
-                        <s:validate />
-                    </h:selectOneMenu>
-                </h:panelGroup>
+            <s:enumItem enumValue="POST_AUTHOR" label="Always use original post author" />
+            <s:enumItem enumValue="BLOG_AUTHOR" label="Always overwrite post author with blog author" />
+            <s:convertEnum />
+            <s:validate />
+        </h:selectOneMenu>
+    </h:panelGroup>
 
-                <h:panelGroup />
-                <h:panelGroup id="parseStatus">
-                    <h:panelGroup rendered="#{remoteFeedMod.parseOk}">
-                        Parsing the feed was successfull! You can proceed.
-                    </h:panelGroup>
-                    <h:panelGroup rendered="#{!remoteFeedMod.parseOk and remoteFeedMod.parseException != null}">
-                        Parsing the feed failed, because of the following exception:
-                        #{remoteFeedMod.parseException.message}
-                    </h:panelGroup>
-                </h:panelGroup>
-            </h:panelGrid>
+    <h:outputLabel id="includeCategoryHeader">
+        <s:fragment rendered="#{remoteFeedMod.parseOk or !new}">
+            <span class="required">*</span> Include only posts from category:
+        </s:fragment>
+    </h:outputLabel>
+    <h:panelGroup id="includeCategoryBody">
+        <s:fragment rendered="#{remoteFeedMod.parseOk or !new}">
+            <h:selectOneMenu id="includeCategory" required="true" value="#{remoteFeedMod.includeCategory}"
+                             style="width: 200px">
+                <f:selectItems value="#{remoteFeedMod.includeCategories}" />
+                <s:validate />
+                <a:support event="onchange" reRender="includeCategoryBody,postsIncluded,regexpHelp" ajaxSingle="true"
+                        action="#{remoteFeedMod.generateVisiblePosts}" />
+            </h:selectOneMenu>
+            <h:inputText id="includeOtherCategory" rendered="#{remoteFeedMod.includeCategory == 'OTHER'}"
+                         value="#{remoteFeedMod.includeOtherCategoryRegexp}" required="true">
+                <s:validate />
+                <a:support event="onblur" reRender="includeCategoryMessage,postsIncluded" ajaxSingle="true"
+                        action="#{remoteFeedMod.generateVisiblePosts}" />
+            </h:inputText>
+            <a:outputPanel id="includeCategoryMessage">
+                <h:message for="includeCategory" styleClass="error" />
+                <h:message for="includeOtherCategory" styleClass="error" />
+            </a:outputPanel>
+        </s:fragment>
+    </h:panelGroup>
 
-            <s:div id="proceed" styleClass="formbuttons">
-                <ul>
-                    <s:fragment rendered="#{!remoteFeedMod.parseOk}">
-                        <li>
-                            <a:commandButton action="#{remoteFeedMod.parseFeed}" value="Read and parse the feed"
-                                             styleClass="submit"
-                                             reRender="parseStatus,proceed,linkMessage,link,captchaGraphic,captchaMessage,postAuthorType" />
-                        </li>
-                    </s:fragment>
-                    <s:fragment rendered="#{remoteFeedMod.parseOk and new}">
-                        <li>
-                            <h:commandButton value="Next &#187;" action="#{remoteFeedMod.saveNew}"
-                                             styleClass="submit_first" />
-                        </li>
-                    </s:fragment>
-                    <s:fragment rendered="#{remoteFeedMod.parseOk and !new}">
-                        <li>
-                            <h:commandButton value="Save" action="#{remoteFeedMod.saveExisting}"
-                                             styleClass="submit" />
-                        </li>
-                    </s:fragment>
-                    <s:fragment rendered="#{!new}">
-                        <li>
-                            <h:commandButton value="Save only 'post author'" action="#{remoteFeedMod.saveOnlyPostAuthorType}"
-                                             styleClass="submit" />
-                        </li>
-                    </s:fragment>
-                    <li>
-                        <s:button value="Cancel" view="#{backTo}" propagation="end" styleClass="submit" />
-                    </li>
-                    <li>
-                        <ui:include src="../../common/ajax_status.xhtml" />
-                    </li>
-                </ul>
-            </s:div>
-        </h:form>
-    </div>
+    <h:panelGroup />
+    <h:panelGroup id="parseStatus">
+        <h:panelGroup rendered="#{remoteFeedMod.parseOk}">
+            Parsing the feed was successfull! You can proceed.
+        </h:panelGroup>
+        <h:panelGroup rendered="#{!remoteFeedMod.parseOk and remoteFeedMod.parseException != null}">
+            Parsing the feed failed, because of the following exception:
+            #{remoteFeedMod.parseException.message}
+        </h:panelGroup>
+    </h:panelGroup>
+</h:panelGrid>
+
+<s:div id="proceed" styleClass="formbuttons">
+    <ul>
+        <s:fragment rendered="#{!remoteFeedMod.parseOk}">
+            <li>
+                <a:commandButton action="#{remoteFeedMod.parseFeed}" value="Read and parse the feed"
+                                 styleClass="submit"
+                                 reRender="parseStatus,proceed,linkMessage,link,captchaGraphic,captchaMessage,postAuthorType,includeCategoryHeader,includeCategoryBody,addressBody,postsIncluded" />
+            </li>
+        </s:fragment>
+        <s:fragment rendered="#{remoteFeedMod.parseOk and new}">
+            <li>
+                <h:commandButton value="Next &#187;" action="#{remoteFeedMod.saveNew}"
+                                 styleClass="submit_first" />
+            </li>
+        </s:fragment>
+        <s:fragment rendered="#{remoteFeedMod.parseOk and !new}">
+            <li>
+                <h:commandButton value="Save all" action="#{remoteFeedMod.saveExisting}"
+                                 styleClass="submit" />
+            </li>
+        </s:fragment>
+        <s:fragment rendered="#{!new}">
+            <li>
+                <h:commandButton value="Save only 'Post author' and 'Include category'" action="#{remoteFeedMod.savePartial}"
+                                 styleClass="submit" />
+            </li>
+        </s:fragment>
+        <li>
+            <s:button value="Cancel" view="#{backTo}" propagation="end" styleClass="submit" />
+        </li>
+        <li>
+            <ui:include src="../../common/ajax_status.xhtml" />
+        </li>
+    </ul>
+</s:div>
+
+<s:div id="postsIncluded">
+    <s:fragment rendered="#{remoteFeedMod.parseOk}">
+        <h4>
+            <s:fragment rendered="#{new}">
+                The following posts will be saved initially:
+            </s:fragment>
+            <s:fragment rendered="#{!new}">
+                The following posts will be merged into current posts on the next update, after saving:
+            </s:fragment>
+        </h4>
+
+        <ul>
+            <ui:repeat var="post" value="#{remoteFeedMod.visiblePosts}">
+                <li>#{post.title}</li>
+            </ui:repeat>
+        </ul>
+    </s:fragment>
+</s:div>
+</h:form>
+</div>
 </ui:composition>

Modified: trunk/view/manage/remote/remote_propose.xhtml
===================================================================
--- trunk/view/manage/remote/remote_propose.xhtml	2008-03-17 18:27:06 UTC (rev 270)
+++ trunk/view/manage/remote/remote_propose.xhtml	2008-03-25 13:24:53 UTC (rev 271)
@@ -18,9 +18,8 @@
             <ul>
                 <li>
                     If you are blogging on a JBoss-related subject, you can aggregate your blog on JBoss.ORG!
-                    Very often blogs of the JBoss Community members include very valuable information,
-                    and we'd like to give it more visibility, so that other members of the Community can easily find
-                    it.
+                    Blogs written by the JBoss Community members are very valuable, and we'd like
+                    to make them much more visible!
                 </li>
                 <li>
                     #{messages['blog.feed.remote.adding.quickstart']}
@@ -32,7 +31,8 @@
                 </li>
                 <li>
                     If you are blogging on a wider area of subjects, please submit a feed of only jboss-related
-                    entries (for example a feed of one category/ tag).
+                    entries (for example a feed of one category/ tag), or select a category after parsing the feed
+                    (if category information is included in the entries of the feed).
                 </li>
                 <li class="last">
                     #{messages['blog.feed.remote.mod.authors']}




More information about the jboss-cvs-commits mailing list