/* * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.arsdigita.cms; import com.arsdigita.categorization.Category; import com.arsdigita.cms.dispatcher.ItemResolver; import com.arsdigita.cms.dispatcher.PageResolver; import com.arsdigita.cms.dispatcher.Resource; import com.arsdigita.cms.dispatcher.ResourceMapping; import com.arsdigita.cms.dispatcher.ResourceType; import com.arsdigita.cms.dispatcher.TemplateResolver; import com.arsdigita.cms.dispatcher.XMLGenerator; // import com.arsdigita.cms.CMSConfig; import com.arsdigita.cms.lifecycle.LifecycleDefinition; import com.arsdigita.cms.lifecycle.LifecycleDefinitionCollection; import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.globalization.Locale; import com.arsdigita.kernel.Group; import com.arsdigita.kernel.SiteNode; import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.persistence.CompoundFilter; import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataAssociationCursor; import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.DataQuery; import com.arsdigita.persistence.FilterFactory; import com.arsdigita.persistence.OID; import com.arsdigita.persistence.SessionManager; import com.arsdigita.util.Assert; import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.web.Application; import com.arsdigita.web.URL; import com.arsdigita.web.Web; import com.arsdigita.workflow.simple.TaskCollection; import com.arsdigita.workflow.simple.WorkflowTemplate; import org.apache.log4j.Logger; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.util.StringTokenizer; import org.apache.log4j.Level; /** *

A content section represents a collection of content that is * managed as a unit. Content sections typically correspond to major * branches of the public site map. For example, a general news site * might have content sections for World, National, Regional, Science * and Technology stories. Each content section has its own production * and deployment environment, including the following:

* *
    * *
  1. It can have its own administration roles, including * managers, producers, editors and designers.

  2. * *
  3. It is associated with one or more specific {@link * com.arsdigita.cms.ContentType content types}. For example, the * "Press" section is associated with Press Releases.

  4. * *
  5. It can have its own default workflows and * lifecycles.

  6. * *
  7. In addition to the content pages themselves, it can have * any number of top-level pages for browsing, searching and any * other desired purpose.

  8. * *
* *

By default, each content section is associated with exactly one * {@link com.arsdigita.kernel.PackageInstance package instance} and * can be mounted at exactly one node in the site map.

* * @author Michael Pih * @author Jack Chung * @version $Revision: #37 $ $DateTime: 2004/08/17 23:15:09 $ * @version $Id: ContentSection.java 2209 2011-06-22 07:59:10Z pboy $ */ public class ContentSection extends Application { private static final Logger s_log = Logger.getLogger(ContentSection.class); public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.cms.ContentSection"; public static final String PACKAGE_TYPE = "content-section"; // public final static String STYLESHEET = "/packages/content-section/xsl/cms.xsl"; protected static final String ID = "id"; protected static final String PACKAGE = "package"; protected static final String NAME = "label"; protected static final String ROOT_FOLDER = "rootFolder"; protected static final String TEMPLATES_FOLDER = "templatesFolder"; protected static final String STAFF_GROUP = "staffGroup"; protected static final String VIEWERS_GROUP = "viewersGroup"; protected static final String DEFAULT_LOCALE = "defaultLocale"; protected static final String LOCALES = "locales"; protected static final String PAGE_RESOLVER_CLASS = "pageResolverClass"; protected static final String ITEM_RESOLVER_CLASS = "itemResolverClass"; protected static final String TEMPLATE_RESOLVER_CLASS = "templateResolverClass"; protected static final String XML_GENERATOR_CLASS = "xmlGeneratorClass"; protected static final String CONTENT_TYPES = "associatedContentTypes"; protected static final String CREATABLE_CONTENT_TYPES = "creatableContentTypes"; protected static final String CONTENT_TYPES_NOT_ASSOC = "notAssociatedContentTypes"; protected static final String LIFECYCLE_DEFINITIONS = "associatedLifecycleDefinitions"; protected static final String WF_TEMPLATES = "associatedWorkflowTemplates"; private final static String ITEM_QUERY = "com.arsdigita.cms.ItemsInSection"; private final static String SECTION_ID = "sectionId"; private static final CMSConfig s_config = new CMSConfig(); static { s_log.debug("Static initializer starting..."); s_config.load(); s_log.debug("Static initializer finished..."); } // Cached properties PageResolver m_pageResolver = null; ItemResolver m_itemResolver = null; TemplateResolver m_templateResolver = null; XMLGenerator m_xmlGenerator = null; // public ContentSection() { // super(BASE_DATA_OBJECT_TYPE); // } // /** * Constructor re-creating a content section object by retrieving its data * object by OID * * @param oid * @throws DataObjectNotFoundException */ public ContentSection(OID oid) throws DataObjectNotFoundException { super(oid); } /** * Constructor re-creating a content section object from its data object. * * @param oid * @throws DataObjectNotFoundException */ public ContentSection(DataObject obj) { super(obj); } /** * Constructor re-creating a content section object by retrieving its data * Object by ID * * @param oid * @throws DataObjectNotFoundException */ public ContentSection(BigDecimal id) throws DataObjectNotFoundException { super(new OID(BASE_DATA_OBJECT_TYPE, id)); } public static CMSConfig getConfig() { return s_config; } /** * @return the base PDL object type for this section. Child classes should * override this method to return the correct value */ @Override public String getBaseDataObjectType() { return BASE_DATA_OBJECT_TYPE; } /** * Fetches a property of the content section. * Publicized the getter for metadata forms. * * @param key The name of the attribute * @return The value of the attribute */ @Override public Object get(String key) { return super.get(key); } /** * Sets a property of the content section. * Publicized the setter for metadata forms. * * @param key The name of the attribute * @param value The value of the attribute */ @Override public void set(String key, Object value) { super.set(key, value); } /** * Sets the content section of the root folder to this section. */ @Override protected void afterSave() { super.afterSave(); // Set the root folder's content section. Folder root = getRootFolder(); root.setContentSection(this); root.save(); } /** * Fetch the name of the content section. * * @return The name of the content section */ public String getName() { //return (String) get(NAME); return getTitle(); } /** * Returns the title of the content section. * * @return A title */ @Override public String getDisplayName() { return getName(); } /** * Set the name of the content section * * @param name The name */ public void setName(String name) { set(NAME, name); } // Left-over from content section as old-style application based on kernel // PackageType and Sitenode instead on new style web.Application. // Retained for reference purpose until the packages Workspace and Service are // migrated to new style application as well. // /** // * Get the package instance for this content section. Each section is // * associated with exactly one package instance. // * // * @return the package instance associated with this content section. // * @post return != null // */ // public PackageInstance getPackageInstance() { // DataObject pkg = (DataObject) get(PACKAGE); // Assert.exists(pkg, "package instance"); // return new PackageInstance(pkg); // } // // /** // * Set the package instance for this content section. // * // * @param pkg The package instance // * @pre ( pkg != null ) // */ // protected void setPackageInstance(PackageInstance pkg) { // Assert.exists(pkg, "package instance"); // setAssociation(PACKAGE, pkg); // } // // /** // * Fetch the site node on which the content section is mounted. // * A content section should be mounted on exactly one site node. If it // * is mounted on more than one site node, only the first site node will // * be returned. // * // * @return The site node // */ // public SiteNode getSiteNode() { // return getPackageInstance().getDefaultMountPoint(); // } /** * Finds the location of the content section. * * @return The URL of the site node on which the content section is mounted. * This URL includes the webapp context path. */ public String getURL() { String sURL = null; //see if there is a request final HttpServletRequest sreq = Web.getRequest(); if (sreq != null) { // If we're running in the scope of a request , generate a URL using the // request, since it will set the scheme correctly and add // any missing global parameters. // // No, we do not want any parameters here, because existing CMS code // expects getURL() to return path only! sURL = URL.there(sreq, this, "/", null).toString(); } else { sURL = URL.there(this, "/", null).toString(); } return sURL; } /** * Gets the full path of the content section. * * @return returns the path of this application including the dispatcher path. * The path does not end in a slash. Does not return null */ public String getFullPath() { return URL.getDispatcherPath() + getPath(); } // Left over, see above // public final String getPath() { // final String path = getSiteNode().getURL(); // // if (Assert.isEnabled()) { // Assert.isTrue(path.endsWith("/")); // } // // return path.substring(0, path.length() - 1); // } /** * Get the folder in which all draft items are contained, directly or * indirectly. This folder will in general contain different kinds of * content items and other folders. The root folder for live items can be * obtained by calling {@link ContentItem#getLiveVersion} on the folder * returned by this method. * * @post return != null * @return the root folder for draft items in this content section. */ public Folder getRootFolder() { DataObject folder = (DataObject) get(ROOT_FOLDER); Assert.exists(folder, "root folder"); return new Folder(folder); } /** * Set the root folder for this content section. * * @param root The root folder */ public void setRootFolder(Folder root) { Assert.exists(root, "root folder"); // Update the content section of the old and new root folders. // This is necessary because the content section is used to determine // which items are a part of the site map (folder hierarchy) of a // content section. // // MP: This only works if the root folder is changed and it contains no // sub-items/folders. The next step is to recursively update items // under the root folder when fetching "all items in a section" is // implemented. if (!isNew()) { Folder oldRoot = getRootFolder(); oldRoot.setContentSection(null); oldRoot.save(); } setAssociation(ROOT_FOLDER, root); } /** * Get the folder in which all templates for this section are contained. * * @post return != null * @return the root folder for all templates within this section */ public Folder getTemplatesFolder() { DataObject folder = (DataObject) get(TEMPLATES_FOLDER); if (folder == null) { return null; } else { return new Folder(folder); } } /** * Set the templates folder for this content section * * @param folder the folder where all templates for this section will * be stored */ public void setTemplatesFolder(Folder folder) { setAssociation(TEMPLATES_FOLDER, folder); } /** * Fetch the root category for the content section. * It will search for a root category matching the * current URL, then progressively strip off bits * of the url until the root site node. * * @deprecated use {@link Category#getRootForObject} instead * * @return The root category * @post ( return != null ) */ public Category getRootCategory() { Category category = Category.getRootForObject(this); Assert.exists(category, "root category"); return category; } /** * Set the root category for this content section. * * @deprecated use {@link Category#setRootForObject} instead * * @param root The root category * @pre ( root != null ) */ public void setRootCategory(Category root) { Assert.exists(root, "root category"); Category.setRootForObject(this, root); } /** * Fetch the staff group for this content section. * * @return The staff group * @post ( return != null ) */ public Group getStaffGroup() { DataObject group = (DataObject) get(STAFF_GROUP); Assert.exists(group, "staff group"); return new Group(group); } /** * Set the staff group for this content section. * * @param group The staff group * @pre ( group != null ) */ public void setStaffGroup(Group group) { Assert.exists(group, "staff group"); setAssociation(STAFF_GROUP, group); } /** * Fetch the viewers group for this content section. * * @return The viewers group * @post ( return != null ) */ public Group getViewersGroup() { DataObject group = (DataObject) get(VIEWERS_GROUP); Assert.exists(group, "viewers group"); return new Group(group); } /** * Set the viewers group for this content section. * * @param group The viewers group * @pre ( group != null ) */ public void setViewersGroup(Group group) { Assert.exists(group, "viewers group"); setAssociation(VIEWERS_GROUP, group); } /** * Get the class name of the {link @com.arsdigita.cms.dispatcher.PageResolver}. * * @return The class name * @post ( return != null ) */ public String getPageResolverClassName() { String prc = (String) get(PAGE_RESOLVER_CLASS); Assert.exists(prc, "Page Resolver class"); return prc; } /** * Get the page resolver for this content section. The page resolver is * used to resolve URLs to * {@link com.arsdigita.cms.dispatcher.ResourceHandler server resources}. * * @return The page resolver */ public PageResolver getPageResolver() { if (m_pageResolver == null) { if (s_log.isDebugEnabled()) { s_log.debug("The page resolver hasn't been loaded yet; " + "loading it now"); } try { final Class prc = Class.forName(getPageResolverClassName()); m_pageResolver = (PageResolver) prc.newInstance(); m_pageResolver.setContentSectionID(getID()); } catch (ClassNotFoundException cnfe) { throw new UncheckedWrapperException(cnfe); } catch (InstantiationException ie) { throw new UncheckedWrapperException(ie); } catch (IllegalAccessException iae) { throw new UncheckedWrapperException(iae); } } if (s_log.isDebugEnabled()) { s_log.debug("Returning page resolver " + m_pageResolver); } return m_pageResolver; } /** * Set the page resolver for this content section. * * @param className The class name */ public void setPageResolverClassName(String className) { set(PAGE_RESOLVER_CLASS, className); m_pageResolver = null; } /** * Get the class name of the {link @com.arsdigita.cms.dispatcher.ItemResolver}. * * @return The class name * @post ( return != null ) */ public String getItemResolverClassName() { String irc = (String) get(ITEM_RESOLVER_CLASS); Assert.exists(irc, "Content Item Resolver class"); s_log.debug("Content Item Resolver Class is " + irc); return irc; } /** * Get the item resolver for this content section. The item * resolver is used to resolve URLs to {@link * com.arsdigita.cms.ContentItem content items}. * * @return The item resolver */ public ItemResolver getItemResolver() { if (m_itemResolver == null) { try { final Class irc = Class.forName(getItemResolverClassName()); m_itemResolver = (ItemResolver) irc.newInstance(); } catch (ClassNotFoundException cnfe) { throw new UncheckedWrapperException(cnfe); } catch (InstantiationException ie) { throw new UncheckedWrapperException(ie); } catch (IllegalAccessException iae) { throw new UncheckedWrapperException(iae); } } return m_itemResolver; } /** * Set the item resolver for this content section. * * @param className The class name */ public void setItemResolverClass(String className) { set(ITEM_RESOLVER_CLASS, className); m_itemResolver = null; } /** * Get the class name of the {link @com.arsdigita.cms.dispatcher.TemplateResolver}. * * @return The class name * @post ( return != null ) */ public String getTemplateResolverClassName() { String trc = (String) get(TEMPLATE_RESOLVER_CLASS); Assert.exists(trc, "Template Resolver class"); return trc; } /** * Returns the template resolver for this content section. * * @return The name of a class that implements * com.arsdigita.cms.dispatcher.TemplateResolver. */ public TemplateResolver getTemplateResolver() { if (m_templateResolver == null) { try { Class trc = Class.forName(getTemplateResolverClassName()); m_templateResolver = (TemplateResolver) trc.newInstance(); } catch (ClassNotFoundException cnfe) { throw new UncheckedWrapperException(cnfe); } catch (InstantiationException ie) { throw new UncheckedWrapperException(ie); } catch (IllegalAccessException iae) { throw new UncheckedWrapperException(iae); } } return m_templateResolver; } /** * Sets the template resolver for this content section. * * @param className The name of a class that implements * com.arsdigita.cms.dispatcher.TemplateResolver. **/ public void setTemplateResolverClass(String className) { set(TEMPLATE_RESOLVER_CLASS, className); m_templateResolver = null; } /** * Get the class name of the {link @com.arsdigita.cms.dispatcher.XMLGenerator}. * * @return The class name */ public String getXMLGeneratorClassName() { String xgc = (String) get(XML_GENERATOR_CLASS); Assert.exists(xgc, "XML Generator class"); return xgc; } /** * Get the XML generator for this content section. The XML generator is * used to transform content items into a DOM element. * * @return The XML generator */ public XMLGenerator getXMLGenerator() { if (m_xmlGenerator == null) { try { Class xgc = Class.forName(getXMLGeneratorClassName()); m_xmlGenerator = (XMLGenerator) xgc.newInstance(); } catch (ClassNotFoundException cnfe) { throw new UncheckedWrapperException(cnfe); } catch (InstantiationException ie) { throw new UncheckedWrapperException(ie); } catch (IllegalAccessException iae) { throw new UncheckedWrapperException(iae); } } return m_xmlGenerator; } /** * Set the XML generator for this content section. * * @param className The class name */ public void setXMLGeneratorClass(String className) { set(XML_GENERATOR_CLASS, className); m_xmlGenerator = null; } ////////////////////////////// // // Globalization. // /** * Gets the default Locale. This is used for translating or creating * content if no locale is specified. * * @return The default locale for a content section, possibly null */ public Locale getDefaultLocale() { DataObject obj = (DataObject) get(DEFAULT_LOCALE); if (obj == null) { return null; } else { return new Locale(obj); } } /** * Sets the default locale for a content section. Only a locale that is * registered to this section can be set as the default locale for this * section. If no locale is passed in, unset the default locale, if it * exists. * * @param locale The locale. If null, unset the default locale. * @pre ( locale in getLocales() || locale == null ) */ public void setDefaultLocale(Locale locale) { setAssociation(DEFAULT_LOCALE, locale); } /** * Returns a collection of Locales associated with this content section. * Each locale represents options for translating content items in this * section. * * @return A collection of locales registered to this content section * @post ( return != null ) */ public SectionLocaleCollection getLocales() { DataAssociation da = (DataAssociation) get(LOCALES); return new SectionLocaleCollection(da); } /** * Register a locale with this content section. * * @param locale The locale * @pre ( locale != null ) */ public void addLocale(Locale locale) { addLocale(locale, false); } /** * Register a locale with this content section. The locale may be * set as the default locale for this content section. * * @param locale The locale * @param isDefault A flag, if true, which indicates that this locale * should be the default locale for this content section. * @pre ( locale != null ) */ public void addLocale(Locale locale, boolean isDefault) { DataAssociation da = (DataAssociation) get(LOCALES); locale.addToAssociation(da); if (isDefault) { setDefaultLocale(locale); } } /** * Unregister a locale from the content section. * * @param locale * @pre ( locale != null ) */ public void removeLocale(Locale locale) { DataAssociation da = (DataAssociation) get(LOCALES); locale.removeFromAssociation(da); } ////////////////////////////// // // Content types. // /** * Get all user-defined content types registered to the content section. * * @return A ContentTypeCollection of registered content types */ public ContentTypeCollection getContentTypes() { return getContentTypes(false); } public ContentTypeCollection getContentTypes(boolean hidden) { DataAssociation da = (DataAssociation) get(CONTENT_TYPES); ContentTypeCollection types = new ContentTypeCollection(da); // Filter out internal content types. types.addFilter("mode != 'I'"); if (!hidden) { types.addFilter("mode != 'H'"); } return types; } public ContentTypeCollection getDescendantsOfContentType(ContentType ct) { ContentTypeCollection ctc = getContentTypes(); // The Filter Factory FilterFactory ff = ctc.getFilterFactory(); // Create an or-filter CompoundFilter or = ff.or(); // The content type must be either of the requested type or.addFilter(ff.equals(ContentType.ID, ct.getID())); // Or must be a descendant of the requested type try { StringTokenizer strTok = new StringTokenizer(ct.getDescendants(), "/"); while (strTok.hasMoreElements()) { or.addFilter(ff.equals(ContentType.ID, (String) strTok.nextElement())); } } catch (Exception ex) { // WTF? The selected content type does not exist in the table??? s_log.error("WTF? The selected content type does not exist in the table???"); } ctc.addFilter(or); return ctc; } /** * Get all user-defined content types registered to the content section * that can be created. * * @return A ContentTypeCollection of content types that are * 1) registered to the content section * 2) user-defined * 3) possess a non-empty creation component in its AuthoringKit. */ public ContentTypeCollection getCreatableContentTypes() { return getCreatableContentTypes(false); } public ContentTypeCollection getCreatableContentTypes(boolean hidden) { DataAssociation da = (DataAssociation) get(CREATABLE_CONTENT_TYPES); ContentTypeCollection types = new ContentTypeCollection(da); // Filter out internal content types. types.addFilter("mode != 'I'"); if (!hidden) { types.addFilter("mode != 'H'"); } return types; } /** * Register a content type to the content section. If the content type is * already registered to the content section, nothing is done. * * @param type The content type */ public void addContentType(ContentType type) { if (!hasContentType(type)) { DataAssociation da = (DataAssociation) get(CONTENT_TYPES); type.addToAssociation(da); } } /** * Unregister a content type from the content section. * * @param type The content type */ public void removeContentType(ContentType type) { DataAssociation da = (DataAssociation) get(CONTENT_TYPES); type.removeFromAssociation(da); } /** * Return true if the content type is registered with this * content section. * * @param type the type to cjeck for * @return true if the content type is registered with this * content section. */ private boolean hasContentType(ContentType type) { DataAssociation da = (DataAssociation) get(CONTENT_TYPES); DataAssociationCursor cursor = da.cursor(); cursor.addEqualsFilter(ID, type.getID()); return (cursor.size() > 0); } /** * Return the user-defined content types that are not registered to * this content section. * * @return A ContentTypeCollection of content types not registered * to the content section */ public ContentTypeCollection getNotAssociatedContentTypes() { DataAssociation da = (DataAssociation) get(CONTENT_TYPES_NOT_ASSOC); ContentTypeCollection types = new ContentTypeCollection(da); // Filter out internal content types. types.addFilter("mode != 'I'"); return types; } ////////////////////////////// // // Lifecycle definitions. // /** * Get all lifecycle definitions registered to the content section. * * @return a LifecycleDefinitionCollection or registered * lifecycle definition. */ public LifecycleDefinitionCollection getLifecycleDefinitions() { return new LifecycleDefinitionCollection(getLifecycleDefinitionsAssociation()); } /** * Register a lifecycle definition to the content section. * * @param definition The lifecycle definition */ public void addLifecycleDefinition(LifecycleDefinition definition) { definition.addToAssociation(getLifecycleDefinitionsAssociation()); } /** * Unregister a lifecycle definition from the content section. * * @param definition The lifecycle definition */ public void removeLifecycleDefinition(LifecycleDefinition definition) { definition.removeFromAssociation(getLifecycleDefinitionsAssociation()); } private DataAssociation getLifecycleDefinitionsAssociation() { return (DataAssociation) get(LIFECYCLE_DEFINITIONS); } ////////////////////////////// // // Workflow templates. // /** * Get all workflow templates registered to the content section. * * @return a TaskCollection of workflow templates. */ public TaskCollection getWorkflowTemplates() { TaskCollection tasks = new TaskCollection(getWorkflowTemplatesAssociation()); tasks.addOrder("label asc"); return tasks; } /** * Register a workflow template to the content section. * * @param template The workflow template */ public void addWorkflowTemplate(WorkflowTemplate template) { template.addToAssociation(getWorkflowTemplatesAssociation()); } /** * Unregister a workflow template from the content section. * * @param template The workflow template */ public void removeWorkflowTemplate(WorkflowTemplate template) { template.removeFromAssociation(getWorkflowTemplatesAssociation()); } private DataAssociation getWorkflowTemplatesAssociation() { return (DataAssociation) get(WF_TEMPLATES); } ////////////////////////////// // // Finding a content section. // /** * Looks up the section given the SiteNode. * * @param node The site node * @return The content section * @pre ( node != null ) * @post ( return != null ) */ public static ContentSection getSectionFromNode(SiteNode node) throws DataObjectNotFoundException { return (ContentSection) retrieveApplicationForSiteNode(node); // BigDecimal sectionId = null; // // PackageInstance pkg = node.getPackageInstance(); // if ( pkg == null ) { // throw new DataObjectNotFoundException( // "No package instance for node_id=" + node.getID().toString()); // } // // return getSectionFromPackage(pkg); } // /** // * Looks up the section given the PackageInstance. // * // * @param pkg The package instance // * @return The content section ID // * @pre ( pkg != null ) // * @post ( return != null ) // */ // public static ContentSection getSectionFromPackage(PackageInstance pkg) // throws DataObjectNotFoundException { // // ContentSection section = null; // // final String query = "com.arsdigita.cms.getSectionFromPackage"; // DataQuery dq = SessionManager.getSession().retrieveQuery(query); // dq.setParameter("packageId", pkg.getID()); // if ( dq.next() ) { // DataObject dobj = (DataObject) dq.get("section"); // if ( dobj != null ) { // section = (ContentSection) DomainObjectFactory.newInstance(dobj); // } // dq.close(); // } else { // throw new DataObjectNotFoundException( // "Failed to fetch a content section for the current package " + // "instance. [package_id =" + pkg.getID().toString() + "]"); // } // return section; // } /** * Get the content section for an item. * * @deprecated use {@link ContentItem#getContentSection} instead * * @pre item != null * @post return != null * @param item A content item * @return The content section of an item */ public static ContentSection getContentSection(ContentItem item) throws DataObjectNotFoundException { return item.getContentSection(); } /** * Get the content section for a folder. * * @deprecated use {@link ContentItem#getContentSection} instead * @pre item != null * @post return != null * @param folder A content folder * @return The content section of the folder */ public static ContentSection getContentSection(Folder folder) throws DataObjectNotFoundException { return folder.getContentSection(); } /** * Retrieve all content sections in the system. * * @return A collection of content sections */ public static ContentSectionCollection getAllSections() { DataCollection da = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); return new ContentSectionCollection(da); } /** * Retrieve the default content section in the system. * * Default section is the first section created during setup, therefore it * is recognized as the one with the lowest id. * * @return The default content section. */ public static ContentSection getDefaultSection() { ContentSectionCollection sections = getAllSections(); sections.addOrder(ID); sections.next(); // positions on the first section ContentSection section = (ContentSection) sections.getDomainObject(); if (sections.isFirst() ) { sections.close(); s_log.debug("Default section is "+section.getName() ); return section; } else { sections.close(); s_log.debug("Section found: "+section.getName()+", but not first." ); return null; } } /** * Convenience method to retrieve the name of the default content section * in the system. * * Default section is the first section created during setup, therefore it * is recognized as the one with the lowest id. * * @return The default content section name. */ public static String getDefaultSectionName() { return getDefaultSection().getBaseDataObjectType(); } /** * Creates a content section of the given name using default values and * returns it. * * @param name Name of the content section * @return ContentSection */ public static ContentSection create(final String name) { Folder folder = createRootFolder(name); Category category = createRootCategory(name); Group staff = createStaffGroup(name); // Some default classes for a content section. String prc = "com.arsdigita.cms.dispatcher.SimplePageResolver"; String irc = "com.arsdigita.cms.dispatcher.MultilingualItemResolver"; String xgc = "com.arsdigita.cms.dispatcher.SimpleXMLGenerator"; String trc = "com.arsdigita.cms.dispatcher.DefaultTemplateResolver"; ContentSection section = ContentSection.create(name, folder, category, staff, prc, irc, xgc, trc); // Set the default context on the root folder to // the content section PermissionService.setContext(folder.getOID(), section.getOID()); createDefaultResources(section); return section; } /** * Create a new content section. This method is called automatically when a * CMS package instance is created. * * @param name The package instance * @param folder The root folder * @param category The root category * @param staff The staff group * @param prc The page resolver class name * @param irc The item resolver class name * @param xgc The XML generator class name * @return The new content section */ public static ContentSection create(String name, Folder folder, Category category, Group staff, String prc, String irc, String xgc) { /** Set default as template resolver class name */ String trc = "com.arsdigita.cms.dispatcher.DefaultTemplateResolver"; return ContentSection.create( name, folder, category, staff, prc, irc, xgc, trc); } /** * Create a new content section. This method is called automatically when a * CMS package instance is created. * * @param name The package instance * @param folder The root folder * @param category The root category * @param staff The staff group * @param prc The page resolver class name * @param irc The item resolver class name * @param xgc The XML generator class name * @param trc The template resolver class name * @return The new content section */ public static ContentSection create(String name, Folder folder, Category category, Group staff, String prc, String irc, String xgc, String trc) { // This could be moved out of here and into the Installer // (passing it into a modified version of create) Group viewers = new Group(); viewers.setName(name + " Viewers"); viewers.save(); // Create template root folder. Folder templates = new Folder(); templates.setName("templates"); templates.setLabel((String) GlobalizationUtil.globalize( "cms.templates").localize()); templates.save(); //create and initialize the content section application ContentSection section = (ContentSection) Application .createApplication(BASE_DATA_OBJECT_TYPE , name, name, null); section.initialize(name, folder, category, staff, prc, irc, xgc, trc, templates, viewers); return section; } /** * Creates and maps default resources to the content section. * * @param section The content section * * MP: create resource types. * MP: use the resources API. * MP: only create resources once. */ protected static void createDefaultResources(ContentSection section) { // XML resources ResourceType rt = ResourceType.findResourceType("xml"); Resource r = rt.createInstance("com.arsdigita.cms.ui.ContentSectionPage"); r.save(); ResourceMapping rm = r.createInstance(section, "admin"); rm.save(); rm = r.createInstance(section, "admin/index"); rm.save(); // XXX What's up with this? The class doesn't exist anymore. //r = rt.createInstance("com.arsdigita.cms.user.ItemIndexPage"); //r.save(); //rm = r.createInstance(section, "index"); //rm.save(); r = rt.createInstance("com.arsdigita.cms.ui.ContentItemPage"); r.save(); rm = r.createInstance(section, "admin/item"); rm.save(); } /** * Creates the root folder for a content section. * * @param name The name of the content section * @return The root folder */ protected static Folder createRootFolder(String name) { Folder root = new Folder(); root.setName("/"); root.setLabel((String) GlobalizationUtil.globalize( "cms.installer.root_folder").localize()); root.save(); return root; } /** * Creates the root category for a content section. * * @param name The name of the content section * @return The root category */ protected static Category createRootCategory(String name) { Category root = new Category("/", "Root Category"); root.save(); return root; } /** * Creates default staff group and associated default roles for a * content section. * * @param name The name of the content section * @return The staff group */ private static Group createStaffGroup(String name) { Group staff = new Group(); staff.setName(name + " Administration"); staff.save(); return staff; } /** * Initialize a newly created content section. * * @param name The package instance name * @param folder The root folder * @param category The root category * @param staff The staff group * @param prc The page resolver class name * @param irc The item resolver class name * @param xgc The XML generator class name * @param trc The template resolver class name * @return The new content section */ public ContentSection initialize( String name, Folder folder, Category category, Group staff, String prc, String irc, String xgc, String trc, Folder templates, Group viewers) { setName(name); //setPackageInstance(pkg); setRootFolder(folder); setRootCategory(category); setStaffGroup(staff); setPageResolverClassName(prc); setItemResolverClass(irc); setXMLGeneratorClass(xgc); setTemplateResolverClass(trc); setTemplatesFolder(templates); setViewersGroup(viewers); save(); return this; } /** * Fetches the child items of this section. An item is defined to be "in" * a content section if it can be found directly in the folder hierarchy * (site map) of the content section. The returned collection * provides methods to filter by various criteria, for example by name or * by whether items are folders or not. */ public Folder.ItemCollection getItems() { DataQuery dq = SessionManager.getSession().retrieveQuery(ITEM_QUERY); dq.setParameter(SECTION_ID, getID()); return new Folder.ItemCollection(dq); } @Override public String getServletPath() { return URL.SERVLET_DIR + "/content-section"; } }