/* ********************************************************************** **
** 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.internal.persist.dao;
import org.eclipse.core.runtime.Assert;
import org.rssowl.core.internal.persist.Folder;
import org.rssowl.core.internal.persist.service.DBHelper;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IFolderChild;
import org.rssowl.core.persist.IMark;
import org.rssowl.core.persist.INewsBin;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.dao.IFolderDAO;
import org.rssowl.core.persist.event.BookMarkEvent;
import org.rssowl.core.persist.event.FolderEvent;
import org.rssowl.core.persist.event.FolderListener;
import org.rssowl.core.persist.event.MarkEvent;
import org.rssowl.core.persist.event.NewsBinEvent;
import org.rssowl.core.persist.event.SearchMarkEvent;
import org.rssowl.core.persist.service.PersistenceException;
import org.rssowl.core.util.ReparentInfo;
import com.db4o.ext.Db4oException;
import com.db4o.query.Query;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* A data-access-object for <code>IFolder</code>s.
*
* @author Ismael Juma (ismael@juma.me.uk)
*/
public final class FolderDAOImpl extends AbstractEntityDAO<IFolder, FolderListener, FolderEvent> implements IFolderDAO {
/** Default constructor using the specific IPersistable for this DAO */
public FolderDAOImpl() {
super(Folder.class, false);
}
/*
* @see org.rssowl.core.internal.persist.dao.AbstractEntityDAO#
* createDeleteEventTemplate(org.rssowl.core.persist.IEntity)
*/
@Override
protected final FolderEvent createDeleteEventTemplate(IFolder entity) {
return createSaveEventTemplate(entity);
}
/*
* @see
* org.rssowl.core.internal.persist.dao.AbstractEntityDAO#createSaveEventTemplate
* (org.rssowl.core.persist.IEntity)
*/
@Override
protected final FolderEvent createSaveEventTemplate(IFolder entity) {
return new FolderEvent(entity, null, true);
}
/*
* @see org.rssowl.core.persist.dao.IFolderDAO#loadRoots()
*/
public Collection<IFolder> loadRoots() {
try {
Query query = fDb.query();
query.constrain(fEntityClass);
query.descend("fParent").constrain(null); //$NON-NLS-1$
List<IFolder> folders = getList(query);
activateAll(folders);
return new ArrayList<IFolder>(folders);
} catch (Db4oException e) {
throw new PersistenceException(e);
}
}
/*
* @see org.rssowl.core.persist.dao.IFolderDAO#reparent(java.util.List)
*/
public final void reparent(List<ReparentInfo<IFolderChild, IFolder>> reparentInfos) {
Assert.isNotNull(reparentInfos, "reparentInfos"); //$NON-NLS-1$
if (reparentInfos.isEmpty())
return;
fWriteLock.lock();
try {
List<FolderEvent> folderEvents = new ArrayList<FolderEvent>(3);
List<MarkEvent> markEvents = new ArrayList<MarkEvent>();
fillFolderChildEvents(reparentInfos, folderEvents, markEvents);
for (FolderEvent event : folderEvents) {
fDb.set(event.getOldParent());
IFolder newParent = event.getEntity().getParent();
if (newParent == null)
fDb.set(event.getEntity());
else
fDb.set(newParent);
}
for (MarkEvent event : markEvents) {
fDb.set(event.getOldParent());
IFolder newParent = event.getEntity().getParent();
fDb.set(newParent);
}
fDb.commit();
} catch (Db4oException e) {
throw DBHelper.rollbackAndPE(fDb, e);
} finally {
fWriteLock.unlock();
}
DBHelper.cleanUpAndFireEvents();
}
private void addFolder(IFolder parent, IFolder child, IFolderChild position, Boolean after) {
child.setParent(parent);
/* The new parent may be null. It becomes a root folder */
if (parent != null)
parent.addFolder(child, position, after);
}
private IFolder removeChildFromFolder(IFolderChild folderChild) {
IFolder oldParent = folderChild.getParent();
oldParent.removeChild(folderChild);
return oldParent;
}
private void addMarkToFolder(IFolder parent, IMark child, IFolderChild position, Boolean after) {
child.setParent(parent);
parent.addMark(child, position, after);
}
private void fillFolderChildEvents(List<ReparentInfo<IFolderChild, IFolder>> reparentInfos, List<FolderEvent> folderEvents, List<MarkEvent> markEvents) {
for (ReparentInfo<IFolderChild, IFolder> reparentInfo : reparentInfos) {
IFolderChild child = reparentInfo.getObject();
IFolder newParent = reparentInfo.getNewParent();
IFolder oldParent = child.getParent();
IFolderChild newPosition = reparentInfo.getNewPosition();
/* Folder */
if (child instanceof IFolder) {
IFolder folder = (IFolder) child;
synchronized (folder) {
removeChildFromFolder(folder);
addFolder(newParent, folder, newPosition, reparentInfo.isAfter());
if (newPosition != null) {
List<IFolder> folderList = Collections.singletonList(folder);
newParent.reorderChildren(folderList, newPosition, reparentInfo.isAfter().booleanValue());
}
}
FolderEvent eventTemplate = new FolderEvent(folder, oldParent, true);
folderEvents.add(eventTemplate);
DBHelper.putEventTemplate(eventTemplate);
}
/* Mark */
else if (child instanceof IMark) {
IMark mark = (IMark) child;
MarkEvent markEvent;
synchronized (mark) {
removeChildFromFolder(mark);
addMarkToFolder(newParent, mark, newPosition, reparentInfo.isAfter());
if (newPosition != null) {
List<IMark> markList = Collections.singletonList(mark);
newParent.reorderChildren(markList, newPosition, reparentInfo.isAfter().booleanValue());
}
}
if (mark instanceof IBookMark)
markEvent = new BookMarkEvent((IBookMark) mark, oldParent, true);
else if (mark instanceof ISearchMark)
markEvent = new SearchMarkEvent((ISearchMark) mark, oldParent, true);
else if (mark instanceof INewsBin)
markEvent = new NewsBinEvent((INewsBin) mark, oldParent, true);
else
throw new IllegalArgumentException("Unknown IMark subclass found: " + child.getClass()); //$NON-NLS-1$
DBHelper.putEventTemplate(markEvent);
markEvents.add(markEvent);
} else {
throw new IllegalArgumentException("Unknown IFolderChild subclass found: " + child.getClass()); //$NON-NLS-1$
}
}
}
}