diff --git a/ccm-cms/src/com/arsdigita/cms/Loader.java b/ccm-cms/src/com/arsdigita/cms/Loader.java index beef86b4d..c7358e8bb 100755 --- a/ccm-cms/src/com/arsdigita/cms/Loader.java +++ b/ccm-cms/src/com/arsdigita/cms/Loader.java @@ -18,13 +18,14 @@ */ package com.arsdigita.cms; +import com.arsdigita.cms.contentsection.ContentSectionConfig; import com.arsdigita.cms.contentsection.ContentSectionSetup; -import com.arsdigita.cms.util.Util; import com.arsdigita.cms.contenttypes.XMLContentTypeHandler; import com.arsdigita.cms.portlet.ContentDirectoryPortlet; import com.arsdigita.cms.portlet.ContentItemPortlet; import com.arsdigita.cms.portlet.ContentSectionsPortlet; import com.arsdigita.cms.portlet.TaskPortlet; +import com.arsdigita.cms.util.Util; import com.arsdigita.formbuilder.util.FormbuilderSetup; import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.KernelExcursion; @@ -38,35 +39,31 @@ import com.arsdigita.util.parameter.StringArrayParameter; import com.arsdigita.web.Application; import com.arsdigita.web.ApplicationType; import com.arsdigita.xml.XML; - import java.util.ArrayList; import java.util.Iterator; import java.util.List; - import org.apache.log4j.Logger; - /** *

Executes nonrecurring at install time and loads (installs and initializes) - * the Content Management System module,including the Content Center, CMS Service - * applications, and CMS Mime Types service persistently into database.

+ * the Content Management System module,including the Content Center, CMS + * Service applications, and CMS Mime Types service persistently into + * database.

* *

This class also optionally initializes user-defined content types.

*

Additional user-defined content sections can be loaded and initilized - * using the recurring

initializer
at any startup. + * using the recurring + *
initializer
at any startup. * - *

The tasks to perform are:

- *
    - *
  1. create CMS package type(content-section)
  2. - *
  3. create Workspace package type and instance
  4. - *
  5. create CMS Service package type and instance
  6. - *
  7. create CMS package (content-section) instance
  8. - *
+ *

The tasks to perform are:

  1. create CMS package + * type(content-section)
  2. create Workspace package type and + * instance
  3. create CMS Service package type and instance
  4. + *
  5. create CMS package (content-section) instance
* - *

Configuration can be modified by configuration parameters before processing, - * otherwise hardcoded default values take effect. After processing, the - * installation values can not be modified anymore without a fresh installation - * of the whole system.

+ *

Configuration can be modified by configuration parameters before + * processing, otherwise hardcoded default values take effect. After processing, + * the installation values can not be modified anymore without a fresh + * installation of the whole system.

* * @author Peter Boy <pboy@barkhof.uni-bremen.de> * @since ccm-cms version 6.6.0 @@ -74,39 +71,38 @@ import org.apache.log4j.Logger; */ public class Loader extends PackageLoader { - /** Creates a s_logging category with name = full name of class */ + /** + * Creates a s_logging category with name = full name of class + */ private static final Logger s_log = Logger.getLogger(Loader.class); - - /** Loader configuration object, singleton design pattern - * NOTE: LoaderConfig only supplies unmutable hard coded defaults! It is - * not possible to alter any of the contained values by specifiying an - * configuration parameter during load step. If a configuration value - * has to be configurable at load time, the parameter must be relocated - * into this Loader class! */ + /** + * Loader configuration object, singleton design pattern NOTE: LoaderConfig + * only supplies unmutable hard coded defaults! It is not possible to alter + * any of the contained values by specifiying an configuration parameter + * during load step. If a configuration value has to be configurable at load + * time, the parameter must be relocated into this Loader class! + */ private static final LoaderConfig s_conf = LoaderConfig.getInstance(); - // /////////////////////////////////////////////////////////////////// // Configurable parameters during load step. // /////////////////////////////////////////////////////////////////// - /** * The name(s) of the content section(s). In case of more than one name the * first is treated as default section. Otherwise the section created is the * default section. More sections can always be created during a subsequent - * system startup using initialization parameters. + * system startup using initialization parameters. */ private final Parameter m_contentSectionNames = new StringArrayParameter( - "com.arsdigita.cms.loader.section_names", - Parameter.REQUIRED, - new String[] {"content"} - ); - - /** List of classnames of internal base content types (needed in every - * section created), generated while loading those content types in - * loadContentTypeDefinitions(files) for later use in register step. */ + "com.arsdigita.cms.loader.section_names", + Parameter.REQUIRED, + new String[]{"content"}); + /** + * List of classnames of internal base content types (needed in every + * section created), generated while loading those content types in + * loadContentTypeDefinitions(files) for later use in register step. + */ private ArrayList m_content_type_list = new ArrayList(); - /** * Standard constructor. */ @@ -114,12 +110,12 @@ public class Loader extends PackageLoader { s_log.debug("CMS.loader (Constructor) invoked"); register(m_contentSectionNames); - + s_log.debug("CMS.loader (Constructor) completed"); } /** - * + * */ public void run(final ScriptContext ctx) { s_log.debug("CMS.loader.run() invoked"); @@ -142,7 +138,7 @@ public class Loader extends PackageLoader { // Step 4) Load CMS content section // Loads content section application type and instance in one step - loadContentSection( (String[]) get(m_contentSectionNames) ); + loadContentSection((String[]) get(m_contentSectionNames)); // Step 5) Loading CMS portlets s_log.debug("CMS.loader going to load portlets"); @@ -154,8 +150,8 @@ public class Loader extends PackageLoader { // Loading forms widget into database FormbuilderSetup fbs = new FormbuilderSetup(); fbs.setup(s_conf.getWidgetTypes(), - s_conf.getProcessListenerTypes(), - s_conf.getDataQueries()); + s_conf.getProcessListenerTypes(), + s_conf.getDataQueries()); } @@ -165,23 +161,23 @@ public class Loader extends PackageLoader { /** * Loads the Workspace subpackage (content-center) into the database. * - * It is made public to be able to invoke it from the update script - * (e.g. 6.6.1-6.6.2). We need separate steps for loading and instantiating + * It is made public to be able to invoke it from the update script (e.g. + * 6.6.1-6.6.2). We need separate steps for loading and instantiating * because update skript requires. */ public static ApplicationType loadWorkspaceApplicationType() { s_log.debug("Creating CMS Workspace..."); - /* Create new type legacy free application type - * NOTE: The wording in the title parameter of ApplicationType - * determines the name of the subdirectory for the XSL stylesheets. - * It gets "urlized", i.e. trimming leading and trailing blanks and - * replacing blanks between words and illegal characters with an - * hyphen and converted to lower case. - * "Content Center" will become "content-center". */ - ApplicationType type = new - ApplicationType(Workspace.INSTANCE_NAME, - Workspace.BASE_DATA_OBJECT_TYPE ); + /* + * Create new type legacy free application type NOTE: The wording in the + * title parameter of ApplicationType determines the name of the + * subdirectory for the XSL stylesheets. It gets "urlized", i.e. + * trimming leading and trailing blanks and replacing blanks between + * words and illegal characters with an hyphen and converted to lower + * case. "Content Center" will become "content-center". + */ + ApplicationType type = new ApplicationType(Workspace.INSTANCE_NAME, + Workspace.BASE_DATA_OBJECT_TYPE); type.setDescription("The content center workspace for content creators."); type.save(); @@ -193,14 +189,14 @@ public class Loader extends PackageLoader { /** * Instantiates the Workspace subpackage (content-center) (in the database). * - * It is made public to be able to invoke it from the update script - * (e.g. 6.6.1-6.6.2). We need separate steps for loading and instantiating + * It is made public to be able to invoke it from the update script (e.g. + * 6.6.1-6.6.2). We need separate steps for loading and instantiating * because update skript requires. * * @param workspaceType */ public static void setupDefaultWorkspaceApplicationInstance( - ApplicationType workspaceType) { + ApplicationType workspaceType) { // create application instance // Whether a legacy compatible or a legacy free application is @@ -209,10 +205,10 @@ public class Loader extends PackageLoader { // old-style package key used as url fragment where to install the instance s_log.debug("Creating CMS Workspace instance ..."); Workspace app = (Workspace) Application.createApplication( - Workspace.BASE_DATA_OBJECT_TYPE, // type - Workspace.PACKAGE_KEY, // url fragment - Workspace.INSTANCE_NAME, // title - null); // parent + Workspace.BASE_DATA_OBJECT_TYPE, // type + Workspace.PACKAGE_KEY, // url fragment + Workspace.INSTANCE_NAME, // title + null); // parent app.setDescription("The default CMS workspace instance."); app.save(); @@ -220,44 +216,42 @@ public class Loader extends PackageLoader { s_log.debug("Done loading CMS Workspace."); } - /** * CMS Service application is used by the Content Management System as a - * store for global resources and assets. - * It is made public to be able to invoke it from the update script - * (e.g. 6.6.1-6.6.2). + * store for global resources and assets. It is made public to be able to + * invoke it from the update script (e.g. 6.6.1-6.6.2). */ public static ApplicationType loadServiceApplicationType() { s_log.debug("Loading CMS Servce Package..."); - /* Create new type legacy free application type - * NOTE: The wording in the title parameter of ApplicationType - * determines the name of the subdirectory for the XSL stylesheets. - * It gets "urlized", i.e. trimming leading and trailing blanks and - * replacing blanks between words and illegal characters with an - * hyphen and converted to lower case. - * "CMS Service" will become "cms-service". */ - ApplicationType type = new ApplicationType("CMS Service", - Service.BASE_DATA_OBJECT_TYPE ); + /* + * Create new type legacy free application type NOTE: The wording in the + * title parameter of ApplicationType determines the name of the + * subdirectory for the XSL stylesheets. It gets "urlized", i.e. + * trimming leading and trailing blanks and replacing blanks between + * words and illegal characters with an hyphen and converted to lower + * case. "CMS Service" will become "cms-service". + */ + ApplicationType type = new ApplicationType("CMS Service", + Service.BASE_DATA_OBJECT_TYPE); type.setDescription("Services to store global resources and assets."); type.save(); return type; } - /** * * @param serviceType */ public static void setupDefaultServiceApplicationInstance( - ApplicationType serviceType) { + ApplicationType serviceType) { // create legacy compatible application instance, // old-style package key used as url fragment where to install the instance Service app = (Service) Application.createApplication( - serviceType, // type - Service.PRIMARY_URL_STUB, // url fragment - "CMS Service Instance", // title + serviceType, // type + Service.PRIMARY_URL_STUB, // url fragment + "CMS Service Instance", // title null); // parent app.setDescription("The default CMS service instance."); app.save(); @@ -265,40 +259,39 @@ public class Loader extends PackageLoader { s_log.debug("Done creating CMS Service Package."); } - /** * Load a content section application type and an initial default - * content-section instance(s). - * Some configuration values which are to be considered as unmutable are - * specified in LoaderConfig. - * Uses new style application in legacy compatible mode. + * content-section instance(s). Some configuration values which are to be + * considered as unmutable are specified in LoaderConfig. Uses new style + * application in legacy compatible mode. * * NOTE: At ccm-cms load time no content type packages are available because * any content type depends on ccm-cms. Therefore, the loading step can not * process content type package assignment! Instead each content type itself - * must assign itself to an appropriate content section at it's load time. + * must assign itself to an appropriate content section at it's load time. * Cf. {@link com.arsdigita.cms.contenttype.AbstractContentTypeLoader}. - * + * * But the load step has to process the cms internal content types! */ private void loadContentSection(String[] sectionNames) { // Step 1: Create content section application type // prerequisite for concrete content-section instance creation. - - /* Create legacy-free application type - * NOTE: The wording in the title parameter of ApplicationType - * determines the name of the subdirectory for the XSL stylesheets. - * It gets "urlized", i.e. trimming leading and trailing blanks and - * replacing blanks between words and illegal characters with an - * hyphen and converted to lower case. - * "Content Section" will become "content-section". */ - ApplicationType type = new ApplicationType( - "Content Section", - ContentSection.BASE_DATA_OBJECT_TYPE ); + + /* + * Create legacy-free application type NOTE: The wording in the title + * parameter of ApplicationType determines the name of the subdirectory + * for the XSL stylesheets. It gets "urlized", i.e. trimming leading and + * trailing blanks and replacing blanks between words and illegal + * characters with an hyphen and converted to lower case. "Content + * Section" will become "content-section". + */ + ApplicationType type = new ApplicationType( + "Content Section", + ContentSection.BASE_DATA_OBJECT_TYPE); type.setDescription("The CMS Content Section application."); type.save(); - + // Step 2: Load CMS specific privileges into central (core) privilege // system. createPrivileges(); @@ -306,73 +299,27 @@ public class Loader extends PackageLoader { // Step 3: Create the installation default content section(s). // ContentSection.create creates a section with several default values // which have to be adopted for a concrete installation. - for (int i = 0 ; i < sectionNames.length ; i++) { - + for (int i = 0; i < sectionNames.length; i++) { + final String sectionName = sectionNames[i]; s_log.debug("Creating content section on /" + sectionName); // Step 1: Validate name for section Util.validateURLParameter("name", sectionName); + + ContentSectionConfig conf = new ContentSectionConfig(); + conf.load(); - // Step 2: Create a section using default values - ContentSection section = ContentSection.create(sectionName); - - // Step 3: Adopt the created section to site specific requirements - // ContentSectionSetup is a convenient class to adopt a - // section created by ContentSection.create() - ContentSectionSetup setup = new ContentSectionSetup(section); - - // Step 3a: Roles (staff group) used in this content section. - // Register roles using a complete set of default roles - // defined in ContentSectionSetup - setup.registerRoles(s_conf.getStuffGroup()); - - // ViewerGroup populated in ContentSection, public access is determined - // by parameter (affecting characteristics of the viewer group) - setup.registerViewers(s_conf.isPubliclyViewable()); - - // Page resolver class, set autonomously by ContentSection.create() - // Item resolver class, configurable, defaults in place. - // Template resolver class, configurable, defaults in place. - // We should not overwrite the default in the initial default configuration - - // register a predefined one-phase lifecycle for items. - setup.registerPublicationCycles(); - // registers predefined "Authoring", "Approval", "Publishing' steps - setup.registerWorkflowTemplates(); - setup.registerResolvers(s_conf.getItemResolverClass(), - s_conf.getTemplateResolverClass()); - // XML generator class, set autonomously by ContentSection.create() - - /* Register internal base content types. Paramter is a list of - * class names created by internal content type load method. - * @see loadContentTypeDefinitions(List) - * External content types (provided by additional packages) are - * not available at CMS load time and can not processed by Loader. - * Registration of those content types are dealt with in the - * respective Loader or in the CMS workspace GUI. - * For each created section the base types get registered. */ - setup.registerContentTypes(m_content_type_list); - - // Section specific categories, usually not used. - // During initial load at install time nor used at all! - // default value is false so no categories get loaded. - if (s_conf.getUseSectionCategories()) { - Iterator files = ((List) s_conf.getCategoryFileList()).iterator(); - while (files.hasNext()) { - setup.registerCategories((String) files.next()); - } - } - - // registers a predefined standard recipient for alerts - setup.registerAlerts(); - - // Load a list of cms tasks and associated alert events - // Currently no functionality to persist them. Not a loader task yet - // setup.loadTaskAlerts(s_conf.getTaskAlerts()); - - section.save(); //persists any changes in the database (DomainObject) - //i.e. creates an object (instance) + ContentSectionSetup.setupContentSectionAppInstance(sectionName, + conf.getDefaultRoles(), + conf.getDefaultWorkflows(), + s_conf.isPubliclyViewable(), + s_conf.getItemResolverClass(), + s_conf.getTemplateResolverClass(), + m_content_type_list, + s_conf.getUseSectionCategories(), + s_conf.getCategoryFileList()); + } } @@ -381,13 +328,13 @@ public class Loader extends PackageLoader { * Parses XML file definition of (internal) base content types and loads * them into database. It fulfills a task similiar to the Loader of external * content type packages. - * + * * The XML config looks like the example below, the "parentType" and "name" - * attributes are optional, and only required for creating - * User Defined ContentTypes. Label corresponds to ContentType's label and - * can be multiple words, and "name" to DynamicObject's name property, - * and must be a single word. The objectType attribute is ignored for - * UDCTs, as it gets dynamically generated. + * attributes are optional, and only required for creating User Defined + * ContentTypes. Label corresponds to ContentType's label and can be + * multiple words, and "name" to DynamicObject's name property, and must be + * a single word. The objectType attribute is ignored for UDCTs, as it gets + * dynamically generated. * * UDCT Copyright *
@@ -404,7 +351,7 @@ public class Loader extends PackageLoader {
      *      </ccm:authoring-kit>
      *   </ccm:content-type>
      * </ccm:content-types>
-     *
+ * * * @see XMLContentTypeHandler */ diff --git a/ccm-cms/src/com/arsdigita/cms/LoaderConfig.java b/ccm-cms/src/com/arsdigita/cms/LoaderConfig.java index 484fe37d3..8eab3f490 100644 --- a/ccm-cms/src/com/arsdigita/cms/LoaderConfig.java +++ b/ccm-cms/src/com/arsdigita/cms/LoaderConfig.java @@ -15,8 +15,6 @@ * 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.runtime.AbstractConfig; @@ -24,11 +22,8 @@ import com.arsdigita.util.parameter.BooleanParameter; import com.arsdigita.util.parameter.Parameter; import com.arsdigita.util.parameter.StringArrayParameter; import com.arsdigita.util.parameter.StringParameter; - import java.util.Arrays; import java.util.List; -import java.util.ArrayList; - import org.apache.log4j.Logger; // IMPLEMENTATION NOTE @@ -36,45 +31,47 @@ import org.apache.log4j.Logger; // initialization process and not yet completed. Functionality is // basically OK so far, but code urgently needs cleaning up and a // check for useful bits. - - /** * Container for various configuration parameters for ccm-cms package loader. - * + * * The parameters are basically immutable for users and administrators and only * accessible to developers and require recompilation. Specifying any of these * parameters during installation takes no effect at all! Parameters which have * to be modifiable must be included in Loader class itself! * * @author pb - * @version $Id: LoaderConfig.java $ + * @author Sören Bernstein (quasi@barkhof.uni-bremen.de) + * @version $Id: LoaderConfig.java $ */ public final class LoaderConfig extends AbstractConfig { - /** Local logger instance fpr debug support */ + /** + * Local logger instance fpr debug support + */ private static final Logger s_log = Logger.getLogger(LoaderConfig.class); - - /** Private Object to hold one's own instance to return to users. */ + /** + * Private Object to hold one's own instance to return to users. + */ private static LoaderConfig s_conf; /** * Returns the singleton configuration record for Loader configuration. * - * @return The ContentSectionConfig record; it cannot be null + * @return The + * ContentSectionConfig record; it cannot be null */ public static synchronized LoaderConfig getInstance() { if (s_conf == null) { s_conf = new LoaderConfig(); - /* Parameters are not stored in registry nor modified by installation - * specification. It is not possible to process a config object at - * Load time! - * s_conf.load(); - */ + /* + * Parameters are not stored in registry nor modified by + * installation specification. It is not possible to process a + * config object at Load time! s_conf.load(); + */ } return s_conf; } - // /** // * The name of the workspace package instance, i.e. URL of the workspace, // * where authors, editors and publishers are working and from which they @@ -91,7 +88,6 @@ public final class LoaderConfig extends AbstractConfig { // "com.arsdigita.cms.loader.workspace_url", // Parameter.REQUIRED, // "content-center"); - // /** // * XML Mapping of the content center tabs to URLs, see // * {@link ContentCenterDispatcher} @@ -105,7 +101,6 @@ public final class LoaderConfig extends AbstractConfig { // "com.arsdigita.cms.loader.content_center_map", // Parameter.REQUIRED, // "/WEB-INF/resources/content-center-map.xml"); - // Update master object if upgrading from old versioning // XXX: shouldn't we just gut this section (and // VersioningUpgrader)? It is an upgrade fix from 5.1 or @@ -118,7 +113,6 @@ public final class LoaderConfig extends AbstractConfig { // if (updateMaster) { // VersioningUpgrader.updateMasterObject(); // } - // XXX: ItemDispatcher is no longer used. Is the following // still a valid enterprise.init parameter? Do we need to // set ContentSectionServlet.s_cacheItems instead of the @@ -128,39 +122,33 @@ public final class LoaderConfig extends AbstractConfig { // ((Boolean)m_conf.getParameter(CACHE_ITEMS)).booleanValue(); // s_log.debug("Set cache items to " + cacheItems); // ItemDispatcher.setCacheItems(cacheItems); - - /** - * Comma separated list of XML definition files for internal content types + * Comma separated list of XML definition files for internal content types * (base types). - * + * * Each internal content type (see package com/arsdigita/cms/contenttypes) - * requires an entry in this list in order to get CMS Loader to load it - * into permanent storage (equivalent to the Loader of each external - * content type package). - * + * requires an entry in this list in order to get CMS Loader to load it into + * permanent storage (equivalent to the Loader of each external content type + * package). + * * Each definition file name has to be fully qualified relative to - * application (context) root. - * Example: - * contentTypeDefinitions = { "/WEB-INF/content-types/Template.xml" }; - * + * application (context) root. Example: contentTypeDefinitions = { + * "/WEB-INF/content-types/Template.xml" }; + * * This parameter should be altered only by developers! */ private final Parameter m_ctDefFiles = new StringArrayParameter( - "com.arsdigita.cms.loader.internal_cts", - Parameter.REQUIRED, - // Generic*.xml added by Quasi in enterprise.init for - // new generic Basetypes in addition to article - new String[] {"/WEB-INF/content-types/GenericAddress.xml", - "/WEB-INF/content-types/GenericArticle.xml", - "/WEB-INF/content-types/GenericContact.xml", - "/WEB-INF/content-types/GenericOrganizationalUnit.xml", - "/WEB-INF/content-types/GenericPerson.xml", - "/WEB-INF/content-types/Template.xml"} - ); - - + "com.arsdigita.cms.loader.internal_cts", + Parameter.REQUIRED, + // Generic*.xml added by Quasi in enterprise.init for + // new generic Basetypes in addition to article + new String[]{"/WEB-INF/content-types/GenericAddress.xml", + "/WEB-INF/content-types/GenericArticle.xml", + "/WEB-INF/content-types/GenericContact.xml", + "/WEB-INF/content-types/GenericOrganizationalUnit.xml", + "/WEB-INF/content-types/GenericPerson.xml", + "/WEB-INF/content-types/Template.xml"}); // /////////////////////////////////////////////////////////////////////// // // Parameters for creating a default content section at installation time. @@ -168,50 +156,38 @@ public final class LoaderConfig extends AbstractConfig { // We list all information here, the code needs to create a section. // // /////////////////////////////////////////////////////////////////////// - - // Section Name, configured by Loader parameter - // Root Folder, set autonomously by ContentSection.create() method - // Template Folder, set autonomously by ContentSection.create() method - /** - * Staff Group - * Contains roles and associated privileges. In loading step a complete - * default configuration is persisted in database, immutable at this point. - * See contentsection.ContentSectionSetup.registerRoles() - * In enterprise.init: name roles, List of roles to create. - * + * Staff Group Contains roles and associated privileges. In loading step a + * complete default configuration is persisted in database, immutable at + * this point. See contentsection.ContentSectionSetup.registerRoles() In + * enterprise.init: name roles, List of roles to create. + * * Not implemented yet! We need a new parameter type "list" which must have * multidimensional capabilities. */ /* - private final Parameter - m_staffGroup = new StringParameter( - "com.arsdigita.cms.loader.section_staff_group", - Parameter.REQUIRED, - null); + * private final Parameter m_staffGroup = new StringParameter( + * "com.arsdigita.cms.loader.section_staff_group", Parameter.REQUIRED, + * null); */ - private List m_staffGroup; - - + private List m_defaultRoles; // Viewer group, set autonomously by ContentSection.create() method. We can // here specify, whether the first ( probalby only) content section should // have a public viewer, i.e. without registration and login. /** - * Whether to make content viewable to 'The Public', ie non-registered users. + * Whether to make content viewable to 'The Public', ie non-registered + * users. * * Parameter name in the old initializer code: PUBLIC. Default true. */ - private final BooleanParameter - m_isPublic = new BooleanParameter( - "com.arsdigita.cms.loader.section_is_public", - Parameter.REQUIRED, - true); - + private final BooleanParameter m_isPublic = new BooleanParameter( + "com.arsdigita.cms.loader.section_is_public", + Parameter.REQUIRED, + true); // Page Resolver Class, set autonomously by ContentSection.create() method. - // Item Resolver Class, configurable. /** * Name of the item resolver class to use for the section (defaults to @@ -220,192 +196,174 @@ public final class LoaderConfig extends AbstractConfig { * Default value (site-wide) is handled via the parameter *
com.arsdigita.cms.default_item_resolver_class
. * Section-specific override can be added here. Only do so if you are - * changing from the default for a specific content section. The class - * must implement
com.arsdigita.cms.dispatcher.ItemResolver
. + * changing from the default for a specific content section. The class must + * implement + *
com.arsdigita.cms.dispatcher.ItemResolver
. * * Parameter name ITEM_RESOLVER_CLASS in the old initializer system. - * Description: The ItemResolver class to use for the section - * (defaults to MultilingualItemResolver) + * Description: The ItemResolver class to use for the section (defaults to + * MultilingualItemResolver) */ - private final Parameter - m_itemResolverClass = new StringParameter( - "com.arsdigita.cms.loader.item_resolver_class", - Parameter.OPTIONAL, null ); - // , "com.arsdigita.cms.dispatcher.MultilingualItemResolver" - - + private final Parameter m_itemResolverClass = new StringParameter( + "com.arsdigita.cms.loader.item_resolver_class", + Parameter.OPTIONAL, null); + // , "com.arsdigita.cms.dispatcher.MultilingualItemResolver" // Template Resolver Class, configurable. /** - * Name of the template resolver class to use for the section - * (defaults to
com.arsdigita.cms.dispatcher.DefaultTemplateResolver
) + * Name of the template resolver class to use for the section (defaults to + *
com.arsdigita.cms.dispatcher.DefaultTemplateResolver
) * * Default value (site-wide) is handled via the parameter *
com.arsdigita.cms.default_template_resolver_class
. * Section-specific override can be added here. Only do so if you are - * changing from the default for a specific content section. The class - * must implement
com.arsdigita.cms.dispatcher.TemplateResolver
. + * changing from the default for a specific content section. The class must + * implement + *
com.arsdigita.cms.dispatcher.TemplateResolver
. * * Parameter name TEMPLATE_RESOLVER_CLASS in the old initializer system. */ - private final Parameter - m_templateResolverClass = new StringParameter( - "com.arsdigita.cms.loader.template_resolver_class", - Parameter.OPTIONAL, - null ); - // "com.arsdigita.cms.dispatcher.DefaultTemplateResolver" ); - - + private final Parameter m_templateResolverClass = new StringParameter( + "com.arsdigita.cms.loader.template_resolver_class", + Parameter.OPTIONAL, + null); + // "com.arsdigita.cms.dispatcher.DefaultTemplateResolver" ); // XML Generator Class, set autonomously by ContentSection.create() method. - - /** * Determins weather to use section specific category tree(s). Defaults to - * false, so standard navigation is used. - * If set to true loader loads the categories from file(s) specified in the - * next parameter ( m_categoryFileList ) + * false, so standard navigation is used. If set to true loader loads the + * categories from file(s) specified in the next parameter ( + * m_categoryFileList ) */ - private final Parameter - m_useSectionCategories = new BooleanParameter - ("com.arsdigita.cms.loader.use_section_categories", - Parameter.REQUIRED, new Boolean(false)); - + private final Parameter m_useSectionCategories = new BooleanParameter("com.arsdigita.cms.loader.use_section_categories", + Parameter.REQUIRED, new Boolean(false)); /** * XML file containing the category tree to load for this content section. - * Usually not loaded {@see m_useSectionCategories). The files listed as - * default values are demo material and must be replaced in a production - * environment. + * Usually not loaded { + * + * @see m_useSectionCategories). The files listed as default values are demo + * material and must be replaced in a production environment. */ - private final Parameter - m_categoryFileList = new StringArrayParameter( - "com.arsdigita.cms.loader.section_categories_toload", - Parameter.REQUIRED, - new String[] {"/WEB-INF/resources/article-categories.xml", - "/WEB-INF/resources/navigation-categories.xml"} ); - + private final Parameter m_categoryFileList = new StringArrayParameter( + "com.arsdigita.cms.loader.section_categories_toload", + Parameter.REQUIRED, + new String[]{"/WEB-INF/resources/article-categories.xml", + "/WEB-INF/resources/navigation-categories.xml"}); // private final Parameter // m_widgetTypes = new StringArrayParameter( // "com.arsdigita.cms.loader.widget_types", // Parameter.REQUIRED, // new String[] {"/WEB-INF/resources/article-categories.xml", // "/WEB-INF/resources/navigation-categories.xml"} ); - - /** List of widgets used in applications forms. Each widget is described by - application indicator, widget name (singular & plural), model class name - and model ui class name. These are really not user or administrator - configurabel and therefore not implemented as ccm parameter. */ + /** + * List of widgets used in applications forms. Each widget is described by + * application indicator, widget name (singular & plural), model class name + * and model ui class name. These are really not user or administrator + * configurabel and therefore not implemented as ccm parameter. + */ private static List widgetTypes = Arrays.asList( - Arrays.asList("forms-cms", "Checkbox group", "Checkbox groups", - "com.arsdigita.formbuilder.PersistentCheckboxGroup", - "com.arsdigita.formbuilder.ui.editors.CheckboxGroupEditor"), - Arrays.asList("forms-cms", "Date field", "Date fields", - "com.arsdigita.formbuilder.PersistentDate", - "com.arsdigita.formbuilder.ui.editors.DateForm"), - Arrays.asList("forms-cms", "Hidden field", "Hidden fields", - "com.arsdigita.formbuilder.PersistentHidden", - "com.arsdigita.formbuilder.ui.editors.HiddenForm"), - Arrays.asList( "forms-cms", "Hidden ID Generator field", - "Hidden ID Generator fields", - "com.arsdigita.formbuilder.HiddenIDGenerator", - "com.arsdigita.formbuilder.ui.editors.HiddenIDGeneratorForm"), - Arrays.asList("forms-cms", "Multiple select box", - "Multiple select boxes", - "com.arsdigita.formbuilder.PersistentMultipleSelect", - "com.arsdigita.formbuilder.ui.editors.MultipleSelectEditor"), - Arrays.asList("forms-cms", "Password field", "Password fields", - "com.arsdigita.formbuilder.PersistentPassword", - "com.arsdigita.formbuilder.ui.editors.PasswordForm"), - Arrays.asList("forms-cms", "Radio group", "Radio groups", - "com.arsdigita.formbuilder.PersistentRadioGroup", - "com.arsdigita.formbuilder.ui.editors.RadioGroupEditor"), - Arrays.asList("forms-cms", "Single select box", - "Single select boxes", - "com.arsdigita.formbuilder.PersistentSingleSelect", - "com.arsdigita.formbuilder.ui.editors.SingleSelectEditor"), - Arrays.asList("forms-cms", "Submit button", "Submit buttons", - "com.arsdigita.formbuilder.PersistentSubmit", - "com.arsdigita.formbuilder.ui.editors.SubmitForm"), - Arrays.asList("forms-cms", "Text area", "Text areas", - "com.arsdigita.formbuilder.PersistentTextArea", - "com.arsdigita.formbuilder.ui.editors.TextAreaForm"), - Arrays.asList("forms-cms", "Text field", "Text fields", - "com.arsdigita.formbuilder.PersistentTextField", - "com.arsdigita.formbuilder.ui.editors.TextFieldForm"), - Arrays.asList("forms-cms", "Data Driven Select Box", - "Data Driven Select Boxes", - "com.arsdigita.formbuilder.DataDrivenSelect", - "com.arsdigita.formbuilder.ui.editors.DataDrivenSelectForm"), - Arrays.asList("forms-cms", "Text Description","Text Descriptions", - "com.arsdigita.formbuilder.PersistentText", - "com.arsdigita.formbuilder.ui.editors.TextForm"), - Arrays.asList("forms-cms", "Text Heading", "Text Headings", - "com.arsdigita.formbuilder.PersistentHeading", - "com.arsdigita.formbuilder.ui.editors.HeadingForm"), - Arrays.asList("forms-cms", "Section Break", "Section Break", - "com.arsdigita.formbuilder.PersistentHorizontalRule", - "com.arsdigita.formbuilder.ui.editors.HorizontalRuleForm"), - Arrays.asList("forms-cms", "User Email Field","User Email Fields", - "com.arsdigita.formbuilder.PersistentEmailField", - "com.arsdigita.formbuilder.ui.editors.EmailFieldForm") - ); - - /** List of process listeners used in applications forms. Each listener is - described by application indicator, process name (singular & plural), - action class name and action ui class name. These are really not user - or administrator configurabel and therefore not implemented as ccm - parameter. */ - private static List processListenerTypes = Arrays.asList( - Arrays.asList("forms-cms", "Confirmation email", - "Confirmation emails", - "com.arsdigita.formbuilder.actions.ConfirmEmailListener", - "com.arsdigita.formbuilder.ui.editors.ConfirmEmailForm"), - Arrays.asList("forms-cms", "URL redirect", "URL redirects", - "com.arsdigita.formbuilder.actions.ConfirmRedirectListener", - "com.arsdigita.formbuilder.ui.editors.ConfirmRedirectForm"), - Arrays.asList("forms-cms", "Simple email", "Simple emails", - "com.arsdigita.formbuilder.actions.SimpleEmailListener", - "com.arsdigita.formbuilder.ui.editors.SimpleEmailForm"), - Arrays.asList("forms-cms", "Templated email", "Templated emails", - "com.arsdigita.formbuilder.actions.TemplateEmailListener", - "com.arsdigita.formbuilder.ui.editors.TemplateEmailForm"), - Arrays.asList( "forms-cms", "Remote Server POST", - "Remote Server POSTs", - "com.arsdigita.formbuilder.actions.RemoteServerPostListener", - "com.arsdigita.formbuilder.ui.editors.RemoteServerPostForm" ), - Arrays.asList( "forms-cms", "XML email", "XML emails", - "com.arsdigita.formbuilder.actions.XMLEmailListener", - "com.arsdigita.formbuilder.ui.editors.XMLEmailForm" ) - ); - - - private static List dataQueries = Arrays.asList( - Arrays.asList("forms-cms", - "com.arsdigita.formbuilder.DataQueryUsers", - "List of all registered users"), - Arrays.asList("forms-cms", - "com.arsdigita.formbuilder.DataQueryPackages", - "List of all installed packages") - ); + Arrays.asList("forms-cms", "Checkbox group", "Checkbox groups", + "com.arsdigita.formbuilder.PersistentCheckboxGroup", + "com.arsdigita.formbuilder.ui.editors.CheckboxGroupEditor"), + Arrays.asList("forms-cms", "Date field", "Date fields", + "com.arsdigita.formbuilder.PersistentDate", + "com.arsdigita.formbuilder.ui.editors.DateForm"), + Arrays.asList("forms-cms", "Hidden field", "Hidden fields", + "com.arsdigita.formbuilder.PersistentHidden", + "com.arsdigita.formbuilder.ui.editors.HiddenForm"), + Arrays.asList("forms-cms", "Hidden ID Generator field", + "Hidden ID Generator fields", + "com.arsdigita.formbuilder.HiddenIDGenerator", + "com.arsdigita.formbuilder.ui.editors.HiddenIDGeneratorForm"), + Arrays.asList("forms-cms", "Multiple select box", + "Multiple select boxes", + "com.arsdigita.formbuilder.PersistentMultipleSelect", + "com.arsdigita.formbuilder.ui.editors.MultipleSelectEditor"), + Arrays.asList("forms-cms", "Password field", "Password fields", + "com.arsdigita.formbuilder.PersistentPassword", + "com.arsdigita.formbuilder.ui.editors.PasswordForm"), + Arrays.asList("forms-cms", "Radio group", "Radio groups", + "com.arsdigita.formbuilder.PersistentRadioGroup", + "com.arsdigita.formbuilder.ui.editors.RadioGroupEditor"), + Arrays.asList("forms-cms", "Single select box", + "Single select boxes", + "com.arsdigita.formbuilder.PersistentSingleSelect", + "com.arsdigita.formbuilder.ui.editors.SingleSelectEditor"), + Arrays.asList("forms-cms", "Submit button", "Submit buttons", + "com.arsdigita.formbuilder.PersistentSubmit", + "com.arsdigita.formbuilder.ui.editors.SubmitForm"), + Arrays.asList("forms-cms", "Text area", "Text areas", + "com.arsdigita.formbuilder.PersistentTextArea", + "com.arsdigita.formbuilder.ui.editors.TextAreaForm"), + Arrays.asList("forms-cms", "Text field", "Text fields", + "com.arsdigita.formbuilder.PersistentTextField", + "com.arsdigita.formbuilder.ui.editors.TextFieldForm"), + Arrays.asList("forms-cms", "Data Driven Select Box", + "Data Driven Select Boxes", + "com.arsdigita.formbuilder.DataDrivenSelect", + "com.arsdigita.formbuilder.ui.editors.DataDrivenSelectForm"), + Arrays.asList("forms-cms", "Text Description", "Text Descriptions", + "com.arsdigita.formbuilder.PersistentText", + "com.arsdigita.formbuilder.ui.editors.TextForm"), + Arrays.asList("forms-cms", "Text Heading", "Text Headings", + "com.arsdigita.formbuilder.PersistentHeading", + "com.arsdigita.formbuilder.ui.editors.HeadingForm"), + Arrays.asList("forms-cms", "Section Break", "Section Break", + "com.arsdigita.formbuilder.PersistentHorizontalRule", + "com.arsdigita.formbuilder.ui.editors.HorizontalRuleForm"), + Arrays.asList("forms-cms", "User Email Field", "User Email Fields", + "com.arsdigita.formbuilder.PersistentEmailField", + "com.arsdigita.formbuilder.ui.editors.EmailFieldForm")); + /** + * List of process listeners used in applications forms. Each listener is + * described by application indicator, process name (singular & plural), + * action class name and action ui class name. These are really not user or + * administrator configurabel and therefore not implemented as ccm + * parameter. + */ + private static List processListenerTypes = Arrays.asList( + Arrays.asList("forms-cms", "Confirmation email", + "Confirmation emails", + "com.arsdigita.formbuilder.actions.ConfirmEmailListener", + "com.arsdigita.formbuilder.ui.editors.ConfirmEmailForm"), + Arrays.asList("forms-cms", "URL redirect", "URL redirects", + "com.arsdigita.formbuilder.actions.ConfirmRedirectListener", + "com.arsdigita.formbuilder.ui.editors.ConfirmRedirectForm"), + Arrays.asList("forms-cms", "Simple email", "Simple emails", + "com.arsdigita.formbuilder.actions.SimpleEmailListener", + "com.arsdigita.formbuilder.ui.editors.SimpleEmailForm"), + Arrays.asList("forms-cms", "Templated email", "Templated emails", + "com.arsdigita.formbuilder.actions.TemplateEmailListener", + "com.arsdigita.formbuilder.ui.editors.TemplateEmailForm"), + Arrays.asList("forms-cms", "Remote Server POST", + "Remote Server POSTs", + "com.arsdigita.formbuilder.actions.RemoteServerPostListener", + "com.arsdigita.formbuilder.ui.editors.RemoteServerPostForm"), + Arrays.asList("forms-cms", "XML email", "XML emails", + "com.arsdigita.formbuilder.actions.XMLEmailListener", + "com.arsdigita.formbuilder.ui.editors.XMLEmailForm")); + private static List dataQueries = Arrays.asList( + Arrays.asList("forms-cms", + "com.arsdigita.formbuilder.DataQueryUsers", + "List of all registered users"), + Arrays.asList("forms-cms", + "com.arsdigita.formbuilder.DataQueryPackages", + "List of all installed packages")); // Currently not a Loader task. There is no way to persist tasks preferences // on a per section base. - /** - * When to generate email alerts: by default, generate email alerts - * on enable, finish, and rollback (happens on rejection) changes. - * There are four action types for each task type: enable, - * disable, finish, and rollback. Note that the values below are - * based on the task labels, and as such are not globalized. + /** + * When to generate email alerts: by default, generate email alerts on + * enable, finish, and rollback (happens on rejection) changes. There are + * four action types for each task type: enable, disable, finish, and + * rollback. Note that the values below are based on the task labels, and as + * such are not globalized. */ /* - private final Parameter - m_taskAlerts = new StringArrayParameter( - "com.arsdigita.cms.task_alerts", - Parameter.REQUIRED, new String[] { - "Authoring:enable:finish:rollback", - "Approval:enable:finish:rollback", - "Deploy:enable:finish:rollback" } ); + * private final Parameter m_taskAlerts = new StringArrayParameter( + * "com.arsdigita.cms.task_alerts", Parameter.REQUIRED, new String[] { + * "Authoring:enable:finish:rollback", "Approval:enable:finish:rollback", + * "Deploy:enable:finish:rollback" } ); */ - - // /////////////////////////////////////////////////////////////////////// // // Parameters controlling Overdue Task alerts: @@ -414,8 +372,6 @@ public final class LoaderConfig extends AbstractConfig { // per section base of to store them in the database at all. So it is // currently not a loader task and commented out here. // /////////////////////////////////////////////////////////////////////// - - // /** // * sendOverdueAlerts: Should we send alerts about overdue tasks at all? // */ @@ -424,7 +380,6 @@ public final class LoaderConfig extends AbstractConfig { // "com.arsdigita.cms.loader.send_overdue_alerts", // Parameter.REQUIRED, // new Boolean(false) ); - // /** // * taskDuration: The time between when a task is enabled (it is made // * available for completion) and when it is @@ -435,7 +390,6 @@ public final class LoaderConfig extends AbstractConfig { // "com.arsdigita.cms.loader.task_duration", // Parameter.REQUIRED, // new Integer(96) ); - // /** // * alertInterval: The time to wait between sending successive alerts on // * the same overdue task (in HOURS) @@ -445,7 +399,6 @@ public final class LoaderConfig extends AbstractConfig { // "com.arsdigita.cms.loader.overdue_alert_interval", // Parameter.REQUIRED, // new Integer(24) ); - // /** // * maxAlerts: The maximum number of alerts to send about any one // * overdue task @@ -455,35 +408,34 @@ public final class LoaderConfig extends AbstractConfig { // "com.arsdigita.cms.loader.mas_alerts", // Parameter.REQUIRED, // new Integer(5) ); - /** - * Standard Constructor. + * Standard Constructor. */ public LoaderConfig() { // register(m_workspaceURL); // register(m_contentCenterMap); - register(m_ctDefFiles); + register(m_ctDefFiles); - // Parameters for creating a content section - register(m_isPublic); - register(m_itemResolverClass); - register(m_templateResolverClass); + // Parameters for creating a content section + register(m_isPublic); + register(m_itemResolverClass); + register(m_templateResolverClass); - register(m_useSectionCategories); - register(m_categoryFileList); + register(m_useSectionCategories); + register(m_categoryFileList); - // (Currently not a loader task) + // (Currently not a loader task) // register(m_taskAlerts); - // Parameters controlling Overdue Task alerts: - // (Currently not a loader task) + // Parameters controlling Overdue Task alerts: + // (Currently not a loader task) // register(m_sendOverdueAlerts); // register(m_taskDuration); // register(m_overdueAlertInterval); // register(m_maxAlerts); - // Does not work at load time! - // loadInfo(); + // Does not work at load time! + // loadInfo(); } @@ -492,7 +444,6 @@ public final class LoaderConfig extends AbstractConfig { // Getter Methods // // ////////////////////////// - // Not used as long as we use old style application (seee above) // /** // * Fetch name (URL) of the workspace package instance, e.g. content-center @@ -501,7 +452,6 @@ public final class LoaderConfig extends AbstractConfig { // public String getWorkspaceURL() { // return (String) get(m_workspaceURL); // } - // Moved to CMSConfig as long as it is not a Loader task. (see above) // /** // * Fetch the file name contaning XML Mapping of the content center tabs @@ -511,101 +461,11 @@ public final class LoaderConfig extends AbstractConfig { // public String getContentCenterMap() { // return (String) get(m_contentCenterMap); // } - public List getCTDefFiles() { String[] ctDefFiles = (String[]) get(m_ctDefFiles); return Arrays.asList(ctDefFiles); } - - - - /** - * Retrieve the STAFF GROUP, i.e. a set of roles (author, editor, publisher, - * manager) and associated privileges for the content section to be created - * (m_contentSectionName). - * - * In loading step a complete default configuration is persisted in database, - * immutable at this point. - * See contentsection.ContentSectionSetup.registerRoles() - * In enterprise.init: name roles, List of roles to create. - * - * Set consists of a set of roles, for each role first field is the role name, - * second is the description, third is a list of privileges, and (optional) - * fourth is the workflow task to assign to. - * - * The set of roles constructed here is a complete set which reflects all - * functions of CMS and forms a necessary base for operations. When the first - * content section is created and loaded into database (during installation) - * this set is created, immutable by installer / administrator. Additional - * content section may be created using a subset. For a very special purpose - * a developer may alter the set. - * - * This method is typically used to construct the initial content section - * during installation. - * - * Not really implemented yet! We need a new parameter type "list" which - * must have multidimensional capabilities. - * - * As a temporary measure a constant list is retrieved. Until now the list - * was burried in enterprise.init and not user available for configuration. - * So it may turn into a permanent solution. - */ - public List getStuffGroup() { - - final List AUTH_PRIVS = Arrays.asList( - "new_item","read_item", "preview_item", "edit_item", - "categorize_items"); - final List EDIT_PRIVS = Arrays.asList( - "new_item","read_item", "preview_item", "edit_item", - "categorize_items", "delete_item", "approve_item" ); - final List PUBL_PRIVS = Arrays.asList( - "new_item","read_item", "preview_item", "edit_item", - "categorize_items", "delete_item", "approve_item", - "publish"); - final List MNGR_PRIVS = Arrays.asList( - "new_item","read_item", "preview_item", "edit_item", - "categorize_items", "delete_item", "approve_item", - "publish", - "staff_admin", "content_type_admin", "lifecycle_admin", - "workflow_admin", "category_admin"); - - m_staffGroup = new ArrayList(); - - m_staffGroup.add - ( new ArrayList() {{ add("Author"); - add("Creates new content"); - add(AUTH_PRIVS); - add("Authoring"); - }} - ); - m_staffGroup.add - ( new ArrayList() {{ add("Editor"); - add("Reviews and approves the author's work"); - add(EDIT_PRIVS); - add("Approval"); - }} - ); - m_staffGroup.add - ( new ArrayList() {{ add("Publisher"); - add("Deploys the content to the web site"); - add(PUBL_PRIVS); - add("Publishing"); - }} - ); - m_staffGroup.add - ( new ArrayList() {{ add("Manager"); - add("Manages the overall content section"); - add(MNGR_PRIVS); - // NB, manager doesn't have any assigned - // task for workflow - (as usual) - }} - ); - - return (List) m_staffGroup ; - - } - /** * Retrieve whether the content-section is publicly viewable (i.e. without * registration and login) @@ -628,10 +488,11 @@ public final class LoaderConfig extends AbstractConfig { return (String) get(m_templateResolverClass); } - /** * Retrieve weather to use section specific categories. If true they are - * loaded using the next parameters file list {@see getUseSectionCategories()} + * loaded using the next parameters file list { + * + * @see getUseSectionCategories()} * * Default value is false, so standard navigation is used. * @return @@ -641,9 +502,9 @@ public final class LoaderConfig extends AbstractConfig { } /** - * Retrieve the list of files containing categories to load. - * In old Initialiser: Parameter name: CATEGORIES - * Deskr. "XML file containing the category tree" + * Retrieve the list of files containing categories to load. In old + * Initialiser: Parameter name: CATEGORIES Deskr. "XML file containing the + * category tree" */ public List getCategoryFileList() { String[] catFiles = (String[]) get(m_categoryFileList); @@ -652,14 +513,13 @@ public final class LoaderConfig extends AbstractConfig { public List getWidgetTypes() { return widgetTypes; - } + } public List getProcessListenerTypes() { return processListenerTypes; - } + } public List getDataQueries() { return dataQueries; - } - + } } diff --git a/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionConfig.java b/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionConfig.java index 2df8f3ea6..844269326 100644 --- a/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionConfig.java +++ b/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionConfig.java @@ -23,14 +23,12 @@ import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.util.parameter.BooleanParameter; import com.arsdigita.util.parameter.IntegerParameter; import com.arsdigita.util.parameter.Parameter; -//import com.arsdigita.util.parameter.ParameterError; import com.arsdigita.util.parameter.StringArrayParameter; import com.arsdigita.util.parameter.StringParameter; - -import java.util.Arrays; -import java.util.List; import java.util.ArrayList; - +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import org.apache.log4j.Logger; /** @@ -39,9 +37,13 @@ import org.apache.log4j.Logger; * Configures parameter which are not persisted in the database and may be * changes during each startup of the system. * @author pb + * @author Sören Bernstein (quasi@barkhof.uni-bremen.de) */ public final class ContentSectionConfig extends AbstractConfig { + private List m_defaultRoles; + private List m_defaultWorkflows; + /** Private Logger instance for debugging purpose. */ private static final Logger s_log = Logger.getLogger(ContentSectionConfig.class); @@ -216,7 +218,6 @@ public final class ContentSectionConfig extends AbstractConfig { // "com.arsdigita.cms.loader.section_staff_group", // Parameter.REQUIRED, // null); - private List m_staffGroup; // Viewer group, set autonomously by ContentSection.create() method. We can @@ -312,7 +313,7 @@ public final class ContentSectionConfig extends AbstractConfig { private final Parameter m_useSectionCategories = new BooleanParameter ("com.arsdigita.cms.section.use_section_categories", - Parameter.REQUIRED, new Boolean(false)); + Parameter.REQUIRED, false); /** * XML file containing the category tree to load for this content section. @@ -460,7 +461,12 @@ public final class ContentSectionConfig extends AbstractConfig { * was burried in enterprise.init and not user available for configuration. * So it may turn into a permanent solution. */ - public List getStuffGroup() { + + /** + * Changed: The forth field is not used anymore + * + */ + public List getDefaultRoles() { final List AUTH_PRIVS = Arrays.asList( "new_item","read_item", "preview_item", "edit_item", @@ -478,43 +484,169 @@ public final class ContentSectionConfig extends AbstractConfig { "publish", "staff_admin", "content_type_admin", "lifecycle_admin", "workflow_admin", "category_admin"); + final List TRST_PRIVS = Arrays.asList( + "new_item","read_item", "preview_item", "edit_item", + "categorize_items", "delete_item", "approve_item", + "publish", "apply_alternate_workflows"); - m_staffGroup = new ArrayList(); + m_defaultRoles = new ArrayList(); - m_staffGroup.add + m_defaultRoles.add ( new ArrayList() {{ add("Author"); add("Creates new content"); add(AUTH_PRIVS); - add("Authoring"); }} ); - m_staffGroup.add + m_defaultRoles.add ( new ArrayList() {{ add("Editor"); add("Reviews and approves the author's work"); add(EDIT_PRIVS); - add("Approval"); }} ); - m_staffGroup.add + m_defaultRoles.add ( new ArrayList() {{ add("Publisher"); add("Deploys the content to the web site"); add(PUBL_PRIVS); - add("Publishing"); }} ); - m_staffGroup.add + m_defaultRoles.add ( new ArrayList() {{ add("Manager"); add("Manages the overall content section"); add(MNGR_PRIVS); - // NB, manager doesn't have any assigned - // task for workflow - (as usual) + }} + ); + m_defaultRoles.add + ( new ArrayList() {{ add("Trusted User"); + add("A trusted user is allowed to create and publish items without review"); + add(TRST_PRIVS); }} ); - return (List) m_staffGroup ; + return (List) m_defaultRoles ; } + public List getDefaultWorkflows() { + + if(m_defaultWorkflows == null) { + + m_defaultWorkflows = new ArrayList(); + + // Prodcution Workflow + m_defaultWorkflows.add( + new HashMap() {{ put("name", "Redigierte Veröffentlichung"); + put("description", "A process that involves creating and approving content."); + put("isDefault", "true"); + put("tasks", + new ArrayList() {{ add( + new HashMap() {{ put("name", "Verfassen"); + put("description", "Create content."); + put("type", "Author"); + put("role", + new ArrayList() {{ add("Author"); + }} + ); + }} + ); + add( + new HashMap() {{ put("name", "Überprüfen"); + put("description", "Approve content."); + put("type", "Edit"); + put("role", + new ArrayList() {{ add("Editor"); + }} + ); + put("dependOn", + new ArrayList() {{ add("Verfassen"); + }} + ); + }} + ); + add( + new HashMap() {{ put("name", "Veröffentlichen"); + put("description", "Deploy content."); + put("type", "Deploy"); + put("role", + new ArrayList() {{ add("Publisher"); + }} + ); + put("dependOn", + new ArrayList() {{ add("Überprüfen"); + }} + ); + }} + ); + }} + ); + }} + ); + + // TrustedUser Workflow + m_defaultWorkflows.add( + new HashMap() {{ put("name", "Direkte Veröffentlichung"); + put("description", "Create and publish content without review"); + put("isDefault", "false"); + put("tasks", + new ArrayList() {{ add( + new HashMap() {{ put("name", "Verfassen"); + put("description", "Create content."); + put("type", "Author"); + put("role", + new ArrayList() {{ add("Author"); + add("Trusted User"); + }} + ); + }} + ); + add( + new HashMap() {{ put("name", "Veröffentlichen"); + put("description", "Deploy content."); + put("type", "Deploy"); + put("role", + new ArrayList() {{ add("Publisher"); + add("Trusted User"); + }} + ); + put("dependOn", + new ArrayList() {{ add("Verfassen"); + }} + ); + }} + ); + }} + ); + }} + ); +/* + // Addiditonal Workflows + m_defaultWorkflows.add( + new HashMap() {{ put("name", ""); + put("description", ""); + put("tasks", + new ArrayList() {{ add( + new HashMap() {{ put("name", ""); + put("description", ""); + put("type", ""); + put("role", + new ArrayList() {{ add(""); + }} + ); + put("dependOn", + new ArrayList() {{ add(""); + }} + ); + }} + ); + }} + ); + }} + ); +*/ + } + + return m_defaultWorkflows; + } + /** * Retrieve whether the content-section is publicly viewable (i.e. without * registration and login) diff --git a/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionSetup.java b/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionSetup.java index df4f18d1a..3abece69e 100644 --- a/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionSetup.java +++ b/ccm-cms/src/com/arsdigita/cms/contentsection/ContentSectionSetup.java @@ -43,7 +43,6 @@ import com.arsdigita.util.Assert; import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.workflow.simple.WorkflowTemplate; import com.arsdigita.xml.XML; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -54,7 +53,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Stack; - import org.apache.log4j.Logger; import org.xml.sax.Attributes; import org.xml.sax.helpers.DefaultHandler; @@ -65,20 +63,21 @@ import org.xml.sax.helpers.DefaultHandler; * into the database. * * @author Peter Boy (pboy@barkhof.uni-bremen.de) + * @author Sören Bernstein (quasi@barkhof.uni-bremen.de) * @author Jon Orris (jorris@redhat.com) - * @version $Id: $ + * @version $Id: $ */ public final class ContentSectionSetup { private static Logger s_log = Logger.getLogger(ContentSectionSetup.class); - private HashMap m_tasks = new HashMap(); + private HashMap m_roles = new HashMap(); private LifecycleDefinition m_lcd; private WorkflowTemplate m_wf; final ContentSection m_section; /** - * Constructor. Using this constructor the content section has to be - * already created using ContentSection.create(name) + * Constructor. Using this constructor the content section has to be already + * created using ContentSection.create(name) * * @param section name of a content section previously created by * ContentSection.create @@ -89,21 +88,22 @@ public final class ContentSectionSetup { } /** - * Wrapper class to create and configure a content section instance - * in one step. + * Wrapper class to create and configure a content section instance in one + * step. * * Method needs a transaction to proceed successfully. - * {@link com.arsdigita.cms.contentsection.Initializer#checkForNewContentSection() } + * {@link com.arsdigita.cms.contentsection.Initializer#checkForNewContentSection() + * } */ - public static void setupContentSectionAppInstance( - String name, - List staffGroup, - Boolean isPubliclyViewable, - String itemResolverClassName, - String templateResolverClassName, - List sectionContentTypes, - Boolean useSectionCategories, - List categoryFileList) { + public static ContentSection setupContentSectionAppInstance(String name, + List defaultRoles, + List defaultWorkflows, + Boolean isPubliclyViewable, + String itemResolverClassName, + String templateResolverClassName, + List sectionContentTypes, + Boolean useSectionCategories, + List categoryFileList) { s_log.info("Creating content section on /" + name); @@ -111,10 +111,10 @@ public final class ContentSectionSetup { ContentSectionSetup setup = new ContentSectionSetup(section); // Setup the access controls - setup.registerRoles(staffGroup); + setup.registerRoles(defaultRoles); + setup.registerWorkflows(defaultWorkflows); setup.registerViewers(isPubliclyViewable); setup.registerPublicationCycles(); - setup.registerWorkflowTemplates(); setup.registerResolvers(itemResolverClassName, templateResolverClassName); // setup.registerContentTypes((List)m_conf.getParameter(TYPES)); @@ -131,17 +131,17 @@ public final class ContentSectionSetup { section.save(); - // return section; + return section; } /** - * Steps through a list of roles which are part of a staff group and + * Steps through a list of roles which are part of a staff group and * delegates processing of each role. - * + * * @param roles */ - public void registerRoles(List roles) { + public void registerRoles(List roles) { Iterator i = roles.iterator(); while (i.hasNext()) { @@ -150,21 +150,13 @@ public final class ContentSectionSetup { String name = (String) role.get(0); String desc = (String) role.get(1); List privileges = (List) role.get(2); - String task = (role.size() > 3 ? (String) role.get(3) : null); s_log.info("Creating role " + name); + Role newRole = registerRole(name, desc, privileges); + m_roles.put(name, newRole); - Role group = registerRole( - name, - desc, - privileges); - - if (task != null) { - m_tasks.put(task, group); - } } - } /** @@ -204,6 +196,15 @@ public final class ContentSectionSetup { } } + // Add site-wide administrator group by default to all roles + PartyCollection partyColl = Party.retrieveAllParties(); + // FIXME: String for Site-wide Admininistrators is hardcoded because + // this group in inserted via sql-command during setup + partyColl.filter("Site-wide Administrators"); + if(partyColl.next()) { + role.add(partyColl.getParty()); + } + return role; } @@ -259,9 +260,9 @@ public final class ContentSectionSetup { /** * Checks for specific item resolver and template resolver classes probably * specified in parameters, otherwise uses system wide default parameters - * specified in CMS global configuration file. Delegates persistence task - * to ContentSection. - * + * specified in CMS global configuration file. Delegates persistence task to + * ContentSection. + * * @param itemResolverClassName * @param templateResolverClassName */ @@ -269,24 +270,22 @@ public final class ContentSectionSetup { String templateResolverClassName) { if (itemResolverClassName != null - && itemResolverClassName.length() > 0) { + && itemResolverClassName.length() > 0) { m_section.setItemResolverClass(itemResolverClassName); s_log.info("Registering " + itemResolverClassName + " as the item resolver class"); } else { - m_section.setItemResolverClass(ContentSection.getConfig() - .getDefaultItemResolverClass().getName()); + m_section.setItemResolverClass(ContentSection.getConfig().getDefaultItemResolverClass().getName()); s_log.info("Registering " + itemResolverClassName + " as the item resolver class"); } if (templateResolverClassName != null - && templateResolverClassName.length() > 0) { + && templateResolverClassName.length() > 0) { m_section.setTemplateResolverClass(templateResolverClassName); s_log.info("Registering " + templateResolverClassName + " as the template resolver class"); } else { - m_section.setTemplateResolverClass(ContentSection.getConfig() - .getDefaultTemplateResolverClass().getName()); + m_section.setTemplateResolverClass(ContentSection.getConfig().getDefaultTemplateResolverClass().getName()); s_log.info("Registering " + templateResolverClassName + " as the template resolver class"); } @@ -295,9 +294,9 @@ public final class ContentSectionSetup { } /** - * Create a (default) publication cycle and store it in the datavbase + * Create a (default) publication cycle and store it in the datavbase * (delegated to package com.arsdigita.cms.lifecycle) - * + * * @throws InitializationException */ public void registerPublicationCycles() @@ -323,86 +322,110 @@ public final class ContentSectionSetup { m_section.save(); } - /** + private void registerWorkflows(List workflows) { + + Iterator workflowsIter = workflows.iterator(); + + while (workflowsIter.hasNext()) { + HashMap newTasks = new HashMap(); + HashMap workflow = (HashMap) workflowsIter.next(); + + // Create a new WorkflowTemplate + WorkflowTemplate wf = new WorkflowTemplate(); + wf.setLabel((String) workflow.get("name")); + wf.setDescription((String) workflow.get("description")); + wf.save(); + + // Add tasks to workflow + Iterator tasksIter = ((List) workflow.get("tasks")).iterator(); + while (tasksIter.hasNext()) { + HashMap task = (HashMap) tasksIter.next(); + + // Setup new task + CMSTask newTask = new CMSTask(); + newTask.setLabel((String) task.get("name")); + newTask.setDescription((String) task.get("description")); + newTask.setTaskType(CMSTaskType.retrieveByName((String) task.get("type"))); + + // Add roles to task + if (task.containsKey("role")) { + Iterator roleIter = ((List) task.get("role")).iterator(); + while (roleIter.hasNext()) { + Role role = m_roles.get(roleIter.next()); + if (role != null) { + newTask.assignGroup(role.getGroup()); + } + } + } + + // Save task + newTask.save(); + + // Save task to HashMap for fast access in the next loop + newTasks.put((String) task.get("name"), newTask); + + } + + // Setup task dependencies (easier to do it after creating all task) + tasksIter = ((List) workflow.get("tasks")).iterator(); + while (tasksIter.hasNext()) { + HashMap task = (HashMap) tasksIter.next(); + CMSTask newTask = newTasks.get((String) task.get("name")); + + if (task.containsKey("dependOn")) { + Iterator dependOnIter = ((List) task.get("dependOn")).iterator(); + while (dependOnIter.hasNext()) { + CMSTask dependOn = newTasks.get(dependOnIter.next()); + if (dependOn != null) { + newTask.addDependency(dependOn); + } + } + } + newTask.save(); + } + + // Add tasks to the workflow + for (CMSTask newTask : newTasks.values()) { + wf.addTask(newTask); + } + + // Save workflow + wf.save(); + + // Add Workflow to current section + m_section.addWorkflowTemplate(wf); + m_section.save(); + + // If this workflow should be the default or is the first one + // save it for easy access in registerContentType + if(m_wf == null || (workflow.containsKey("isDefault") && workflow.get("isDefault").equals("true"))) { + m_wf = wf; + } + } + } + + /** * Defines a (default for section) workflow which gets persisted in tne * database. + * + * This one is probably deprecated. * * @throws InitializationException */ - public void registerWorkflowTemplates() - throws ConfigError { + public void registerWorkflowTemplates() throws ConfigError { - // The 3-step production workflow. - WorkflowTemplate wf = new WorkflowTemplate(); - wf.setLabel((String) GlobalizationUtil.globalize( - "cms.installer.production_workflow").localize()); - wf.setDescription("A process that involves creating and approving content."); - wf.save(); + ContentSectionConfig config = new ContentSectionConfig(); + config.load(); + registerWorkflows(config.getDefaultWorkflows()); - CMSTask authoring = new CMSTask(); - authoring.setLabel((String) GlobalizationUtil.globalize( - "cms.installer.authoring").localize()); - authoring.setDescription("Create content."); - authoring.save(); - - - Role author = (Role) m_tasks.get("Authoring"); - if (author != null) { - authoring.assignGroup(author.getGroup()); - } - - authoring.setTaskType(CMSTaskType.retrieve(CMSTaskType.AUTHOR)); - authoring.save(); - - CMSTask approval = new CMSTask(); - approval.setLabel((String) GlobalizationUtil.globalize( - "cms.installer.approval").localize()); - approval.setDescription("Approve content."); - approval.save(); - approval.addDependency(authoring); - approval.save(); - - Role approver = (Role) m_tasks.get("Approval"); - if (approver != null) { - approval.assignGroup(approver.getGroup()); - } - - approval.setTaskType(CMSTaskType.retrieve(CMSTaskType.EDIT)); - approval.save(); - - - CMSTask deploy = new CMSTask(); - deploy.setLabel((String) GlobalizationUtil.globalize( - "cms.installer.deploy").localize()); - deploy.setDescription("Deploy content."); - deploy.save(); - deploy.addDependency(approval); - deploy.save(); - - Role publisher = (Role) m_tasks.get("Publishing"); - if (publisher != null) { - deploy.assignGroup(publisher.getGroup()); - } - - deploy.setTaskType(CMSTaskType.retrieve(CMSTaskType.DEPLOY)); - deploy.save(); - - wf.addTask(authoring); - wf.addTask(approval); - wf.addTask(deploy); - wf.save(); - - m_section.addWorkflowTemplate(wf); - m_section.save(); - - m_wf = wf; } - /** + /** * Steps through a list of content types to be available for this content * section and delegates processing of each type. - * - * @param types list of content types to be available for this content section + * + * @param types list of content types to be available for this content + * section */ public void registerContentTypes(List types) { @@ -424,8 +447,9 @@ public final class ContentSectionSetup { } /** - * Process one content type and registers it with the current content section. - * + * Process one content type and registers it with the current content + * section. + * * @param name * @return */ @@ -456,9 +480,9 @@ public final class ContentSectionSetup { } /** - * + * * @param type - * @param filename + * @param filename */ void registerTemplate(ContentType type, String filename) { // Use the base of the file name (ie without path & extension) @@ -487,7 +511,7 @@ public final class ContentSectionSetup { if (stream == null) { throw new IllegalStateException((String) GlobalizationUtil.globalize( - "cms.installer.cannot_find_file").localize() + filename); + "cms.installer.cannot_find_file").localize() + filename); } final BufferedReader input = new BufferedReader(new InputStreamReader(stream)); @@ -514,8 +538,7 @@ public final class ContentSectionSetup { temp.save(); - TemplateManagerFactory.getInstance() - .addTemplate(m_section, type, temp, "public"); + TemplateManagerFactory.getInstance().addTemplate(m_section, type, temp, "public"); temp.publish(m_lcd, new Date()); } @@ -545,6 +568,8 @@ public final class ContentSectionSetup { alert.setDescription( "Receive alerts regarding expiration of pubished content"); alert.save(); + + } // // Currently there is no way to persists alert preferemces, therefore @@ -602,8 +627,8 @@ public final class ContentSectionSetup { // } // ///////////////////// Private Class Section //////////////////////////// /** - * SAX Handler for category lists. Creates the categories as they are - * defined, with structure, in the xml document. + * SAX Handler for category lists. Creates the categories as they are + * defined, with structure, in the xml document. */ private class CategoryHandler extends DefaultHandler { @@ -679,6 +704,4 @@ public final class ContentSectionSetup { } } } // END private class CategoryHandler - - } diff --git a/ccm-cms/src/com/arsdigita/cms/contentsection/Initializer.java b/ccm-cms/src/com/arsdigita/cms/contentsection/Initializer.java index f04c0d408..e39f8000d 100644 --- a/ccm-cms/src/com/arsdigita/cms/contentsection/Initializer.java +++ b/ccm-cms/src/com/arsdigita/cms/contentsection/Initializer.java @@ -22,26 +22,23 @@ package com.arsdigita.cms.contentsection; import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ContentSectionCollection; +import com.arsdigita.cms.workflow.CMSTask; import com.arsdigita.cms.workflow.UnfinishedTaskNotifier; -import com.arsdigita.persistence.SessionManager; -import com.arsdigita.persistence.TransactionContext; import com.arsdigita.domain.DomainObject; import com.arsdigita.kernel.ACSObjectInstantiator; import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.TransactionContext; import com.arsdigita.runtime.CompoundInitializer; -import com.arsdigita.runtime.ContextInitEvent; import com.arsdigita.runtime.ContextCloseEvent; -// import com.arsdigita.runtime.DataInitEvent; +import com.arsdigita.runtime.ContextInitEvent; import com.arsdigita.runtime.DomainInitEvent; import com.arsdigita.web.Application; -import com.arsdigita.cms.workflow.CMSTask; - import java.util.Enumeration; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.Timer; import java.util.Vector; - import org.apache.log4j.Logger; @@ -188,7 +185,9 @@ public class Initializer extends CompoundInitializer { for (Enumeration el=s_unfinishedTimers.elements(); el.hasMoreElements(); ) { unfinishedTimer = (Timer) el.nextElement(); - if(unfinishedTimer != null) unfinishedTimer.cancel(); + if(unfinishedTimer != null) { + unfinishedTimer.cancel(); + } unfinishedTimer = null; // s_unfinishedTimer = null; } @@ -221,7 +220,8 @@ public class Initializer extends CompoundInitializer { txn.beginTxn(); ContentSectionSetup.setupContentSectionAppInstance (newSectionName, - s_conf.getStuffGroup(), + s_conf.getDefaultRoles(), + s_conf.getDefaultWorkflows(), s_conf.isPubliclyViewable(), s_conf.getItemResolverClass(), s_conf.getTemplateResolverClass(), diff --git a/ccm-cms/src/com/arsdigita/cms/workflow/CMSTaskType.java b/ccm-cms/src/com/arsdigita/cms/workflow/CMSTaskType.java index 6bb127b1f..0978c4e60 100755 --- a/ccm-cms/src/com/arsdigita/cms/workflow/CMSTaskType.java +++ b/ccm-cms/src/com/arsdigita/cms/workflow/CMSTaskType.java @@ -19,215 +19,206 @@ package com.arsdigita.cms.workflow; import com.arsdigita.cms.ContentItem; -import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ContentType; -import com.arsdigita.cms.SecurityManager; -import com.arsdigita.cms.ui.ContentItemPage; -import com.arsdigita.cms.util.GlobalizationUtil; -import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.domain.DomainObject; import com.arsdigita.domain.DomainObjectFactory; -import com.arsdigita.kernel.Group; -import com.arsdigita.kernel.KernelHelper; -import com.arsdigita.kernel.Party; -import com.arsdigita.kernel.User; -import com.arsdigita.kernel.UserCollection; -import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.kernel.permissions.PrivilegeDescriptor; -import com.arsdigita.messaging.Message; -import com.arsdigita.notification.Notification; import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataAssociationCursor; import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataObject; -import com.arsdigita.persistence.DataOperation; -import com.arsdigita.persistence.DataQuery; -import com.arsdigita.persistence.Filter; import com.arsdigita.persistence.OID; -import com.arsdigita.persistence.Session; import com.arsdigita.persistence.SessionManager; -import com.arsdigita.persistence.metadata.ObjectType; -import com.arsdigita.util.Assert; import com.arsdigita.util.UncheckedWrapperException; -import com.arsdigita.versioning.TagCollection; -import com.arsdigita.versioning.Transaction; -import com.arsdigita.versioning.TransactionCollection; -import com.arsdigita.versioning.Versions; -import com.arsdigita.web.URL; -import com.arsdigita.workflow.simple.TaskComment; -import com.arsdigita.workflow.simple.TaskException; -import com.arsdigita.workflow.simple.UserTask; -import org.apache.log4j.Logger; -import java.math.BigDecimal; -import java.util.Date; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.Map; -import java.util.Set; +import org.apache.log4j.Logger; /** - * This class represents a task type in the CMS system. The task type has attributes that impact on - * the behaviour of tasks of that type + * This class represents a task type in the CMS system. The task type has + * attributes that impact on the behaviour of tasks of that type * * * @author chris.gilbert at westsussex.gov.uk - * @version $Id: $ + * @version $Id: $ */ public class CMSTaskType extends DomainObject { - public static final String BASE_DATA_OBJECT_TYPE = - "com.arsdigita.cms.workflow.CMSTaskType"; - - - private static Map s_taskURLGeneratorCache = new HashMap(); - + public static final String BASE_DATA_OBJECT_TYPE = + "com.arsdigita.cms.workflow.CMSTaskType"; + private static Map s_taskURLGeneratorCache = new HashMap(); // pdl attribute names - public static final String ID = "taskTypeID"; - public static final String NAME = "name"; - public static final String DEFAULT_URL_GENERATOR_CLASS = - "defaultUrlGeneratorClass"; - public static final String PRIVILEGE = "privilege"; - public static final String URL_GENERATORS = "generators"; + public static final String ID = "taskTypeID"; + public static final String NAME = "name"; + public static final String DEFAULT_URL_GENERATOR_CLASS = + "defaultUrlGeneratorClass"; + public static final String PRIVILEGE = "privilege"; + public static final String URL_GENERATORS = "generators"; + private static final Logger s_log = Logger.getLogger(CMSTaskType.class); + // known task types + public static final Integer AUTHOR = new Integer(1); + public static final Integer EDIT = new Integer(2); + public static final Integer DEPLOY = new Integer(3); + // cache task type domain objects to save unnecessary db lookups + public static Map s_taskTypes = new HashMap(); + private static Map s_taskNameMap = new HashMap(); - private static final Logger s_log = Logger.getLogger(CMSTaskType.class); + static { + s_taskNameMap.put("Author", AUTHOR); + s_taskNameMap.put("Edit", EDIT); + s_taskNameMap.put("Deploy",DEPLOY); + } + + public static CMSTaskType retrieve(Integer id) { - // known task types - - public static final Integer AUTHOR = new Integer(1); - public static final Integer EDIT = new Integer(2); - public static final Integer DEPLOY = new Integer(3); + if (id == null) { + throw new IllegalArgumentException("Parameter id must not be null"); + } - // cache task type domain objects to save unnecessary db lookups - public static Map s_taskTypes = new HashMap(); + CMSTaskType type = s_taskTypes.get(id); + if (type == null) { + type = new CMSTaskType(id); + s_taskTypes.put(id, type); + } + return type; - public static CMSTaskType retrieve (Integer id) { - CMSTaskType type = (CMSTaskType)s_taskTypes.get(id); - if (type == null) { - type = new CMSTaskType(id); - s_taskTypes.put(id, type); - } - return type; - - } - private CMSTaskType(Integer id) { - super(new OID(BASE_DATA_OBJECT_TYPE, id)); - } + } - public CMSTaskType(DataObject obj) { - super(obj); - } + public static CMSTaskType retrieveByName(String name) { - /** - * create a message object and associate it with the current application instance - * - */ - public CMSTaskType() { - super(BASE_DATA_OBJECT_TYPE); - setID(); - - } - - public Integer getID(){ - return ((Integer)get(ID)); - } - - /** - * allocate a unique integer to the message - * - */ - private void setID() { - DataCollection allTypes = - SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); - allTypes.addOrder(ID + " desc"); - Integer id = new Integer(1); - if (allTypes.next()) { - CMSTaskType taskType = - (CMSTaskType) DomainObjectFactory.newInstance( - allTypes.getDataObject()); - int currentMaxID = taskType.getID().intValue(); - id = new Integer(currentMaxID + 1); - allTypes.close(); - } - set(ID, id); - } - - public String getName() { - return (String)get(NAME); - } - - public PrivilegeDescriptor getPrivilege () { - return PrivilegeDescriptor.get((String)get(PRIVILEGE)); - } - - private TaskURLGenerator getDefaultTaskURLGenerator () throws ClassNotFoundException, IllegalAccessException, InstantiationException { - String generatorClassName = (String)get(DEFAULT_URL_GENERATOR_CLASS); - Class URLGenerator = Class.forName(generatorClassName); - return (TaskURLGenerator)URLGenerator.newInstance(); - -} - - public TaskURLGenerator getURLGenerator(String event, ContentItem item) { - String key = getID() + " " + event + " " + item.getContentType().getID(); - s_log.debug("looking up url generator for key " + key); - TaskURLGenerator generator = (TaskURLGenerator) - s_taskURLGeneratorCache.get(key); - if (generator == null) { - s_log.debug("no generator found in cache"); - DataAssociationCursor generators = ((DataAssociation)get(URL_GENERATORS)).cursor(); - generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event); - generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE + "." + ContentType.ID, item.getContentType().getID()); - try { - - while (generators.next()) { - s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for content type " + item.getContentType().getLabel()); - // generator class available for this specific event and this specific content type - generator = ((TaskEventURLGenerator)DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator(); - generators.close(); - } - if (generator == null) { - generators.reset(); - generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event); - generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE, null); - while (generators.next()) { - s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for any content type"); - // generator class available for this specific event - generator = ((TaskEventURLGenerator)DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator(); - generators.close(); - } - } - - if (generator == null) { - - s_log.debug("no specific generator for " + event + " event on task type " + getName()+ ". Revert to default"); - // fall back on default - generator = getDefaultTaskURLGenerator(); - } - s_taskURLGeneratorCache.put(key, generator); - } catch(Exception e) { - throw new UncheckedWrapperException("Unable to retrieve a URL generator for event " + event + " on task type " + getID() + " ", e); - - } - } - - return generator; - } - - - /** - * - * Should be used when UI is implemented for managing task types. If a specific TaskURLGenerator - * is added or removed for an event, then the cached TaskURLGenerator needs to be removed - * @param event - */ - public void clearCachedEntry(String event) { - String key = getID() + " " + event; - s_taskURLGeneratorCache.remove(key); - - } - - - - + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException("Parameter name must not be null or empty"); + } + Integer id = s_taskNameMap.get(name); + if (id == null) { + for (CMSTaskType type : s_taskTypes.values()) { + if (!s_taskNameMap.containsKey(type.getName())) { + s_taskNameMap.put(type.getName(), type.getID()); + } + if (name.equals(type.getName())) { + id = type.getID(); + } + } + } + return retrieve(id); + + } + + private CMSTaskType(Integer id) { + super(new OID(BASE_DATA_OBJECT_TYPE, id)); + } + + public CMSTaskType(DataObject obj) { + super(obj); + } + + /** + * create a message object and associate it with the current application + * instance + * + */ + public CMSTaskType() { + super(BASE_DATA_OBJECT_TYPE); + setID(); + + } + + public Integer getID() { + return ((Integer) get(ID)); + } + + /** + * allocate a unique integer to the message + * + */ + private void setID() { + DataCollection allTypes = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + allTypes.addOrder(ID + " desc"); + Integer id = new Integer(1); + if (allTypes.next()) { + CMSTaskType taskType = + (CMSTaskType) DomainObjectFactory.newInstance( + allTypes.getDataObject()); + int currentMaxID = taskType.getID().intValue(); + id = new Integer(currentMaxID + 1); + allTypes.close(); + } + set(ID, id); + } + + public String getName() { + return (String) get(NAME); + } + + public PrivilegeDescriptor getPrivilege() { + return PrivilegeDescriptor.get((String) get(PRIVILEGE)); + } + + private TaskURLGenerator getDefaultTaskURLGenerator() throws ClassNotFoundException, IllegalAccessException, InstantiationException { + String generatorClassName = (String) get(DEFAULT_URL_GENERATOR_CLASS); + Class URLGenerator = Class.forName(generatorClassName); + return (TaskURLGenerator) URLGenerator.newInstance(); + + } + + public TaskURLGenerator getURLGenerator(String event, ContentItem item) { + String key = getID() + " " + event + " " + item.getContentType().getID(); + s_log.debug("looking up url generator for key " + key); + TaskURLGenerator generator = (TaskURLGenerator) s_taskURLGeneratorCache.get(key); + if (generator == null) { + s_log.debug("no generator found in cache"); + DataAssociationCursor generators = ((DataAssociation) get(URL_GENERATORS)).cursor(); + generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event); + generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE + "." + ContentType.ID, item.getContentType().getID()); + try { + + while (generators.next()) { + s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for content type " + item.getContentType().getLabel()); + // generator class available for this specific event and this specific content type + generator = ((TaskEventURLGenerator) DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator(); + generators.close(); + } + if (generator == null) { + generators.reset(); + generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event); + generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE, null); + while (generators.next()) { + s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for any content type"); + // generator class available for this specific event + generator = ((TaskEventURLGenerator) DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator(); + generators.close(); + } + } + + if (generator == null) { + + s_log.debug("no specific generator for " + event + " event on task type " + getName() + ". Revert to default"); + // fall back on default + generator = getDefaultTaskURLGenerator(); + } + s_taskURLGeneratorCache.put(key, generator); + } catch (Exception e) { + throw new UncheckedWrapperException("Unable to retrieve a URL generator for event " + event + " on task type " + getID() + " ", e); + + } + } + + return generator; + } + + /** + * + * Should be used when UI is implemented for managing task types. If a + * specific TaskURLGenerator is added or removed for an event, then the + * cached TaskURLGenerator needs to be removed + * + * @param event + */ + public void clearCachedEntry(String event) { + String key = getID() + " " + event; + s_taskURLGeneratorCache.remove(key); + + } }