ccm-core & ccm-cms incorporating

r1637 | chrisg23 | 2007-09-17 12:14:27 +0200 (Mo, 17 Sep 2007)

Sourceforge patch 1796099 - allow URL Generators to be registered for specific content types. 

Requires upgrade script to be run: ccm-run ccm-cms --from-version 6.5.2 --to-version 6.5.3!

------------------------------------------------------------------------

r1638 | chrisg23 | 2007-09-17 13:48:34 +0200 (Mo, 17 Sep 2007)

Sourceforge patch 1796156 - allow notes to be shown on basic properties authoring step

------------------------------------------------------------------------

r1639 | chrisg23 | 2007-09-17 15:20:13 +0200 (Mo, 17 Sep 2007)

Sourceforge patch 1781131 - workaround to bypass query filtering bug if permission filtering folder contents

------------------------------------------------------------------------
r1641 | chrisg23 | 2007-09-17 15:46:27 +0200 (Mo, 17 Sep 2007) | 1 line
Geänderte Pfade:
   M /trunk/ccm-core/src/com/arsdigita/notification/Notification.java

Sourceforge patch 1714842 - if message delete has been specified for a notification, only delete it when the last 
referring notification is deleted (several notification records may refer to the same message)

------------------------------------------------------------------------

r1642 | chrisg23 | 2007-09-17 16:05:26 +0200 (Mo, 17 Sep 2007) | 1 line

Sourceforge patch 1727634 - retain specified ordering when paging through folder contents (previously every time you changed to a new page it reverted to default name ordering)

------------------------------------------------------------------------

r1643 | chrisg23 | 2007-09-17 16:19:06 +0200 (Mo, 17 Sep 2007) | 1 line

Sourceforge patch 1783195 - IMPORTANT BUGFIX - if you use fixed length lifecycles with expiry notifications then you are probably affected by this - notifications are not created and  sent if you have relied on the default end date set by the lifecycle, only if you explicitly entered a date on the publish form. To fix the timebomb of items that are due to expire without notification, there is a command line program in package uk.gov.westsussex.wsgfl.jobs called CreateMissingNotificationPhases. Package is in ccm-wsx-wsgfl-custom module in contrib area of the repository. To use this, it is best to copy the job class and the accompanying pdl file query-missing-notification-phases to your own custom application, or else install ccm-wsx-wsgfl-custom but strip away everything except those 2 files and the initialiser - removing all bits of the initialiser except the data init. Do not add ccm-wsx-wsgfl-custom to your instance as it is, at it overrides some files in the default Aplaws installation



git-svn-id: https://svn.libreccm.org/ccm/trunk@13 8810af33-2d31-482b-a856-94f89814c4df
master
pb 2008-02-15 16:04:19 +00:00
parent 576ecedbd1
commit 5dcbb5e070
18 changed files with 278 additions and 93 deletions

View File

@ -2,11 +2,11 @@
<ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project"
name="ccm-cms"
prettyName="Red Hat CCM Content Management System"
version="6.5.2"
release="4"
version="6.5.3"
release="1"
webapp="ROOT">
<ccm:dependencies>
<ccm:requires name="ccm-core" version="6.5.2" relation="ge"/>
<ccm:requires name="ccm-core" version="6.5.5" relation="ge"/>
</ccm:dependencies>
<ccm:contacts>
<ccm:contact uri="http://www.redhat.com/software/ccm" type="website"/>

View File

@ -16,6 +16,7 @@ model com.arsdigita.cms.workflow;
import com.arsdigita.workflow.simple.*;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.cms.ContentType;
object type CMSTask extends UserTask {
composite CMSTaskType [1..1] taskType = join cms_tasks.task_type_id to cms_task_types.task_type_id;
@ -36,6 +37,7 @@ object type CMSTaskType {
object type TaskEventURLGenerator {
Integer [1..1] generatorID = cms_task_url_generators.generator_id INTEGER;
String [1..1] event = cms_task_url_generators.event VARCHAR(100);
ContentType [0..1] contentType = join cms_task_url_generators.content_type to content_types.type_id;
String [1..1] urlGeneratorClass = cms_task_url_generators.classname VARCHAR(128);
object key (generatorID);

View File

@ -0,0 +1,6 @@
alter table CMS_TASK_URL_GENERATORS
add (content_type INTEGER);
alter table cms_task_url_generators add
constraint cms_tas_url_gen_con_ty_f_lz1y5 foreign key (content_type)
references content_types(type_id);

View File

@ -0,0 +1,24 @@
--
-- Copyright (C) 2007 Chris Gilbert. 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
--
-- $Id: oracle-se-6.5.2-6.5.3.sql 293 2005-02-22 15:10:39Z cgilbert $
-- $DateTime: 2004/08/16 18:10:38 $
PROMPT Red Hat Enterprise CMS 6.5.2 -> 6.5.3 Upgrade Script (Oracle)
@@ ../default/upgrade/6.5.2-6.5.3/cms_task_url_generators_upgrade.sql

View File

@ -0,0 +1,26 @@
--
-- Copyright (C) 2007 Chris Gilbert 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
--
-- $DateTime: 2004/08/17 23:15:09 $
\echo Red Hat Enterprise CMS 6.5.2 -> 6.5.3 Upgrade Script (PostgreSQL)
begin;
\i ../default/upgrade/6.5.2-6.5.3/cms_task_url_generators_upgrade.sql
commit;

View File

@ -29,5 +29,8 @@
<version from="6.5.0" to="6.5.1">
<script sql="ccm-cms/upgrade/::database::-6.5.0-6.5.1.sql"/>
</version>
<version from="6.5.2" to="6.5.3">
<script sql="ccm-cms/upgrade/::database::-6.5.2-6.5.3.sql"/>
</version>
</upgrade>

View File

@ -26,8 +26,10 @@ import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.domain.DomainCollectionIterator;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.User;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.DataQuery;
@ -235,14 +237,13 @@ public class Folder extends ContentItem {
* @return child items of this folder
*/
public ItemCollection getItems(boolean bSort) {
final DataQuery query = SessionManager.getSession().retrieveQuery
(ITEMS_QUERY);
query.setParameter(PARENT, getID());
DataQueryDataCollectionAdapter adapter = new DataQueryDataCollectionAdapter(ITEMS_QUERY, ITEM);
adapter.setParameter(PARENT, getID());
Assert.unequal(PENDING, getVersion());
query.setParameter(VERSION, getVersion());
adapter.setParameter(VERSION, getVersion());
return new ItemCollection(query, bSort);
return new ItemCollection(adapter, bSort);
}
/**
@ -593,12 +594,30 @@ public class Folder extends ContentItem {
private DataQuery m_query;
/**
* Constructor
* @param adapter an adapter constructed using the query name rather than a
* DataQuery object. This constructor must be used if there is any
* intention to permission filter the results as only a DataQueryDataCollectionAdapter
* constructed using query name has the bug fix to allow permission filtering
*
* @param bSort whether to sort the collection by isFolder and ID
*/
public ItemCollection (DataQueryDataCollectionAdapter adapter, boolean bSort) {
super(adapter);
doAlias(adapter);
init(adapter, bSort);
}
public ItemCollection (DataQueryDataCollectionAdapter adapter) {
this(adapter, true);
}
/**
* Constructor
* @param query the Data Query to use to retrieve the collection
* @param bSort whether to sort the collection by isFolder and ID
*/
//ideally, we wouldn't sort the collection by default and only provide
//one constructor. But, that would break the existing API
public ItemCollection(DataQuery query, boolean bSort) {

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2007 Chris Gilbert 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.ui.authoring;
import com.arsdigita.bebop.Component;
import com.arsdigita.cms.ItemSelectionModel;
/**
* class used for decoupled display components that caters
* for a callback to provide them with a handle on the ItemSelectionModel
* @author chris.gilbert@westsussex.gov.uk
*
*/
public interface AdditionalDisplayComponent extends Component {
public void setItemSelectionModel (ItemSelectionModel model);
}

View File

@ -18,6 +18,11 @@
*/
package com.arsdigita.cms.ui.authoring;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.ActionEvent;
@ -63,6 +68,23 @@ public class SimpleEditStep extends SecurityPropertyEditor
private static final String STREAMLINED = "_streamlined";
private static final String STREAMLINED_DONE = "1";
private static List s_additionalDisplayComponents = new ArrayList();
/**
* allow additional display components to be added to all implementations
* of SimpleEditStep. This allows shared optional packages such as notes to
* display information on the initial authoring page of all content types without
* causing dependencies from ccm-cms.
*
* Any additional components must be added before the edit step is created.
* An initialiser is a suitable location
*
* @param c
*/
public static void addAdditionalDisplayComponent(AdditionalDisplayComponent c) {
s_additionalDisplayComponents.add(c);
}
/**
* Construct a new SimpleEditStep component
*
@ -104,6 +126,15 @@ public class SimpleEditStep extends SecurityPropertyEditor
showDisplayPane(state);
}
});
Iterator it = s_additionalDisplayComponents.iterator();
while (it.hasNext()) {
AdditionalDisplayComponent component = (AdditionalDisplayComponent)it.next();
component.setItemSelectionModel(itemModel);
addDisplayComponent(component);
}
}
/**

View File

@ -32,9 +32,12 @@ import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.DefaultTableColumnModel;
@ -114,21 +117,15 @@ public class FolderBrowser extends Table {
private final static String SORT_KEY_LAST_MODIFIED_DATE = "lastModified";
private final static String SORT_KEY_CREATION_DATE = "creationDate";
private RequestLocal m_sortType = new RequestLocal() {
public Object initialValue(PageState state) {
return SORT_KEY_NAME;
}
};
private final RequestLocal m_sortDirection = new RequestLocal() {
public Object initialValue(PageState state) {
return SORT_ACTION_UP;
}
};
private StringParameter m_sortType = new StringParameter("sortType");
private StringParameter m_sortDirection = new StringParameter("sortDirn");
public FolderBrowser(FolderSelectionModel currentFolder) {
//super(new FolderTableModelBuilder(), s_headers);
super();
m_sortType.setDefaultValue(SORT_KEY_NAME);
m_sortDirection.setDefaultValue(SORT_ACTION_UP);
setModelBuilder(new FolderTableModelBuilder(currentFolder));
setColumnModel(new DefaultTableColumnModel(hideIndexColumn() ? s_noIndexHeaders : s_headers));
setHeader(new TableHeader(getColumnModel()));
@ -145,6 +142,24 @@ public class FolderBrowser extends Table {
m_currentFolder = currentFolder;
/*
This code should be uncommented if the desired behaviour is for a change
of folder to cause reversion to default ordering of contained items
(by name ascending). Our feeling is that the user selected ordering
should be retained for the duration of the folder browsing session. If
anyone wants this alternative behaviour it should be brought in under
the control of a config parameter.
m_currentFolder.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
PageState state = e.getPageState();
state.setValue(m_sortType, m_sortType.getDefaultValue());
state.setValue(m_sortDirection, m_sortDirection.getDefaultValue());
}});
*/
setClassAttr("dataTable");
getHeader().setDefaultRenderer(new com.arsdigita.cms.ui.util.DefaultTableCellRenderer());
@ -182,7 +197,8 @@ public class FolderBrowser extends Table {
super.register(p);
p.addComponentStateParam(this, m_currentFolder.getStateParameter());
p.addComponentStateParam(this, m_sortType);
p.addComponentStateParam(this, m_sortDirection);
p.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final PageState state = e.getPageState();
@ -209,11 +225,11 @@ public class FolderBrowser extends Table {
String key = state.getControlEventName();
String value = state.getControlEventValue();
if ( SORT_ACTION_UP.equals(key) ) {
m_sortType.set(state, value);
m_sortDirection.set(state, SORT_ACTION_UP);
state.setValue(m_sortType, value);
state.setValue(m_sortDirection, SORT_ACTION_UP);
} else if ( SORT_ACTION_DOWN.equals(key) ) {
m_sortType.set(state, value);
m_sortDirection.set(state, SORT_ACTION_DOWN);
state.setValue(m_sortType, value);
state.setValue(m_sortDirection, SORT_ACTION_DOWN);
} else {
super.respond(state);
//throw new ServletException("Unknown control event: " + key);
@ -282,9 +298,9 @@ public class FolderBrowser extends Table {
itemColl.setRange(new Integer(paginator.getFirst(state)),
new Integer(paginator.getLast(state) + 1));
String sortKey = (String)m_sortType.get(state);
String sortKey = (String)state.getValue(m_sortType);
String direction = "asc";
if (SORT_ACTION_DOWN.equals((String)m_sortDirection.get(state))) {
if (SORT_ACTION_DOWN.equals((String)state.getValue(m_sortDirection))) {
direction = "desc";
}
@ -342,9 +358,9 @@ public class FolderBrowser extends Table {
boolean isSelected, Object key,
int row, int column) {
String headerName = (String)((GlobalizedMessage)value).localize();
String sortKey = (String)m_sortType.get(state);
String sortKey = (String)state.getValue(m_sortType);
final boolean isCurrentKey = sortKey.equals(m_key);
final String currentSortDirection = (String)m_sortDirection.get(state);
final String currentSortDirection = (String)state.getValue(m_sortDirection);
String imageURLStub = null;
if (SORT_ACTION_UP.equals(currentSortDirection)) {

View File

@ -452,12 +452,12 @@ class ItemLifecycleSelectForm extends BaseForm {
// Apply the new lifecycle.
ContentItem pending = item.publish(cycleDef, startDate);
final Lifecycle lifecycle = pending.getLifecycle();
// XXX domlay Whoa. This must be broken for multiphase
// lifecycles.
if (endDate != null) {
final Lifecycle lifecycle = pending.getLifecycle();
// update individual phases
final PhaseCollection phases = lifecycle.getPhases();
@ -465,12 +465,23 @@ class ItemLifecycleSelectForm extends BaseForm {
while (phases.next()) {
final Phase phase = phases.getPhase();
java.util.Date thisEnd = phase.getEndDate();
java.util.Date thisStart = phase.getStartDate();
if (thisStart.compareTo(endDate) > 0) {
phase.setStartDate(endDate);
phase.save();
}
if (thisEnd == null || thisEnd.compareTo(endDate) > 0) {
phase.setEndDate(endDate);
phase.save();
}
}
}
// endOfCycle may be the original date according to lifecycle phase definitions, or endDate if that was before
// natural end of lifecycle
java.util.Date endOfCycle = lifecycle.getEndDate();
if (endOfCycle != null) {
// if advance notification is requested (!= 0)
// add another phase at the start of which the user is notified
@ -490,12 +501,12 @@ class ItemLifecycleSelectForm extends BaseForm {
if (notificationPeriod > 0) {
notificationDate =
computeNotificationDate(endDate, notificationPeriod);
computeNotificationDate(endOfCycle, notificationPeriod);
s_log.debug("adding custom phase");
Phase expirationImminentPhase =
lifecycle.addCustomPhase("expirationImminent",
new Long(notificationDate.getTime()),
new Long(endDate.getTime()));
new Long(endOfCycle.getTime()));
expirationImminentPhase.
setListenerClassName("com.arsdigita.cms.lifecycle.NotifyLifecycleListener");
expirationImminentPhase.save();
@ -510,7 +521,7 @@ class ItemLifecycleSelectForm extends BaseForm {
item.save();
final Workflow workflow = m_workflow.getWorkflow(state);
try {
try {
finish(workflow, item, Web.getContext().getUser());
} catch (TaskException te) {
throw new FormProcessException(te);

View File

@ -255,13 +255,15 @@ public class CMSTask extends UserTask {
Assert.assertNotNull(item, "item associated with this CMSTask");
String authoringURL = getAuthoringURL(item);
String fullURL = URL.there(getTaskType().getURLGenerator(operation).generateURL(item.getID(), getID()), null).getURL();
String fullURL = getTaskType().getURLGenerator(operation, item).generateURL(item.getID(), getID());
s_log.debug("URL retrieved from generator: " + fullURL);
if (!fullURL.startsWith("http")) {
// url is not fully qualified
fullURL = URL.there(fullURL, null).getURL();
}
// see CMSResources.properties for how these values are used
Object[] g11nArgs = new Object[10];
// cg - make this configurable. Because our content section managers have access to all
// folders, they get all notifications, but they want to know which area it relates to -
// first folder in item path tells them. config parameter - full item path or just display name
// g11nArgs[0] =((ContentItem)item.getParent()).getPath();
Object[] g11nArgs = new Object[11];
g11nArgs[0] = item.getDisplayName();
g11nArgs[1] = new Double(getTaskType().getID().doubleValue());
g11nArgs[2] = fullURL;
@ -283,7 +285,9 @@ public class CMSTask extends UserTask {
}
g11nArgs[8] = getStartDate();
g11nArgs[9] = URL.there(authoringURL, null).getURL();
//if added to email, allows recipient to identify if the item is in a folder
// they are interested in
g11nArgs[10] = ((ContentItem)item.getParent()).getPath();
String subject = (String) GlobalizationUtil.globalize("cms.ui.workflow.email.subject." + operation,
g11nArgs).localize();
String body = (String) GlobalizationUtil.globalize("cms.ui.workflow.email.body." + operation,
@ -481,8 +485,10 @@ public class CMSTask extends UserTask {
}
}
}
// bugfix - if author is null above then we break out
// of loop early. If normal exit and so cursor has already closed then the
// next line has no effect
hist.close();
//hist.close here if not closed
if (author == null) {
// fallback: creator is always available in audit trail
author = item.getCreationUser();

View File

@ -20,6 +20,7 @@ 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;
@ -168,23 +169,36 @@ public class CMSTaskType extends DomainObject {
}
public TaskURLGenerator getURLGenerator(String event) {
String key = getID() + " " + event;
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("generator not found in cache");
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());
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");

View File

@ -18,51 +18,14 @@
*/
package com.arsdigita.cms.workflow;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.domain.DataObjectNotFoundException;
import org.apache.log4j.Logger;
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.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;
/**
* This class represents enables fine grained control of the url that is
@ -87,6 +50,7 @@ public class TaskEventURLGenerator extends DomainObject {
public static final String EVENT = "event";
public static final String URL_GENERATOR_CLASS =
"urlGeneratorClass";
public static final String CONTENT_TYPE = "contentType";
private static final Logger s_log = Logger.getLogger(TaskEventURLGenerator.class);

View File

@ -35,6 +35,7 @@ import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.FormErrorDisplay;
import com.arsdigita.bebop.form.Submit;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
@ -150,6 +151,7 @@ public class PropertyEditor extends SimpleContainer {
private List m_list;
private PropertyEditorModelBuilder m_builder;
private RequestLocal m_model;
private java.util.List m_additionalDisplayComponents = new ArrayList();
/**
* Constructs a new, empty <code>PropertyEditor</code>.
@ -276,6 +278,13 @@ public class PropertyEditor extends SimpleContainer {
return (String)m_list.getSelectedKey(state);
}
/**
* add an additional component below the list of links
* @param c
*/
public void addDisplayComponent(Component c) {
m_additionalDisplayComponents.add(c);
}
/**
* Adds the display component if it has not been added already.
*
@ -288,6 +297,10 @@ public class PropertyEditor extends SimpleContainer {
m_displayPane.add(c);
m_displayPane.add(m_list);
Iterator it = m_additionalDisplayComponents.iterator();
while (it.hasNext()) {
m_displayPane.add((Component)it.next());
}
m_display = c;
}

View File

@ -552,11 +552,11 @@ public class Table extends BlockStylable implements BebopConstants {
* @param p the page that contains this table
*/
public void register(Page p) {
ParameterModel m = getRowSelectionModel().getStateParameter();
ParameterModel m = getRowSelectionModel() == null ? null : getRowSelectionModel().getStateParameter();
if ( m != null ) {
p.addComponentStateParam(this, m);
}
m = getColumnSelectionModel().getStateParameter();
m = getColumnSelectionModel() == null ? null : getColumnSelectionModel().getStateParameter();
if ( m != null ) {
p.addComponentStateParam(this, m);
}
@ -601,7 +601,7 @@ public class Table extends BlockStylable implements BebopConstants {
* <code>false</code> otherwise.
*/
public boolean isSelectedRow(PageState s, Object rowKey) {
if ( rowKey == null ) {
if ( rowKey == null || getRowSelectionModel() == null) {
return false;
}
return getRowSelectionModel().isSelected(s)
@ -619,7 +619,7 @@ public class Table extends BlockStylable implements BebopConstants {
* <code>false</code> otherwise.
*/
public boolean isSelectedColumn(PageState s, Object column) {
if ( column == null ) {
if ( column == null || getColumnSelectionModel() == null) {
return false;
}
return getColumnSelectionModel().isSelected(s)

View File

@ -283,6 +283,9 @@ public class TableHeader extends SimpleComponent {
* @param column the index of the column to test
*/
protected boolean isSelected(PageState s, Object key, int column) {
if (getTable().getColumnSelectionModel() == null) {
return false;
}
Object sel = getTable()
.getColumnSelectionModel().getSelectedKey(s);
if(sel == null) {

View File

@ -22,7 +22,9 @@ import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.Party;
import com.arsdigita.messaging.Message;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.SessionManager;
import java.math.BigDecimal;
import java.util.Date;
@ -468,6 +470,17 @@ public class Notification extends ACSObject implements NotificationConstants {
if (msg == null) {
msgDelete = false;
}
// find if there are other referring notifications. If so msgdelete = false
// so only the last notification tries to delete the message
DataCollection notifications = SessionManager.getSession().retrieve(Notification.BASE_DATA_OBJECT_TYPE);
notifications.addEqualsFilter(MESSAGE_ID, msg.getID());
notifications.addNotEqualsFilter(ID, this.getID());
if (notifications.size() > 0) {
// other notifications that still refer to the message. Let
// the last one out delete the message else foreign key breach
// brings down the whole request queue process
msgDelete = false;
}
} else {
msg = null;
}