Weitere Ergänzungen an Methode Folder#retrieveFolder(String). Es kann jetzt optional eine Content-Sections im Pfad angegeben werden.

git-svn-id: https://svn.libreccm.org/ccm/trunk@2055 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2013-01-30 10:19:30 +00:00
parent c5886fb8da
commit 8c44bab86e
1 changed files with 162 additions and 176 deletions

View File

@ -48,21 +48,15 @@ import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
/** /**
* This class represents folders for which to organize items in a tree * This class represents folders for which to organize items in a tree hierarchy.
* hierarchy.
* *
* Folders will only ever exist as draft or live versions. There * Folders will only ever exist as draft or live versions. There should never be any folders that are pending. The
* should never be any folders that are pending. The pending versions * pending versions of ordinary content items are stored in the live version of folders.
* of ordinary content items are stored in the live version of
* folders.
* *
* Folders cannot have their own lifecycles. The methods to get or set * Folders cannot have their own lifecycles. The methods to get or set lifecycles are no-ops.
* lifecycles are no-ops.
* *
* You should never call {@link #publish} or {@link #unpublish} on a * You should never call {@link #publish} or {@link #unpublish} on a folder; at present, these methods only log a
* folder; at present, these methods only log a warning when they are * warning when they are called. In the future, these warnings may be turned into actual errors.
* called. In the future, these warnings may be turned into actual
* errors.
* *
* @author Jack Chung * @author Jack Chung
* @author Michael Pih * @author Michael Pih
@ -72,14 +66,11 @@ import java.util.Iterator;
public class Folder extends ContentItem { public class Folder extends ContentItem {
private static final Logger s_log = Logger.getLogger(Folder.class); private static final Logger s_log = Logger.getLogger(Folder.class);
public static final String BASE_DATA_OBJECT_TYPE = public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.cms.Folder"; "com.arsdigita.cms.Folder";
public static final String INDEX = "index"; public static final String INDEX = "index";
public static final String HOME_FOLDER = "homeFolder"; public static final String HOME_FOLDER = "homeFolder";
public static final String HOME_SECTION = "homeSection"; public static final String HOME_SECTION = "homeSection";
private static final String ITEMS_QUERY = "com.arsdigita.cms.ItemsInFolder"; private static final String ITEMS_QUERY = "com.arsdigita.cms.ItemsInFolder";
private static final String PRIMARY_INSTANCES_QUERY = private static final String PRIMARY_INSTANCES_QUERY =
"com.arsdigita.cms.PrimaryInstancesInFolder"; "com.arsdigita.cms.PrimaryInstancesInFolder";
@ -89,7 +80,6 @@ public class Folder extends ContentItem {
private static final String NAME = "name"; private static final String NAME = "name";
private final static String ITEM = "item"; private final static String ITEM = "item";
private boolean m_wasNew; private boolean m_wasNew;
protected static final String ITEMS = "items"; protected static final String ITEMS = "items";
/** /**
@ -100,25 +90,24 @@ public class Folder extends ContentItem {
} }
/** /**
* Constructor. The contained <code>DataObject</code> is retrieved * Constructor. The contained
* from the persistent storage mechanism with an <code>OID</code> * <code>DataObject</code> is retrieved from the persistent storage mechanism with an
* specified by <cod>oid</code>. * <code>OID</code> specified by <cod>oid</code>.
* *
* @param oid The <code>OID</code> for the retrieved * @param oid The <code>OID</code> for the retrieved <code>DataObject</code>.
* <code>DataObject</code>.
*/ */
public Folder(final OID oid) throws DataObjectNotFoundException { public Folder(final OID oid) throws DataObjectNotFoundException {
super(oid); super(oid);
} }
/** /**
* Constructor. The contained <code>DataObject</code> is retrieved * Constructor. The contained
* from the persistent storage mechanism with an <code>OID</code> * <code>DataObject</code> is retrieved from the persistent storage mechanism with an
* specified by <code>id</code> and * <code>OID</code> specified by
* <code>id</code> and
* <code>Folder.BASE_DATA_OBJECT_TYPE</code>. * <code>Folder.BASE_DATA_OBJECT_TYPE</code>.
* *
* @param id The <code>id</code> for the retrieved * @param id The <code>id</code> for the retrieved <code>DataObject</code>
* <code>DataObject</code>
*/ */
public Folder(final BigDecimal id) throws DataObjectNotFoundException { public Folder(final BigDecimal id) throws DataObjectNotFoundException {
this(new OID(BASE_DATA_OBJECT_TYPE, id)); this(new OID(BASE_DATA_OBJECT_TYPE, id));
@ -145,9 +134,10 @@ public class Folder extends ContentItem {
item.copy(this, true); item.copy(this, true);
} }
} }
/** /**
* @return the base PDL object type for this item. Child classes * @return the base PDL object type for this item. Child classes should override this method to return the correct
* should override this method to return the correct value * value
*/ */
public String getBaseDataObjectType() { public String getBaseDataObjectType() {
return BASE_DATA_OBJECT_TYPE; return BASE_DATA_OBJECT_TYPE;
@ -162,18 +152,16 @@ public class Folder extends ContentItem {
s_log.debug("Deleting folder"); s_log.debug("Deleting folder");
if (!isEmpty()) { if (!isEmpty()) {
throw new IllegalStateException throw new IllegalStateException("Attempt to delete non-empty folder " + getOID() + "; "
("Attempt to delete non-empty folder " + getOID() + "; " + + "only empty folders can be deleted");
"only empty folders can be deleted");
} }
super.delete(); super.delete();
} }
protected void beforeDelete() { protected void beforeDelete() {
DataCollection maps = SessionManager.getSession().retrieve DataCollection maps = SessionManager.getSession().retrieve(UserHomeFolderMap.BASE_DATA_OBJECT_TYPE);
(UserHomeFolderMap.BASE_DATA_OBJECT_TYPE); maps.addEqualsFilter(HOME_FOLDER + "." + ID, getID());
maps.addEqualsFilter(HOME_FOLDER + "." + ID,getID());
while (maps.next()) { while (maps.next()) {
maps.getDataObject().delete(); maps.getDataObject().delete();
} }
@ -207,9 +195,8 @@ public class Folder extends ContentItem {
final ContentSection section = getContentSection(); final ContentSection section = getContentSection();
if (section != null && if (section != null && (this.equals(section.getRootFolder()) || this.
(this.equals(section.getRootFolder()) || equals(section.getTemplatesFolder()))) {
this.equals(section.getTemplatesFolder()))) {
PermissionService.setContext(this, section); PermissionService.setContext(this, section);
} }
} }
@ -225,9 +212,8 @@ public class Folder extends ContentItem {
} }
/** /**
* Fetches the child items of this folder. The returned collection * Fetches the child items of this folder. The returned collection provides methods to filter by various criteria,
* provides methods to filter by various criteria, for example by * for example by name or by whether items are folders or not.
* name or by whether items are folders or not.
* *
* @param bSort whether to sort the collection by isFolder and ID * @param bSort whether to sort the collection by isFolder and ID
* @return child items of this folder * @return child items of this folder
@ -243,10 +229,9 @@ public class Folder extends ContentItem {
} }
/** /**
* Fetches the child items of this folder. The returned collection * Fetches the child items of this folder. The returned collection provides methods to filter by various criteria,
* provides methods to filter by various criteria, for example by * for example by name or by whether items are folders or not. The items returned by this method are sorted by
* name or by whether items are folders or not. The items returned * isFolder and ID
* by this method are sorted by isFolder and ID
* *
* @return child items of this folder, sorted by isFolder and ID * @return child items of this folder, sorted by isFolder and ID
*/ */
@ -254,14 +239,11 @@ public class Folder extends ContentItem {
return getItems(true); return getItems(true);
} }
/** /**
* Returns collection of primary language instances for bundles in * Returns collection of primary language instances for bundles in this folder.
* this folder.
*/ */
public ItemCollection getPrimaryInstances() { public ItemCollection getPrimaryInstances() {
final DataQuery query = SessionManager.getSession().retrieveQuery final DataQuery query = SessionManager.getSession().retrieveQuery(PRIMARY_INSTANCES_QUERY);
(PRIMARY_INSTANCES_QUERY);
query.setParameter(PARENT, getID()); query.setParameter(PARENT, getID());
Assert.isNotEqual(PENDING, getVersion()); Assert.isNotEqual(PENDING, getVersion());
@ -272,14 +254,11 @@ public class Folder extends ContentItem {
} }
/** /**
* Returns a child content item in this folder (which could itself * Returns a child content item in this folder (which could itself be a folder) with the specified name.
* be a folder) with the specified name.
* *
* @param name The name of the item * @param name The name of the item
* @param isFolder If true, only return a subfolder. Otherwise, * @param isFolder If true, only return a subfolder. Otherwise, return any subitem
* return any subitem * @return The item with the given name, or null if no such item exists in the folder
* @return The item with the given name, or null if no such item
* exists in the folder
*/ */
public ContentItem getItem(final String name, public ContentItem getItem(final String name,
final boolean isFolder) { final boolean isFolder) {
@ -299,13 +278,12 @@ public class Folder extends ContentItem {
if (items.next()) { if (items.next()) {
DataObject dataObj = items.getDataObject(); DataObject dataObj = items.getDataObject();
ContentItem result = (ContentItem)DomainObjectFactory ContentItem result = (ContentItem) DomainObjectFactory
.newInstance(dataObj); .newInstance(dataObj);
if (items.next()) { if (items.next()) {
s_log.warn("Item in folder has a duplicate name; one " + s_log.warn("Item in folder has a duplicate name; one " + "is " + result + " and one is "
"is " + result + " and one is " + + (ContentItem) DomainObjectFactory
(ContentItem)DomainObjectFactory
.newInstance(items.getDataObject())); .newInstance(items.getDataObject()));
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -334,7 +312,6 @@ public class Folder extends ContentItem {
} }
} }
/** /**
* Fetches the label of the folder. * Fetches the label of the folder.
*/ */
@ -354,12 +331,10 @@ public class Folder extends ContentItem {
} }
/** /**
* Set the version of the folder. An attempt to set the version to * Set the version of the folder. An attempt to set the version to pending will result in the folder's version being
* pending will result in the folder's version being set to live. We will * set to live. We will never have any pending versions of folders, only live or draft.
* never have any pending versions of folders, only live or draft.
* *
* Pending versions of items are stored in the live version of a * Pending versions of items are stored in the live version of a folder.
* folder.
*/ */
protected void setVersion(String version) { protected void setVersion(String version) {
if (ContentItem.PENDING.equals(version)) { if (ContentItem.PENDING.equals(version)) {
@ -372,7 +347,6 @@ public class Folder extends ContentItem {
// //
// Publish/unpublish stuff // Publish/unpublish stuff
// //
public void unpublish() { public void unpublish() {
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {
s_log.info("Unpublishing folder " + this); s_log.info("Unpublishing folder " + this);
@ -393,9 +367,9 @@ public class Folder extends ContentItem {
// //
// Lifecycle stuff // Lifecycle stuff
// //
/** /**
* Always returns <code>null</code>, as folders do not have lifecycles. * Always returns
* <code>null</code>, as folders do not have lifecycles.
* *
* @return a <code>Lifecycle</code> value * @return a <code>Lifecycle</code> value
*/ */
@ -435,16 +409,12 @@ public class Folder extends ContentItem {
// //
// Index item // Index item
// //
/** /**
* Get the (special) index item for the folder. The index item is * Get the (special) index item for the folder. The index item is what carries all the user-editable attributes of
* what carries all the user-editable attributes of the * the folder. The index item is what should be published when a index page for a folder is desired.
* folder. The index item is what should be published when a index
* page for a folder is desired.
* *
* The index item is an ordinary item in every respect, i.e., it * The index item is an ordinary item in every respect, i.e., it is part of the collection returned by
* is part of the collection returned by <code>getItems()</code>, * <code>getItems()</code>, you cannot delete a folder if it still has an index item etc.
* you cannot delete a folder if it still has an index item etc.
*/ */
public ContentBundle getIndexItem() { public ContentBundle getIndexItem() {
// BECAUSE INDEX ITEM MIGHT NOT BE UPDATED FOR PUBLISHED // BECAUSE INDEX ITEM MIGHT NOT BE UPDATED FOR PUBLISHED
@ -478,8 +448,7 @@ public class Folder extends ContentItem {
/** /**
* Sets the index item. This also adds the item to the folder. * Sets the index item. This also adds the item to the folder.
* *
* @param item The index item with the folder's user-editable * @param item The index item with the folder's user-editable attributes
* attributes
*/ */
public final void setIndexItem(final ContentBundle item) { public final void setIndexItem(final ContentBundle item) {
setAssociation(INDEX, item); setAssociation(INDEX, item);
@ -495,15 +464,15 @@ public class Folder extends ContentItem {
} }
/** /**
* Returns <code>true</code> if the folder is empty. * Returns
* <code>true</code> if the folder is empty.
* *
* @return <code>true</code> if the folder is empty * @return <code>true</code> if the folder is empty
*/ */
public boolean isEmpty() { public boolean isEmpty() {
final Session session = SessionManager.getSession(); final Session session = SessionManager.getSession();
final DataQuery query = session.retrieveQuery final DataQuery query = session.retrieveQuery("com.arsdigita.cms.folderNotEmpty");
("com.arsdigita.cms.folderNotEmpty");
query.setParameter("id", getID()); query.setParameter("id", getID());
final boolean result = !query.next(); final boolean result = !query.next();
@ -514,17 +483,17 @@ public class Folder extends ContentItem {
} }
/** /**
* Returns <code>true</code> if the folder contains at least one * Returns
* folder, <code>false</code> if the folder does not contain any * <code>true</code> if the folder contains at least one folder,
* folders, but is either empty or contains only ordinary items. * <code>false</code> if the folder does not contain any folders, but is either empty or contains only ordinary
* items.
* *
* @return <code>true</code> if the folder contains other folders. * @return <code>true</code> if the folder contains other folders.
*/ */
public boolean containsFolders() { public boolean containsFolders() {
final Session session = SessionManager.getSession(); final Session session = SessionManager.getSession();
final DataQuery query = session.retrieveQuery final DataQuery query = session.retrieveQuery("com.arsdigita.cms.folderHasNoSubFolders");
("com.arsdigita.cms.folderHasNoSubFolders");
query.setParameter("id", getID()); query.setParameter("id", getID());
final boolean result = !query.next(); final boolean result = !query.next();
@ -535,25 +504,23 @@ public class Folder extends ContentItem {
} }
/** /**
* Copy the specified property (attribute or association) from the specified * Copy the specified property (attribute or association) from the specified source folder. This method almost
* source folder. This method almost completely overrides the * completely overrides the metadata-driven methods in
* metadata-driven methods in <code>ObjectCopier</code>. If the property in * <code>ObjectCopier</code>. If the property in question is an association to
* question is an association to <code>ContentItem</code>(s), this method * <code>ContentItem</code>(s), this method should <em>only</em> call
* should <em>only</em> call <code>FooContentItem newChild = * <code>FooContentItem newChild =
* copier.copyItem(originalChild)</code>. An attempt to call any other * copier.copyItem(originalChild)</code>. An attempt to call any other method in order to copy the child will most
* method in order to copy the child will most likely have disastrous * likely have disastrous consequences.
* consequences.
* *
* If a child class overrides this method, it should return * If a child class overrides this method, it should return
* <code>super.copyProperty</code> in order to indicate that it is * <code>super.copyProperty</code> in order to indicate that it is not interested in handling the property in any
* not interested in handling the property in any special way. * special way.
* *
* @param srcItem the source item * @param srcItem the source item
* @param property the property to copy * @param property the property to copy
* @param copier the ItemCopier * @param copier the ItemCopier
* @return true if the property was copied, false to indicate that * @return true if the property was copied, false to indicate that regular metadata-driven methods should be used to
* regular metadata-driven methods should be used to copy the * copy the property
* property
*/ */
public boolean copyProperty(final CustomCopy srcItem, public boolean copyProperty(final CustomCopy srcItem,
final Property property, final Property property,
@ -575,42 +542,41 @@ public class Folder extends ContentItem {
} }
/** /**
* A collection of items that can be filtered to return only folders or * A collection of items that can be filtered to return only folders or only nonfolders.
* only nonfolders.
*/ */
public static class ItemCollection public static class ItemCollection
extends com.arsdigita.cms.ItemCollection { extends com.arsdigita.cms.ItemCollection {
private final static String IS_FOLDER = "isFolder"; private final static String IS_FOLDER = "isFolder";
private final static String HAS_CHILDREN = "hasChildren"; private final static String HAS_CHILDREN = "hasChildren";
private final static String ITEM = "item"; private final static String ITEM = "item";
private final static String HAS_LIVE_VERSION = "hasLiveVersion"; private final static String HAS_LIVE_VERSION = "hasLiveVersion";
private final static String TYPE_LABEL = "type.label"; private final static String TYPE_LABEL = "type.label";
private final static String AUDIT_TRAIL="item.auditing"; private final static String AUDIT_TRAIL = "item.auditing";
private DataQuery m_query; private DataQuery m_query;
/** /**
* Constructor * Constructor
* @param adapter an adapter constructed using the query name rather than a *
* DataQuery object. This constructor must be used if there is any * @param adapter an adapter constructed using the query name rather than a DataQuery object. This constructor
* intention to permission filter the results as only a DataQueryDataCollectionAdapter * must be used if there is any intention to permission filter the results as only a
* constructed using query name has the bug fix to allow permission filtering * DataQueryDataCollectionAdapter constructed using query name has the bug fix to allow permission filtering
* *
* @param bSort whether to sort the collection by isFolder and ID * @param bSort whether to sort the collection by isFolder and ID
*/ */
public ItemCollection (DataQueryDataCollectionAdapter adapter, boolean bSort) { public ItemCollection(DataQueryDataCollectionAdapter adapter, boolean bSort) {
super(adapter); super(adapter);
doAlias(adapter); doAlias(adapter);
init(adapter, bSort); init(adapter, bSort);
} }
public ItemCollection (DataQueryDataCollectionAdapter adapter) { public ItemCollection(DataQueryDataCollectionAdapter adapter) {
this(adapter, true); this(adapter, true);
} }
/** /**
* Constructor * Constructor
*
* @param query the Data Query to use to retrieve the collection * @param query the Data Query to use to retrieve the collection
* @param bSort whether to sort the collection by isFolder and ID * @param bSort whether to sort the collection by isFolder and ID
*/ */
@ -623,13 +589,11 @@ public class Folder extends ContentItem {
} }
/** /**
* Convenience Constructor that always sorts the collection * Convenience Constructor that always sorts the collection by isFolder and ID
* by isFolder and ID
* *
* jensp 2011-06: I changed this because this silly sorting affects * jensp 2011-06: I changed this because this silly sorting affects the ItemSearchWidget and makes it pretty
* the ItemSearchWidget and makes it pretty useless... I've not noticed * useless... I've not noticed any negative effects, so it seams no problem. Sorting is now set by the
* any negative effects, so it seams no problem. Sorting is now set by * caller/user of the {@code ItemCollection}.
* the caller/user of the {@code ItemCollection}.
* *
* @param query the Data Query to use to retrieve the collection * @param query the Data Query to use to retrieve the collection
*/ */
@ -656,8 +620,7 @@ public class Folder extends ContentItem {
} }
/** /**
* Sets the range of the dataquery. This is used by the * Sets the range of the dataquery. This is used by the paginator.
* paginator.
* *
* @param beginIndex The start index * @param beginIndex The start index
* @param endIndex The end index * @param endIndex The end index
@ -672,14 +635,12 @@ public class Folder extends ContentItem {
} }
/** /**
* For performance reaons, override superclass methods and * For performance reaons, override superclass methods and try to get the audit info without instantiating a
* try to get the audit info without instantiating a content item. * content item. We know this can help because the getPrimaryInstances query retrieves the audit info directly
* We know this can help because the getPrimaryInstances
* query retrieves the audit info directly
*/ */
public Date getCreationDate() { public Date getCreationDate() {
DataObject dobj = (DataObject) get(AUDIT_TRAIL); DataObject dobj = (DataObject) get(AUDIT_TRAIL);
if (dobj != null){ if (dobj != null) {
BasicAuditTrail audit = new BasicAuditTrail(dobj); BasicAuditTrail audit = new BasicAuditTrail(dobj);
return audit.getCreationDate(); return audit.getCreationDate();
} else { } else {
@ -689,7 +650,7 @@ public class Folder extends ContentItem {
public Date getLastModifiedDate() { public Date getLastModifiedDate() {
DataObject dobj = (DataObject) get(AUDIT_TRAIL); DataObject dobj = (DataObject) get(AUDIT_TRAIL);
if (dobj != null){ if (dobj != null) {
BasicAuditTrail audit = new BasicAuditTrail(dobj); BasicAuditTrail audit = new BasicAuditTrail(dobj);
return audit.getLastModifiedDate(); return audit.getLastModifiedDate();
} else { } else {
@ -698,9 +659,8 @@ public class Folder extends ContentItem {
} }
/** /**
* Return the pretty name of the content type of the current item. If * Return the pretty name of the content type of the current item. If the current item is a folder, the string
* the current item is a folder, the string <tt>Folder</tt> is * <tt>Folder</tt> is returned, otherwise the label of the item's content type.
* returned, otherwise the label of the item's content type.
* *
* @return the pretty name of the content type of the current item. * @return the pretty name of the content type of the current item.
*/ */
@ -715,9 +675,8 @@ public class Folder extends ContentItem {
/** /**
* Filter the collection by whether items are folders or not. * Filter the collection by whether items are folders or not.
* *
* @param v <code>true</code> if the data query should only list folders, * @param v <code>true</code> if the data query should only list folders, <code>false</code> if the data query
* <code>false</code> if the data query should only list non-folder * should only list non-folder items.
* items.
* *
*/ */
public void addFolderFilter(final boolean v) { public void addFolderFilter(final boolean v) {
@ -725,11 +684,10 @@ public class Folder extends ContentItem {
} }
/** /**
* Return <code>true</code> if the current item in the collection is a * Return
* folder. * <code>true</code> if the current item in the collection is a folder.
* *
* @return <code>true</code> if the current item in the collection is a * @return <code>true</code> if the current item in the collection is a folder.
* folder.
*/ */
public boolean isFolder() { public boolean isFolder() {
Boolean result = (Boolean) m_query.get(IS_FOLDER); Boolean result = (Boolean) m_query.get(IS_FOLDER);
@ -743,7 +701,7 @@ public class Folder extends ContentItem {
public boolean isLive() { public boolean isLive() {
String version = (String) get(ContentItem.VERSION); String version = (String) get(ContentItem.VERSION);
if (ContentItem.LIVE.equals(version) ) { if (ContentItem.LIVE.equals(version)) {
return true; return true;
} }
Boolean hasLive = (Boolean) m_query.get(HAS_LIVE_VERSION); Boolean hasLive = (Boolean) m_query.get(HAS_LIVE_VERSION);
@ -763,12 +721,11 @@ public class Folder extends ContentItem {
} }
/** /**
* Called by <code>VersionCopier</code> to determine whether to * Called by
* publish associated items when an item goes live. This will only * <code>VersionCopier</code> to determine whether to publish associated items when an item goes live. This will
* have an effect for non-component associations where the item is * only have an effect for non-component associations where the item is not yet published. Override default for
* not yet published. Override default for <code>Folder</code>s * <code>Folder</code>s since they don't have their own lifecycles and a folder must be published when an item in it
* since they don't have their own lifecycles and a folder must be * goes live.
* published when an item in it goes live.
* *
* @return whether to publish this item * @return whether to publish this item
*/ */
@ -776,18 +733,18 @@ public class Folder extends ContentItem {
return true; return true;
} }
public static void setUserHomeFolder(User user,Folder folder) { public static void setUserHomeFolder(User user, Folder folder) {
UserHomeFolderMap map = UserHomeFolderMap.findOrCreateUserHomeFolderMap(user,folder.getContentSection()); UserHomeFolderMap map = UserHomeFolderMap.findOrCreateUserHomeFolderMap(user, folder.getContentSection());
map.setHomeFolder(folder); map.setHomeFolder(folder);
map.save(); map.save();
} }
public static Folder getUserHomeFolder(User user,ContentSection section) { public static Folder getUserHomeFolder(User user, ContentSection section) {
Folder folder = null; Folder folder = null;
UserHomeFolderMap map = UserHomeFolderMap.findUserHomeFolderMap(user,section); UserHomeFolderMap map = UserHomeFolderMap.findUserHomeFolderMap(user, section);
if ( map != null ) { if (map != null) {
folder = map.getHomeFolder(); folder = map.getHomeFolder();
if ( folder != null ) { if (folder != null) {
CMSContext context = CMS.getContext(); CMSContext context = CMS.getContext();
SecurityManager sm; SecurityManager sm;
if (context.hasSecurityManager()) { if (context.hasSecurityManager()) {
@ -795,7 +752,7 @@ public class Folder extends ContentItem {
} else { } else {
sm = new SecurityManager(section); sm = new SecurityManager(section);
} }
if ( !sm.canAccess(user,SecurityConstants.PREVIEW_PAGES,folder) ) { if (!sm.canAccess(user, SecurityConstants.PREVIEW_PAGES, folder)) {
folder = null; folder = null;
} }
} }
@ -830,7 +787,7 @@ public class Folder extends ContentItem {
final Folder rootFolder = section.getRootFolder(); final Folder rootFolder = section.getRootFolder();
Folder folder = rootFolder; Folder folder = rootFolder;
for(String token : pathTokens) { for (String token : pathTokens) {
if ((token == null) || token.isEmpty() || "/".equals(token)) { if ((token == null) || token.isEmpty() || "/".equals(token)) {
continue; continue;
} }
@ -859,13 +816,42 @@ public class Folder extends ContentItem {
/** /**
* Retrieves a folder of the current content section by its path. The path is given in a UNIX like synatax and must * Retrieves a folder of the current content section by its path. The path is given in a UNIX like synatax and must
* be an absolute path starting with '/'. * be an absolute path starting with '/'. The path may be precceded with the name of content section, separated by
* ':'. If a content section if given, the path is relative to this content section. If the no content section is
* given, the current content section returned by {@code CMS.getContext().getContentSection()}. Please note that
* {@code CMS.getContext().getContentSection()} may return null.
*
* Examples for valid paths:
*
* <pre>
* /persons/members
* content:/persons/members
* publications:/monographs
* </pre>
* *
* @param path The path of the folder to retrieve relative to the current content section. * @param path The path of the folder to retrieve relative to the current content section.
* @return The folder with the given path from the content section. If there is no such folder, {@code null} is * @return The folder with the given path from the content section. If there is no such folder, {@code null} is
* returned. It is up to the caller to check the returned value for {@code null} and take appropriate actions. * returned. It is up to the caller to check the returned value for {@code null} and take appropriate actions.
*/ */
public static Folder retrieveFolder(final String path) { public static Folder retrieveFolder(final String path) {
final String[] tokens = path.split(":");
if (tokens.length == 1) {
return retrieveFolder(CMS.getContext().getContentSection(), path); return retrieveFolder(CMS.getContext().getContentSection(), path);
} else if (tokens.length == 2) {
final ContentSectionCollection sections = ContentSection.getAllSections();
sections.addEqualsFilter("label", tokens[0]);
if (sections.isEmpty()) {
return null;
} else {
sections.next();
final ContentSection section = sections.getContentSection();
return retrieveFolder(section, tokens[1]);
}
} else {
throw new IllegalArgumentException("Invalid path syntax. Valid syntax: "
+ "[contentsection:]/path/to/folder'");
}
} }
} }