/* ********************************************************************** **
** 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;
import org.eclipse.core.runtime.Assert;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IFolderChild;
import org.rssowl.core.persist.IMark;
import org.rssowl.core.persist.reference.FolderReference;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Folders store a number of Marks in an hierachical order. The hierachical
* order is achieved by allowing to store Folders inside Folders.
* <p>
* In case a Blogroll Link is set for the Folder, it is to be interpreted as
* root-folder of a "Synchronized Blogroll". This special kind of Folder allows
* to synchronize its contents from a remote OPML file that contains a number of
* Feeds.
* </p>
*
* @author bpasero
*/
public class Folder extends AbstractEntity implements IFolder {
private String fName;
private String fBlogrollLink;
private IFolder fParent;
private List<IFolderChild> fChildren;
/**
* Creates a new Folder with the given ID and Name as a Child of the given
* FolderReference. In case the FolderReference is <code>NULL</code>, this
* Folder is root-leveld.
*
* @param id The unique ID of this Folder.
* @param parent The parent Folder this Folder belongs to, or
* @param name The Name of this Folder. <code>NULL</code>, if this Folder
* is a Root-Folder.
*/
public Folder(Long id, IFolder parent, String name) {
super(id);
Assert.isNotNull(name, "The type Folder requires a Name that is not NULL"); //$NON-NLS-1$
fParent = parent;
fName = name;
fChildren = new ArrayList<IFolderChild>(5);
}
/**
* Default constructor for deserialization
*/
protected Folder() {
// As per javadoc
}
/*
* @see org.rssowl.core.persist.IFolder#sort()
*/
public void sort() {
Collections.sort(fChildren, new Comparator<IFolderChild>() {
public int compare(IFolderChild child1, IFolderChild child2) {
/* Sort by Name if classes equal */
if (child1.getClass().equals(child2.getClass()))
return child1.getName().toLowerCase().compareTo(child2.getName().toLowerCase());
/* Sort Marks to Bottom */
if (child1 instanceof IMark)
return 1;
/* Sort Folders to Top */
return -1;
}
});
}
/*
* @see org.rssowl.core.persist.IFolder#addMark(org.rssowl.core.persist.IMark,
* org.rssowl.core.persist.IFolderChild, boolean)
*/
public synchronized void addMark(IMark mark, IFolderChild position, Boolean after) {
Assert.isNotNull(mark, "Exception adding NULL as Mark into Folder"); //$NON-NLS-1$
Assert.isTrue(equals(mark.getParent()), "The Mark has a different Folder set!"); //$NON-NLS-1$
addChild(mark, position, after);
}
/*
* @see org.rssowl.core.model.types.IFolder#getMarks()
*/
public synchronized List<IMark> getMarks() {
return extractTypes(IMark.class, fChildren);
}
/*
* @see org.rssowl.core.persist.IFolder#addFolder(org.rssowl.core.persist.IFolder,
* org.rssowl.core.persist.IFolderChild, boolean)
*/
public synchronized void addFolder(IFolder folder, IFolderChild position, Boolean after) {
Assert.isNotNull(folder, "Exception adding NULL as Child Folder into Parent Folder"); //$NON-NLS-1$
Assert.isTrue(equals(folder.getParent()), "The Folder has a different Parent Folder set!"); //$NON-NLS-1$
addChild(folder, position, after);
}
/*
* @see org.rssowl.core.persist.IFolder#isEmpty()
*/
public synchronized boolean isEmpty() {
return fChildren.isEmpty();
}
/*
* @see org.rssowl.core.persist.IFolder#containsChild(org.rssowl.core.persist.IFolderChild)
*/
public synchronized boolean containsChild(IFolderChild child) {
return fChildren.contains(child);
}
/*
* @see org.rssowl.core.persist.IFolder#getChildren()
*/
public synchronized List<IFolderChild> getChildren() {
return new ArrayList<IFolderChild>(fChildren);
}
/*
* @see org.rssowl.core.persist.IFolder#removeChild(org.rssowl.core.persist.IFolderChild)
*/
public synchronized boolean removeChild(IFolderChild child) {
return fChildren.remove(child);
}
private void addChild(IFolderChild child, IFolderChild position, Boolean after) {
/* Mask Null */
after = (after == null) ? Boolean.FALSE : after;
/* Add to end of List if Position is unknown */
if (position == null)
fChildren.add(child);
/* Position is provided */
else {
int index = fChildren.indexOf(position);
/* Insert to end of List */
if (index < 0 || (index == fChildren.size() && after))
fChildren.add(child);
/* Insert after Position */
else if (after)
fChildren.add(index + 1, child);
/* Insert before Position */
else
fChildren.add(index, child);
}
}
/*
* @see org.rssowl.core.model.types.IFolder#getFolders()
*/
public synchronized List<IFolder> getFolders() {
return extractTypes(IFolder.class, fChildren);
}
private <T> List<T> extractTypes(Class<T> type, List<? super T> list) {
List<T> types = new ArrayList<T>(list.size());
for (Object object : list) {
if (type.isInstance(object))
types.add(type.cast(object));
}
return types;
}
/*
* @see org.rssowl.core.model.types.IFolder#setBlogrollLink(java.net.URI)
*/
public synchronized void setBlogrollLink(URI blogrollLink) {
fBlogrollLink = getURIText(blogrollLink);
}
/*
* @see org.rssowl.core.model.types.IFolder#getName()
*/
public synchronized String getName() {
return fName;
}
/*
* @see org.rssowl.core.model.types.IFolder#setName(java.lang.String)
*/
public synchronized void setName(String name) {
Assert.isNotNull(name, "The type Folder requires a Name that is not NULL"); //$NON-NLS-1$
fName = name;
}
/*
* @see org.rssowl.core.model.types.IFolder#getParent()
*/
public synchronized IFolder getParent() {
return fParent;
}
/*
* @see org.rssowl.core.model.types.Reparentable#setParent(java.lang.Object)
*/
public synchronized void setParent(IFolder newParent) {
fParent = newParent;
}
/*
* @see org.rssowl.core.model.types.IFolder#getBlogrollLink()
*/
public synchronized URI getBlogrollLink() {
return createURI(fBlogrollLink);
}
/*
* @see org.rssowl.core.persist.IFolder#reorderChildren(java.util.List,
* org.rssowl.core.persist.IFolderChild, boolean)
*/
public synchronized void reorderChildren(List<? extends IFolderChild> children, IFolderChild position, Boolean after) {
Assert.isTrue(fChildren.contains(position));
Assert.isTrue(fChildren.containsAll(children));
/* Mask Null */
after = (after == null) ? Boolean.FALSE : after;
/* First, remove the given Marks */
fChildren.removeAll(children);
int index = fChildren.indexOf(position);
/* Insert to end of List */
if (index == fChildren.size() && after)
fChildren.addAll(children);
/* Insert after Position */
else if (after)
fChildren.addAll(index + 1, children);
/* Insert before Position */
else
fChildren.addAll(index, children);
}
/**
* Compare the given type with this type for identity.
*
* @param folder to be compared.
* @return whether this object and <code>folder</code> are identical. It
* compares all the fields.
*/
public synchronized boolean isIdentical(IFolder folder) {
if (this == folder)
return true;
if (!(folder instanceof Folder))
return false;
synchronized (folder) {
Folder f = (Folder) folder;
return (getId() == null ? f.getId() == null : getId().equals(f.getId())) &&
(fParent == null ? f.fParent == null : fParent.equals(f.fParent)) &&
(fName == null ? f.fName == null : fName.equals(f.fName)) &&
(getBlogrollLink() == null ? f.getBlogrollLink() == null : getBlogrollLink().equals(f.getBlogrollLink())) &&
(fChildren == null ? f.fChildren == null : fChildren.equals(f.fChildren)) &&
(getProperties() == null ? f.getProperties() == null : getProperties().equals(f.getProperties()));
}
}
/*
* @see org.rssowl.core.persist.IEntity#toReference()
*/
public FolderReference toReference() {
return new FolderReference(getIdAsPrimitive());
}
/*
* @see org.rssowl.core.internal.persist.AbstractEntity#toString()
*/
@Override
public synchronized String toString() {
return super.toString() + "Name = " + fName + ")"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Returns a String describing the state of this Entity.
*
* @return A String describing the state of this Entity.
*/
public synchronized String toLongString() {
return super.toString() + "Name = " + fName + ", Blogroll Link = " + fBlogrollLink + ", Children = " + fChildren.toString() + ", Parent Folder = " + (fParent != null ? fParent.getId() : "none") + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
}
}