/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** All rights reserved **
** **
** This program and the accompanying materials are made available under **
** the terms of the Eclipse Public License v1.0 which accompanies this **
** distribution, and is available at: **
** http://www.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.core.tests.model;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.persist.BookMark;
import org.rssowl.core.internal.persist.Category;
import org.rssowl.core.internal.persist.Feed;
import org.rssowl.core.internal.persist.Folder;
import org.rssowl.core.internal.persist.Guid;
import org.rssowl.core.internal.persist.Image;
import org.rssowl.core.internal.persist.Label;
import org.rssowl.core.internal.persist.News;
import org.rssowl.core.internal.persist.NewsBin;
import org.rssowl.core.internal.persist.NewsContainer;
import org.rssowl.core.internal.persist.Person;
import org.rssowl.core.internal.persist.SearchCondition;
import org.rssowl.core.internal.persist.SearchMark;
import org.rssowl.core.internal.persist.Source;
import org.rssowl.core.internal.persist.service.DBManager;
import org.rssowl.core.persist.IAttachment;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.ICategory;
import org.rssowl.core.persist.IConditionalGet;
import org.rssowl.core.persist.IFeed;
import org.rssowl.core.persist.IFilterAction;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IImage;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.IMark;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.INewsBin;
import org.rssowl.core.persist.IPersistable;
import org.rssowl.core.persist.IPerson;
import org.rssowl.core.persist.ISearch;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.ISource;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.INews.State;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.IConditionalGetDAO;
import org.rssowl.core.persist.dao.IFeedDAO;
import org.rssowl.core.persist.dao.INewsDAO;
import org.rssowl.core.persist.event.BookMarkAdapter;
import org.rssowl.core.persist.event.BookMarkEvent;
import org.rssowl.core.persist.event.BookMarkListener;
import org.rssowl.core.persist.event.CategoryAdapter;
import org.rssowl.core.persist.event.CategoryEvent;
import org.rssowl.core.persist.event.CategoryListener;
import org.rssowl.core.persist.event.FeedAdapter;
import org.rssowl.core.persist.event.FeedEvent;
import org.rssowl.core.persist.event.FeedListener;
import org.rssowl.core.persist.event.FolderAdapter;
import org.rssowl.core.persist.event.FolderEvent;
import org.rssowl.core.persist.event.FolderListener;
import org.rssowl.core.persist.event.LabelAdapter;
import org.rssowl.core.persist.event.LabelEvent;
import org.rssowl.core.persist.event.LabelListener;
import org.rssowl.core.persist.event.NewsAdapter;
import org.rssowl.core.persist.event.NewsEvent;
import org.rssowl.core.persist.event.NewsListener;
import org.rssowl.core.persist.event.PersonAdapter;
import org.rssowl.core.persist.event.PersonEvent;
import org.rssowl.core.persist.event.PersonListener;
import org.rssowl.core.persist.event.SearchMarkAdapter;
import org.rssowl.core.persist.event.SearchMarkEvent;
import org.rssowl.core.persist.event.SearchMarkListener;
import org.rssowl.core.persist.reference.FeedLinkReference;
import org.rssowl.core.persist.reference.FeedReference;
import org.rssowl.core.persist.reference.NewsReference;
import org.rssowl.core.persist.service.PersistenceException;
import org.rssowl.core.persist.service.UniqueConstraintException;
import org.rssowl.core.tests.TestUtils;
import com.db4o.ObjectContainer;
import com.db4o.query.Query;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author Ismael Juma (ismael@juma.me.uk)
*/
@SuppressWarnings("nls")
public class DBManagerTest {
private static final String NOT_IDENTICAL_MESSAGE = "Item in the database is not identical to initial item.";
private IModelFactory fTypesFactory;
private ObjectContainer fDb;
private INewsDAO fNewsDAO;
/**
* @throws Exception
*/
@Before
public void setUp() throws Exception {
Owl.getPersistenceService().recreateSchema();
fTypesFactory = Owl.getModelFactory();
fDb = DBManager.getDefault().getObjectContainer();
fNewsDAO = DynamicDAO.getDAO(INewsDAO.class);
}
/**
* @throws Exception
*/
@Test
public void testNewsDaoLoadAllFromFeed() throws Exception {
IFolder root = fTypesFactory.createFolder(null, null, "Root");
INewsBin bin = fTypesFactory.createNewsBin(null, root, "Bin");
DynamicDAO.save(root);
IFeed parent = fTypesFactory.createFeed(null, new URI("http://www.feed.com"));
INews news = fTypesFactory.createNews(null, parent, new Date());
DynamicDAO.save(parent);
INews newsCopy = fTypesFactory.createNews(news, bin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(bin);
Collection<INews> newsFromFeed = DynamicDAO.getDAO(INewsDAO.class).loadAll(new FeedLinkReference(parent.getLink()), INews.State.getVisible());
assertEquals(1, newsFromFeed.size());
assertEquals(news, newsFromFeed.iterator().next());
}
/**
*
*/
@Test
public void testAddDuplicateNewsDeadlocks() {
List<INews> newsList = new ArrayList<INews>();
IFeed feed = createFeed();
INews news = createNews(feed);
newsList.add(news);
newsList.add(news);
DynamicDAO.saveAll(newsList);
}
/**
* Tests that {@link INewsDAO#setState(Set, State, boolean)} works correctly.
* @throws Exception s
*/
@Test
public void testNewsDAODeleteByStates() throws Exception {
String feed0Link = "http://www.feed0.com";
IFeed feed = fTypesFactory.createFeed(null, new URI(feed0Link));
INews news = fTypesFactory.createNews(null, feed, new Date());
news.setState(INews.State.HIDDEN);
String news0Guid = "news0";
fTypesFactory.createGuid(news, news0Guid, true);
news = fTypesFactory.createNews(null, feed, new Date());
news.setState(INews.State.NEW);
String news1Guid = "news1";
fTypesFactory.createGuid(news, news1Guid, true);
DynamicDAO.save(feed);
String feed1Link = "http://www.feed1.com";
feed = fTypesFactory.createFeed(null, new URI(feed1Link));
news = fTypesFactory.createNews(null, feed, new Date());
news.setState(INews.State.HIDDEN);
String news2Guid = "news2";
fTypesFactory.createGuid(news, news2Guid, true);
news = fTypesFactory.createNews(null, feed, new Date());
news.setState(INews.State.READ);
String news3Guid = "news3";
fTypesFactory.createGuid(news, news3Guid, true);
DynamicDAO.save(feed);
news = null;
feed = null;
System.gc();
final Set<NewsEvent> newsEvents = new HashSet<NewsEvent>();
NewsListener newsListener = new NewsListener() {
public void entitiesAdded(Set<NewsEvent> events) {
fail("Only update events expected");
}
public void entitiesDeleted(Set<NewsEvent> events) {
fail("Only update events expected");
}
public void entitiesUpdated(Set<NewsEvent> events) {
newsEvents.addAll(events);
}
};
DynamicDAO.addEntityListener(INews.class, newsListener);
try {
fNewsDAO.setState(EnumSet.of(INews.State.HIDDEN), INews.State.DELETED, false);
assertEquals(2, newsEvents.size());
for (NewsEvent newsEvent : newsEvents) {
String guid = newsEvent.getEntity().getGuid().getValue();
assertEquals(INews.State.DELETED, newsEvent.getEntity().getState());
assertEquals(true, guid.equals(news0Guid) || guid.equals(news2Guid));
}
IFeedDAO feedDao = DynamicDAO.getDAO(IFeedDAO.class);
feed = feedDao.load(new URI(feed0Link));
assertEquals(2, feed.getNews().size());
feed = feedDao.load(new URI(feed1Link));
assertEquals(2, feed.getNews().size());
} finally {
DynamicDAO.removeEntityListener(INews.class, newsListener);
}
}
/**
* Tests that saving a NewsBin with a INews that was never saved in DELETED
* state causes the INews to be removed from the INewsBin.
* @throws Exception
*/
@Test
@Ignore("Not sure we need to support this case")
public void testSaveNewsBinWithNeverSavedNewsInDeletedState() throws Exception {
IFeed feed = fTypesFactory.createFeed(null, new URI("http://www.feed.com"));
INews news = fTypesFactory.createNews(null, feed, new Date());
news.setState(INews.State.DELETED);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
assertEquals(0, newsBin.getNews().size());
assertEquals(null, fNewsDAO.load(newsCopy.getId()));
}
/**
* Test case where original news is copied with a state != NEW, the copied news
* state is changed to NEW before saving and then it's saved. The news bin
* should have the news in the right bucket after save is finished.
* @throws Exception
*/
@Test
public void testCopyReadNewsButSaveWithNewState() throws Exception {
IFeed feed = fTypesFactory.createFeed(null, new URI("http://www.feed.com"));
INews news = fTypesFactory.createNews(null, feed, new Date());
news.setState(INews.State.READ);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
newsCopy.setState(INews.State.NEW);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
assertEquals(1, newsBin.getNews(EnumSet.of(INews.State.NEW)).size());
}
/**
*
*/
@Test
public void testSetStateWhereTwoEquivalentNewsAreChangedToInvisible() {
IFeed feed0 = createFeed();
INews news0 = fTypesFactory.createNews(null, feed0, new Date());
URI link = createURI("http://rssowl.org");
news0.setLink(link);
IFeed feed1 = fTypesFactory.createFeed(null, createURI("http://www.afeedlink.com"));
INews news1 = fTypesFactory.createNews(null, feed1, new Date());
news1.setLink(link);
DynamicDAO.save(feed0);
DynamicDAO.save(feed1);
DynamicDAO.getDAO(INewsDAO.class).setState(Arrays.asList(news0, news1), INews.State.HIDDEN, true, false);
assertEquals(INews.State.HIDDEN, news0.getState());
assertEquals(INews.State.HIDDEN, news1.getState());
}
/**
* Tests that deleting a INews.isCopy() will cause either:
* <li>The original feed not to be deleted if it is referenced by a BM or
* another INews.isCopy()</li>
* <li>The original feed to be deleted otherwise.</li>
*/
@Test
public void testDeleteNewsIsCopy() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
fTypesFactory.createGuid(news, "http://www.link.com", true);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
IBookMark bookMark = fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
/* Feed referenced by bookMark and newsCopy */
fNewsDAO.setState(Collections.singleton(newsCopy), INews.State.DELETED, false, false);
assertEquals(feed, DynamicDAO.load(IFeed.class, feed.getId()));
newsCopy = fTypesFactory.createNews(news, newsBin);
fNewsDAO.save(newsCopy);
DynamicDAO.save(newsBin);
DynamicDAO.delete(bookMark);
newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin2");
DynamicDAO.save(newsBin);
INews newsCopy2 = fTypesFactory.createNews(newsCopy, newsBin);
DynamicDAO.save(newsCopy2);
DynamicDAO.save(newsBin);
/* Feed referenced by newsCopy and newsCopy2 */
fNewsDAO.setState(Collections.singleton(newsCopy), INews.State.DELETED, false, false);
assertEquals(feed, DynamicDAO.load(IFeed.class, feed.getId()));
/* Feed referenced by newsCopy2 which is being deleted */
fNewsDAO.setState(Collections.singleton(newsCopy2), INews.State.DELETED, false, false);
assertEquals(null, DynamicDAO.load(IFeed.class, feed.getId()));
}
/**
* Tests that changing the state of a INews#isCopy() does not update the
* NewsCounter for its feed. Also tests that the parent INewsBin is updated.
*/
@Test
public void testNewsCopyStateChangeDoesNotUpdateNewsCounter() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
fTypesFactory.createGuid(news, "http://www.link.com", true);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
IBookMark bookMark = fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
assertEquals(1, bookMark.getNewsCount(EnumSet.of(INews.State.NEW)));
assertEquals(1, newsBin.getNewsCount(EnumSet.of(INews.State.NEW)));
fNewsDAO.setState(Collections.singleton(newsCopy), INews.State.READ, false, false);
assertEquals(1, bookMark.getNewsCount(EnumSet.of(INews.State.NEW)));
assertEquals(0, newsBin.getNewsCount(EnumSet.of(INews.State.NEW)));
}
/**
* Tests that news copy is actually deleted and removed from INewsBin when
* it's saved after changing state to DELETED. Also checks that INewsBin is
* updated if the state of the INews contained in it is changed to HIDDEN.
*/
@Test
public void testNewsIsCopyActuallyDeletedOnDeleteStateChange() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
fTypesFactory.createGuid(news, "http://www.link.com", true);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
fNewsDAO.setState(Collections.singleton(newsCopy), INews.State.HIDDEN, false, false);
assertEquals(1, newsBin.getNewsRefs().size());
assertEquals(1, newsBin.getNewsRefs(EnumSet.of(INews.State.HIDDEN)).size());
assertEquals(0, newsBin.getNewsRefs(EnumSet.of(INews.State.NEW)).size());
assertEquals(newsCopy, newsBin.getNews().get(0));
fNewsDAO.setState(Collections.singleton(newsCopy), INews.State.DELETED, false, false);
assertEquals(0, newsBin.getNewsRefs().size());
assertNull(fNewsDAO.load(newsCopy.getId()));
}
/**
* Tests that copying a sticky news from the original feed to a INewsBin
* followed by deletion of the original IBookMark works correctly. In other words,
* we want to verify that the original feed is not deleted with the IBookMark.
*/
@Test
public void testCopyStickyNewsAndDeleteOriginalBookMark() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
news.setFlagged(true);
fTypesFactory.createGuid(news, "http://www.link.com", true);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
IBookMark mark = fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
DynamicDAO.delete(mark);
/*
* Mark containing the feed was deleted, but feed is not deleted because
* it's still referenced by a copied news. The feed is hence empty.
*/
assertEquals(0, feed.getNews().size());
assertEquals(1, newsBin.getNewsRefs().size());
assertEquals(newsCopy, newsBin.getNews().get(0));
}
/**
* Tests that deleting a IBookMark where the feed has news copies does not
* delete the feed.
*/
@Test
public void testDeleteBookMarkWithNewsCopies() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
fTypesFactory.createGuid(news, "http://www.link.com", true);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
IBookMark bookMark = fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Mark");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "bin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
DynamicDAO.delete(bookMark);
feed = DynamicDAO.load(IFeed.class, feed.getId());
assertNotNull(feed);
assertEquals(0, feed.getNews().size());
}
/**
* Tests that querying on News#fParentId to determine if it is contained
* in a INewsBin works.
*/
@Test
public void testQueryNewsOnIsCopy() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
fTypesFactory.createGuid(news, "http://www.link.com", true);
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
INewsBin newsBin = fTypesFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, newsBin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(newsBin);
Query query = fDb.query();
query.constrain(News.class);
query.descend("fParentId").constrain(0).not();
List<?> newsCopies = query.execute();
assertEquals(1, newsCopies.size());
assertEquals(newsCopy, newsCopies.get(0));
query = fDb.query();
query.constrain(News.class);
query.descend("fParentId").constrain(0);
List<?> newsList = query.execute();
assertEquals(1, newsList.size());
assertEquals(news, newsList.get(0));
query = fDb.query();
query.constrain(News.class);
query.descend("fGuidValue").constrain(news.getGuid().getValue());
query.descend("fParentId").constrain(0).not();
newsCopies = query.execute();
assertEquals(1, newsCopies.size());
assertEquals(newsCopy, newsCopies.get(0));
query = fDb.query();
query.constrain(News.class);
query.descend("fGuidValue").constrain(news.getGuid().getValue());
query.descend("fParentId").constrain(0);
newsList = query.execute();
assertEquals(1, newsList.size());
assertEquals(news, newsList.get(0));
}
/**
* Tests that deleting a search condition removes it and its search field from
* the database.
*/
@Test
public void testDeleteSearchCondition() {
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
ISearchMark searchMark = fTypesFactory.createSearchMark(null, folder, "Mark");
DynamicDAO.save(folder);
ISearchField searchField = fTypesFactory.createSearchField(0, "SomeEntity");
ISearchCondition searchCondition = fTypesFactory.createSearchCondition(null, searchMark, searchField, SearchSpecifier.BEGINS_WITH, "value");
DynamicDAO.save(searchMark);
assertNotNull(DynamicDAO.load(ISearchCondition.class, searchCondition.getId()));
long searchFieldId = fDb.ext().getID(searchCondition.getField());
assertNotNull(fDb.ext().getByID(searchFieldId));
DynamicDAO.delete(searchCondition);
assertNull(DynamicDAO.load(ISearchCondition.class, searchCondition.getId()));
assertNull(fDb.ext().getByID(searchFieldId));
assertEquals(0, searchMark.getSearchConditions().size());
}
/**
* Tests that deleting a search mark removes it from the database and cascades
* it appropriately to its children.
*/
@Test
public void testDeleteSearchMark() {
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
ISearchMark searchMark = fTypesFactory.createSearchMark(null, folder, "Mark");
ISearchField searchField = fTypesFactory.createSearchField(0, "SomeEntity");
ISearchCondition searchCondition = fTypesFactory.createSearchCondition(null, searchMark, searchField, SearchSpecifier.BEGINS_WITH, "value");
DynamicDAO.save(folder);
assertNotNull(DynamicDAO.load(ISearchMark.class, searchMark.getId()));
assertNotNull(DynamicDAO.load(ISearchCondition.class, searchCondition.getId()));
long searchFieldId = fDb.ext().getID(searchCondition.getField());
assertNotNull(fDb.ext().getByID(searchFieldId));
DynamicDAO.delete(searchMark);
assertNull(DynamicDAO.load(ISearchMark.class, searchMark.getId()));
assertNull(DynamicDAO.load(ISearchCondition.class, searchCondition.getId()));
assertNull(fDb.ext().getByID(searchFieldId));
}
/**
* Tests that deleting a news bin deletes the internal news container too.
*/
@Test
public void testDeleteNewsBinDeletesNewsContainer() {
IFeed feed = createFeed();
INews news = fTypesFactory.createNews(null, feed, new Date());
DynamicDAO.save(feed);
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
fTypesFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
NewsBin bin = (NewsBin) fTypesFactory.createNewsBin(null, folder, "News Bin");
DynamicDAO.save(folder);
INews newsCopy = fTypesFactory.createNews(news, bin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(bin);
/* Ensure that arrays are treated specially by db4o, don't need to delete them manually */
assertFalse(fDb.ext().isStored(bin.internalGetNewsContainer().internalGetNewsIds()));
NewsContainer newsContainer = bin.internalGetNewsContainer();
DynamicDAO.delete(bin);
assertFalse(fDb.ext().isStored(newsContainer));
}
/**
* Tests that deleting a news bin is not sending out folder-deleted events.
*/
@Test
public void testDeleteBinIsNotSendindFolderDeleteEvents() {
IFolder folder = fTypesFactory.createFolder(null, null, "Folder");
INewsBin bin = fTypesFactory.createNewsBin(null, folder, "News Bin");
DynamicDAO.save(folder);
assertNotNull(DynamicDAO.load(INewsBin.class, bin.getId()));
final boolean[] bool = new boolean[] { false };
FolderAdapter folderListener = new FolderAdapter() {
@Override
public void entitiesDeleted(Set<FolderEvent> events) {
bool[0] = true;
}
};
DynamicDAO.addEntityListener(IFolder.class, folderListener);
DynamicDAO.delete(bin);
assertNull(DynamicDAO.load(INewsBin.class, bin.getId()));
DynamicDAO.removeEntityListener(IFolder.class, folderListener);
assertFalse("Unexpected Folder Event", bool[0]);
}
private ICategory createFeedCategory() throws PersistenceException {
IFeed feed = DynamicDAO.save(createFeed());
ICategory category = fTypesFactory.createCategory(null, feed);
category.setName("categoryName");
category.setDomain("some/domain");
category.setProperty("one_property", "value");
return category;
}
private ICategory createNewsCategory() throws PersistenceException {
IFeed feed = DynamicDAO.save(createFeed());
INews news = DynamicDAO.save(createNews(feed));
ICategory category = fTypesFactory.createCategory(null, news);
category.setName("categoryName");
category.setDomain("some/domain");
category.setProperty("one_property", "value");
return category;
}
private IBookMark createBookMark() throws PersistenceException {
IFolder folder = DynamicDAO.save(createFolder());
return createBookMark(folder);
}
private ISearchMark createSearchMark() throws PersistenceException {
IFolder folder = DynamicDAO.save(createFolder());
return createSearchMark(folder);
}
private IBookMark createBookMark(IFolder folder) throws PersistenceException {
IFeed feed = createFeed();
IFeed savedFeed = Owl.getPersistenceService().getDAOService().getFeedDAO().load(feed.getLink());
if (savedFeed == null)
savedFeed = DynamicDAO.save(feed);
IBookMark bookMark = fTypesFactory.createBookMark(null, folder, new FeedLinkReference(savedFeed.getLink()), "Default bookmark");
bookMark.setLastVisitDate(createDate());
bookMark.setPopularity(50);
bookMark.setErrorLoading(false);
return bookMark;
}
private IFolder createFolder() {
return createFolder(null);
}
private IFolder createFolder(IFolder parent) {
IFolder folder = fTypesFactory.createFolder(null, parent, "SomeFolder");
folder.setBlogrollLink(createURI("http://someuri.com"));
folder.setProperty("somekey", "somevalue");
return folder;
}
/**
* Checks: - Addition of person - That ADD event is issued - Updating of
* person - That UPDATE event is issued - Getting of person
*/
@Test
public void testAddUpdateAndGetPerson() {
IFeed feed = createFeed();
final Person initialJohn = (Person) createPersonJohn(feed);
final Person[] updatedJohn = new Person[1];
final boolean[] personAddedCalled = new boolean[] { false };
final boolean[] personUpdatedCalled = new boolean[] { false };
PersonListener personListener = null;
try {
personListener = new PersonAdapter() {
@Override
public void entitiesAdded(Set<PersonEvent> events) {
for (PersonEvent event : events) {
personAddedCalled[0] = true;
Person dbPerson = (Person) event.getEntity();
initialJohn.setId(dbPerson.getId());
assertTrue(initialJohn.isIdentical(dbPerson));
}
}
@Override
public void entitiesUpdated(Set<PersonEvent> events) {
PersonEvent event = events.iterator().next();
personUpdatedCalled[0] = true;
Person dbPerson = (Person) event.getEntity();
assertTrue(updatedJohn[0].isIdentical(dbPerson));
}
};
DynamicDAO.addEntityListener(IPerson.class, personListener);
long savedJohnId = DynamicDAO.save(initialJohn).getId().longValue();
System.gc();
IPerson savedJohn = DynamicDAO.load(IPerson.class, savedJohnId);
initialJohn.setId(savedJohn.getId());
assertTrue(initialJohn.isIdentical(savedJohn));
URI oldJohnEmail = savedJohn.getEmail();
IPerson dan = createPersonDan(feed);
dan.setEmail(oldJohnEmail);
DynamicDAO.removeEntityListener(IPerson.class, personListener);
DynamicDAO.save(dan);
savedJohn.setEmail(createURI("anewemailaddress@gmail.com"));
updatedJohn[0] = (Person) savedJohn;
DynamicDAO.addEntityListener(IPerson.class, personListener);
DynamicDAO.save(savedJohn);
assertTrue(personAddedCalled[0]);
assertTrue(personUpdatedCalled[0]);
DynamicDAO.delete(updatedJohn[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (personListener != null) {
DynamicDAO.removeEntityListener(IPerson.class, personListener);
}
}
}
/**
* Tests that {@link News#merge(INews)} copies the link property correctly.
*
* @throws Exception
*/
@Test
public void testNewsMergeLink() throws Exception {
IFeed feed = DynamicDAO.save(createFeed());
INews news = fTypesFactory.createNews(null, feed, new Date());
news.setId(1L);
news.setLink(createURI("http://www.uri.com"));
INews anotherNews = fTypesFactory.createNews(null, feed, new Date());
URI uri = createURI("http://www.anotheruri.com");
anotherNews.setLink(uri);
news.merge(anotherNews);
assertEquals(uri, news.getLink());
}
/**
* Tests INews#setLink.
*
* @throws Exception
*/
@Test
public void testNewsSetLink() throws Exception {
IFeed feed = DynamicDAO.save(createFeed());
INews news = fTypesFactory.createNews(null, feed, new Date());
URI uri = createURI("http://uri.com");
news.setLink(uri);
assertEquals(uri, news.getLink());
news.setLink(null);
assertNull(news.getLink());
news.setLink(uri);
assertEquals(uri, news.getLink());
URI anotherUri = createURI("http://anotheruri.com");
news.setLink(anotherUri);
assertEquals(anotherUri, news.getLink());
}
/**
* Tests deleting a INews and checking that the parent feed doesn't have it
* anymore.
*
* @throws PersistenceException
*/
@Test
public void testDeleteNews() throws PersistenceException {
IFeed feed = createFeed();
feed = DynamicDAO.save(feed);
INews news = createNews(feed);
news = DynamicDAO.save(news);
Long newsId = news.getId();
DynamicDAO.delete(new NewsReference(newsId).resolve());
feed = DynamicDAO.load(IFeed.class, feed.getId());
assertEquals(0, feed.getNews().size());
assertNull(DynamicDAO.load(INews.class, newsId));
}
/**
* Tests loading the root folders.
*/
@Test
public void testLoadRootFolders() {
try {
// Save root folders
IFolder folder1 = createFolder();
folder1 = DynamicDAO.save(folder1);
IFolder folder2 = fTypesFactory.createFolder(null, null, "AnotherFolder");
folder2 = DynamicDAO.save(folder2);
// Save non-root folder
IFolder nonRootFolder = createFolderWithParent();
DynamicDAO.save(nonRootFolder);
Collection<IFolder> rootFolderRefs = Owl.getPersistenceService().getDAOService().getFolderDAO().loadRoots();
assertEquals(3, rootFolderRefs.size());
for (IFolder rootFolder : rootFolderRefs) {
assertTrue(rootFolder.equals(folder1) || rootFolder.equals(folder2) || rootFolder.equals(nonRootFolder.getParent()));
}
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Simply adds and deletes a IBookMark and fails if an exceptions is thrown.
*/
@Test
public void testAddAndDeleteBookMark() {
try {
IBookMark bookMark = createBookMark();
bookMark = DynamicDAO.save(bookMark);
DynamicDAO.delete(bookMark);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Simply adds and deletes a ICategory with a feed as parent and fails if an
* exception is thrown.
*/
@Test
public void testAddAndDeleteFeedCategory() {
try {
ICategory category = createFeedCategory();
ICategory savedCategory = DynamicDAO.save(category);
DynamicDAO.delete(savedCategory);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Simply adds and deletes a ICategory with a news as parent and fails if an
* exception is thrown.
*/
@Test
public void testAddAndDeleteNewsCategory() {
try {
ICategory category = createNewsCategory();
ICategory savedCategory = DynamicDAO.save(category);
DynamicDAO.delete(savedCategory);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Adds, retrieves and checks if the added object matches the retrieved one.
*/
@Test
public void testAddAndGetFeedCategory() {
Category category = (Category) createFeedCategory();
DynamicDAO.save(category);
Collection<ICategory> categories = DynamicDAO.loadAll(ICategory.class);
assertEquals(1, categories.size());
category.setId(categories.iterator().next().getId());
assertTrue(category.isIdentical(categories.iterator().next()));
DynamicDAO.deleteAll(categories);
}
/**
* Adds, retrieves and checks if the added object matches the retrieved one.
*/
public void testAddAndGetNewsCategory() {
Category category = (Category) createNewsCategory();
DynamicDAO.save(category);
Collection<ICategory> categories = DynamicDAO.loadAll(ICategory.class);
assertEquals(1, categories.size());
category.setId(categories.iterator().next().getId());
assertTrue(category.isIdentical(categories.iterator().next()));
DynamicDAO.deleteAll(categories);
}
private ILabel createLabel() {
ILabel label = fTypesFactory.createLabel(null, "someLabel");
label.setColor("200,100,009");
return label;
}
/**
* Checks: - Addition of label - That ADD event is issued - Updating of label -
* That UPDATE event is issued - Getting of label
*/
@Test
public void testAddUpdateAndGetLabel() {
final Label initialLabel = (Label) createLabel();
final Label[] updatedLabel = new Label[1];
final boolean[] labelAddedCalled = new boolean[] { false };
final boolean[] labelUpdatedCalled = new boolean[] { false };
LabelListener labelListener = null;
try {
labelListener = new LabelAdapter() {
@Override
public void entitiesAdded(Set<LabelEvent> events) {
for (LabelEvent event : events) {
labelAddedCalled[0] = true;
Label dbLabel = (Label) event.getEntity();
initialLabel.setId(dbLabel.getId());
assertTrue(initialLabel.isIdentical(dbLabel));
}
}
@Override
public void entitiesUpdated(Set<LabelEvent> events) {
LabelEvent event = events.iterator().next();
labelUpdatedCalled[0] = true;
Label dbLabel = (Label) event.getEntity();
assertTrue(updatedLabel[0].isIdentical(dbLabel));
}
};
DynamicDAO.addEntityListener(ILabel.class, labelListener);
long savedLabelId = DynamicDAO.save(initialLabel).getId().longValue();
System.gc();
ILabel dbLabel = DynamicDAO.load(ILabel.class, savedLabelId);
initialLabel.setId(dbLabel.getId());
assertTrue(initialLabel.isIdentical(dbLabel));
dbLabel.setColor("255,255,137");
updatedLabel[0] = (Label) dbLabel;
DynamicDAO.save(dbLabel);
assertTrue(labelAddedCalled[0]);
assertTrue(labelUpdatedCalled[0]);
DynamicDAO.delete(updatedLabel[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (labelListener != null) {
DynamicDAO.removeEntityListener(ILabel.class, labelListener);
}
}
}
private void doTestAddUpdateGetAndDeleteSearchFilter(boolean gc) {
/* Add */
{
ISearch search = fTypesFactory.createSearch(null);
search.setMatchAllConditions(true);
ISearchCondition condition1 = fTypesFactory.createSearchCondition(fTypesFactory.createSearchField(INews.TITLE, INews.class.getName()), SearchSpecifier.IS, "Foo");
search.addSearchCondition(condition1);
ISearchCondition condition2 = fTypesFactory.createSearchCondition(fTypesFactory.createSearchField(INews.ATTACHMENTS_CONTENT, INews.class.getName()), SearchSpecifier.CONTAINS, "Bar");
search.addSearchCondition(condition2);
ISearchFilter filter = fTypesFactory.createSearchFilter(null, search, "Filter");
filter.setEnabled(true);
filter.setOrder(5);
IFilterAction action = fTypesFactory.createFilterAction("org.rssowl.ActionId1");
action.setData(100);
filter.addAction(action);
action = fTypesFactory.createFilterAction("org.rssowl.ActionId2");
action.setData(new Long[] { 1l, 2l, 3l });
filter.addAction(action);
filter = DynamicDAO.save(filter);
if (gc)
System.gc();
Collection<ISearchFilter> filters = DynamicDAO.loadAll(ISearchFilter.class);
assertEquals(1, filters.size());
ISearchFilter savedFilter = filters.iterator().next();
assertEquals(filter.getName(), savedFilter.getName());
assertEquals(filter.getOrder(), savedFilter.getOrder());
assertEquals(filter.isEnabled(), savedFilter.isEnabled());
List<IFilterAction> actions = savedFilter.getActions();
assertEquals(2, actions.size());
assertEquals("org.rssowl.ActionId1", actions.get(0).getActionId());
assertEquals(100, actions.get(0).getData());
assertEquals("org.rssowl.ActionId2", actions.get(1).getActionId());
assertEquals(true, Arrays.equals((Object[]) actions.get(1).getData(), new Long[] { 1l, 2l, 3l }));
ISearch savedSearch = savedFilter.getSearch();
assertEquals(search.matchAllConditions(), savedSearch.matchAllConditions());
List<ISearchCondition> savedConditions = savedSearch.getSearchConditions();
assertEquals(2, savedConditions.size());
assertEquals(true, ((SearchCondition) savedConditions.get(0)).isIdentical(condition1));
assertEquals(true, ((SearchCondition) savedConditions.get(1)).isIdentical(condition2));
}
/* Update */
{
Collection<ISearchFilter> filters = DynamicDAO.loadAll(ISearchFilter.class);
ISearchFilter savedFilter = filters.iterator().next();
savedFilter.setName("Disabled Filter");
savedFilter.setEnabled(false);
savedFilter.setOrder(1);
List<IFilterAction> actions = savedFilter.getActions();
savedFilter.removeAction(actions.get(0));
actions.get(1).setData(new Long[] { 3l, 2l, 1l });
IFilterAction action = fTypesFactory.createFilterAction("org.rssowl.ActionId3");
action.setData(200);
savedFilter.addAction(action);
ISearch savedSearch = savedFilter.getSearch();
savedSearch.setMatchAllConditions(false);
List<ISearchCondition> savedConditions = savedSearch.getSearchConditions();
ISearchCondition condition1 = savedConditions.get(0);
condition1.setSpecifier(SearchSpecifier.CONTAINS_NOT);
savedSearch.removeSearchCondition(savedConditions.get(1));
ISearchCondition condition2 = fTypesFactory.createSearchCondition(fTypesFactory.createSearchField(INews.LOCATION, INews.class.getName()), SearchSpecifier.IS, new Long[][] { { 2l } });
savedSearch.addSearchCondition(condition2);
DynamicDAO.save(savedFilter);
if (gc)
System.gc();
filters = DynamicDAO.loadAll(ISearchFilter.class);
assertEquals(1, filters.size());
ISearchFilter loadedFilter = filters.iterator().next();
assertEquals(savedFilter.getName(), loadedFilter.getName());
assertEquals(savedFilter.getOrder(), loadedFilter.getOrder());
assertEquals(savedFilter.isEnabled(), loadedFilter.isEnabled());
List<IFilterAction> loadedActions = loadedFilter.getActions();
assertEquals(2, loadedActions.size());
assertEquals("org.rssowl.ActionId2", loadedActions.get(0).getActionId());
assertEquals(true, Arrays.equals((Object[]) actions.get(1).getData(), new Long[] { 3l, 2l, 1l }));
assertEquals("org.rssowl.ActionId3", loadedActions.get(1).getActionId());
assertEquals(200, loadedActions.get(1).getData());
ISearch loadedSearch = loadedFilter.getSearch();
assertEquals(savedSearch.matchAllConditions(), loadedSearch.matchAllConditions());
List<ISearchCondition> loadedConditions = loadedSearch.getSearchConditions();
assertEquals(2, loadedConditions.size());
assertEquals(true, ((SearchCondition) loadedConditions.get(0)).isIdentical(condition1));
assertEquals(true, ((SearchCondition) loadedConditions.get(1)).isIdentical(condition2));
}
/* Delete */
{
Collection<ISearchFilter> filters = DynamicDAO.loadAll(ISearchFilter.class);
assertEquals(1, filters.size());
DynamicDAO.delete(filters.iterator().next());
if (gc)
System.gc();
filters = DynamicDAO.loadAll(ISearchFilter.class);
assertTrue(filters.isEmpty());
}
}
/**
* Test add, update, get and delete of ISearchFilter
*/
@Test
public void testAddUpdateGetAndDeleteSearchFilter() {
doTestAddUpdateGetAndDeleteSearchFilter(true);
doTestAddUpdateGetAndDeleteSearchFilter(false);
}
/**
* Checks: - Addition of category - That ADD event is issued - Updating of
* category - That UPDATE event is issued - Getting of category
*/
@Test
public void testAddUpdateAndGetCategory() {
final Category[] initialCategory = new Category[1];
try {
initialCategory[0] = (Category) createNewsCategory();
} catch (PersistenceException e) {
fail(e.getMessage());
}
final Category[] updatedCategory = new Category[1];
final boolean[] categoryAddedCalled = new boolean[] { false };
final boolean[] categoryUpdatedCalled = new boolean[] { false };
CategoryListener categoryListener = null;
try {
categoryListener = new CategoryAdapter() {
@Override
public void entitiesAdded(Set<CategoryEvent> events) {
CategoryEvent event = events.iterator().next();
try {
categoryAddedCalled[0] = true;
Category dbCategory = (Category) event.getEntity();
initialCategory[0].setId(dbCategory.getId());
assertTrue(initialCategory[0].isIdentical(dbCategory));
dbCategory.setDomain("newDomain/newDomain");
updatedCategory[0] = dbCategory;
DynamicDAO.save(dbCategory);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
@Override
public void entitiesUpdated(Set<CategoryEvent> events) {
CategoryEvent event = events.iterator().next();
categoryUpdatedCalled[0] = true;
Category dbCategory = (Category) event.getEntity();
assertTrue(updatedCategory[0].isIdentical(dbCategory));
}
};
DynamicDAO.addEntityListener(ICategory.class, categoryListener);
DynamicDAO.save(initialCategory[0]);
assertTrue(categoryAddedCalled[0]);
assertTrue(categoryUpdatedCalled[0]);
DynamicDAO.delete(updatedCategory[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (categoryListener != null) {
DynamicDAO.removeEntityListener(ICategory.class, categoryListener);
}
}
}
/**
* Tests adding, updating and getting a folder with no parent.
*/
@Test
public void testAddUpdateAndGetFolder() {
final Folder initialFolder = (Folder) createFolder();
final Folder[] updatedFolder = new Folder[1];
final boolean[] folderAddedCalled = new boolean[] { false };
final boolean[] folderUpdatedCalled = new boolean[] { false };
FolderListener folderListener = null;
try {
folderListener = new FolderAdapter() {
@Override
public void entitiesAdded(Set<FolderEvent> events) {
for (FolderEvent event : events) {
try {
folderAddedCalled[0] = true;
Folder dbFolder = (Folder) event.getEntity();
initialFolder.setId(dbFolder.getId());
assertTrue(NOT_IDENTICAL_MESSAGE, initialFolder.isIdentical(dbFolder));
dbFolder.setBlogrollLink(createURI("http://www.newuri.com"));
dbFolder.setName("New name");
updatedFolder[0] = dbFolder;
DynamicDAO.save(dbFolder);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
}
@Override
public void entitiesUpdated(Set<FolderEvent> events) {
for (FolderEvent event : events) {
folderUpdatedCalled[0] = true;
Folder dbFolder = (Folder) event.getEntity();
assertTrue(updatedFolder[0].isIdentical(dbFolder));
}
}
};
DynamicDAO.addEntityListener(IFolder.class, folderListener);
DynamicDAO.save(initialFolder);
assertTrue(folderAddedCalled[0]);
assertTrue(folderUpdatedCalled[0]);
DynamicDAO.delete(updatedFolder[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (folderListener != null) {
DynamicDAO.removeEntityListener(IFolder.class, folderListener);
}
}
}
private IFolder createFolderWithParent() throws PersistenceException {
IFolder parentFolder = createFolder();
parentFolder = DynamicDAO.save(parentFolder);
IFolder folder = fTypesFactory.createFolder(null, parentFolder, "MainFolder");
folder.setBlogrollLink(createURI("http://www.rssowl.com"));
folder.setProperty("skey", "svalue");
return folder;
}
/**
* Tests adding, updating and getting a folder that has a parent.
*/
@Test
public void testAddUpdateAndGetFolderWithParent() {
final Folder[] initialFolder = new Folder[1];
final String[] folderName = new String[1];
try {
initialFolder[0] = (Folder) createFolderWithParent();
folderName[0] = initialFolder[0].getName();
} catch (PersistenceException e) {
fail(e.getMessage());
}
final Folder[] updatedFolder = new Folder[1];
final boolean[] folderAddedCalled = new boolean[] { false };
final boolean[] folderUpdatedCalled = new boolean[] { false };
FolderListener folderListener = null;
try {
folderListener = new FolderAdapter() {
@Override
public void entitiesAdded(Set<FolderEvent> events) {
for (FolderEvent event : events) {
try {
folderAddedCalled[0] = true;
Folder dbFolder = (Folder) event.getEntity();
initialFolder[0].setId(dbFolder.getId());
assertTrue(initialFolder[0].isIdentical(dbFolder));
dbFolder.setBlogrollLink(createURI("http://www.newuri.com"));
updatedFolder[0] = dbFolder;
DynamicDAO.save(dbFolder);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
}
@Override
public void entitiesUpdated(Set<FolderEvent> events) {
for (FolderEvent event : events) {
/* Ignore event from parent */
if (!folderName[0].equals(event.getEntity().getName())) {
return;
}
folderUpdatedCalled[0] = true;
Folder dbFolder = (Folder) event.getEntity();
assertTrue(updatedFolder[0].isIdentical(dbFolder));
}
}
};
DynamicDAO.addEntityListener(IFolder.class, folderListener);
DynamicDAO.save(initialFolder[0]);
assertTrue(folderAddedCalled[0]);
assertTrue(folderUpdatedCalled[0]);
DynamicDAO.delete(updatedFolder[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (folderListener != null) {
DynamicDAO.removeEntityListener(IFolder.class, folderListener);
}
}
}
/**
* When updating a child folder, the root event should be on the folder where
* save is called.
*/
@Test
public void testRootFolderWhenFolderChildIsUpdated() {
final Folder[] initialFolder = new Folder[1];
final String[] folderName = new String[1];
try {
initialFolder[0] = (Folder) createFolderWithParent();
folderName[0] = initialFolder[0].getName();
} catch (PersistenceException e) {
fail(e.getMessage());
}
FolderListener folderListener = null;
try {
folderListener = new FolderAdapter() {
@Override
public void entitiesAdded(Set<FolderEvent> events) {
for (FolderEvent event : events) {
if (folderName[0].equals(event.getEntity().getName())) {
assertEquals(true, event.isRoot());
} else {
assertEquals(false, event.isRoot());
}
}
}
};
DynamicDAO.addEntityListener(IFolder.class, folderListener);
DynamicDAO.save(initialFolder[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (folderListener != null) {
DynamicDAO.removeEntityListener(IFolder.class, folderListener);
}
}
}
private IPerson createPersonJohn(IPersistable type) {
IPerson person = fTypesFactory.createPerson(null, type);
person.setName("John");
person.setEmail(createURI("john@hotmail.com"));
person.setUri(createURI("http://mysite.hotmail.com"));
person.setProperty("property", "property_value");
return person;
}
URI createURI(String uri) {
try {
return new URI(uri);
} catch (URISyntaxException e) {
// should not happen;
return null;
}
}
private IPerson createPersonMary(IPersistable type) {
IPerson person = fTypesFactory.createPerson(null, type);
person.setName("Mary");
person.setEmail(createURI("mary@hotmail.com"));
person.setUri(createURI("http://mary.hotmail.com"));
person.setProperty("test", "property");
return person;
}
@SuppressWarnings("unused")
private IPerson createPersonDan(IPersistable type) {
IPerson person = fTypesFactory.createPerson(null, type);
person.setName("Dan");
person.setEmail(createURI("dan@yahoo.com"));
return person;
}
/**
* Saves the same feed twice without merging. Should throw an
* UniqueConstraintException.
*
* @throws PersistenceException
*/
@Test(expected = UniqueConstraintException.class)
public void testSaveFeedTwice() throws PersistenceException {
DynamicDAO.save(createFeed());
DynamicDAO.save(createFeed());
}
/**
* Saves the same feed twice, but merge it before saving it a second time. No
* exception should be thrown.
*/
@Test
public void testSaveFeedTwiceAfterMerging() {
IFeed savedFeed = DynamicDAO.save(createFeed());
savedFeed.merge(createFeed());
DynamicDAO.save(savedFeed);
}
/**
* Tests adding, updating and getting a bookmark.
*/
@Test
public void testAddUpdateAndGetBookMark() {
BookMarkListener bookMarkListener = null;
try {
final BookMark initialBookMark = (BookMark) createBookMark();
final BookMark[] updatedBookMark = new BookMark[1];
final boolean[] bookMarkAddedCalled = new boolean[] { false };
final boolean[] bookMarkUpdatedCalled = new boolean[] { false };
bookMarkListener = new BookMarkAdapter() {
@Override
public void entitiesAdded(Set<BookMarkEvent> events) {
BookMarkEvent event = events.iterator().next();
try {
bookMarkAddedCalled[0] = true;
BookMark dbBookMark = (BookMark) event.getEntity();
initialBookMark.setId(dbBookMark.getId());
assertTrue(initialBookMark.isIdentical(dbBookMark));
dbBookMark.setName("Another name");
updatedBookMark[0] = dbBookMark;
DynamicDAO.save(dbBookMark);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
@Override
public void entitiesUpdated(Set<BookMarkEvent> events) {
BookMarkEvent event = events.iterator().next();
bookMarkUpdatedCalled[0] = true;
BookMark dbBookMark = (BookMark) event.getEntity();
assertTrue(updatedBookMark[0].isIdentical(dbBookMark));
}
};
DynamicDAO.addEntityListener(IBookMark.class, bookMarkListener);
DynamicDAO.save(initialBookMark);
assertTrue(bookMarkAddedCalled[0]);
assertTrue(bookMarkUpdatedCalled[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
}
finally {
if (bookMarkListener != null) {
DynamicDAO.removeEntityListener(IBookMark.class, bookMarkListener);
}
}
}
/**
* Tests adding, updating and getting a ISearchMark.
*/
@Test
public void testAddUpdateAndGetSearchMark() {
SearchMarkListener searchMarkListener = null;
try {
final SearchMark initialSearchMark = (SearchMark) createSearchMark();
final SearchMark[] updatedSearchMark = new SearchMark[1];
final boolean[] searchMarkAddedCalled = new boolean[] { false };
final boolean[] searchMarkUpdatedCalled = new boolean[] { false };
searchMarkListener = new SearchMarkAdapter() {
@Override
public void entitiesAdded(Set<SearchMarkEvent> events) {
SearchMarkEvent event = events.iterator().next();
try {
searchMarkAddedCalled[0] = true;
SearchMark dbSearchMark = (SearchMark) event.getEntity();
initialSearchMark.setId(dbSearchMark.getId());
assertTrue(initialSearchMark.isIdentical(dbSearchMark));
dbSearchMark.setName("Another name");
updatedSearchMark[0] = dbSearchMark;
DynamicDAO.save(dbSearchMark);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
@Override
public void entitiesUpdated(Set<SearchMarkEvent> events) {
SearchMarkEvent event = events.iterator().next();
searchMarkUpdatedCalled[0] = true;
SearchMark dbSearchMark = (SearchMark) event.getEntity();
assertTrue(updatedSearchMark[0].isIdentical(dbSearchMark));
}
};
DynamicDAO.addEntityListener(ISearchMark.class, searchMarkListener);
DynamicDAO.save(initialSearchMark);
assertTrue(searchMarkAddedCalled[0]);
assertTrue(searchMarkUpdatedCalled[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
}
finally {
if (searchMarkListener != null) {
DynamicDAO.removeEntityListener(ISearchMark.class, searchMarkListener);
}
}
}
private Date createDate() {
return new Date();
}
private IImage createImage(IFeed feed) {
IImage image = fTypesFactory.createImage(feed);
image.setHomepage(createURI("http://www.rssowl.org/image.png"));
return image;
}
/**
* Tests that saving a news with an attachment stores the attachment
* correctly.
*/
@Test
public void testAddAttachmentToNewsAfterGC() {
NewsListener newsListener = null;
try {
IFeed feed = createFeed();
INews news = createNews(feed);
List<IAttachment> attachments = new ArrayList<IAttachment>(news.getAttachments());
for (IAttachment attachment : attachments)
news.removeAttachment(attachment);
DynamicDAO.save(feed);
NewsReference newsRef = new NewsReference(feed.getNews().get(0).getId());
fTypesFactory.createAttachment(null, news);
DynamicDAO.save(feed);
feed = null;
news = null;
System.gc();
assertEquals(1, newsRef.resolve().getAttachments().size());
newsListener = new NewsAdapter() {
@Override
public void entitiesUpdated(Set<NewsEvent> events) {
assertEquals(1, events.size());
int attachmentsSize = events.iterator().next().getOldNews().getAttachments().size();
assertEquals(1, attachmentsSize);
}
};
DynamicDAO.addEntityListener(INews.class, newsListener);
DynamicDAO.save(newsRef.resolve());
} finally {
if (newsListener != null)
DynamicDAO.removeEntityListener(INews.class, newsListener);
}
}
/**
* Tests adding, updating and getting a news.
*/
@Test
public void testAddUpdateAndGetNews() {
final IFeed feed;
try {
feed = DynamicDAO.save(createFeed());
} catch (PersistenceException e) {
fail(e.getMessage());
return;
}
final News initialNews = (News) createNews(feed);
final Feed[] initialFeed = new Feed[1];
final Person[] initialAuthor = new Person[1];
final Source[] initialSource = new Source[1];
final Guid[] initialGuid = new Guid[1];
final News[] updatedNews = new News[1];
final boolean[] NewsAddedCalled = new boolean[] { false };
final boolean[] NewsUpdatedCalled = new boolean[] { false };
NewsListener newsListener = null;
try {
newsListener = new NewsAdapter() {
@Override
public void entitiesAdded(Set<NewsEvent> events) {
NewsEvent event = events.iterator().next();
NewsAddedCalled[0] = true;
initialFeed[0] = (Feed) initialNews.getFeedReference().resolve();
initialAuthor[0] = (Person) initialNews.getAuthor();
initialSource[0] = (Source) initialNews.getSource();
initialGuid[0] = (Guid) initialNews.getGuid();
final News dbNews = (News) event.getEntity();
initialAuthor[0].setId(dbNews.getAuthor().getId());
initialAuthor[0].isIdentical(dbNews.getAuthor());
//FIXME Find a way to verify this without changing the id from the
//event handler
// initialNews.setId(dbNews.getId());
// assertTrue(initialNews.isIdentical(dbNews));
}
@Override
public void entitiesUpdated(Set<NewsEvent> events) {
NewsEvent event = events.iterator().next();
NewsUpdatedCalled[0] = true;
News dbNews = (News) event.getEntity();
assertTrue(updatedNews[0].isIdentical(dbNews));
}
};
DynamicDAO.addEntityListener(INews.class, newsListener);
INews news = DynamicDAO.save(initialNews);
news.setDescription("The description has been changed in the news");
news.setState(State.UNREAD);
updatedNews[0] = (News) news;
DynamicDAO.save(news);
assertTrue(NewsAddedCalled[0]);
assertTrue(NewsUpdatedCalled[0]);
DynamicDAO.delete(updatedNews[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (newsListener != null) {
DynamicDAO.removeEntityListener(INews.class, newsListener);
}
}
}
/**
* Tests that {@link IFeedDAO#save(IFeed)} cascades the complex types of INews
* appropriately.
*/
@Test
public void testSaveFeedNewsCascadeWithGC() {
IFeed feed = createFeed();
INews news = createNews(feed);
DynamicDAO.save(feed);
String authorName = news.getAuthor().getName();
URI attachmentLink = news.getAttachments().get(0).getLink();
String categoryName = news.getCategories().get(0).getName();
URI sourceLink = news.getSource().getLink();
DynamicDAO.save(news);
NewsReference newsRef = new NewsReference(news.getId());
feed = null;
news = null;
System.gc();
news = newsRef.resolve();
assertNewsEquals(categoryName, attachmentLink, authorName, sourceLink, news);
authorName = authorName + " changed";
attachmentLink = createURI(attachmentLink.toString() + "/new");
categoryName = categoryName + " changed";
sourceLink = createURI(sourceLink.toString() + "/new");
updateNews(authorName, attachmentLink, categoryName, sourceLink, news);
DynamicDAO.save(news.getFeedReference().resolve());
news = null;
System.gc();
news = newsRef.resolve();
assertNewsEquals(categoryName, attachmentLink, authorName, sourceLink, news);
}
/**
* Tests that {@link INewsDAO#save(INews)} cascades the complex types
* appropriately.
*/
@Test
public void testSaveNewsCascadeWithGC() {
IFeed feed = createFeed();
DynamicDAO.save(feed);
INews news = createNews(feed);
String authorName = news.getAuthor().getName();
URI attachmentLink = news.getAttachments().get(0).getLink();
String categoryName = news.getCategories().get(0).getName();
URI sourceLink = news.getSource().getLink();
DynamicDAO.save(news);
NewsReference newsRef = new NewsReference(news.getId());
feed = null;
news = null;
System.gc();
news = newsRef.resolve();
assertNewsEquals(categoryName, attachmentLink, authorName, sourceLink, news);
authorName = authorName + " changed";
attachmentLink = createURI(attachmentLink.toString() + "/new");
categoryName = categoryName + " changed";
sourceLink = createURI(sourceLink.toString() + "/new");
updateNews(authorName, attachmentLink, categoryName, sourceLink, news);
DynamicDAO.save(news);
news = null;
System.gc();
news = newsRef.resolve();
assertNewsEquals(categoryName, attachmentLink, authorName, sourceLink, news);
}
/**
* Tests that {@link DynamicDAO#saveAll(Collection)} cascades the complex
* types appropriately.
*/
@Test
public void testSaveNewsListCascadeWithGC() {
IFeed feed = createFeed();
DynamicDAO.save(feed);
INews news = createNews(feed);
String authorName = news.getAuthor().getName();
URI attachmentLink = news.getAttachments().get(0).getLink();
String categoryName = news.getCategories().get(0).getName();
URI sourceLink = news.getSource().getLink();
DynamicDAO.saveAll(Collections.singletonList(news));
NewsReference newsRef = new NewsReference(news.getId());
feed = null;
news = null;
System.gc();
news = newsRef.resolve();
assertNewsEquals(categoryName, attachmentLink, authorName, sourceLink, news);
authorName = authorName + " changed";
attachmentLink = createURI(attachmentLink.toString() + "/new");
categoryName = categoryName + " changed";
sourceLink = createURI(sourceLink.toString() + "/new");
updateNews(authorName, attachmentLink, categoryName, sourceLink, news);
DynamicDAO.saveAll(Collections.singletonList(news));
news = null;
System.gc();
news = newsRef.resolve();
assertNewsEquals(categoryName, attachmentLink, authorName, sourceLink, news);
}
private void updateNews(String authorName, URI attachmentLink, String categoryName, URI sourceLink, INews news) {
news.getAuthor().setName(authorName);
news.getAttachments().get(0).setLink(attachmentLink);
news.getCategories().get(0).setName(categoryName);
news.getSource().setLink(sourceLink);
}
private void assertNewsEquals(String categoryName, URI attachmentLink, String authorName, URI sourceLink, INews news) {
assertNotNull(news);
assertEquals(1, news.getCategories().size());
assertEquals(categoryName, news.getCategories().get(0).getName());
assertEquals(1, news.getAttachments().size());
assertEquals(attachmentLink, news.getAttachments().get(0).getLink());
assertEquals(authorName, news.getAuthor().getName());
assertEquals(sourceLink, news.getSource().getLink());
}
private INews createNews(IFeed feed) {
INews news = fTypesFactory.createNews(null, feed, createDate());
IAttachment attachment = fTypesFactory.createAttachment(null, news);
attachment.setLink(createURI("http://attachmenturi.com"));
ICategory category = fTypesFactory.createCategory(null, news);
category.setName("Category name #1");
news.setAuthor(createPersonMary(news));
news.setBase(createURI("http://www.someuri.com"));
news.setComments("One comment");
news.setState(State.HIDDEN);
news.setDescription("News description");
fTypesFactory.createGuid(news, "someGUIDvalue", null);
news.setLink(createURI("http://www.somelocation.com/feed.rss"));
news.setModifiedDate(createDate());
news.setProperty("property", "value");
news.setPublishDate(createDate());
ISource source = fTypesFactory.createSource(news);
source.setLink(createURI("http://www.someuri.com"));
news.setSource(source);
news.setTitle("This is the news title");
news.setRating(70);
return news;
}
private Feed createFeed() {
return createFeed("http://www.rssowl.org/feed.rss");
}
private Feed createFeed(String link) {
Feed feed = (Feed) fTypesFactory.createFeed(null, createURI(link));
feed.setTitle("feed title");
feed.setDescription("feed description");
feed.setHomepage(createURI("http://www.rssowl.org"));
feed.setAuthor(createPersonJohn(feed));
feed.setLanguage("English");
feed.setCopyright("This feed is copyrighted");
feed.setDocs(createURI("http://www.rssowl.org/documentation.html"));
feed.setGenerator("Manual");
feed.setImage(createImage(feed));
feed.setPublishDate(createDate());
feed.setLastBuildDate(createDate());
feed.setLastModifiedDate(createDate());
feed.setWebmaster("Webmaster");
feed.setTTL(60);
feed.setFormat("RSS");
feed.setProperty("feedProperty", "randomValue");
feed.setBase(createURI("http://www.baseuri.com/"));
return feed;
}
/**
* Saves feed and verifies that the feed still contains the news after being
* GC'd and reloaded. See bug #261.
*
* @throws Exception
*/
@Test
public void testFeedRetainsLinkToNewsAfterSave() throws Exception {
IFeed feed = createFeed();
/* Need to save this without the news first */
DynamicDAO.save(feed);
createNews(feed);
DynamicDAO.save(feed);
long feedId = feed.getId();
feed = null;
System.gc();
IFeed savedFeed = DynamicDAO.load(IFeed.class, feedId);
assertEquals(1, savedFeed.getNews().size());
DynamicDAO.delete(new FeedReference(feedId).resolve());
}
/**
* @throws Exception
*/
@Test
public void testDeleteFeed() throws Exception {
IFeed feed = createFeed();
createNews(feed);
fTypesFactory.createNews(null, feed, new Date());
DynamicDAO.save(feed);
FeedReference feedRef = new FeedReference(feed.getId());
System.gc();
DynamicDAO.delete(feedRef.resolve());
assertNull(DynamicDAO.load(IFeed.class, feedRef.getId()));
}
/**
* @throws Exception
*/
@Test
public void testDeleteFeedDeletesConditionalGet() throws Exception {
IFeed feed = createFeed();
DynamicDAO.save(feed);
IConditionalGet conditionalGet = fTypesFactory.createConditionalGet("2005/11/04", feed.getLink(), null);
DynamicDAO.save(conditionalGet);
DynamicDAO.delete(feed);
assertNull(DynamicDAO.load(IFeed.class, feed.getId()));
assertNull(DynamicDAO.getDAO(IConditionalGetDAO.class).load(feed.getLink()));
}
/**
*
*/
@Test
public void testAddUpdateAndGetConditionalGet() {
IFeed feed = createFeed();
DynamicDAO.save(feed);
final String ifModifiedSince = "2005/11/04";
final String ifNoneMatch = "2005/05/12";
IConditionalGet conditionalGet = fTypesFactory.createConditionalGet(ifModifiedSince, feed.getLink(), ifNoneMatch);
DynamicDAO.save(conditionalGet);
conditionalGet = null;
System.gc();
conditionalGet = DynamicDAO.getDAO(IConditionalGetDAO.class).load(feed.getLink());
assertEquals(ifModifiedSince, conditionalGet.getIfModifiedSince());
assertEquals(ifNoneMatch, conditionalGet.getIfNoneMatch());
assertEquals(feed.getLink().toString(), conditionalGet.getLink().toString());
}
/**
* Simply adds and deletes a feed and fails if an exception is thrown
*/
@Test
public void testAddAndDeleteFeed() {
try {
IFeed feed = createFeed();
feed = DynamicDAO.save(feed);
DynamicDAO.delete(new FeedReference(feed.getId()).resolve());
assertNull(DynamicDAO.load(IFeed.class, feed.getId()));
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Simply adds and deletes a feed and fails if an exception is thrown
*/
@Test
public void testAddAndDeleteFeed2() {
try {
IFeed feed = createFeed();
feed = DynamicDAO.save(feed);
DynamicDAO.delete(feed);
assertNull(DynamicDAO.load(IFeed.class, feed.getId()));
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Tests adding, updating and getting a feed.
*/
// TODO Need to test news and categories
@Test
public void testAddUpdateAndGetFeed() {
final Feed initialFeed = createFeed();
final Person[] initialAuthor = new Person[1];
final Image[] initialImage = new Image[1];
final Feed[] updatedFeed = new Feed[1];
final boolean[] feedAddedCalled = new boolean[] { false };
final boolean[] feedUpdatedCalled = new boolean[] { false };
FeedListener feedListener = null;
try {
feedListener = new FeedAdapter() {
@Override
public void entitiesAdded(Set<FeedEvent> events) {
FeedEvent event = events.iterator().next();
try {
feedAddedCalled[0] = true;
initialAuthor[0] = (Person) initialFeed.getAuthor();
initialImage[0] = (Image) initialFeed.getImage();
Feed dbFeed = (Feed) event.getEntity();
initialAuthor[0].setId(dbFeed.getAuthor().getId());
initialAuthor[0].isIdentical(dbFeed.getAuthor());
initialImage[0].equals(dbFeed.getImage());
initialFeed.setId(dbFeed.getId());
assertTrue(NOT_IDENTICAL_MESSAGE, initialFeed.isIdentical(dbFeed));
dbFeed.setCopyright("GPL");
dbFeed.setFormat("someDifferentformat");
dbFeed.getImage().setHeight(150);
dbFeed.getImage().setDescription("Some new description");
dbFeed.getImage().setTitle("yet another title");
updatedFeed[0] = dbFeed;
DynamicDAO.save(dbFeed);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
@Override
public void entitiesUpdated(Set<FeedEvent> events) {
FeedEvent event = events.iterator().next();
feedUpdatedCalled[0] = true;
Feed dbFeed = (Feed) event.getEntity();
assertTrue(updatedFeed[0].isIdentical(dbFeed));
}
};
DynamicDAO.addEntityListener(IFeed.class, feedListener);
DynamicDAO.save(initialFeed);
assertTrue(feedAddedCalled[0]);
assertTrue(feedUpdatedCalled[0]);
assertTrue(DynamicDAO.exists(IFeed.class, initialFeed.getId()));
DynamicDAO.delete(updatedFeed[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (feedListener != null) {
DynamicDAO.removeEntityListener(IFeed.class, feedListener);
}
}
}
/**
* Tests that the image attribute override solves the name clashes between
* certain column names in Feed and Image.
*/
@Test
public void testImageAttributeOverride() {
final Feed initialFeed = createFeed();
final URI feedLink = initialFeed.getLink();
IImage image = fTypesFactory.createImage(initialFeed);
image.setHomepage(createURI("http://www.someuri.com"));
initialFeed.setImage(image);
initialFeed.getImage().setDescription("Some description");
initialFeed.getImage().setTitle("Title");
initialFeed.getImage().setHomepage(createURI("http://www.imageuri.com"));
final Feed[] updatedFeed = new Feed[1];
FeedListener feedListener = null;
try {
feedListener = new FeedAdapter() {
@Override
public void entitiesAdded(Set<FeedEvent> events) {
try {
FeedEvent event = events.iterator().next();
Feed dbFeed = (Feed) event.getEntity();
dbFeed.setDescription("feed description2");
dbFeed.setTitle("feed title2");
dbFeed.getImage().setDescription("Some new description");
dbFeed.getImage().setTitle("yet another title");
dbFeed.getImage().setHomepage(createURI("http://www.newimageuri.com"));
updatedFeed[0] = dbFeed;
DynamicDAO.save(dbFeed);
} catch (PersistenceException e) {
TestUtils.fail(e);
}
}
@Override
public void entitiesUpdated(Set<FeedEvent> events) {
try {
FeedEvent event = events.iterator().next();
// TODO Add method to load entities without using the cache and
// then use it here. Atm, this test won't actually show the bug
// we want it to show because it's getting the feed from the cache
// bypassing the db inconsistency
Feed dbFeed = (Feed) event.getEntity();
assertEquals(feedLink.toString(), dbFeed.getLink().toString());
} catch (RuntimeException re) {
fail(re.getMessage());
}
}
};
DynamicDAO.addEntityListener(IFeed.class, feedListener);
DynamicDAO.save(initialFeed);
DynamicDAO.delete(updatedFeed[0]);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (feedListener != null) {
DynamicDAO.removeEntityListener(IFeed.class, feedListener);
}
}
}
/**
* Tests that no event is sent when NewsManager#setState() is called and the
* new state is the same as the old state.
*/
@Test
public void testNewsManagerSetSameStateWithQuery() {
final IFeed feed;
try {
feed = DynamicDAO.save(createFeed());
} catch (PersistenceException e) {
fail(e.getMessage());
return;
}
final News initialNews = (News) createNews(feed);
initialNews.setState(State.NEW);
INews news = null;
try {
news = DynamicDAO.save(initialNews);
} catch (PersistenceException e) {
fail(e.getMessage());
return;
}
NewsListener newsListener = null;
try {
newsListener = new NewsListener() {
public void entitiesAdded(Set<NewsEvent> events) {
fail("No events should have been fired, but NewsListener#entitiesAdded() was called");
}
public void entitiesDeleted(Set<NewsEvent> events) {
fail("No events should have been fired, but NewsListener#newsDeleted() was called.");
}
public void entitiesUpdated(Set<NewsEvent> events) {
fail("No events should have been fired, but NewsListener#newsUpdated() was called.");
}
};
DynamicDAO.addEntityListener(INews.class, newsListener);
List<INews> newsList = new ArrayList<INews>();
newsList.add(news);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.NEW, true, false);
DynamicDAO.removeEntityListener(INews.class, newsListener);
DynamicDAO.delete(news);
DynamicDAO.delete(feed);
} catch (PersistenceException e) {
fail(e.getMessage());
} finally {
if (newsListener != null) {
DynamicDAO.removeEntityListener(INews.class, newsListener);
}
}
}
/**
* Tests {@link INewsDAO#setState(Collection, State, boolean, boolean)}
*/
@Test
public void testNewsManagerSetState() {
final IFeed feed;
feed = DynamicDAO.save(createFeed());
final News initialNews = (News) createNews(feed);
initialNews.setState(State.NEW);
INews newsItem = null;
NewsReference newsRef = null;
newsItem = DynamicDAO.save(initialNews);
newsRef = new NewsReference(newsItem.getId());
List<INews> newsList = new ArrayList<INews>();
newsList.add(newsItem);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.UPDATED, true, false);
INews news = newsRef.resolve();
assertEquals(State.UPDATED, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.DELETED, true, false);
news = newsRef.resolve();
assertEquals(State.DELETED, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.HIDDEN, false, false);
news = newsRef.resolve();
assertEquals(State.HIDDEN, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.READ, false, false);
news = newsRef.resolve();
assertEquals(State.READ, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.UNREAD, true, false);
news = newsRef.resolve();
assertEquals(State.UNREAD, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.NEW, true, false);
news = newsRef.resolve();
assertEquals(State.NEW, news.getState());
// Make sure it doesn't change when we set it to the same
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.NEW, true, false);
news = newsRef.resolve();
assertEquals(State.NEW, news.getState());
DynamicDAO.delete(newsRef.resolve());
DynamicDAO.delete(feed);
}
/**
* Tests that affectEquivalentNews is not supported when the news is not
* visible.
*/
@Test(expected = IllegalArgumentException.class)
public void testNewsDAOSetStateFromDeletedWithAffectEquivalentNews() {
final IFeed feed;
feed = DynamicDAO.save(createFeed());
final News initialNews = (News) createNews(feed);
initialNews.setState(State.NEW);
INews newsItem = null;
NewsReference newsRef = null;
newsItem = DynamicDAO.save(initialNews);
newsRef = new NewsReference(newsItem.getId());
List<INews> newsList = new ArrayList<INews>();
newsList.add(newsItem);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.DELETED, true, false);
INews news = newsRef.resolve();
assertEquals(State.DELETED, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.HIDDEN, true, false);
}
/**
* Tests that affectEquivalentNews is not supported when the news is not
* visible.
*/
@Test(expected = IllegalArgumentException.class)
public void testNewsDAOSetStateFromHiddenWithAffectEquivalentNews() {
final IFeed feed;
feed = DynamicDAO.save(createFeed());
final News initialNews = (News) createNews(feed);
initialNews.setState(State.NEW);
INews newsItem = null;
NewsReference newsRef = null;
newsItem = DynamicDAO.save(initialNews);
newsRef = new NewsReference(newsItem.getId());
List<INews> newsList = new ArrayList<INews>();
newsList.add(newsItem);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.HIDDEN, true, false);
INews news = newsRef.resolve();
assertEquals(State.HIDDEN, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.READ, true, false);
}
/**
* Tests that the folders inside the folder are returned from the db in the
* same order as they were saved.
*
* @throws PersistenceException
*/
@Test
public void testFoldersOrder() throws PersistenceException {
IFolder root = createFolder();
root = DynamicDAO.save(root);
for (int i = 0; i < 10; ++i) {
IFolder child = createFolder(root);
child.setName(String.valueOf(i));
}
root = DynamicDAO.save(root);
int counter = 0;
for (IFolder child : root.getFolders()) {
String name = String.valueOf(counter++);
assertEquals(name, child.getName());
}
}
/**
* Tests that the marks inside the folder are returned from the db in the same
* order as they were saved.
*
* @throws PersistenceException
*/
@Test
public void testMarksOrder() throws PersistenceException {
IFolder root = createFolder();
root = DynamicDAO.save(root);
int count = 10;
for (int i = 0; i < count; ++i) {
IBookMark child = createBookMark(root);
child.setName(String.valueOf(i));
}
int count2 = count * 2;
for (int i = count; i < count2; ++i) {
ISearchMark child = createSearchMark(root);
child.setName(String.valueOf(i));
}
root = DynamicDAO.save(root);
int counter = 0;
for (IMark child : root.getMarks()) {
String name = String.valueOf(counter++);
assertEquals(name, child.getName());
}
}
private ISearchMark createSearchMark(IFolder folder) {
ISearchMark mark = fTypesFactory.createSearchMark(null, folder, "SomeName");
mark.setCreationDate(new Date());
mark.setLastVisitDate(createDate());
mark.setPopularity(50);
ISearchField field1 = fTypesFactory.createSearchField(INews.STATE, INews.class.getName());
fTypesFactory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, State.NEW);
ISearchField field2 = fTypesFactory.createSearchField(INews.STATE, INews.class.getName());
fTypesFactory.createSearchCondition(null, mark, field2, SearchSpecifier.IS, State.UPDATED);
ISearchField field3 = fTypesFactory.createSearchField(INews.STATE, INews.class.getName());
fTypesFactory.createSearchCondition(null, mark, field3, SearchSpecifier.IS, State.UNREAD);
return mark;
}
/**
* Tests that {@link INewsDAO#setState(Collection, State, boolean, boolean)}
* changes the state in news that have the same link but are in different
* feeds.
*/
@Test
public void testNewsManagerSetStateWithMultipleFeedsAndGuidNull() {
final IFeed feed1;
IFeed feed2;
NewsAdapter newsAdapter;
try {
feed1 = DynamicDAO.save(createFeed());
IFeed tempFeed = createFeed("http://adifferentlink.com");
tempFeed.setTitle("A different title");
feed2 = DynamicDAO.save(tempFeed);
} catch (PersistenceException e) {
fail(e.getMessage());
return;
}
final NewsReference[] newsRef = new NewsReference[1];
newsAdapter = new NewsAdapter() {
@Override
public void entitiesAdded(Set<NewsEvent> events) {
assertEquals(1, events.size());
newsRef[0] = new NewsReference(events.iterator().next().getEntity().getId());
}
};
DynamicDAO.addEntityListener(INews.class, newsAdapter);
final News initialNews1 = (News) createNews(feed1);
initialNews1.setGuid(null);
initialNews1.setState(State.NEW);
final News initialNews2 = (News) createNews(feed2);
initialNews2.setGuid(null);
initialNews2.setState(State.NEW);
INews newsItem1 = null;
NewsReference newsRef1 = null;
INews newsItem2 = null;
NewsReference newsRef2 = null;
NewsReference newsRef3 = null;
try {
DynamicDAO.save(feed1);
newsRef1 = newsRef[0];
newsItem1 = newsRef1.resolve();
feed2 = DynamicDAO.save(feed2);
newsRef2 = newsRef[0];
newsItem2 = newsRef2.resolve();
final News initialNews3 = (News) createNews(feed2);
initialNews3.setTitle("Some other title");
initialNews3.setGuid(null);
initialNews3.setLink(null);
initialNews3.setState(State.NEW);
DynamicDAO.save(feed2);
newsRef3 = newsRef[0];
} catch (PersistenceException e) {
fail(e.getMessage());
return;
} finally {
DynamicDAO.removeEntityListener(INews.class, newsAdapter);
}
try {
List<INews> newsList1 = new ArrayList<INews>();
newsList1.add(newsItem1);
List<INews> newsList2 = new ArrayList<INews>();
newsList2.add(newsItem2);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.UPDATED, true, false);
INews news1 = newsRef1.resolve();
INews news2 = newsRef2.resolve();
INews news3 = newsRef3.resolve();
assertEquals(State.UPDATED, news1.getState());
assertEquals(State.UPDATED, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList2, State.READ, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.READ, news1.getState());
assertEquals(State.READ, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.UNREAD, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.UNREAD, news1.getState());
assertEquals(State.UNREAD, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList2, State.READ, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.READ, news1.getState());
assertEquals(State.READ, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.UNREAD, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.UNREAD, news1.getState());
assertEquals(State.UNREAD, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList2, State.NEW, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.NEW, news1.getState());
assertEquals(State.NEW, news2.getState());
assertEquals(State.NEW, news3.getState());
// Make sure it doesn't change when we set it to the same
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.NEW, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.NEW, news1.getState());
assertEquals(State.NEW, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.HIDDEN, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.HIDDEN, news1.getState());
assertEquals(State.HIDDEN, news2.getState());
assertEquals(State.NEW, news3.getState());
DynamicDAO.delete(newsRef1.resolve());
DynamicDAO.delete(newsRef2.resolve());
DynamicDAO.delete(feed1);
DynamicDAO.delete(feed2);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Tests that {@link INewsDAO#setState(Collection, State, boolean, boolean)}
* changes the state in news that have the same guid but are in different
* feeds.
*/
@Test
public void testNewsManagerSetStateWithMultipleFeeds() {
final IFeed feed1;
IFeed feed2;
NewsListener newsAdapter = null;
try {
feed1 = DynamicDAO.save(createFeed());
IFeed tempFeed = createFeed("http://adifferentlink.com");
tempFeed.setTitle("A different title");
feed2 = DynamicDAO.save(tempFeed);
} catch (PersistenceException e) {
fail(e.getMessage());
return;
}
final News initialNews1 = (News) createNews(feed1);
initialNews1.setState(State.NEW);
final News initialNews2 = (News) createNews(feed2);
initialNews2.setState(State.NEW);
final NewsReference[] newsRef = new NewsReference[1];
newsAdapter = new NewsAdapter() {
@Override
public void entitiesAdded(Set<NewsEvent> events) {
assertEquals(1, events.size());
newsRef[0] = new NewsReference(events.iterator().next().getEntity().getId());
}
};
DynamicDAO.addEntityListener(INews.class, newsAdapter);
INews newsItem1 = null;
NewsReference newsRef1 = null;
INews newsItem2 = null;
NewsReference newsRef2 = null;
NewsReference newsRef3 = null;
try {
DynamicDAO.save(feed1);
newsRef1 = newsRef[0];
newsItem1 = newsRef1.resolve();
feed2 = DynamicDAO.save(feed2);
newsRef2 = newsRef[0];
newsItem2 = newsRef2.resolve();
final News initialNews3 = (News) createNews(feed2);
initialNews3.setTitle("Some other title");
initialNews3.setGuid(null);
initialNews3.setLink(null);
initialNews3.setState(State.NEW);
DynamicDAO.save(feed2);
newsRef3 = newsRef[0];
} catch (PersistenceException e) {
fail(e.getMessage());
return;
} finally {
DynamicDAO.removeEntityListener(INews.class, newsAdapter);
}
try {
List<INews> newsList1 = new ArrayList<INews>();
newsList1.add(newsItem1);
List<INews> newsList2 = new ArrayList<INews>();
newsList2.add(newsItem2);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.UPDATED, true, false);
INews news1 = newsRef1.resolve();
INews news2 = newsRef2.resolve();
INews news3 = newsRef3.resolve();
assertEquals(State.UPDATED, news1.getState());
assertEquals(State.UPDATED, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList2, State.READ, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.READ, news1.getState());
assertEquals(State.READ, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.UNREAD, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.UNREAD, news1.getState());
assertEquals(State.UNREAD, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList2, State.READ, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.READ, news1.getState());
assertEquals(State.READ, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.UNREAD, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.UNREAD, news1.getState());
assertEquals(State.UNREAD, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList2, State.NEW, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.NEW, news1.getState());
assertEquals(State.NEW, news2.getState());
assertEquals(State.NEW, news3.getState());
// Make sure it doesn't change when we set it to the same
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.NEW, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.NEW, news1.getState());
assertEquals(State.NEW, news2.getState());
assertEquals(State.NEW, news3.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList1, State.DELETED, true, false);
news1 = newsRef1.resolve();
news2 = newsRef2.resolve();
news3 = newsRef3.resolve();
assertEquals(State.DELETED, news1.getState());
assertEquals(State.DELETED, news2.getState());
assertEquals(State.NEW, news3.getState());
DynamicDAO.delete(newsRef1.resolve());
DynamicDAO.delete(newsRef2.resolve());
DynamicDAO.delete(feed1);
DynamicDAO.delete(feed2);
} catch (PersistenceException e) {
fail(e.getMessage());
}
}
/**
* Tests {@link INewsDAO#setState(Collection, State, boolean, boolean)}.
*/
@Test
public void testNewsManagerSetStateWithGuidNull() {
final IFeed feed = DynamicDAO.save(createFeed());
final News initialNews = (News) createNews(feed);
initialNews.setState(State.NEW);
initialNews.setGuid(null);
INews newsItem = null;
NewsReference newsRef = null;
newsItem = DynamicDAO.save(initialNews);
newsRef = new NewsReference(newsItem.getId());
List<INews> newsList = new ArrayList<INews>();
newsList.add(newsItem);
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.UPDATED, true, false);
INews news = newsRef.resolve();
assertEquals(State.UPDATED, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.READ, true, false);
news = newsRef.resolve();
assertEquals(State.READ, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.UNREAD, true, false);
news = newsRef.resolve();
assertEquals(State.UNREAD, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.READ, true, false);
news = newsRef.resolve();
assertEquals(State.READ, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.UNREAD, true, false);
news = newsRef.resolve();
assertEquals(State.UNREAD, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.NEW, true, false);
news = newsRef.resolve();
assertEquals(State.NEW, news.getState());
// Make sure it doesn't change when we set it to the same
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.NEW, true, false);
news = newsRef.resolve();
assertEquals(State.NEW, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.DELETED, true, false);
news = newsRef.resolve();
assertEquals(State.DELETED, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.READ, false, false);
news = newsRef.resolve();
assertEquals(State.READ, news.getState());
Owl.getPersistenceService().getDAOService().getNewsDAO().setState(newsList, State.HIDDEN, false, false);
news = newsRef.resolve();
assertEquals(State.HIDDEN, news.getState());
DynamicDAO.delete(newsRef.resolve());
DynamicDAO.delete(feed);
}
/**
* Tests {@link NewsCounterService} for added news that are DELETED
*/
@Test
public void testNewsCounterOnDeletedAddedNews() {
final IFeed feed = DynamicDAO.save(createFeed());
INews news = createNews(feed);
news.setFlagged(true);
news.setState(INews.State.DELETED);
DynamicDAO.save(news);
IFolder folder = Owl.getModelFactory().createFolder(null, null, "Root");
IBookMark bookmark = Owl.getModelFactory().createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Bookmark");
DynamicDAO.save(bookmark);
assertEquals(0, bookmark.getStickyNewsCount());
assertEquals(0, bookmark.getNewsCount(INews.State.getVisible()));
}
/**
* Tests {@link NewsCounterService} for added news that are DELETED and Sticky
*/
@Test
public void testNewsCounterOnStickyDeletedNews() {
final IFeed feed = DynamicDAO.save(createFeed());
INews news = createNews(feed);
news.setState(INews.State.NEW);
news.setFlagged(true);
DynamicDAO.save(news);
IFolder folder = Owl.getModelFactory().createFolder(null, null, "Root");
IBookMark bookmark = Owl.getModelFactory().createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Bookmark");
DynamicDAO.save(bookmark);
assertEquals(1, bookmark.getStickyNewsCount());
assertEquals(1, bookmark.getNewsCount(INews.State.getVisible()));
DynamicDAO.getDAO(INewsDAO.class).setState(Collections.singleton(news), INews.State.HIDDEN, false, false);
assertEquals(0, bookmark.getStickyNewsCount());
assertEquals(0, bookmark.getNewsCount(INews.State.getVisible()));
DynamicDAO.getDAO(INewsDAO.class).setState(Collections.singleton(news), INews.State.DELETED, false, false);
assertEquals(0, bookmark.getStickyNewsCount());
assertEquals(0, bookmark.getNewsCount(INews.State.getVisible()));
}
}