[jboss-cvs] JBossBlog SVN: r142 - in trunk: src/action/org/jboss/blog/session and 14 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Nov 28 15:53:08 EST 2007


Author: adamw
Date: 2007-11-28 15:53:08 -0500 (Wed, 28 Nov 2007)
New Revision: 142

Added:
   trunk/src/action/org/jboss/blog/session/merge/
   trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java
   trunk/src/action/org/jboss/blog/session/merge/ListPostsIterator.java
   trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java
   trunk/src/action/org/jboss/blog/session/merge/PostsIterator.java
   trunk/src/action/org/jboss/blog/session/update/UpdateException.java
   trunk/src/action/org/jboss/blog/tools/GeneralTools.java
   trunk/src/test/org/
   trunk/src/test/org/jboss/
   trunk/src/test/org/jboss/blog/
   trunk/src/test/org/jboss/blog/session/
   trunk/src/test/org/jboss/blog/session/merge/
   trunk/src/test/org/jboss/blog/session/merge/test/
   trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java
Removed:
   trunk/src/test/readme.txt
Modified:
   trunk/blog.iml
   trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java
   trunk/src/action/org/jboss/blog/session/feed/FeedsServiceImpl.java
   trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java
   trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedUpdateBean.java
   trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java
Log:


Modified: trunk/blog.iml
===================================================================
--- trunk/blog.iml	2007-11-28 12:50:56 UTC (rev 141)
+++ trunk/blog.iml	2007-11-28 20:53:08 UTC (rev 142)
@@ -97,6 +97,16 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="module-library">
+      <library name="testng">
+        <CLASSES>
+          <root url="jar://$MODULE_DIR$/lib/testng.jar!/" />
+          <root url="jar://$MODULE_DIR$/lib/easymock.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
     <orderEntryProperties />
   </component>
 </module>

Modified: trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java	2007-11-28 12:50:56 UTC (rev 141)
+++ trunk/src/action/org/jboss/blog/session/feed/FeedUpdate.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -1,10 +1,11 @@
 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);
+    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-11-28 12:50:56 UTC (rev 141)
+++ trunk/src/action/org/jboss/blog/session/feed/FeedsServiceImpl.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -49,7 +49,7 @@
             return ((FeedPosts) Component.getInstance(feedPostsComponentName)).getPosts(feed, from, to);
         } else {
             return (List<Post>) entityManager.createQuery(
-                    "select post from Post post where post.feed = ?1 order by post.published desc")
+                    "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();
         }
     }

Modified: trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java	2007-11-28 12:50:56 UTC (rev 141)
+++ trunk/src/action/org/jboss/blog/session/feed/aggregated/AggregatedFeedPostsBean.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -26,7 +26,7 @@
                 "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")
+                        "order by post.published desc, post.link")
                 .setParameter(1, feed).setMaxResults(to-from).setFirstResult(from).getResultList();
     }
 }

Modified: trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedUpdateBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedUpdateBean.java	2007-11-28 12:50:56 UTC (rev 141)
+++ trunk/src/action/org/jboss/blog/session/feed/remote/RemoteFeedUpdateBean.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -1,8 +1,15 @@
 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.model.Feed;
+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;
 
@@ -12,7 +19,28 @@
 @Name("remoteFeedUpdate")
 @Scope(ScopeType.STATELESS)
 public class RemoteFeedUpdateBean implements FeedUpdate {
-    public void update(Feed feed) {
+    @In
+    private ParserService parserService;
+
+    @In
+    private MergeServiceBean mergeService;
+
+    public void update(Feed feed) throws UpdateException {
         System.out.println("Updating " + feed.getName());
+
+        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());
     }
 }

Added: trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/merge/FeedsServicePostsIterator.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,73 @@
+package org.jboss.blog.session.merge;
+
+import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.service.FeedsService;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class FeedsServicePostsIterator implements PostsIterator {
+    private FeedsService feedsService;
+    private Feed feed;
+
+    private int chunkSize;
+    private int nextFrom;
+    private Post current;
+
+    private Iterator<Post> iterator;
+    private int lastChunkSize;
+
+    public FeedsServicePostsIterator(FeedsService feedsService, Feed feed, int chunkSize) {
+        this.feedsService = feedsService;
+        this.feed = feed;
+        this.chunkSize = chunkSize;
+
+        nextFrom = 0;
+
+        readNextChunk();
+
+        if (iterator.hasNext()) {
+            current = iterator.next();
+        } else {
+            current = null;
+        }
+    }
+
+    private void readNextChunk() {
+        List<Post> posts = feedsService.getPosts(feed, nextFrom, nextFrom+chunkSize-1);
+        iterator = posts.iterator();
+        lastChunkSize = posts.size();
+        nextFrom += chunkSize;
+    }
+
+    public Post getCurrent() {
+        return current;
+    }
+
+    public boolean finished() {
+        return current == null;
+    }
+
+    public Post next() {
+        if (iterator.hasNext()) {
+            current = iterator.next();
+        } else {
+            if (lastChunkSize < chunkSize) {
+                current = null;
+            } else {
+                readNextChunk();
+                if (iterator.hasNext()) {
+                    current = iterator.next();
+                } else {
+                    current = null;
+                }
+            }
+        }
+
+        return current;
+    }
+}

Added: trunk/src/action/org/jboss/blog/session/merge/ListPostsIterator.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/ListPostsIterator.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/merge/ListPostsIterator.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,42 @@
+package org.jboss.blog.session.merge;
+
+import org.jboss.blog.model.Post;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class ListPostsIterator implements PostsIterator {
+    private Iterator<Post> iterator;
+    private Post current;
+
+    public ListPostsIterator(List<Post> posts) {
+        iterator = posts.iterator();
+
+        if (iterator.hasNext()) {
+            current = iterator.next();
+        } else {
+            current = null;
+        }
+    }
+
+    public Post getCurrent() {
+        return current;
+    }
+
+    public boolean finished() {
+        return current == null;
+    }
+
+    public Post next() {
+        if (iterator.hasNext()) {
+            current = iterator.next();
+        } else {
+            current = null;
+        }
+
+        return current;
+    }
+}

Added: trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,108 @@
+package org.jboss.blog.session.merge;
+
+import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.service.FeedsService;
+import org.jboss.blog.tools.GeneralTools;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.AutoCreate;
+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("mergeService")
+ at AutoCreate
+ at Scope(ScopeType.STATELESS)
+public class MergeServiceBean {
+    @In
+    private FeedsService feedsService;
+
+    @In
+    private EntityManager entityManager;
+
+    private void savePost(Feed feed, Post post) {
+        post.setFeed(feed);
+        entityManager.persist(post);
+    }
+
+    /**
+     * Merges the given posts; checks for changes in:
+     * - author
+     * - content
+     * - link
+     * - dateModified
+     * - title
+     *
+     * The published date is assumed to be the same.
+     *
+     * Doesn't check for changes in:
+     * - categories.
+     *
+     * Also, in case of a title change, the titleAsId is not chagned.
+     *
+     * @param mergeTo Post to which to merge the changes.
+     * @param mergeFrom Post from which to merge the changes.
+     */
+    private void mergePosts(Post mergeTo, Post mergeFrom) {
+        if (!GeneralTools.objectsEquals(mergeTo.getAuthor(), mergeFrom.getAuthor())) {
+            mergeTo.setAuthor(mergeFrom.getAuthor());
+        }
+
+        if (!GeneralTools.objectsEquals(mergeTo.getContent(), mergeFrom.getContent())) {
+            mergeTo.setContent(mergeFrom.getContent());
+        }
+
+        if (!GeneralTools.objectsEquals(mergeTo.getLink(), mergeFrom.getLink())) {
+            mergeTo.setLink(mergeFrom.getLink());
+        }
+
+        if (!GeneralTools.objectsEquals(mergeTo.getModified(), mergeFrom.getModified())) {
+            mergeTo.setModified(mergeFrom.getModified());
+        }
+
+        if (!GeneralTools.objectsEquals(mergeTo.getTitle(), mergeFrom.getTitle())) {
+            mergeTo.setTitle(mergeFrom.getTitle());
+        }
+    }
+
+    public void merge(Feed feed, List<Post> posts) {
+        ListPostsIterator mergeFrom = new ListPostsIterator(posts);
+        FeedsServicePostsIterator mergeTo = new FeedsServicePostsIterator(feedsService, feed, posts.size()+1);
+
+        while (!mergeFrom.finished()) {
+            if (mergeTo.finished()) {
+                // no more current posts
+                savePost(feed, mergeFrom.getCurrent());
+                mergeFrom.next();
+            } else {
+                int publishedCompare = mergeTo.getCurrent().getPublished().compareTo(
+                        mergeFrom.getCurrent().getPublished());
+                int linksCompare = - mergeTo.getCurrent().getLink().compareTo(mergeFrom.getCurrent().getLink());
+
+                int compare = publishedCompare == 0 ? linksCompare : publishedCompare;
+
+                if (compare < 0) {
+                    // mergeTo post is before mergeFrom post
+                    savePost(feed, mergeFrom.getCurrent());
+                    mergeFrom.next();
+                } else if (compare == 0) {
+                    mergePosts(mergeTo.getCurrent(), mergeFrom.getCurrent());
+                    mergeFrom.next();
+                    mergeTo.next();
+                } else {
+                    // mergeTo post is after mergeFrom post
+                    // proceeding to the next mergeTo post (if exists)
+                    mergeTo.next();
+                }
+            }
+        }
+
+        entityManager.flush();
+    }
+}

Added: trunk/src/action/org/jboss/blog/session/merge/PostsIterator.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/PostsIterator.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/merge/PostsIterator.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,12 @@
+package org.jboss.blog.session.merge;
+
+import org.jboss.blog.model.Post;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public interface PostsIterator {
+    public Post getCurrent();
+    public Post next();
+    public boolean finished();
+}

Modified: trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java	2007-11-28 12:50:56 UTC (rev 141)
+++ trunk/src/action/org/jboss/blog/session/parser/ParserServiceImpl.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -22,6 +22,8 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 /**
@@ -80,6 +82,17 @@
                 }
             }
 
+            Collections.sort(posts, new Comparator<Post>() {
+                public int compare(Post post1, Post post2) {
+                    int dateCompare = - post1.getPublished().compareTo(post2.getPublished());
+                    if (dateCompare == 0) {
+                        return post1.getLink().compareTo(post2.getLink());
+                    } else {
+                        return dateCompare;
+                    }
+                }
+            });
+
             return feed;
         } catch (FeedException e) {
             throw new ParserException(e);

Added: trunk/src/action/org/jboss/blog/session/update/UpdateException.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/update/UpdateException.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/update/UpdateException.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,21 @@
+package org.jboss.blog.session.update;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class UpdateException extends RuntimeException {
+    public UpdateException() {
+    }
+
+    public UpdateException(String message) {
+        super(message);
+    }
+
+    public UpdateException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public UpdateException(Throwable cause) {
+        super(cause);
+    }
+}

Added: trunk/src/action/org/jboss/blog/tools/GeneralTools.java
===================================================================
--- trunk/src/action/org/jboss/blog/tools/GeneralTools.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/tools/GeneralTools.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,14 @@
+package org.jboss.blog.tools;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class GeneralTools {
+    public static boolean objectsEquals(Object o1, Object o2) {
+        if (o1 == null) {
+            return o2 == null;
+        } else {
+            return o1.equals(o2);
+        }
+    }
+}

Added: trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java
===================================================================
--- trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java	                        (rev 0)
+++ trunk/src/test/org/jboss/blog/session/merge/test/MergeServiceTest.java	2007-11-28 20:53:08 UTC (rev 142)
@@ -0,0 +1,243 @@
+package org.jboss.blog.session.merge.test;
+
+import static org.easymock.EasyMock.*;
+import org.jboss.blog.model.Feed;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.service.FeedsService;
+import org.jboss.blog.session.merge.MergeServiceBean;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ * @author <a href="mailto:adam at warski.org">Adam Warski</a>
+ */
+public class MergeServiceTest {
+    private MergeServiceBean mergeServiceBean;
+
+    private Post post_2007_11_01_t1_c1_l1;
+    private Post post_2007_11_01_t2_c2_l2;
+    private Post post_2007_11_02_t3_c3_l3;
+    private Post post_2007_11_02_t1_c1_l4;
+    private Post post_2007_11_03_t4_c4_l5;
+    private Post post_2007_11_03_t5_c5_l6;
+    private Post post_2007_11_03_t6_c6_l6;
+    private Post post_2007_11_04_t6_c6_l7;
+    private Post post_2007_11_05_t6_c6_l8;
+
+    private EntityManager mockEntityManager;
+    private FeedsService mockFeedsService;
+
+    private Post createPost(Date published, String title, String content, String link) {
+        Post post = new Post();
+        post.setPublished(published);
+        post.setTitle(title);
+        post.setContent(content);
+        post.setLink(link);
+
+        return post;
+    }
+
+    private Date createDate(int year, int month, int day) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(year, month, day, 0, 0, 0);
+
+        return cal.getTime();
+    }
+
+    private void setField(Object o, String fieldName, Object setTo)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field f = o.getClass().getDeclaredField(fieldName);
+        f.setAccessible(true);
+        f.set(o, setTo);
+    }
+
+    @BeforeClass
+    public void setupClass() {
+        mergeServiceBean = new MergeServiceBean();
+    }
+
+    @BeforeMethod
+    public void setupPosts() {        
+        post_2007_11_01_t1_c1_l1 = createPost(createDate(2007, 11, 1), "title1", "content1", "link1");
+        post_2007_11_01_t2_c2_l2 = createPost(createDate(2007, 11, 1), "title2", "content2", "link2");
+        post_2007_11_02_t3_c3_l3 = createPost(createDate(2007, 11, 2), "title3", "content3", "link3");
+        post_2007_11_02_t1_c1_l4 = createPost(createDate(2007, 11, 2), "title1", "content1", "link4");
+        post_2007_11_03_t4_c4_l5 = createPost(createDate(2007, 11, 3), "title4", "content4", "link5");
+        post_2007_11_03_t5_c5_l6 = createPost(createDate(2007, 11, 3), "title5", "content5", "link6");
+        post_2007_11_03_t6_c6_l6 = createPost(createDate(2007, 11, 3), "title6", "content6", "link6");
+        post_2007_11_04_t6_c6_l7 = createPost(createDate(2007, 11, 4), "title6", "content6", "link7");
+        post_2007_11_05_t6_c6_l8 = createPost(createDate(2007, 11, 5), "title6", "content6", "link8");
+    }
+
+    @BeforeMethod
+    public void setupMocks() throws IllegalAccessException, NoSuchFieldException {
+        mockEntityManager = createMock(EntityManager.class);
+        setField(mergeServiceBean, "entityManager", mockEntityManager);
+
+        mockFeedsService = createMock(FeedsService.class);
+        setField(mergeServiceBean, "feedsService", mockFeedsService);
+    }
+
+    @Test
+    public void testMergeIdentical() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> posts = Arrays.asList(post_2007_11_02_t3_c3_l3,
+                post_2007_11_01_t1_c1_l1);
+        
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 2)).andReturn(posts);        
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, posts);
+        
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+
+    @Test
+    public void testMergeToEmpty() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> mergeTo = new ArrayList<Post>();
+        List<Post> mergeFrom = Arrays.asList(post_2007_11_02_t3_c3_l3,
+                post_2007_11_01_t1_c1_l1);
+
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 2)).andReturn(mergeTo);        
+        mockEntityManager.persist(post_2007_11_02_t3_c3_l3);
+        mockEntityManager.persist(post_2007_11_01_t1_c1_l1);
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, mergeFrom);
+
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+
+    @Test
+    public void testMergeFromEmpty() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> mergeTo = Arrays.asList(post_2007_11_02_t3_c3_l3,
+                post_2007_11_01_t1_c1_l1);
+        List<Post> mergeFrom = new ArrayList<Post>();
+
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 0)).andReturn(mergeTo);
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, mergeFrom);
+
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+
+    @Test
+    public void testMergeInterleaving_WithoutIntersection() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> mergeTo = Arrays.asList(post_2007_11_05_t6_c6_l8,
+                post_2007_11_03_t4_c4_l5, post_2007_11_01_t1_c1_l1);
+        List<Post> mergeFrom = Arrays.asList(post_2007_11_04_t6_c6_l7,
+                post_2007_11_02_t1_c1_l4);
+
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 2)).andReturn(mergeTo);        
+        mockEntityManager.persist(post_2007_11_04_t6_c6_l7);
+        mockEntityManager.persist(post_2007_11_02_t1_c1_l4);
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, mergeFrom);
+
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+
+    @Test
+    public void testMergeInterleaving_WithIntersection() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> mergeTo = Arrays.asList(post_2007_11_05_t6_c6_l8,
+                post_2007_11_04_t6_c6_l7, post_2007_11_02_t1_c1_l4,
+                post_2007_11_01_t1_c1_l1);
+        List<Post> mergeFrom = Arrays.asList(post_2007_11_04_t6_c6_l7,
+                post_2007_11_03_t5_c5_l6, post_2007_11_01_t2_c2_l2);
+
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 3)).andReturn(mergeTo);
+        mockEntityManager.persist(post_2007_11_03_t5_c5_l6);
+        expect(mockFeedsService.getPosts((Feed) null, 4, 7)).andReturn(new ArrayList<Post>());
+        mockEntityManager.persist(post_2007_11_01_t2_c2_l2);
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, mergeFrom);
+
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+
+    @Test
+    public void testMergeChangedPost() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> mergeTo = Arrays.asList(post_2007_11_05_t6_c6_l8,
+                post_2007_11_04_t6_c6_l7, post_2007_11_03_t5_c5_l6,
+                post_2007_11_03_t4_c4_l5, post_2007_11_02_t3_c3_l3);
+        List<Post> mergeFrom = Arrays.asList(post_2007_11_05_t6_c6_l8,
+                post_2007_11_04_t6_c6_l7, post_2007_11_03_t6_c6_l6,
+                post_2007_11_03_t4_c4_l5, post_2007_11_02_t3_c3_l3);
+
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 5)).andReturn(mergeTo);
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, mergeFrom);
+        assert "title6".equals(mergeTo.get(2).getTitle());
+        assert "content6".equals(mergeTo.get(2).getContent());        
+
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+
+    @Test
+    public void testMergeOld() throws IllegalAccessException, NoSuchFieldException {
+        List<Post> mergeTo1 = Arrays.asList(post_2007_11_05_t6_c6_l8, post_2007_11_04_t6_c6_l7);
+        List<Post> mergeTo2 = Arrays.asList(post_2007_11_03_t5_c5_l6, post_2007_11_03_t4_c4_l5);
+        List<Post> mergeTo3 = Arrays.asList(post_2007_11_01_t1_c1_l1);
+        List<Post> mergeFrom = Arrays.asList(post_2007_11_02_t1_c1_l4);
+
+        // Behaviour of mocks
+        expect(mockFeedsService.getPosts((Feed) null, 0, 1)).andReturn(mergeTo1);
+        expect(mockFeedsService.getPosts((Feed) null, 2, 3)).andReturn(mergeTo2);
+        expect(mockFeedsService.getPosts((Feed) null, 4, 5)).andReturn(mergeTo3);
+        mockEntityManager.persist(post_2007_11_02_t1_c1_l4);
+        mockEntityManager.flush();
+
+        // Test
+        replay(mockEntityManager);
+        replay(mockFeedsService);
+
+        mergeServiceBean.merge(null, mergeFrom);
+
+        verify(mockEntityManager);
+        verify(mockFeedsService);
+    }
+}

Deleted: trunk/src/test/readme.txt
===================================================================
--- trunk/src/test/readme.txt	2007-11-28 12:50:56 UTC (rev 141)
+++ trunk/src/test/readme.txt	2007-11-28 20:53:08 UTC (rev 142)
@@ -1,9 +0,0 @@
-If you want to run tests using the Eclipse TestNG plugin, you'll need to add
-these jars to the top of your TestNG classpath.  Using the Run Dialog, select
-xml suite to run, and add /lib/test/jboss-embedded-all.jar, 
-/lib/test/hibernate-all.jar, /lib/test/thirdparty-all.jar, /lib/embedded-api.jar, 
-/lib/jboss-deployers.jar and /bootstrap as the first entries in the User 
-classpath.
-
-To add tests to your project create a TestNG xml descriptor called *Test.xml e.g.
-FooTest.xml next to your test classes and run ant test.
\ No newline at end of file




More information about the jboss-cvs-commits mailing list