[jboss-cvs] JBossBlog SVN: r164 - in trunk: resources/META-INF and 22 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Jan 7 11:29:09 EST 2008


Author: adamw
Date: 2008-01-07 11:29:09 -0500 (Mon, 07 Jan 2008)
New Revision: 164

Added:
   trunk/src/action/org/jboss/blog/session/feed/dao/
   trunk/src/action/org/jboss/blog/session/feed/dao/AggregatedFeedDao.java
   trunk/src/action/org/jboss/blog/session/feed/dao/FeedDao.java
   trunk/src/action/org/jboss/blog/session/feed/dao/RemoteFeedDao.java
   trunk/src/action/org/jboss/blog/session/feed/mod/
   trunk/src/action/org/jboss/blog/session/feed/mod/AggregatedFeedModBean.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/posts/DatabaseFeedPosts.java
   trunk/src/action/org/jboss/blog/session/feed/type/FeedTypes.java
   trunk/src/action/org/jboss/blog/session/feed/update/
   trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java
   trunk/src/action/org/jboss/blog/session/scanner/
   trunk/src/action/org/jboss/blog/session/scanner/AnnotationScanner.java
   trunk/src/action/org/jboss/blog/session/scanner/ClassHandler.java
   trunk/src/action/org/jboss/blog/session/scanner/Init.java
   trunk/src/model/org/jboss/blog/model/feed/
   trunk/src/model/org/jboss/blog/model/feed/AggregatedFeed.java
   trunk/src/model/org/jboss/blog/model/feed/Feed.java
   trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java
   trunk/src/tools/org/jboss/blog/tools/KeyNotMappedException.java
   trunk/src/tools/org/jboss/blog/tools/KeySafeMap.java
Removed:
   trunk/explode.launch
   trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java
   trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedModBean.java
   trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java
   trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedTypeRegisterBean.java
   trunk/src/action/org/jboss/blog/session/feed/posts/DefaultFeedPostsBean.java
   trunk/src/action/org/jboss/blog/session/feed/posts/FeedPosts.java
   trunk/src/action/org/jboss/blog/session/feed/remote/
   trunk/src/action/org/jboss/blog/session/feed/type/AbstractFeedType.java
   trunk/src/action/org/jboss/blog/session/feed/type/FeedTypesBean.java
   trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedModBean.java
   trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedTypeRegisterBean.java
   trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdateBean.java
   trunk/src/model/org/jboss/blog/model/AggregatedFeed.java
   trunk/src/model/org/jboss/blog/model/Feed.java
   trunk/src/model/org/jboss/blog/model/RemoteFeed.java
Modified:
   trunk/blog.iml
   trunk/resources/META-INF/persistence-dev.xml
   trunk/resources/META-INF/persistence-prod.xml
   trunk/src/action/org/jboss/blog/session/converter/FeedConverter.java
   trunk/src/action/org/jboss/blog/session/feed/FeedModBean.java
   trunk/src/action/org/jboss/blog/session/feed/FeedsServiceImpl.java
   trunk/src/action/org/jboss/blog/session/feed/InvalidFeedTypeException.java
   trunk/src/action/org/jboss/blog/session/feed/type/FeedType.java
   trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java
   trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java
   trunk/src/action/org/jboss/blog/session/parser/ParserService.java
   trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java
   trunk/src/action/org/jboss/blog/session/update/UpdateHandlerImpl.java
   trunk/src/action/org/jboss/blog/session/update/UpdateManager.java
   trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java
   trunk/src/action/org/jboss/blog/session/view/LinkServiceBean.java
   trunk/src/action/org/jboss/blog/session/xml/velocity/VelocityXmlService.java
   trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java
   trunk/src/model/org/jboss/blog/model/Post.java
   trunk/src/services/org/jboss/blog/service/FeedsService.java
   trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java
   trunk/view/manage/add.xhtml
   trunk/view/manage/index.xhtml
Log:


Modified: trunk/blog.iml
===================================================================
--- trunk/blog.iml	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/blog.iml	2008-01-07 16:29:09 UTC (rev 164)
@@ -139,6 +139,15 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/lib/javassist.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
     <orderEntryProperties />
   </component>
 </module>

Deleted: trunk/explode.launch
===================================================================
--- trunk/explode.launch	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/explode.launch	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
-	<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
-	<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
-	<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
-	<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="clean,unexplode,restart,buildtest,"/>
-	<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
-	<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-		<listEntry value="1"/>
-	</listAttribute>
-	<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
-	<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-	<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
-	<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
-	<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="clean,unexplode,restart,buildtest,"/>
-	<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="explode,buildtest,"/>
-	<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="blog"/>
-	<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-		<listEntry value="/blog/build.xml"/>
-	</listAttribute>
-	<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/blog/build.xml}"/>
-</launchConfiguration>

Modified: trunk/resources/META-INF/persistence-dev.xml
===================================================================
--- trunk/resources/META-INF/persistence-dev.xml	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/resources/META-INF/persistence-dev.xml	2008-01-07 16:29:09 UTC (rev 164)
@@ -8,9 +8,9 @@
     <persistence-unit name="blog">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
         <jta-data-source>java:/blogDatasource</jta-data-source>
-        <class>org.jboss.blog.model.Feed</class>
-        <class>org.jboss.blog.model.RemoteFeed</class>
-        <class>org.jboss.blog.model.AggregatedFeed</class>
+        <class>org.jboss.blog.model.feed.Feed</class>
+        <class>org.jboss.blog.model.feed.RemoteFeed</class>
+        <class>org.jboss.blog.model.feed.AggregatedFeed</class>
         <class>org.jboss.blog.model.Category</class>
         <class>org.jboss.blog.model.Post</class>
         <class>org.jboss.blog.model.Template</class>

Modified: trunk/resources/META-INF/persistence-prod.xml
===================================================================
--- trunk/resources/META-INF/persistence-prod.xml	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/resources/META-INF/persistence-prod.xml	2008-01-07 16:29:09 UTC (rev 164)
@@ -8,9 +8,9 @@
     <persistence-unit name="blog">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
         <jta-data-source>java:/blogDatasource</jta-data-source>
-        <class>org.jboss.blog.model.Feed</class>
-        <class>org.jboss.blog.model.RemoteFeed</class>
-        <class>org.jboss.blog.model.AggregatedFeed</class>
+        <class>org.jboss.blog.model.feed.Feed</class>
+        <class>org.jboss.blog.model.feed.RemoteFeed</class>
+        <class>org.jboss.blog.model.feed.AggregatedFeed</class>
         <class>org.jboss.blog.model.Category</class>
         <class>org.jboss.blog.model.Post</class>
         <class>org.jboss.blog.model.Template</class>

Modified: trunk/src/action/org/jboss/blog/session/converter/FeedConverter.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/converter/FeedConverter.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/converter/FeedConverter.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.converter;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.service.FeedNotFoundException;
 import org.jboss.seam.Component;
 import org.jboss.seam.annotations.Name;

Modified: trunk/src/action/org/jboss/blog/session/feed/FeedModBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/FeedModBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/FeedModBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.feed;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.model.Template;
 import org.jboss.blog.model.XmlType;

Deleted: trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,11 +0,0 @@
-package org.jboss.blog.session.feed;
-
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.session.update.UpdateException;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
-public interface FeedUpdate {
-    public void update(Feed feed) throws UpdateException;
-}

Modified: trunk/src/action/org/jboss/blog/session/feed/FeedsServiceImpl.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/FeedsServiceImpl.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/FeedsServiceImpl.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,12 +1,10 @@
 package org.jboss.blog.session.feed;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.service.FeedNotFoundException;
 import org.jboss.blog.service.FeedsService;
-import org.jboss.blog.session.feed.type.FeedTypesBean;
-import org.jboss.blog.session.feed.posts.FeedPosts;
-import org.jboss.seam.Component;
+import org.jboss.blog.session.feed.type.FeedTypes;
 import org.jboss.seam.annotations.AutoCreate;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
@@ -28,7 +26,7 @@
     private EntityManager entityManager;
 
     @In
-    private FeedTypesBean feedTypes;
+    private FeedTypes feedTypes;
 
     @SuppressWarnings("unchecked")
     public List<Feed> getAllFeeds() {
@@ -45,9 +43,7 @@
     }
     
     public List<Post> getPosts(Feed feed, int from, int to) {
-        String feedPostsComponentName = feedTypes.getFeedType(feed.getClass()).getFeedPostsComponentName();
-
-        return ((FeedPosts) Component.getInstance(feedPostsComponentName)).getPosts(feed, from, to);
+        return feedTypes.getFeedDao(feed).getPosts(from, to);
     }
 
     public List<Post> getPosts(String feedName, int from, int to) throws FeedNotFoundException {

Modified: trunk/src/action/org/jboss/blog/session/feed/InvalidFeedTypeException.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/InvalidFeedTypeException.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/InvalidFeedTypeException.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -4,4 +4,18 @@
  * @author <a href="mailto:adam at warski.org">Adam Warski</a>
  */
 public class InvalidFeedTypeException extends RuntimeException {
+    public InvalidFeedTypeException() {
+    }
+
+    public InvalidFeedTypeException(String message) {
+        super(message);
+    }
+
+    public InvalidFeedTypeException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public InvalidFeedTypeException(Throwable cause) {
+        super(cause);
+    }
 }

Deleted: trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedModBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedModBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedModBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,120 +0,0 @@
-package org.jboss.blog.session.feed.aggregated;
-
-import org.jboss.blog.model.AggregatedFeed;
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.model.Post;
-import org.jboss.blog.service.FeedsService;
-import org.jboss.blog.session.feed.FeedModBean;
-import org.jboss.blog.session.feed.InvalidFeedTypeException;
-import org.jboss.blog.session.view.LinkServiceBean;
-import org.jboss.blog.tools.GeneralTools;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.faces.FacesMessages;
-import org.jboss.seam.annotations.Create;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-
-import javax.faces.model.SelectItem;
-import javax.faces.application.FacesMessage;
-import javax.persistence.EntityManager;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Scope(ScopeType.CONVERSATION)
- at Name("aggregatedFeedMod")
-public class AggregatedFeedModBean implements Serializable {
-    @In
-    private FeedModBean feedMod;
-
-    @In
-    private EntityManager entityManager;
-
-    @In
-    private FeedsService feedsService;
-    
-    @In
-    private FacesMessages facesMessages;
-
-    @In
-    private LinkServiceBean linkService;
-
-    private AggregatedFeed aggregatedFeed;
-
-    // We have to use SelectItem-s because of a bug with coerce in JSF RI.
-    private List<SelectItem> availableFeeds;
-    private List<String> selectedFeeds;
-
-    public AggregatedFeed getAggregatedFeed() {
-        if (aggregatedFeed == null) {
-            if (feedMod.getFeed() == null) {
-                aggregatedFeed = new AggregatedFeed();
-                aggregatedFeed.setFeeds(new ArrayList<Feed>());
-                aggregatedFeed.setPosts(new ArrayList<Post>());
-
-                feedMod.initNewFeed(aggregatedFeed);
-                aggregatedFeed.setLink(linkService.generateFeedPageLink(aggregatedFeed));
-            } else {
-                if (feedMod.getFeed() instanceof AggregatedFeed) {
-                    aggregatedFeed = (AggregatedFeed) feedMod.getFeed();
-                } else {
-                    throw new InvalidFeedTypeException();
-                }
-            }
-        }
-
-        return aggregatedFeed;
-    }
-
-    @Create
-    public void populateLists() {
-        availableFeeds = new ArrayList<SelectItem>();
-        for (Feed feed : feedsService.getAllFeeds()) {
-            if (!GeneralTools.objectsEquals(getAggregatedFeed().getName(), feed.getName())) {
-                availableFeeds.add(new SelectItem(feed.getName()));
-            }
-        }
-
-        selectedFeeds = new ArrayList<String>();
-        for (Feed feed : getAggregatedFeed().getFeeds()) {
-            selectedFeeds.add(feed.getName());
-        }
-    }
-
-    public List<SelectItem> getAvailableFeeds() {
-        return availableFeeds;
-    }
-
-    public List<String> getSelectedFeeds() {
-        return selectedFeeds;
-    }
-
-    public void setSelectedFeeds(List<String> selectedFeeds) {
-        this.selectedFeeds = selectedFeeds;
-    }
-
-    private void save() {
-        List<Feed> currentAggregatedFeeds = getAggregatedFeed().getFeeds();
-        currentAggregatedFeeds.clear();
-
-        for (String si : getSelectedFeeds()) {
-            currentAggregatedFeeds.add(feedsService.getFeed(si));
-        }
-    }
-
-    public void saveNew() {
-        save();
-    }
-
-    public void saveExisting() {
-        save();
-        entityManager.flush();
-
-        facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "blog.feed.aggregated.updated",
-                getAggregatedFeed().getName());
-    }
-}

Deleted: trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,32 +0,0 @@
-package org.jboss.blog.session.feed.aggregated;
-
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.model.Post;
-import org.jboss.blog.session.feed.posts.FeedPosts;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-
-import javax.persistence.EntityManager;
-import java.util.List;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Name("aggregatedFeedPosts")
- at Scope(ScopeType.STATELESS)
-public class AggregatedFeedPostsBean implements FeedPosts {
-    @In
-    private EntityManager entityManager;
-
-    @SuppressWarnings("unchecked")
-    public List<Post> getPosts(Feed feed, int from, int to) {
-        return entityManager.createQuery(
-                "select post from Post post " +
-                        "where post.feed in " +
-                        "(select feed from AggregatedFeed af, Feed feed where af = ?1 and feed in elements(af.feeds)) " +
-                        "order by post.published desc, post.link")
-                .setParameter(1, feed).setMaxResults(to-from).setFirstResult(from).getResultList();
-    }
-}

Deleted: trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedTypeRegisterBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedTypeRegisterBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedTypeRegisterBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,36 +0,0 @@
-package org.jboss.blog.session.feed.aggregated;
-
-import org.jboss.blog.model.AggregatedFeed;
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.session.feed.type.AbstractFeedType;
-import org.jboss.seam.annotations.Name;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Name("aggregatedFeedTypeRegister")
-public class AggregatedFeedTypeRegisterBean extends AbstractFeedType {
-    public String getName() {
-        return "aggregated";
-    }
-
-    public Class<? extends Feed> getModelClass() {
-        return AggregatedFeed.class;
-    }
-
-    public String getAddPage() {
-        return "/manage/aggregated/aggregated_add.xhtml";
-    }
-
-    public String getEditPage() {
-        return "/manage/aggregated/aggregated_edit.xhtml";
-    }
-
-    public String getFeedPostsComponentName() {
-        return "aggregatedFeedPosts";
-    }
-
-    public String getFeedUpdateComponentName() {
-        return null;
-    }
-}

Added: trunk/src/action/org/jboss/blog/session/feed/dao/AggregatedFeedDao.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/dao/AggregatedFeedDao.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/dao/AggregatedFeedDao.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,34 @@
+package org.jboss.blog.session.feed.dao;
+
+import org.jboss.blog.model.feed.AggregatedFeed;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.session.feed.posts.AggregatedFeedPosts;
+import org.jboss.blog.session.feed.type.FeedType;
+import org.jboss.seam.Component;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at FeedType(
+        name = "aggregated",
+        addPage = "/manage/aggregated/aggregated_add.xhtml",
+        editPage = "/manage/aggregated/aggregated_edit.xhtml",
+        model = AggregatedFeed.class)
+public class AggregatedFeedDao implements FeedDao {
+    private AggregatedFeed aggregatedFeed;
+
+    public AggregatedFeedDao(AggregatedFeed aggregatedFeed) {
+        this.aggregatedFeed = aggregatedFeed;
+    }
+
+    public List<Post> getPosts(int from, int to) {
+        return ((AggregatedFeedPosts) Component.getInstance("aggregatedFeedPosts")).getPosts(
+                aggregatedFeed, from, to);
+    }
+
+    public void update() {
+
+    }
+}

Added: trunk/src/action/org/jboss/blog/session/feed/dao/FeedDao.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/dao/FeedDao.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/dao/FeedDao.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,14 @@
+package org.jboss.blog.session.feed.dao;
+
+import org.jboss.blog.model.Post;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public interface FeedDao {
+    public List<Post> getPosts(int from, int to);
+
+    public void update();
+}

Added: trunk/src/action/org/jboss/blog/session/feed/dao/RemoteFeedDao.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/dao/RemoteFeedDao.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/dao/RemoteFeedDao.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,35 @@
+package org.jboss.blog.session.feed.dao;
+
+import org.jboss.blog.model.feed.RemoteFeed;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.session.feed.posts.DatabaseFeedPosts;
+import org.jboss.blog.session.feed.type.FeedType;
+import org.jboss.blog.session.feed.update.RemoteFeedUpdate;
+import org.jboss.seam.Component;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at FeedType(
+        name = "remote",
+        addPage = "/manage/remote/remote_add.xhtml",
+        editPage = "/manage/remote/remote_edit.xhtml",
+        model = RemoteFeed.class)
+public class RemoteFeedDao implements FeedDao {
+    private RemoteFeed remoteFeed;
+
+    public RemoteFeedDao(RemoteFeed remoteFeed) {
+        this.remoteFeed = remoteFeed;
+    }
+
+    public List<Post> getPosts(int from, int to) {
+        return ((DatabaseFeedPosts) Component.getInstance("databaseFeedPosts")).getPosts(
+                remoteFeed, from, to);
+    }
+
+    public void update() {
+        ((RemoteFeedUpdate) Component.getInstance("remoteFeedUpdate")).update(remoteFeed);
+    }
+}

Copied: trunk/src/action/org/jboss/blog/session/feed/mod/AggregatedFeedModBean.java (from rev 159, trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedModBean.java)
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/mod/AggregatedFeedModBean.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/mod/AggregatedFeedModBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,120 @@
+package org.jboss.blog.session.feed.mod;
+
+import org.jboss.blog.model.feed.AggregatedFeed;
+import org.jboss.blog.model.feed.Feed;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.service.FeedsService;
+import org.jboss.blog.session.feed.FeedModBean;
+import org.jboss.blog.session.feed.InvalidFeedTypeException;
+import org.jboss.blog.session.view.LinkServiceBean;
+import org.jboss.blog.tools.GeneralTools;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.faces.FacesMessages;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+
+import javax.faces.model.SelectItem;
+import javax.faces.application.FacesMessage;
+import javax.persistence.EntityManager;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Scope(ScopeType.CONVERSATION)
+ at Name("aggregatedFeedMod")
+public class AggregatedFeedModBean implements Serializable {
+    @In
+    private FeedModBean feedMod;
+
+    @In
+    private EntityManager entityManager;
+
+    @In
+    private FeedsService feedsService;
+    
+    @In
+    private FacesMessages facesMessages;
+
+    @In
+    private LinkServiceBean linkService;
+
+    private AggregatedFeed aggregatedFeed;
+
+    // We have to use SelectItem-s because of a bug with coerce in JSF RI.
+    private List<SelectItem> availableFeeds;
+    private List<String> selectedFeeds;
+
+    public AggregatedFeed getAggregatedFeed() {
+        if (aggregatedFeed == null) {
+            if (feedMod.getFeed() == null) {
+                aggregatedFeed = new AggregatedFeed();
+                aggregatedFeed.setFeeds(new ArrayList<Feed>());
+                aggregatedFeed.setPosts(new ArrayList<Post>());
+
+                feedMod.initNewFeed(aggregatedFeed);
+                aggregatedFeed.setLink(linkService.generateFeedPageLink(aggregatedFeed));
+            } else {
+                if (feedMod.getFeed() instanceof AggregatedFeed) {
+                    aggregatedFeed = (AggregatedFeed) feedMod.getFeed();
+                } else {
+                    throw new InvalidFeedTypeException();
+                }
+            }
+        }
+
+        return aggregatedFeed;
+    }
+
+    @Create
+    public void populateLists() {
+        availableFeeds = new ArrayList<SelectItem>();
+        for (Feed feed : feedsService.getAllFeeds()) {
+            if (!GeneralTools.objectsEquals(getAggregatedFeed().getName(), feed.getName())) {
+                availableFeeds.add(new SelectItem(feed.getName()));
+            }
+        }
+
+        selectedFeeds = new ArrayList<String>();
+        for (Feed feed : getAggregatedFeed().getFeeds()) {
+            selectedFeeds.add(feed.getName());
+        }
+    }
+
+    public List<SelectItem> getAvailableFeeds() {
+        return availableFeeds;
+    }
+
+    public List<String> getSelectedFeeds() {
+        return selectedFeeds;
+    }
+
+    public void setSelectedFeeds(List<String> selectedFeeds) {
+        this.selectedFeeds = selectedFeeds;
+    }
+
+    private void save() {
+        List<Feed> currentAggregatedFeeds = getAggregatedFeed().getFeeds();
+        currentAggregatedFeeds.clear();
+
+        for (String si : getSelectedFeeds()) {
+            currentAggregatedFeeds.add(feedsService.getFeed(si));
+        }
+    }
+
+    public void saveNew() {
+        save();
+    }
+
+    public void saveExisting() {
+        save();
+        entityManager.flush();
+
+        facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "blog.feed.aggregated.updated",
+                getAggregatedFeed().getName());
+    }
+}

Copied: trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java (from rev 159, trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedModBean.java)
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/mod/RemoteFeedModBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,108 @@
+package org.jboss.blog.session.feed.mod;
+
+import org.jboss.blog.model.feed.Feed;
+import org.jboss.blog.model.feed.RemoteFeed;
+import org.jboss.blog.session.feed.FeedModBean;
+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.seam.ScopeType;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.faces.FacesMessages;
+
+import javax.faces.application.FacesMessage;
+import javax.persistence.EntityManager;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Scope(ScopeType.CONVERSATION)
+ at Name("remoteFeedMod")
+public class RemoteFeedModBean implements Serializable {
+    @In
+    private ParserService parserService;
+
+    @In
+    private FeedModBean feedMod;
+
+    @In
+    private EntityManager entityManager;
+
+    @In
+    private FacesMessages facesMessages;
+
+    private RemoteFeed remoteFeed;
+
+    private Feed parsedFeed;
+
+    private boolean parseOk;
+    private Exception parseException;
+
+    public RemoteFeed getRemoteFeed() {
+        if (remoteFeed == null) {
+            if (feedMod.getFeed() == null) {
+                remoteFeed = new RemoteFeed();
+                feedMod.initNewFeed(remoteFeed);
+
+                if (StringTools.isEmpty(remoteFeed.getLink())) {
+                    remoteFeed.setLink(remoteFeed.getRemoteLink());
+                }
+            } else {
+                if (feedMod.getFeed() instanceof RemoteFeed) {
+                    remoteFeed = (RemoteFeed) feedMod.getFeed();
+                } else {
+                    throw new InvalidFeedTypeException();
+                }
+            }
+        }
+
+        return remoteFeed;
+    }
+
+    public boolean isParseOk() {
+        return parseOk;
+    }
+
+    public void setParseOk(boolean parseOk) {
+        this.parseOk = parseOk;
+    }
+
+    public Exception getParseException() {
+        return parseException;
+    }
+
+    public void setParseException(Exception parseException) {
+        this.parseException = parseException;
+    }
+
+    public void parseFeed() {
+        try {
+            parsedFeed = parserService.parse(getRemoteFeed().getRemoteLink());
+            setParseOk(true);
+        } catch (ParserException e) {
+            setParseException(e);
+            setParseOk(false);
+        }
+    }
+
+    public void saveNew() {
+        getRemoteFeed().setAuthor(parsedFeed.getAuthor());
+        getRemoteFeed().setDescription(parsedFeed.getDescription());
+        getRemoteFeed().setLink(parsedFeed.getLink());
+        getRemoteFeed().setPosts(parsedFeed.getPosts());
+        getRemoteFeed().setTitle(parsedFeed.getTitle());
+    }
+
+    public void saveExisting() {
+        getRemoteFeed().setLink(parsedFeed.getLink());
+
+        entityManager.flush();
+
+        facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "blog.feed.remote.updated",
+                getRemoteFeed().getName());
+    }
+}

Copied: trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java (from rev 161, trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java)
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/posts/AggregatedFeedPosts.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,31 @@
+package org.jboss.blog.session.feed.posts;
+
+import org.jboss.blog.model.feed.AggregatedFeed;
+import org.jboss.blog.model.Post;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Name("aggregatedFeedPosts")
+ at Scope(ScopeType.STATELESS)
+public class AggregatedFeedPosts {
+    @In
+    private EntityManager entityManager;
+
+    @SuppressWarnings("unchecked")
+    public List<Post> getPosts(AggregatedFeed feed, int from, int to) {
+        return entityManager.createQuery(
+                "select post from Post post " +
+                        "where post.feed in " +
+                        "(select feed from AggregatedFeed af, Feed feed where af = ?1 and feed in elements(af.feeds)) " +
+                        "order by post.published desc, post.link")
+                .setParameter(1, feed).setMaxResults(to-from).setFirstResult(from).getResultList();
+    }
+}

Copied: trunk/src/action/org/jboss/blog/session/feed/posts/DatabaseFeedPosts.java (from rev 161, trunk/src/action/org/jboss/blog/session/feed/posts/DefaultFeedPostsBean.java)
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/posts/DatabaseFeedPosts.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/posts/DatabaseFeedPosts.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,28 @@
+package org.jboss.blog.session.feed.posts;
+
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.ScopeType;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.model.feed.Feed;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Name("databaseFeedPosts")
+ at Scope(ScopeType.STATELESS)
+public class DatabaseFeedPosts {
+    @In
+    private EntityManager entityManager;
+
+    @SuppressWarnings("unchecked")
+    public List<Post> getPosts(Feed feed, int from, int to) {
+        return (List<Post>) entityManager.createQuery(
+                "select post from Post post where post.feed = ?1 order by post.published desc, post.link")
+                .setParameter(1, feed).setMaxResults(to-from).setFirstResult(from).getResultList();
+    }
+}

Deleted: trunk/src/action/org/jboss/blog/session/feed/posts/DefaultFeedPostsBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/posts/DefaultFeedPostsBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/posts/DefaultFeedPostsBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,28 +0,0 @@
-package org.jboss.blog.session.feed.posts;
-
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.ScopeType;
-import org.jboss.blog.model.Post;
-import org.jboss.blog.model.Feed;
-
-import javax.persistence.EntityManager;
-import java.util.List;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Name("defaultFeedPosts")
- at Scope(ScopeType.STATELESS)
-public class DefaultFeedPostsBean implements FeedPosts {
-    @In
-    private EntityManager entityManager;
-
-    @SuppressWarnings("unchecked")
-    public List<Post> getPosts(Feed feed, int from, int to) {
-        return (List<Post>) entityManager.createQuery(
-                "select post from Post post where post.feed = ?1 order by post.published desc, post.link")
-                .setParameter(1, feed).setMaxResults(to-from).setFirstResult(from).getResultList();
-    }
-}

Deleted: trunk/src/action/org/jboss/blog/session/feed/posts/FeedPosts.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/posts/FeedPosts.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/posts/FeedPosts.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,13 +0,0 @@
-package org.jboss.blog.session.feed.posts;
-
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.model.Post;
-
-import java.util.List;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
-public interface FeedPosts {
-    public List<Post> getPosts(Feed feed, int from, int to);
-}

Deleted: trunk/src/action/org/jboss/blog/session/feed/type/AbstractFeedType.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/type/AbstractFeedType.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/type/AbstractFeedType.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,17 +0,0 @@
-package org.jboss.blog.session.feed.type;
-
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Observer;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
-public abstract class AbstractFeedType implements FeedType {
-    @In
-    private FeedTypesBean feedTypes;
-
-    @Observer("org.jboss.seam.postInitialization")
-    public void register() {
-        feedTypes.registerType(this);
-    }
-}

Modified: trunk/src/action/org/jboss/blog/session/feed/type/FeedType.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/type/FeedType.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/type/FeedType.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,16 +1,22 @@
 package org.jboss.blog.session.feed.type;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
 /**
  * @author <a href="mailto:adam at warski.org">Adam Warski</a>
  */
-public interface FeedType {
-    public String getName();
-    public Class<? extends Feed> getModelClass();
-    public String getAddPage();
-    public String getEditPage();
-    
-    public String getFeedPostsComponentName();
-    public String getFeedUpdateComponentName();
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface FeedType {
+    public String name();
+    public Class<? extends Feed> model();
+    public String addPage();
+    public String editPage();
+
+    //public String feedUpdateComponentName();
 }

Copied: trunk/src/action/org/jboss/blog/session/feed/type/FeedTypes.java (from rev 161, trunk/src/action/org/jboss/blog/session/feed/type/FeedTypesBean.java)
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/type/FeedTypes.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/type/FeedTypes.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,94 @@
+package org.jboss.blog.session.feed.type;
+
+import org.jboss.blog.model.feed.Feed;
+import org.jboss.blog.session.feed.InvalidFeedTypeException;
+import org.jboss.blog.session.feed.dao.FeedDao;
+import org.jboss.blog.session.scanner.ClassHandler;
+import org.jboss.blog.tools.KeySafeMap;
+import org.jboss.blog.tools.KeyNotMappedException;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.log.Log;
+import org.jboss.seam.annotations.*;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Name("feedTypes")
+ at Scope(ScopeType.APPLICATION)
+ at AutoCreate
+public class FeedTypes implements ClassHandler {
+    @Logger
+    private Log log;
+
+    private Map<Class<? extends Feed>, FeedType> feedTypes;
+    private Map<Class<? extends Feed>, Constructor<? extends FeedDao>> feedDaos;
+
+    public FeedTypes() {
+        feedTypes = KeySafeMap.wrap(new ConcurrentHashMap<Class<? extends Feed>, FeedType>());
+        feedDaos = KeySafeMap.wrap(new ConcurrentHashMap<Class<? extends Feed>, Constructor<? extends FeedDao>>());
+    }
+
+    public FeedType[] getAllTypes() {
+        return feedTypes.values().toArray(new FeedType[feedTypes.size()]);
+    }
+
+    public FeedType getFeedType(Feed feed) throws InvalidFeedTypeException {
+        try {
+            return feedTypes.get(feed.getClass());
+        } catch (KeyNotMappedException e) {
+            throw new InvalidFeedTypeException(feed.getClass().getName());
+        }
+    }
+
+    public FeedDao getFeedDao(Feed feed) {
+        try {
+            return feedDaos.get(feed.getClass()).newInstance(feed);
+        } catch (InstantiationException e) {
+            throw new RuntimeException(e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException(e);
+        } catch (KeyNotMappedException e) {
+            throw new InvalidFeedTypeException(feed.getClass().getName());
+        }
+    }
+
+    private void registerDao(Class<? extends FeedDao> daoClass) {
+        FeedType feedType = daoClass.getAnnotation(FeedType.class);
+
+        if (feedType == null) {
+            throw new IllegalArgumentException(
+                    "Feed dao class: " + daoClass.getName() + " isn't annotated with @FeedType.");
+        }
+
+        Constructor<? extends FeedDao> constructor;
+        try {
+            constructor = daoClass.getConstructor(feedType.model());
+        } catch (NoSuchMethodException e) {
+            log.error("Feed dao class: " + daoClass.getName() + " doesn't define a one-arg constructor (" +
+                    feedType.model().getName() + "), as the @FeedType annotation states.");
+            return;
+        }
+
+        log.info("Registering feed dao class: ", daoClass.getName(), ".");
+
+        feedDaos.put(feedType.model(), constructor);
+        feedTypes.put(feedType.model(), feedType);
+    }
+
+    public void handleClass(Class<?> toHandle) {
+        if (FeedDao.class.isAssignableFrom(toHandle)) {
+            //noinspection unchecked
+            registerDao((Class<? extends FeedDao>) toHandle);
+        } else {
+            log.error("Class " + toHandle.getName() + " is annotated with @FeedType but doesn't implement the " +
+                    "FeedDao interface.");
+        }
+    }
+}

Deleted: trunk/src/action/org/jboss/blog/session/feed/type/FeedTypesBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/type/FeedTypesBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/feed/type/FeedTypesBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,42 +0,0 @@
-package org.jboss.blog.session.feed.type;
-
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.session.feed.InvalidFeedTypeException;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.AutoCreate;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Name("feedTypes")
- at Scope(ScopeType.APPLICATION)
- at AutoCreate
-public class FeedTypesBean {
-    private Map<Class<? extends Feed>, FeedType> feedTypes;
-
-    public FeedTypesBean() {
-        feedTypes = new ConcurrentHashMap<Class<? extends Feed>, FeedType>();
-    }
-
-    public void registerType(FeedType feedType) {
-        feedTypes.put(feedType.getModelClass(), feedType);
-    }
-
-    public FeedType[] getAllTypes() {
-        return feedTypes.values().toArray(new FeedType[feedTypes.size()]);
-    }
-
-    public FeedType getFeedType(Class<? extends Feed> c) throws InvalidFeedTypeException {
-        FeedType entry = feedTypes.get(c);
-        if (entry == null) {
-            throw new InvalidFeedTypeException();
-        }
-
-        return entry;
-    }
-}

Copied: trunk/src/action/org/jboss/blog/session/feed/update (from rev 159, trunk/src/action/org/jboss/blog/session/feed/remote)

Deleted: trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedModBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedModBean.java	2007-12-10 11:16:30 UTC (rev 159)
+++ trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedModBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,108 +0,0 @@
-package org.jboss.blog.session.feed.remote;
-
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.model.RemoteFeed;
-import org.jboss.blog.session.feed.FeedModBean;
-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.seam.ScopeType;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.faces.FacesMessages;
-
-import javax.faces.application.FacesMessage;
-import javax.persistence.EntityManager;
-import java.io.Serializable;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Scope(ScopeType.CONVERSATION)
- at Name("remoteFeedMod")
-public class RemoteFeedModBean implements Serializable {
-    @In
-    private ParserService parserService;
-
-    @In
-    private FeedModBean feedMod;
-
-    @In
-    private EntityManager entityManager;
-
-    @In
-    private FacesMessages facesMessages;
-
-    private RemoteFeed remoteFeed;
-
-    private Feed parsedFeed;
-
-    private boolean parseOk;
-    private Exception parseException;
-
-    public RemoteFeed getRemoteFeed() {
-        if (remoteFeed == null) {
-            if (feedMod.getFeed() == null) {
-                remoteFeed = new RemoteFeed();
-                feedMod.initNewFeed(remoteFeed);
-
-                if (StringTools.isEmpty(remoteFeed.getLink())) {
-                    remoteFeed.setLink(remoteFeed.getRemoteLink());
-                }
-            } else {
-                if (feedMod.getFeed() instanceof RemoteFeed) {
-                    remoteFeed = (RemoteFeed) feedMod.getFeed();
-                } else {
-                    throw new InvalidFeedTypeException();
-                }
-            }
-        }
-
-        return remoteFeed;
-    }
-
-    public boolean isParseOk() {
-        return parseOk;
-    }
-
-    public void setParseOk(boolean parseOk) {
-        this.parseOk = parseOk;
-    }
-
-    public Exception getParseException() {
-        return parseException;
-    }
-
-    public void setParseException(Exception parseException) {
-        this.parseException = parseException;
-    }
-
-    public void parseFeed() {
-        try {
-            parsedFeed = parserService.parse(getRemoteFeed().getRemoteLink());
-            setParseOk(true);
-        } catch (ParserException e) {
-            setParseException(e);
-            setParseOk(false);
-        }
-    }
-
-    public void saveNew() {
-        getRemoteFeed().setAuthor(parsedFeed.getAuthor());
-        getRemoteFeed().setDescription(parsedFeed.getDescription());
-        getRemoteFeed().setLink(parsedFeed.getLink());
-        getRemoteFeed().setPosts(parsedFeed.getPosts());
-        getRemoteFeed().setTitle(parsedFeed.getTitle());
-    }
-
-    public void saveExisting() {
-        getRemoteFeed().setLink(parsedFeed.getLink());
-
-        entityManager.flush();
-
-        facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "blog.feed.remote.updated",
-                getRemoteFeed().getName());
-    }
-}

Deleted: trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedTypeRegisterBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedTypeRegisterBean.java	2007-12-10 11:16:30 UTC (rev 159)
+++ trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedTypeRegisterBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,47 +0,0 @@
-package org.jboss.blog.session.feed.remote;
-
-import org.jboss.blog.model.RemoteFeed;
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.session.feed.FeedType;
-import org.jboss.blog.session.feed.FeedTypesBean;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Observer;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Name("remoteFeedTypeRegister")
-public class RemoteFeedTypeRegisterBean implements FeedType {
-    public String getName() {
-        return "remote";
-    }
-
-    public Class<? extends Feed> getModelClass() {
-        return RemoteFeed.class;
-    }
-
-    public String getAddPage() {
-        return "/manage/remote/remote_add.xhtml";
-    }
-
-    public String getEditPage() {
-        return "/manage/remote/remote_edit.xhtml";
-    }
-
-    public String getFeedPostsComponentName() {
-        return null;
-    }
-
-    public String getFeedUpdateComponentName() {
-        return "remoteFeedUpdate";
-    }
-
-    @In
-    private FeedTypesBean feedTypes;
-
-    @Observer("org.jboss.seam.postInitialization")
-    public void register() {
-        feedTypes.registerType(this);
-    }
-}

Added: trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdate.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,36 @@
+package org.jboss.blog.session.feed.update;
+
+import org.jboss.blog.model.feed.Feed;
+import org.jboss.blog.model.feed.RemoteFeed;
+import org.jboss.blog.session.parser.ParserException;
+import org.jboss.blog.session.parser.ParserService;
+import org.jboss.blog.session.merge.MergeServiceBean;
+import org.jboss.blog.session.update.UpdateException;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Name("remoteFeedUpdate")
+ at Scope(ScopeType.STATELESS)
+public class RemoteFeedUpdate {
+    @In
+    private ParserService parserService;
+
+    @In
+    private MergeServiceBean mergeService;
+
+    public void update(RemoteFeed feed) throws UpdateException {
+        Feed parsedFeed;
+        try {
+            parsedFeed = parserService.parse(feed.getRemoteLink());
+        } catch (ParserException e) {
+            throw new UpdateException(e);
+        }
+
+        mergeService.merge(feed, parsedFeed.getPosts());
+    }
+}

Deleted: trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdateBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedUpdateBean.java	2007-12-10 11:16:30 UTC (rev 159)
+++ trunk/src/action/org/jboss/blog/session/feed/update/RemoteFeedUpdateBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,44 +0,0 @@
-package org.jboss.blog.session.feed.remote;
-
-import org.jboss.blog.model.Feed;
-import org.jboss.blog.model.RemoteFeed;
-import org.jboss.blog.session.feed.FeedUpdate;
-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.session.merge.MergeServiceBean;
-import org.jboss.blog.session.update.UpdateException;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Name("remoteFeedUpdate")
- at Scope(ScopeType.STATELESS)
-public class RemoteFeedUpdateBean implements FeedUpdate {
-    @In
-    private ParserService parserService;
-
-    @In
-    private MergeServiceBean mergeService;
-
-    public void update(Feed feed) throws UpdateException {
-        if (!(feed instanceof RemoteFeed)) {
-            throw new InvalidFeedTypeException();
-        }
-
-        RemoteFeed remoteFeed = (RemoteFeed) feed;
-
-        Feed parsedFeed;
-        try {
-            parsedFeed = parserService.parse(remoteFeed.getRemoteLink());
-        } catch (ParserException e) {
-            throw new UpdateException(e);
-        }
-
-        mergeService.merge(remoteFeed, parsedFeed.getPosts());
-    }
-}

Modified: trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.merge;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.service.FeedsService;
 

Modified: trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.merge;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.service.FeedsService;
 import org.jboss.blog.tools.GeneralTools;

Modified: trunk/src/action/org/jboss/blog/session/parser/ParserService.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/parser/ParserService.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/parser/ParserService.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.parser;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 
 import javax.ejb.Local;
 

Modified: trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -8,7 +8,7 @@
 import com.sun.syndication.io.SyndFeedInput;
 import com.sun.syndication.io.XmlReader;
 import org.jboss.blog.model.Category;
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.session.category.CategoryServiceBean;
 import org.jboss.blog.tools.StringTools;

Added: trunk/src/action/org/jboss/blog/session/scanner/AnnotationScanner.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/scanner/AnnotationScanner.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/scanner/AnnotationScanner.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,173 @@
+package org.jboss.blog.session.scanner;
+
+import org.jboss.seam.log.Logging;
+import org.jboss.seam.log.Log;
+
+import java.lang.annotation.Annotation;
+import java.util.Map;
+import java.util.Enumeration;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.DataInputStream;
+
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.AnnotationsAttribute;
+
+/**
+ * Almost the same as {@link org.jboss.seam.deployment.Scanner}.
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class AnnotationScanner {
+    private static final Log log = Logging.getLog(AnnotationScanner.class);
+
+    private ClassLoader classLoader;
+    private Map<Class<? extends Annotation>, ClassHandler> handlers;
+
+    public AnnotationScanner(ClassLoader classLoader, Map<Class<? extends Annotation>, ClassHandler> handlers) {
+        this.classLoader = classLoader;
+        this.handlers = handlers;
+
+        
+    }
+
+    private void addParentURLsOfResource(Set<String> urlPaths, String resourceName) throws IOException {
+        Enumeration<URL> urlEnum = classLoader.getResources(resourceName);
+        while (urlEnum.hasMoreElements()) {
+            String urlPath = urlEnum.nextElement().getFile();
+            urlPath = URLDecoder.decode(urlPath, "UTF-8");
+
+            if (urlPath.startsWith("file:")) {
+                // On windows urlpath looks like file:/C: on Linux file:/home
+                // substring(5) works for both
+                urlPath = urlPath.substring(5);
+            }
+
+            if (urlPath.indexOf('!') > 0) {
+                urlPath = urlPath.substring(0, urlPath.indexOf('!'));
+            } else {
+                File dirOrArchive = new File(urlPath);
+                if (resourceName != null && resourceName.lastIndexOf('/') > 0) {
+                    dirOrArchive = dirOrArchive.getParentFile();
+                }
+
+                urlPath = dirOrArchive.getParent();
+            }
+
+            String dirOrArchiveName;
+            if (urlPath.lastIndexOf('/') != 0) {
+                dirOrArchiveName = urlPath.substring(urlPath.lastIndexOf('/') + 1);
+            } else {
+                dirOrArchiveName = urlPath;
+            }
+
+            if (dirOrArchiveName.contains("blog")) {
+                urlPaths.add(urlPath);
+            }
+        }
+    }
+
+    private Set<String> getUrlPaths() throws IOException {
+        Set<String> urlPaths = new HashSet<String>();
+
+        addParentURLsOfResource(urlPaths, "seam.properties");
+        addParentURLsOfResource(urlPaths, "META-INF/seam.properties");
+        addParentURLsOfResource(urlPaths, "META-INF/components.xml");
+
+        return urlPaths;
+    }
+
+    public void scan() {
+        Set<String> urlPaths;
+
+        try {
+            urlPaths = getUrlPaths();
+        } catch (IOException e) {
+            log.error("Error obtaining url paths.", e);
+            return;
+        }
+
+        for (String urlPath : urlPaths) {
+            try {
+                File file = new File(urlPath);
+
+                if (file.isDirectory()) {
+                    scanDirectory(file, null);
+                } else {
+                    scanArchive(file);
+                }
+            } catch (IOException e) {
+                log.error("Error while scanning url: " + urlPath, e);
+            }
+        }
+    }
+
+    private void scanArchive(File file) throws IOException {
+        ZipFile zipFile = new ZipFile(file);
+        Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
+
+        while (zipEntries.hasMoreElements()) {
+            ZipEntry zipEntry = zipEntries.nextElement();
+
+            scanItem(zipEntry.getName());
+        }
+    }
+
+    private void scanDirectory(File file, String relativePath) throws IOException {
+        for (File child : file.listFiles()) {
+            String newRealtivePath = relativePath == null ? child.getName() : relativePath + "/" + child.getName();
+
+            if (child.isDirectory()) {
+                scanDirectory(child, newRealtivePath);
+            } else {
+                scanItem(newRealtivePath);
+            }
+        }
+    }
+
+    private ClassFile getClassFile(String name) throws IOException
+    {
+        InputStream stream = classLoader.getResourceAsStream(name);
+        DataInputStream dstream = new DataInputStream(stream);
+
+        try {
+            return new ClassFile(dstream);
+        } finally {
+            dstream.close();
+            stream.close();
+        }
+    }
+
+    private String filenameToClassname(String filename) {
+        return filename.substring(0, filename.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
+    }
+
+    private void scanItem(String name) throws IOException {
+        if (name.endsWith(".class")) {
+            ClassFile classFile = getClassFile(name);
+
+            AnnotationsAttribute visibleAnnotations = (AnnotationsAttribute)
+                    classFile.getAttribute(AnnotationsAttribute.visibleTag);
+
+            if (visibleAnnotations == null) {
+                return;
+            }
+
+            for (Map.Entry<Class<? extends Annotation>, ClassHandler> entry : handlers.entrySet()) {
+                if (visibleAnnotations.getAnnotation(entry.getKey().getName()) != null) {
+                    try {
+                        entry.getValue().handleClass(classLoader.loadClass(filenameToClassname(name)));
+                    } catch (ClassNotFoundException e) {
+                        log.error("Error while loading class.", e);
+                    }
+                }
+            }
+        }
+    }
+}

Added: trunk/src/action/org/jboss/blog/session/scanner/ClassHandler.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/scanner/ClassHandler.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/scanner/ClassHandler.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,8 @@
+package org.jboss.blog.session.scanner;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public interface ClassHandler {
+    public void handleClass(Class<?> toHandle);
+}

Added: trunk/src/action/org/jboss/blog/session/scanner/Init.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/scanner/Init.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/scanner/Init.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,34 @@
+package org.jboss.blog.session.scanner;
+
+import org.jboss.seam.annotations.*;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.core.Events;
+import org.jboss.blog.session.feed.type.FeedType;
+import org.jboss.blog.session.feed.type.FeedTypes;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.annotation.Annotation;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Name("blogInit")
+ at Scope(ScopeType.APPLICATION)
+ at AutoCreate
+public class Init {
+    @In
+    private FeedTypes feedTypes;
+
+    @Observer("org.jboss.seam.postInitialization")
+    public void scanForBlogAnnotations() {
+        Map<Class<? extends Annotation>, ClassHandler> handlers =
+                new HashMap<Class<? extends Annotation>, ClassHandler>();
+        
+        handlers.put(FeedType.class, feedTypes);
+
+        new AnnotationScanner(Thread.currentThread().getContextClassLoader(), handlers).scan();
+
+        Events.instance().raiseEvent("org.jboss.blog.postBlogInit");                
+    }
+}

Modified: trunk/src/action/org/jboss/blog/session/update/UpdateHandlerImpl.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/update/UpdateHandlerImpl.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/update/UpdateHandlerImpl.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,10 +1,8 @@
 package org.jboss.blog.session.update;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.service.FeedsService;
-import org.jboss.blog.session.feed.type.FeedTypesBean;
-import org.jboss.blog.session.feed.FeedUpdate;
-import org.jboss.seam.Component;
+import org.jboss.blog.session.feed.type.FeedTypes;
 import org.jboss.seam.annotations.AutoCreate;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
@@ -24,15 +22,12 @@
     private FeedsService feedsService;
 
     @In
-    private FeedTypesBean feedTypes;
+    private FeedTypes feedTypes;
 
     public void update(Date expiration, long interval) {
         for (Feed feed : feedsService.getAllFeeds()) {
-            String feedUpdateComponentName = feedTypes.getFeedType(feed.getClass()).getFeedUpdateComponentName();
-            if (feedUpdateComponentName != null) {
-                ((FeedUpdate) Component.getInstance(feedUpdateComponentName)).update(feed);
-            }
-        }
+            feedTypes.getFeedDao(feed).update();
+        } 
     }
 
     @Remove

Modified: trunk/src/action/org/jboss/blog/session/update/UpdateManager.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/update/UpdateManager.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/update/UpdateManager.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,10 +1,7 @@
 package org.jboss.blog.session.update;
 
 import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Observer;
-import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.*;
 
 import java.util.Date;
 
@@ -17,7 +14,7 @@
     @In 
     private UpdateHandler updateHandler;
 
-    @Observer("org.jboss.seam.postInitialization")
+    @Observer("org.jboss.blog.postBlogInit")
     public void register() {
         updateHandler.update(new Date(), 60000 * 15);
     }

Modified: trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.view;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.service.FeedsService;
 import org.jboss.seam.ScopeType;

Modified: trunk/src/action/org/jboss/blog/session/view/LinkServiceBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/view/LinkServiceBean.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/view/LinkServiceBean.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.view;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.model.XmlType;
 import org.jboss.seam.ScopeType;

Modified: trunk/src/action/org/jboss/blog/session/xml/velocity/VelocityXmlService.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/xml/velocity/VelocityXmlService.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/xml/velocity/VelocityXmlService.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -3,7 +3,7 @@
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.model.XmlType;
 import org.jboss.blog.service.FeedsService;
@@ -17,7 +17,6 @@
 
 import javax.ejb.Remove;
 import javax.ejb.Stateless;
-import javax.persistence.EntityManager;
 import javax.servlet.ServletResponse;
 import javax.annotation.PostConstruct;
 import java.util.List;

Modified: trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.session.xml.velocity.tools;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.model.XmlType;
 import org.jboss.blog.session.view.LinkServiceBean;

Deleted: trunk/src/model/org/jboss/blog/model/AggregatedFeed.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/AggregatedFeed.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/model/org/jboss/blog/model/AggregatedFeed.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,23 +0,0 @@
-package org.jboss.blog.model;
-
-import javax.persistence.Entity;
-import javax.persistence.ManyToMany;
-import javax.persistence.Transient;
-import java.util.List;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Entity
-public class AggregatedFeed extends Feed {
-    @ManyToMany
-    private List<Feed> feeds;
-
-    public List<Feed> getFeeds() {
-        return feeds;
-    }
-
-    public void setFeeds(List<Feed> feeds) {
-        this.feeds = feeds;
-    }
-}

Deleted: trunk/src/model/org/jboss/blog/model/Feed.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/Feed.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/model/org/jboss/blog/model/Feed.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,163 +0,0 @@
-package org.jboss.blog.model;
-
-import org.hibernate.validator.Length;
-import org.hibernate.validator.NotEmpty;
-import org.hibernate.validator.Pattern;
-
-import javax.persistence.*;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Entity
- at Inheritance(strategy = InheritanceType.SINGLE_TABLE)
-public class Feed {
-    @Id
-    @GeneratedValue
-    @Column(updatable = false)
-    private Integer id;
-
-    @NotEmpty
-    @Length(max = 16)
-    @Column(unique = true)
-    @Pattern(regex = "^[a-z0-9_]*$", message = "#{messages['blog.feed.new.invalidname']}")
-    private String name;
-
-    @NotEmpty
-    @Length(max = 512)
-    private String title;
-
-    @Length(max = 256)
-    private String author;
-
-    @Length(max = 512)
-    @NotEmpty
-    private String link;
-
-    @OneToMany(cascade = {CascadeType.REMOVE}, mappedBy = "feed")
-    private List<Post> posts;
-
-    @Lob
-    private String description;
-
-    @ManyToMany
-    private Map<XmlType, Template> templates;
-
-    @Column
-    private int maxPostsInFeed;
-
-    @Column
-    private boolean useBlogAuthorInPosts;
-
-    @Column
-    private int maxPostsOnPage;
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-    public String getAuthor() {
-        return author;
-    }
-
-    public void setAuthor(String author) {
-        this.author = author;
-    }
-
-    public String getLink() {
-        return link;
-    }
-
-    public void setLink(String link) {
-        this.link = link;
-    }
-
-    public List<Post> getPosts() {
-        return posts;
-    }
-
-    public void setPosts(List<Post> posts) {
-        this.posts = posts;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public Map<XmlType, Template> getTemplates() {
-        return templates;
-    }
-
-    public void setTemplates(Map<XmlType, Template> templates) {
-        this.templates = templates;
-    }
-
-    public int getMaxPostsInFeed() {
-        return maxPostsInFeed;
-    }
-
-    public void setMaxPostsInFeed(int maxPostsInFeed) {
-        this.maxPostsInFeed = maxPostsInFeed;
-    }
-
-    public int getMaxPostsOnPage() {
-        return maxPostsOnPage;
-    }
-
-    public void setMaxPostsOnPage(int maxPostsOnPage) {
-        this.maxPostsOnPage = maxPostsOnPage;
-    }
-
-    public boolean isUseBlogAuthorInPosts() {
-        return useBlogAuthorInPosts;
-    }
-
-    public void setUseBlogAuthorInPosts(boolean useBlogAuthorInPosts) {
-        this.useBlogAuthorInPosts = useBlogAuthorInPosts;
-    }
-
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof Feed)) return false;
-
-        Feed feed = (Feed) o;
-
-        if (id != null ? !id.equals(feed.id) : feed.id != null) return false;
-        if (name != null ? !name.equals(feed.name) : feed.name != null) return false;
-
-        return true;
-    }
-
-    public int hashCode() {
-        int result;
-        result = (id != null ? id.hashCode() : 0);
-        result = 31 * result + (name != null ? name.hashCode() : 0);
-        return result;
-    }
-}

Modified: trunk/src/model/org/jboss/blog/model/Post.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/Post.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/model/org/jboss/blog/model/Post.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -7,6 +7,7 @@
 import org.hibernate.validator.Pattern;
 import org.jboss.blog.tools.StripHtmlBridge;
 import org.jboss.blog.tools.StringTools;
+import org.jboss.blog.model.feed.Feed;
 
 import javax.persistence.*;
 import java.util.Date;

Deleted: trunk/src/model/org/jboss/blog/model/RemoteFeed.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/RemoteFeed.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/model/org/jboss/blog/model/RemoteFeed.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,25 +0,0 @@
-package org.jboss.blog.model;
-
-import org.hibernate.validator.Length;
-import org.hibernate.validator.NotEmpty;
-
-import javax.persistence.Entity;
-import javax.persistence.Transient;
-
-/**
- * @author <a href="mailto:adam at warski.org">Adam Warski</a>
- */
- at Entity
-public class RemoteFeed extends Feed {
-    @NotEmpty
-    @Length(max = 512)
-    private String remoteLink;
-
-    public String getRemoteLink() {
-        return remoteLink;
-    }
-
-    public void setRemoteLink(String remoteLink) {
-        this.remoteLink = remoteLink;
-    }
-}

Copied: trunk/src/model/org/jboss/blog/model/feed/AggregatedFeed.java (from rev 159, trunk/src/model/org/jboss/blog/model/AggregatedFeed.java)
===================================================================
--- trunk/src/model/org/jboss/blog/model/feed/AggregatedFeed.java	                        (rev 0)
+++ trunk/src/model/org/jboss/blog/model/feed/AggregatedFeed.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,22 @@
+package org.jboss.blog.model.feed;
+
+import javax.persistence.Entity;
+import javax.persistence.ManyToMany;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Entity
+public class AggregatedFeed extends Feed {
+    @ManyToMany
+    private List<Feed> feeds;
+
+    public List<Feed> getFeeds() {
+        return feeds;
+    }
+
+    public void setFeeds(List<Feed> feeds) {
+        this.feeds = feeds;
+    }
+}

Copied: trunk/src/model/org/jboss/blog/model/feed/Feed.java (from rev 159, trunk/src/model/org/jboss/blog/model/Feed.java)
===================================================================
--- trunk/src/model/org/jboss/blog/model/feed/Feed.java	                        (rev 0)
+++ trunk/src/model/org/jboss/blog/model/feed/Feed.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,166 @@
+package org.jboss.blog.model.feed;
+
+import org.hibernate.validator.Length;
+import org.hibernate.validator.NotEmpty;
+import org.hibernate.validator.Pattern;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.model.XmlType;
+import org.jboss.blog.model.Template;
+
+import javax.persistence.*;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Entity
+ at Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+public class Feed {
+    @Id
+    @GeneratedValue
+    @Column(updatable = false)
+    private Integer id;
+
+    @NotEmpty
+    @Length(max = 16)
+    @Column(unique = true)
+    @Pattern(regex = "^[a-z0-9_]*$", message = "#{messages['blog.feed.new.invalidname']}")
+    private String name;
+
+    @NotEmpty
+    @Length(max = 512)
+    private String title;
+
+    @Length(max = 256)
+    private String author;
+
+    @Length(max = 512)
+    @NotEmpty
+    private String link;
+
+    @OneToMany(cascade = {CascadeType.REMOVE}, mappedBy = "feed")
+    private List<Post> posts;
+
+    @Lob
+    private String description;
+
+    @ManyToMany
+    private Map<XmlType, Template> templates;
+
+    @Column
+    private int maxPostsInFeed;
+
+    @Column
+    private boolean useBlogAuthorInPosts;
+
+    @Column
+    private int maxPostsOnPage;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(String author) {
+        this.author = author;
+    }
+
+    public String getLink() {
+        return link;
+    }
+
+    public void setLink(String link) {
+        this.link = link;
+    }
+
+    public List<Post> getPosts() {
+        return posts;
+    }
+
+    public void setPosts(List<Post> posts) {
+        this.posts = posts;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Map<XmlType, Template> getTemplates() {
+        return templates;
+    }
+
+    public void setTemplates(Map<XmlType, Template> templates) {
+        this.templates = templates;
+    }
+
+    public int getMaxPostsInFeed() {
+        return maxPostsInFeed;
+    }
+
+    public void setMaxPostsInFeed(int maxPostsInFeed) {
+        this.maxPostsInFeed = maxPostsInFeed;
+    }
+
+    public int getMaxPostsOnPage() {
+        return maxPostsOnPage;
+    }
+
+    public void setMaxPostsOnPage(int maxPostsOnPage) {
+        this.maxPostsOnPage = maxPostsOnPage;
+    }
+
+    public boolean isUseBlogAuthorInPosts() {
+        return useBlogAuthorInPosts;
+    }
+
+    public void setUseBlogAuthorInPosts(boolean useBlogAuthorInPosts) {
+        this.useBlogAuthorInPosts = useBlogAuthorInPosts;
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof Feed)) return false;
+
+        Feed feed = (Feed) o;
+
+        if (id != null ? !id.equals(feed.id) : feed.id != null) return false;
+        if (name != null ? !name.equals(feed.name) : feed.name != null) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        int result;
+        result = (id != null ? id.hashCode() : 0);
+        result = 31 * result + (name != null ? name.hashCode() : 0);
+        return result;
+    }
+}

Copied: trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java (from rev 159, trunk/src/model/org/jboss/blog/model/RemoteFeed.java)
===================================================================
--- trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java	                        (rev 0)
+++ trunk/src/model/org/jboss/blog/model/feed/RemoteFeed.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,24 @@
+package org.jboss.blog.model.feed;
+
+import org.hibernate.validator.Length;
+import org.hibernate.validator.NotEmpty;
+
+import javax.persistence.Entity;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+ at Entity
+public class RemoteFeed extends Feed {
+    @NotEmpty
+    @Length(max = 512)
+    private String remoteLink;
+
+    public String getRemoteLink() {
+        return remoteLink;
+    }
+
+    public void setRemoteLink(String remoteLink) {
+        this.remoteLink = remoteLink;
+    }
+}

Modified: trunk/src/services/org/jboss/blog/service/FeedsService.java
===================================================================
--- trunk/src/services/org/jboss/blog/service/FeedsService.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/services/org/jboss/blog/service/FeedsService.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,6 +1,6 @@
 package org.jboss.blog.service;
 
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.service.FeedNotFoundException;
 

Modified: trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java
===================================================================
--- trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -1,7 +1,7 @@
 package org.jboss.blog.session.merge.test;
 
 import static org.easymock.EasyMock.*;
-import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.feed.Feed;
 import org.jboss.blog.model.Post;
 import org.jboss.blog.service.FeedsService;
 import org.jboss.blog.session.merge.MergeServiceBean;

Added: trunk/src/tools/org/jboss/blog/tools/KeyNotMappedException.java
===================================================================
--- trunk/src/tools/org/jboss/blog/tools/KeyNotMappedException.java	                        (rev 0)
+++ trunk/src/tools/org/jboss/blog/tools/KeyNotMappedException.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,21 @@
+package org.jboss.blog.tools;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class KeyNotMappedException extends RuntimeException {
+    public KeyNotMappedException() {
+    }
+
+    public KeyNotMappedException(String message) {
+        super(message);
+    }
+
+    public KeyNotMappedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public KeyNotMappedException(Throwable cause) {
+        super(cause);
+    }
+}

Added: trunk/src/tools/org/jboss/blog/tools/KeySafeMap.java
===================================================================
--- trunk/src/tools/org/jboss/blog/tools/KeySafeMap.java	                        (rev 0)
+++ trunk/src/tools/org/jboss/blog/tools/KeySafeMap.java	2008-01-07 16:29:09 UTC (rev 164)
@@ -0,0 +1,84 @@
+package org.jboss.blog.tools;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.Collection;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class KeySafeMap<K, V> implements Map<K, V> {
+    private Map<K, V> delegate;
+
+    public KeySafeMap(Map<K, V> delegate) {
+        if (delegate == null) {
+            throw new IllegalArgumentException("Delegate map cannot be null!");
+        }
+
+        this.delegate = delegate;
+    }
+
+    public static <K, V> KeySafeMap<K, V> wrap(Map<K, V> toWrap) {
+        return new KeySafeMap<K, V>(toWrap);
+    }
+
+    public int size() {
+        return delegate.size();
+    }
+
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    public boolean containsKey(Object key) {
+        return delegate.containsKey(key);
+    }
+
+    public boolean containsValue(Object value) {
+        return delegate.containsValue(value);
+    }
+
+    public V get(Object key) {
+        if (containsKey(key)) {
+            return delegate.get(key);
+        } else {
+            throw new KeyNotMappedException(StringTools.safeToString(key));
+        }
+    }
+
+    public V put(K key, V value) {
+        return delegate.put(key, value);
+    }
+
+    public V remove(Object key) {
+        return delegate.remove(key);
+    }
+
+    public void putAll(Map<? extends K, ? extends V> t) {
+        delegate.putAll(t);
+    }
+
+    public void clear() {
+        delegate.clear();
+    }
+
+    public Set<K> keySet() {
+        return delegate.keySet();
+    }
+
+    public Collection<V> values() {
+        return delegate.values();
+    }
+
+    public Set<Entry<K, V>> entrySet() {
+        return delegate.entrySet();
+    }
+
+    public boolean equals(Object o) {
+        return delegate.equals(o);
+    }
+
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+}

Modified: trunk/view/manage/add.xhtml
===================================================================
--- trunk/view/manage/add.xhtml	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/view/manage/add.xhtml	2008-01-07 16:29:09 UTC (rev 164)
@@ -17,7 +17,7 @@
         <ul>
             <ui:repeat var="feedType" value="#{feedTypes.allTypes}">
                 <li>
-                    <s:link value="Add a new #{feedType.name} feed" view="#{feedType.addPage}" />
+                    <s:link value="Add a new #{feedType.name()} feed" view="#{feedType.addPage()}" />
                 </li>
             </ui:repeat>
         </ul>

Modified: trunk/view/manage/index.xhtml
===================================================================
--- trunk/view/manage/index.xhtml	2007-12-21 16:34:36 UTC (rev 163)
+++ trunk/view/manage/index.xhtml	2008-01-07 16:29:09 UTC (rev 164)
@@ -20,12 +20,12 @@
 
         <ui:repeat var="feed" value="#{feedsService.allFeeds}">
             <p>
-                #{feed.title} (#{feed.name}, #{feedTypes.getFeedType(feed.class).name}) <br />
+                #{feed.title} (#{feed.name}, #{feedTypes.getFeedType(feed).name()}) <br />
                 <s:link view="/manage/feed_edit.xhtml" value="Edit common">
                     <f:param name="name" value="#{feed.name}" />
                 </s:link>
                 <br />
-                <s:link view="#{feedTypes.getFeedType(feed.class).editPage}" value="Edit specific">
+                <s:link view="#{feedTypes.getFeedType(feed).editPage()}" value="Edit specific">
                     <f:param name="name" value="#{feed.name}" />
                 </s:link>
                 <br />




More information about the jboss-cvs-commits mailing list