From 11177abc3154d5ad171afc5a2af8a6c9bb484fdf Mon Sep 17 00:00:00 2001 From: jensp Date: Sun, 29 Jan 2012 13:07:33 +0000 Subject: [PATCH] Objektlisten zeigen jetzt auch ExtraXML an, wenn specialize true ist. git-svn-id: https://svn.libreccm.org/ccm/trunk@1477 8810af33-2d31-482b-a856-94f89814c4df --- ccm-cms/src/com/arsdigita/cms/CMSConfig.java | 2 +- .../src/com/arsdigita/cms/ContentItem.java | 679 +++++++++--------- .../ui/GenericOrgaUnitExtraXmlGenerator.java | 81 +-- .../ui/lifecycle/ItemLifecycleItemPane.java | 2 +- .../ui/lifecycle/ItemLifecycleSelectForm.java | 11 +- .../cms/ui/lifecycle/PublishLock.java | 10 +- .../cms/CMSDataCollectionRenderer.java | 20 + 7 files changed, 416 insertions(+), 389 deletions(-) diff --git a/ccm-cms/src/com/arsdigita/cms/CMSConfig.java b/ccm-cms/src/com/arsdigita/cms/CMSConfig.java index 599240674..28454eb6f 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSConfig.java +++ b/ccm-cms/src/com/arsdigita/cms/CMSConfig.java @@ -600,7 +600,7 @@ public final class CMSConfig extends AbstractConfig { private final Parameter m_threadPublishing = new BooleanParameter( "com.arsdigita.cms.lifecycle.threaded_publishing", Parameter.REQUIRED, - false); + true); // /////////////////////////////////////////// // publishToFile package related parameter diff --git a/ccm-cms/src/com/arsdigita/cms/ContentItem.java b/ccm-cms/src/com/arsdigita/cms/ContentItem.java index aaf1a50aa..d6e764206 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentItem.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentItem.java @@ -73,34 +73,34 @@ import java.util.Set; * *

Publishing Items

* - * The {@link #publish(LifecycleDefinition,java.util.Date)} method can - * be used to schedule the item for publication. The publication of an - * item proceeds in two steps: - + * The {@link #publish(LifecycleDefinition,java.util.Date)} method can be used + * to schedule the item for publication. The publication of an item proceeds in + * two steps: + * * 1. Pending Version * - * A pending version is immediately created for the item, and each - * subitem of the item. When the internal - * createPendingVersion method is called, the content - * item will attempt to clone itself in order to create the pending - * version. + * A pending version is immediately created for the item, and each subitem of + * the item. When the internal + * createPendingVersion method is called, the content item will + * attempt to clone itself in order to create the pending version. * - * First, the item will clone itself and all of its scalar - * attributes.Then, the item will clone all of its - * composite relations. After that, the item will - * copy all of its non-composite associations "by reference". If a - * target of any association is a ContentItem, the cloned - * item will reference the live or pending version of the target item. + * First, the item will clone itself and all of its scalar attributes.Then, the + * item will clone all of its composite relations. After that, + * the item will copy all of its non-composite associations "by reference". If a + * target of any association is a + * ContentItem, the cloned item will reference the live or pending + * version of the target item. * - * For example, consider Articles A and B, both of which - * reference an ImageAsset I: + * For example, consider + * Articles A and B, both of which reference an + * ImageAsset I: * *
  * A ---> I <--- B
  * 
* - * When A is published, creating a pending version A', I will be - * published as well: + * When A is published, creating a pending version A', I will be published as + * well: * *
  * A ---> I <--- B
@@ -114,84 +114,71 @@ import java.util.Set;
  * A'---> I'<--- B'
  * 
* - * In order to work correctly with the automatic publishing code, - * every subclass of ContentItem (such as "FooItem - * extends ContentItem") must adhere to the following - * guidelines: + * In order to work correctly with the automatic publishing code, every subclass + * of + * ContentItem (such as "FooItem extends ContentItem") must + * adhere to the following guidelines: * - * + *
  • If the PDL file for the subclass contains any link attributes, read-only + * associations, or in general any associations that are not standard, the + * subclass must implement the {@link #copyProperty(ContentItem, String, ItemCopier)} + * method. For examples on how to implement it, see the methods's javadoc and + * the sample implementation in the {@link Article} class.
  • * - * After the pending version is created, the version copier will - * assign it a new lifecycle, based on the values passed in to {@link - * #publish(LifecycleDefinition, java.util.Date)}, but only - * if the new pending version is a regular aggregation (not a - * composition). In theory, it should make no difference whether the - * new pending version is a composition or not; however, some bugs - * within the publishing code currently prevent this from working - * correctly. For this reason, it is critically important to - * pass the right parameter to {@link ItemCopier#copy} - * the {@link #copyProperty(ContentItem, String, + * After the pending version is created, the version copier will assign it a new + * lifecycle, based on the values passed in to {@link + * #publish(LifecycleDefinition, java.util.Date)}, but only if the new + * pending version is a regular aggregation (not a composition). In theory, it + * should make no difference whether the new pending version is a composition or + * not; however, some bugs within the publishing code currently prevent this + * from working correctly. For this reason, it is critically important + * to pass the right parameter to {@link ItemCopier#copy} the {@link #copyProperty(ContentItem, String, * ItemCopier)} method. * * 2. Live Version * - * When the lifecycle finally rolls around to the start date specified - * in the publish method, the pending versions for the - * item and all the subitems will be promoted to live, and the item - * will appear on the live site. Another publishing bug currently - * makes it a requirement to reload the original item from - * the database after it has been successfully published; I am working - * on fixing this. + * When the lifecycle finally rolls around to the start date specified in the + * publish method, the pending versions for the item and all the + * subitems will be promoted to live, and the item will appear on the live site. + * Another publishing bug currently makes it a requirement to reload + * the original item from the database after it has been successfully published; + * I am working on fixing this. * * 3. Unpublishing * - * When the lifecycle for an item expires, its live version is deleted - * and removed from the live site, along with all its subitems. + * When the lifecycle for an item expires, its live version is deleted and + * removed from the live site, along with all its subitems. * * 4. Future work * - * The new data model makes it possible to have multiple pending - * versions for a content item; it should also be theoretically - * possible to archive expired live versions, as opposed to deletin g - * them. There are no Java APIs for this functionality as of yet, - * however. + * The new data model makes it possible to have multiple pending versions for a + * content item; it should also be theoretically possible to archive expired + * live versions, as opposed to deletin g them. There are no Java APIs for this + * functionality as of yet, however. * *

    Copying Items

    * - * The {@link ItemCopier#copy} method may be used to create a - * nearly identical copy of the item, according to the rules described - * above. The new item will be a full-fledged, standalone item. Note - * that the services (such as categories) will not be automatically - * transferred to the new copy of the item; the {@link - * #copyServicesFrom(ContentItem)} method must be called on the new - * item to transfer the services. Calling this method is not a - * requirement, however. + * The {@link ItemCopier#copy} method may be used to create a nearly identical + * copy of the item, according to the rules described above. The new item will + * be a full-fledged, standalone item. Note that the services (such as + * categories) will not be automatically transferred to the new copy of the + * item; the {@link + * #copyServicesFrom(ContentItem)} method must be called on the new item to + * transfer the services. Calling this method is not a requirement, however. * * @author Uday Mathur * @author Jack Chung @@ -211,8 +198,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { MODEL + ".getPendingSortedByLifecycle"; public static final String BASE_DATA_OBJECT_TYPE = MODEL + ".ContentItem"; /** - * A state marking the draft or master item corresponding to a - * live or pending version of that item. + * A state marking the draft or master item corresponding to a live or + * pending version of that item. */ public static final String DRAFT = "draft"; /** @@ -241,7 +228,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { private VersionCache m_live; private boolean m_wasNew; private Reporter m_reporter; - private BasicAuditTrail m_audit_trail; + private BasicAuditTrail m_audit_trail; /** * Default constructor. This creates a new content item. @@ -253,11 +240,14 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Constructor. The contained DataObject is retrieved - * from the persistent storage mechanism with an OID - * specified by oid. + * Constructor. The contained + * DataObject is retrieved from the persistent storage + * mechanism with an + * OID specified by + * oid. * - * @param oid The OID for the retrieved + * @param oid The + * OID for the retrieved * DataObject */ public ContentItem(final OID oid) throws DataObjectNotFoundException { @@ -265,12 +255,15 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Constructor. The contained DataObject is retrieved - * from the persistent storage mechanism with an OID - * specified by id and + * Constructor. The contained + * DataObject is retrieved from the persistent storage + * mechanism with an + * OID specified by + * id and * ContentItem.BASE_DATA_OBJECT_TYPE. * - * @param id The id for the retrieved + * @param id The + * id for the retrieved * DataObject */ public ContentItem(final BigDecimal id) @@ -279,22 +272,22 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Constructor. Retrieves or creates a content item using the + * Constructor. Retrieves or creates a content item using the * DataObject argument. * - * @param obj The DataObject with which to create or - * load a content item + * @param obj The + * DataObject with which to create or load a content item */ public ContentItem(final DataObject obj) { super(obj); } /** - * Constructor. Creates a new content item using the given data - * object type. Such items are created as draft versions. + * Constructor. Creates a new content item using the given data object type. + * Such items are created as draft versions. * - * @param type The String data object type of the - * item to create + * @param type The + * String data object type of the item to create */ public ContentItem(final String type) { super(type); @@ -320,8 +313,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { }; /** - * Called from the base class (DomainObject) - * constructors. + * Called from the base class ( + * DomainObject) constructors. */ protected void initialize() { super.initialize(); @@ -377,7 +370,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * @return the base PDL object type for this item. Child classes should - * override this method to return the correct value + * override this method to return the correct value */ @Override public String getBaseDataObjectType() { @@ -386,8 +379,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Publicized getter method for use by metadata forms. + * * @param key - * @return + * @return */ @Override public Object get(final String key) { @@ -396,8 +390,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Public setter method for use by metadata forms. + * * @param key - * @param value + * @param value */ @Override public void set(final String key, final Object value) { @@ -406,10 +401,10 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Public add for use by metadata forms. - * + * * @param propertyName * @param dobj - * @return + * @return */ @Override public DataObject add(String propertyName, DomainObject dobj) { @@ -418,9 +413,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Public remove for use by metadata forms - * + * * @param propertyName - * @param dobj + * @param dobj */ @Override public void remove(String propertyName, DomainObject dobj) { @@ -428,8 +423,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * For new content items, sets the associated content type if it - * has not been already set. + * For new content items, sets the associated content type if it has not + * been already set. */ @Override protected void beforeSave() { @@ -445,27 +440,17 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } } - /* - - removed cg - object observer sets context based - on parent whenever parent is updated - - protected void afterSave() { - super.afterSave(); - s_log.info("******After Save of object " + getOID()); - // Set the object's context to its parent object for - // permissioning. - if (m_wasNew) { - final ACSObject parent = getParent(); - if (parent == null) { - s_log.info("parent is null - set context to content section"); - PermissionService.setContext(this, getContentSection()); - } else { - s_log.info("parent is " + parent.getOID()); - PermissionService.setContext(this, parent); - } - } - } + /* * + * removed cg - object observer sets context based on parent whenever parent + * is updated + * + * protected void afterSave() { super.afterSave(); s_log.info("******After + * Save of object " + getOID()); // Set the object's context to its parent + * object for // permissioning. if (m_wasNew) { final ACSObject parent = + * getParent(); if (parent == null) { s_log.info("parent is null - set + * context to content section"); PermissionService.setContext(this, + * getContentSection()); } else { s_log.info("parent is " + + * parent.getOID()); PermissionService.setContext(this, parent); } } } */ private void setDefaultContentSection() { s_log.debug("Setting the default content section"); @@ -491,8 +476,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Fetch the display name of the content item. The display name for - * a {@link com.arsdigita.cms.ContentItem} is the name property. + * Fetch the display name of the content item. The display name for a {@link com.arsdigita.cms.ContentItem} + * is the name property. * * @return The name of the content item */ @@ -533,7 +518,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Set the parent object. * - * @param object The ACSObject parent + * @param object The + * ACSObject parent */ public final void setParent(final ACSObject object) { setAssociation(PARENT, object); @@ -543,7 +529,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Fetches all the child items of this item. * - * @return an ItemCollection of children + * @return an + * ItemCollection of children */ public final ItemCollection getChildren() { final DataAssociationCursor cursor = @@ -590,16 +577,17 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Returns the content section to which this item belongs. - * Fetches the denormalized content section of an item. If one is - * not found, this method returns null. + * Returns the content section to which this item belongs. Fetches the + * denormalized content section of an item. If one is not found, this method + * returns null. * - * Since cms_items.section_id is a denormalization, - * this method may return null even if the item "belongs" to a - * content section. For example, calling + * Since + * cms_items.section_id is a denormalization, this method may + * return null even if the item "belongs" to a content section. For example, + * calling * getContentSection() on an Article's - * ImageAsset will return null even though the image - * asset should belong to the same section as the article. + * ImageAsset will return null even though the image asset + * should belong to the same section as the article. * * @return The content section to which this item belongs */ @@ -620,18 +608,20 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Return the path to the item starting at its root. The path is - * absolute, of the form /x/y/z where x and - * y are the names of the item's grandparent and parent - * respectively, and z is the name of the item itself. + * Return the path to the item starting at its root. The path is absolute, + * of the form /x/y/z where x and y are the names + * of the item's grandparent and parent respectively, and z is the + * name of the item itself. * * The item's root is the ancestor reachable through repeated * getParent() calls whose parent is * null. This is usually a folder, but may be any - * {@see com.arsdigita.kernel.ACSObject}. + * { * - * Note that the name of the root folder of the content section - * where the item resides is not included in the path. + * @see com.arsdigita.kernel.ACSObject}. + * + * Note that the name of the root folder of the content section where the + * item resides is not included in the path. * * @see #getPathInfo(boolean) * @return the path from the item's root to the item @@ -668,14 +658,15 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Return a collection of ancestors starting from the item's root to the - * item's parent item. For items contained in folders this is similar to - * a directory path to the item. The collection starts with the root item - * and ends with the item's direct parent. + * item's parent item. For items contained in folders this is similar to a + * directory path to the item. The collection starts with the root item and + * ends with the item's direct parent. * *

    The item's root is the ancestor reachable through repeated - * getParent() calls whose parent is null. This - * is usually a folder, but may be any {@see - * com.arsdigita.kernel.ACSObject}. + * getParent() calls whose parent is + * null. This is usually a folder, but may be any { + * + * @see com.arsdigita.kernel.ACSObject}. * * @see #getPathInfo(boolean) * @@ -687,17 +678,21 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Return a collection of ancestors starting from the item's root to the - * item's parent item (if includeSelf is false) - * or to the item itself otherwise. For items contained in folders this - * is similar to a directory path to the item. The collection starts with - * the root item and ends with the item's direct parent. + * item's parent item (if + * includeSelf is + * false) or to the item itself otherwise. For items contained + * in folders this is similar to a directory path to the item. The + * collection starts with the root item and ends with the item's direct + * parent. * *

    The item's root is the ancestor reachable through repeated - * getParent() calls whose parent is null. This - * is usually a folder, but may be any {@see - * com.arsdigita.kernel.ACSObject}. + * getParent() calls whose parent is + * null. This is usually a folder, but may be any { * - * @param includeSelf a boolean value. + * @see com.arsdigita.kernel.ACSObject}. + * + * @param includeSelf a + * boolean value. * @return the items on the path to the root folder. */ public ItemCollection getPathInfo(boolean includeSelf) { @@ -752,8 +747,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Sets the version tag. * - * @param version A version tag, {@link #LIVE} or {@link #DRAFT} - * or {@link #PENDING} + * @param version A version tag, {@link #LIVE} or {@link #DRAFT} or {@link #PENDING} */ protected void setVersion(final String version) { set(VERSION, version); @@ -762,18 +756,21 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Returns true if this item is a DRAFT - * version. + * Returns + * true if this item is a + * DRAFT version. * - * @return true if this item is a DRAFT - * version + * @return + * true if this item is a + * DRAFT version */ public boolean isDraftVersion() { return DRAFT.equals(getVersion()); } /** - * Returns the DRAFT version of this content item. + * Returns the + * DRAFT version of this content item. * * @return the draft version */ @@ -797,8 +794,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Fetches the draft (aka, "master" or "working") version of this - * content item. + * Fetches the draft (aka, "master" or "working") version of this content + * item. * * @return the working version representation of the * ContentItem, possibly this item @@ -809,18 +806,21 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Returns true if this item is a + * Returns + * true if this item is a * PENDING version. * - * @return true if this is one of the - * pending versions + * @return + * true if + * this is one of the pending versions */ public boolean isPendingVersion() { return PENDING.equals(getVersion()); } /** - * Returns one PENDING version of this content item. + * Returns one + * PENDING version of this content item. * * @return one of the pending versions */ @@ -853,7 +853,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - *

    Fetches the pending versions, if any, of this content item. The + *

    Fetches the pending versions, if any, of this content item. The * versions are returned in chronological order, sorted by their respective * lifecycle's start date.

    * @@ -910,22 +910,24 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Returns true if this item is a LIVE - * version. + * Returns + * true if this item is a + * LIVE version. * - * @return true if this is the live - * version + * @return + * true if + * this is the live version */ public boolean isLiveVersion() { return LIVE.equals(getVersion()); } /** - * Fetches the live version of this content item. Returns null if - * there is none. + * Fetches the live version of this content item. Returns null if there is + * none. * - * @return a ContentItem representing the live - * version + * @return a + * ContentItem representing the live version */ public ContentItem getLiveVersion() { if (s_log.isDebugEnabled()) { @@ -963,7 +965,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Sets the live version. * - * @param version The ContentItem to set live + * @param version The + * ContentItem to set live */ protected void setLiveVersion(final ContentItem version) { if (s_log.isDebugEnabled()) { @@ -989,8 +992,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Get the live version for the item. If no live version exists, - * return the latest pending version, if any. + * Get the live version for the item. If no live version exists, return the + * latest pending version, if any. * * @return the public version for this item, or null if none */ @@ -1019,16 +1022,16 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { // Publishing methods // /** - * Method to determine whether this ContentItem should - * be automatically published to the file system. + * Method to determine whether this ContentItem should be automatically + * published to the file system. */ protected boolean canPublishToFS() { return true; } /** - * Publish this item to the filesystem; can only be called on a - * live version. + * Publish this item to the filesystem; can only be called on a live + * version. */ protected void publishToFS() { if (!canPublishToFS()) { @@ -1059,11 +1062,12 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Returns true if this item has a publicly viewable version. - * This item is not necessarily the live version nor is this - * method to be confused with isPublished. + * Returns true if this item has a publicly viewable version. This item is + * not necessarily the live version nor is this method to be confused with + * isPublished. * - * @return true if this content item has a live + * @return + * true if this content item has a live * version, or if it is the live version */ public boolean isLive() { @@ -1073,8 +1077,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Makes an item live or not live. * - * @param version the version which should become live, null to - * make the item non-live + * @param version the version which should become live, null to make the + * item non-live */ public void setLive(final ContentItem version) { if (s_log.isDebugEnabled()) { @@ -1180,8 +1184,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { * Schedules an item for publication. * * @param cycleDef The lifecycle definition - * @param startDate The time to schedule the start of the - * lifecycle. If null, use the current time as the start date. + * @param startDate The time to schedule the start of the lifecycle. If + * null, use the current time as the start date. * * @return the new pending version */ @@ -1196,12 +1200,13 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { + "definition " + cycleDef + " and start date " + startDate); } - /* amended Chris Gilbert + /* + * amended Chris Gilbert * * Some content types may have their own lifecycles with their own - * default listeners. Previous implementation just enforced - * the listener retrieved from getPublisherClassName. This amendment - * looks for a default listener in the cycle definition first + * default listeners. Previous implementation just enforced the listener + * retrieved from getPublisherClassName. This amendment looks for a + * default listener in the cycle definition first * */ String listener = cycleDef.getDefaultListener(); @@ -1243,10 +1248,10 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Unpublishes an item. This method removes the item's lifecycle - * and removes all pending versions. It is intended for use in UI - * code, and it should not be used for making items go "unlive". - * Instead, use setLive(null). + * Unpublishes an item. This method removes the item's lifecycle and removes + * all pending versions. It is intended for use in UI code, and it should + * not be used for making items go "unlive". Instead, use + * setLive(null). */ public void unpublish() { if (s_log.isDebugEnabled()) { @@ -1291,9 +1296,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Republish the item - * @parameter reset - if true create a new lifecycle, if false use existing - * Called from ui.lifecycle.ItemLifecycleItemPane.java + * Republish the item @parameter reset - if true create a new lifecycle, if + * false use existing Called from ui.lifecycle.ItemLifecycleItemPane.java */ public void republish(boolean reset) { if (s_log.isDebugEnabled()) { @@ -1433,8 +1437,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Returns an iterator over the categories associated with this - * content item which is associated with the given use context + * Returns an iterator over the categories associated with this content item + * which is associated with the given use context * * @param useContext the category use context * @@ -1468,14 +1472,13 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Sets a category as the default/primary category for this - * item. Actual default assignment is performed on the bundle if - * one exists. + * Sets a category as the default/primary category for this item. Actual + * default assignment is performed on the bundle if one exists. * - * If this category is not already assigned to this item, then - * this method also adds the category to the item. + * If this category is not already assigned to this item, then this method + * also adds the category to the item. * - * @param category The category to set as the default. + * @param category The category to set as the default. * */ public void setDefaultCategory(Category category) { @@ -1493,7 +1496,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Adds a category to this content item (or its bundle if one exists) * - * @param category The category to add this item to + * @param category The category to add this item to * */ public void addCategory(Category category) { @@ -1510,7 +1513,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Removes a category from this content item (or its bundle if one exists) * - * @param category The category to remove this item from + * @param category The category to remove this item from * */ public void removeCategory(Category category) { @@ -1528,19 +1531,16 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { // Versioning stuff // /** - * Recursively copy this item, creating a clone. - * Reassign composite associations from the copy to point - * to the copies of original items. This method will not - * automatically transfer services (such as categories) - * to the copy; the {@link #copyServicesFrom(ContentItem)} method - * should be called to accomplish this. - *

    - * NOTE: This method will also save the item and all - * of its unpublished subitems. + * Recursively copy this item, creating a clone. Reassign composite + * associations from the copy to point to the copies of original items. This + * method will not automatically transfer services (such as categories) to + * the copy; the {@link #copyServicesFrom(ContentItem)} method should be + * called to accomplish this.

    NOTE: This method will also save the item + * and all of its unpublished subitems. * - * NOTE: This method should be final with the addition of makeCopy, - * but is not just in case there are extensions in some PS code. - * The 'non-finalness' of this method should be considered deprecated. + * NOTE: This method should be final with the addition of makeCopy, but is + * not just in case there are extensions in some PS code. The + * 'non-finalness' of this method should be considered deprecated. * * @return the live version for this item * @see #copyServicesFrom(ContentItem) @@ -1554,12 +1554,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Recursively copy this item, creating a clone. - * Reassign composite associations from the copy to point - * to the copies of original items. - *

    - * NOTE: This method will save the item and all - * of its unpublished subitems. + * Recursively copy this item, creating a clone. Reassign composite + * associations from the copy to point to the copies of original items.

    + * NOTE: This method will save the item and all of its unpublished subitems. * * @param newParent The new parent item for this item * @param copyServices Copy services if true @@ -1593,8 +1590,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Performs the actual mechanics of copying a content item. - * Non-final so that subtypes can extend copying behavior. + * Performs the actual mechanics of copying a content item. Non-final so + * that subtypes can extend copying behavior. * * @return A new copy of the item */ @@ -1613,11 +1610,11 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Variant of {@link ACSObject#makeCopy} which allows to pass the (further) + * Variant of {@link ACSObject#makeCopy} which allows to pass the (further) * language of the copy. - * + * * @param language - * @return + * @return */ protected ContentItem makeCopy(String language) { if (s_log.isDebugEnabled()) { @@ -1636,17 +1633,15 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Transfer services, such as categories, - * from the passed-in item to this item. This method should be - * called immediately after {@link ItemCopier#copy}, as follows: - *

     Article newArticle = (Article)oldArticle.copyItem();
    -     * newArticle.copyServicesFrom(oldArticle);
    - *

    - * WARNING: This method will most likely crash if you call it twice - * in a row. + * Transfer services, such as categories, from the passed-in item to this + * item. This method should be called immediately after {@link ItemCopier#copy}, + * as follows:

     Article newArticle = (Article)oldArticle.copyItem();
    +     * newArticle.copyServicesFrom(oldArticle);

    + * WARNING: This method will most likely crash if you call it twice in a + * row. * - * @param source the ContentItem whose services will be - * copied + * @param source the + * ContentItem whose services will be copied * @see #copy() */ public void copyServicesFrom(final ContentItem source) { @@ -1654,12 +1649,12 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Recursively copy this item, creating a pending version. - * Reassign composite associations from the pending version to - * point to the pending/live versions of other items. + * Recursively copy this item, creating a pending version. Reassign + * composite associations from the pending version to point to the + * pending/live versions of other items. * - * NOTE: This method will also save the item and all of its - * unpublished subitems. + * NOTE: This method will also save the item and all of its unpublished + * subitems. * * @param cycle the lifecycle to use. A null cycle implies that a live * version should be created. @@ -1674,8 +1669,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Promote the specified pending version to live. Delete the old - * live version, if any. + * Promote the specified pending version to live. Delete the old live + * version, if any. * * @param pending The pending item to promote */ @@ -1718,9 +1713,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Recursively update the version attribute of the current - * content item to the new value. Used by the lifecycle listener - * to promote a pending version to live. + * Recursively update the version attribute of the current content item to + * the new value. Used by the lifecycle listener to promote a pending + * version to live. * * @param version The new Version to set */ @@ -1732,9 +1727,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Recursively copy this item, creating a live version. Reassign - * component associations from the live version to point to the - * live versions of other items. + * Recursively copy this item, creating a live version. Reassign component + * associations from the live version to point to the live versions of other + * items. * * @return the live version for this item */ @@ -1749,14 +1744,16 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Copy the specified property (attribute or association) from the - * specified source item. This method almost completely overrides - * the metadata-driven methods in ObjectCopier. ... + * Copy the specified property (attribute or association) from the specified + * source item. This method almost completely overrides the metadata-driven + * methods in + * ObjectCopier. ... * - * ObjectCopier will no longer call it, so existing - * implementations need to update to the new signature + * ObjectCopier will no longer call it, so existing implementations need to + * update to the new signature * - * @deprecated use {@link #copyProperty(CustomCopy, Property, ItemCopier)} instead + * @deprecated use {@link #copyProperty(CustomCopy, Property, ItemCopier)} + * instead */ protected final boolean copyProperty(final ContentItem source, final String attribute, @@ -1766,35 +1763,35 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Copy the specified property (attribute or association) from the - * specified source item. This method almost completely overrides - * the metadata-driven methods in ObjectCopier. If - * the property in question is an association to - * ContentItem(s), this method should only - * call FooContentItem newChild = copier.copy(srcItem, this, - * riginalChild, property); An attempt to call any other - * method in order to copy the child will most likely have - * disastrous consequences. In fact, this copier method should - * generally be called for any DomainObject copies, later making - * custom changes, unless the copying behavior itself is different - * from the default (or the item should not be copied at all at + * Copy the specified property (attribute or association) from the specified + * source item. This method almost completely overrides the metadata-driven + * methods in + * ObjectCopier. If the property in question is an association + * to + * ContentItem(s), this method should only call + * FooContentItem newChild = copier.copy(srcItem, this, + * riginalChild, property); An attempt to call any other method in + * order to copy the child will most likely have disastrous consequences. In + * fact, this copier method should generally be called for any DomainObject + * copies, later making custom changes, unless the copying behavior itself + * is different from the default (or the item should not be copied at all at * this point). * * - * If a subclass of a class which implements CustomCopy overrides - * this method, it should return super.copyProperty - * for properties which do not need custom behavior in order to - * indicate that it is not interested in handling the property in - * any special way. + * If a subclass of a class which implements CustomCopy overrides this + * method, it should return + * super.copyProperty for properties which do not need custom + * behavior in order to indicate that it is not interested in handling the + * property in any special way. * - * As a hypothetical example (no longer reflected in Article - * itself), the {@link Article} class extends - * ContentItem. It defines an association to 0..n - * {@link ImageAsset}. Unfortunately, the association has - * "order_n" and "caption" link attributes, which cannot be copied - * automatically, since the persistence system doesn't know enough - * about them. The following sample code from the {@link Article} - * class ensures that images are copied correctly: + * As a hypothetical example (no longer reflected in Article itself), the {@link Article} + * class extends + * ContentItem. It defines an association to 0..n + * {@link ImageAsset}. Unfortunately, the association has "order_n" and + * "caption" link attributes, which cannot be copied automatically, since + * the persistence system doesn't know enough about them. The following + * sample code from the {@link Article} class ensures that images are copied + * correctly: * *

    
          * public boolean copyProperty(CustomCopy srcItem, Property property, ItemCopier copier) {
    @@ -1831,24 +1828,23 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
          * 
    * * Note that for top-level item associations, - * VersionCopier will return null since - * the actual associatons are only created at "go live" time, so - * the ability to override behavior for top-level item - * associations is somewhat limited. A common case for needing to - * override copyProperty to handle these associations would be to - * auto-publish the target of the association but still handle the - * association updating normally. In this case, copyProperty would - * call publish() separately on the associated object, and then - * return false to indicate that the copier should - * continue to handle the association normally. + * VersionCopier will return + * null since the actual associatons are only created at "go + * live" time, so the ability to override behavior for top-level item + * associations is somewhat limited. A common case for needing to override + * copyProperty to handle these associations would be to auto-publish the + * target of the association but still handle the association updating + * normally. In this case, copyProperty would call publish() separately on + * the associated object, and then return + * false to indicate that the copier should continue to handle + * the association normally. * * @param source the source CustomCopy item * @param property the property to copy * @param copier a temporary class that is able to copy a child item - * correctly. - * @return true if the property was copied; false to indicate - * that regular metadata-driven methods should be used - * to copy the property. + * correctly. + * @return true if the property was copied; false to indicate that regular + * metadata-driven methods should be used to copy the property. */ public boolean copyProperty(final CustomCopy source, final Property property, @@ -1942,18 +1938,16 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Copy services from the source item. This method is the analogue of - * the {@link #copyProperty} method above. The object copier will - * call this method whenever an item has been successfully published, - * in order to transfer services such as categorization or permissions - * to the live version. - *

    - * This method is requied to return false to signal the object copier - * to transfer default services from the source item; or true - * in order to abort further processing of services. + * Copy services from the source item. This method is the analogue of the {@link #copyProperty} + * method above. The object copier will call this method whenever an item + * has been successfully published, in order to transfer services such as + * categorization or permissions to the live version.

    This method is + * requied to return false to signal the object copier to transfer default + * services from the source item; or true in order to abort further + * processing of services. * - * @return true to tell the object copier to stop copying services for - * this item, false otherwise + * @return true to tell the object copier to stop copying services for this + * item, false otherwise */ public boolean copyServices(ContentItem srcItem) { return false; @@ -1985,8 +1979,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Get the locale for this content item. * - * @return The locale of the item - * @post return != null + * @return The locale of the item @post return != null */ public com.arsdigita.globalization.Locale getLocale() { Locale locale = null; @@ -2032,6 +2025,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { // /** * Assert that this item is a top-level master object + * * @deprecated with no replacement */ public final void assertMaster() { @@ -2078,9 +2072,9 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Remove any Links pointing to this item before deletion. - * XXX This should go away when one-way association targets can - * specify the equivalent of on delete set null + * Remove any Links pointing to this item before deletion. XXX This should + * go away when one-way association targets can specify the equivalent of on + * delete set null */ @Override protected void beforeDelete() { @@ -2112,11 +2106,12 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Overriding the Auditing interface in order to use the denormalized - * information + * Overriding the Auditing interface in order to use the denormalized + * information */ /** * Gets the user who created the object. May be null. + * * @return the user who created the object. */ @Override @@ -2126,6 +2121,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Gets the creation date of the object. + * * @return the creation date. */ @Override @@ -2134,8 +2130,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } /** - * Gets the IP address associated with creating an object. May be - * null. + * Gets the IP address associated with creating an object. May be null. + * * @return the creation IP address. */ @Override @@ -2145,6 +2141,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Gets the user who last modified the object. May be null. + * * @return the last modifying user. */ @Override @@ -2154,6 +2151,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Gets the last modified date. + * * @return the last modified date. */ @Override @@ -2163,35 +2161,48 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { /** * Gets the last modified IP address. May be null. + * * @return the IP address associated with the last modification. */ @Override public String getLastModifiedIP() { return m_audit_trail.getLastModifiedIP(); } - + /** - *

    - * Override this to explicit that your content items - * have extra XML to generate. An overriding implementation should call - * the super method, and append its generators to the list. Example: - *

    + *

    Override this to explicit that your content items have extra XML to + * generate. An overriding implementation should call the super method, and + * append its generators to the list. Example:

    *
          * {@code
          * @Override
          * public List getExtraXMLGenerators() {
    -     *   final List generators = 
    +     *   final List generators =
          *     super.getExtraXMLGenerators();
    -     *   
    +     *
          *   generators.add(new YourExtraXMLGenerator());
    -     * 
    +     *
          *   return generators;
          * }
          * }
    -     * 
    + * + * * @return A list of all extra XML Generators for this content item. */ public List getExtraXMLGenerators() { return new ArrayList(); } + + /** + *

    Override this method if your content items have extra XML for list + * views. You may return the same XML generators as in + * {@link #getExtraXMLGenerators()}. But beware: The page state passed to + * generators returned by this method will may be null.

    + * + * @return A list of all extra XML Generators for lists views of + * this content item. + */ + public List getExtraListXMLGenerators() { + return new ArrayList(); + } } diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitExtraXmlGenerator.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitExtraXmlGenerator.java index 854f571fc..d7fbab3bf 100644 --- a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitExtraXmlGenerator.java +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitExtraXmlGenerator.java @@ -17,23 +17,20 @@ import java.util.Map; import org.apache.log4j.Logger; /** - *

    - * Base class for {@link ExtraXMLGenerator}s for sub classes of - * {@link GenericOrganizationalUnit}. The only method which has to be + *

    Base class for {@link ExtraXMLGenerator}s for sub classes of + * {@link GenericOrganizationalUnit}. The only method which has to be * overwritten is {@link #getTabConfig()}. This method will return the tabs - * (instances of implementations of {@link GenericOrgaUnitTab}). The - * {@link #generateXML(com.arsdigita.cms.ContentItem, com.arsdigita.xml.Element, com.arsdigita.bebop.PageState)} - * method delegates the XML creation to this objects. - *

    - *

    - * {@link GenericOrganizationalUnit} does not include this generator. - * The subclasses of {@link GenericOrganizationalUnit} are responsible for - * integrating the subclasses of this class by overwriting the - * {@link ContentPage#getExtraXMLGenerators()}. - *

    - * - * @author Jens Pelzetter - * @version $Id$ + * (instances of implementations of {@link GenericOrgaUnitTab}). The + * {@link #generateXML(com.arsdigita.cms.ContentItem, com.arsdigita.xml.Element, com.arsdigita.bebop.PageState)} + * method delegates the XML creation to this objects.

    + * {@link GenericOrganizationalUnit} does not include this generator. The + * subclasses of {@link GenericOrganizationalUnit} are responsible for + * integrating the subclasses of this class by overwriting the + * {@link ContentPage#getExtraXMLGenerators()}.

    + * + * @author Jens Pelzetter + * @version $Id: GenericOrgaUnitExtraXmlGenerator.java 1186 2011-10-21 18:20:36Z + * jensp $ */ public abstract class GenericOrgaUnitExtraXmlGenerator implements ExtraXMLGenerator { @@ -62,7 +59,8 @@ public abstract class GenericOrgaUnitExtraXmlGenerator final GenericOrganizationalUnit orgaunit = (GenericOrganizationalUnit) item; final Map tabs = - processTabConfig(getTabConfig()); + processTabConfig( + getTabConfig()); String selected = state.getRequest().getParameter( SELECTED_TAB_PARAM); if (showOnly != null && !showOnly.isEmpty()) { @@ -73,7 +71,8 @@ public abstract class GenericOrgaUnitExtraXmlGenerator } final long availableStart = System.currentTimeMillis(); if ((showOnly == null) || showOnly.isEmpty()) { - for (Map.Entry entry : tabs.entrySet()) { + for (Map.Entry entry : + tabs.entrySet()) { if (entry.getValue().hasData(orgaunit)) { createAvailableTabElem(availableTabsElem, entry.getKey(), @@ -81,20 +80,25 @@ public abstract class GenericOrgaUnitExtraXmlGenerator } } } - logger.debug(String.format("Created available tabs XML for " - + "GenericOrganizationalUnit '%s' in %d ms.", - orgaunit.getName(), - System.currentTimeMillis() - availableStart)); + logger.debug(String.format( + "Created available tabs XML for " + + "GenericOrganizationalUnit '%s' in %d ms.", + orgaunit.getName(), + System.currentTimeMillis() + - availableStart)); - if (tabs.containsKey(selected) && tabs.get(selected).hasData(orgaunit)) { + if (tabs.containsKey(selected) && tabs.get(selected).hasData( + orgaunit)) { final GenericOrgaUnitTab selectedTab = tabs.get(selected); - final Element selectedTabElem = orgaUnitTabsElem.newChildElement( + final Element selectedTabElem = + orgaUnitTabsElem.newChildElement( "selectedTab"); selectedTab.generateXml(orgaunit, selectedTabElem, state); } else { orgaUnitTabsElem.newChildElement("selectedTabNotAvailable"); } + logger.debug(String.format("Generated XML for GenericOrganizationalUnit " + "'%s' in %d ms", orgaunit.getName(), @@ -102,10 +106,10 @@ public abstract class GenericOrgaUnitExtraXmlGenerator } /** - * Can be used from a JSP template for Navigation to show only a specific - * tab in category. - * - * @param showOnly + * Can be used from a JSP template for Navigation to show only a specific + * tab in category. + * + * @param showOnly */ public void setShowOnly(final String showOnly) { this.showOnly = showOnly; @@ -124,25 +128,16 @@ public abstract class GenericOrgaUnitExtraXmlGenerator } /** - *

    - * This method should return a string containing all tabs to use. The string - * must have to following format: - *

    - *

    + *

    This method should return a string containing all tabs to use. The + * string must have to following format:

    * * tabName:fullyQualifedClassName;... - * - *

    - *

    - * Example: - *

    - *

    + *

    Example:

    * * foo:com.arsdigita.cms.contenttypes.ui.FooTab;bar:com.arsdigita.cms.contenttypes.BarTab;fooBar:com.arsdigita.cms.contenttypes.ui.FooBarTab - * - *

    - * - * @return + *

    + * + * @return */ public abstract String getTabConfig(); diff --git a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java index 85f139e4f..669eed592 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleItemPane.java @@ -303,7 +303,7 @@ class ItemLifecycleItemPane extends BaseItemPane { newInstance(OID.valueOf(itemOid)); PublishLock.getInstance().lock(item); republish(item, false); - PublishLock.getInstance().unlock(item); + PublishLock.getInstance().unlock(item); } } } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java index 5c9578f21..e9b69c627 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java @@ -386,7 +386,7 @@ class ItemLifecycleSelectForm extends BaseForm { public void run() { PublishLock.getInstance().lock(item); publisher.publish(); - PublishLock.getInstance().unlock(item); + PublishLock.getInstance().unlock(item); } }; final Thread thread = new Thread(threadAction); @@ -529,9 +529,9 @@ class ItemLifecycleSelectForm extends BaseForm { * "com.arsdigita.cms.lifecycle.NotifyLifecycleListener"); * expirationImminentPhase.save(); } } * - * // Force the lifecycle scheduler to run to avoid any // scheduler - * delay for items that should be published // immediately. - * pending.getLifecycle().start(); + * // Force the lifecycle scheduler to run to avoid any // + * scheduler delay for items that should be published // + * immediately. pending.getLifecycle().start(); * * item.save(); * @@ -542,8 +542,7 @@ class ItemLifecycleSelectForm extends BaseForm { * active. if * (ContentSection.getConfig().getUseStreamlinedCreation()) { throw * new RedirectSignal(URL.there(state.getRequest(), - * Utilities.getWorkspaceURL()), true); - } + * Utilities.getWorkspaceURL()), true); } */ } } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/PublishLock.java b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/PublishLock.java index 6ff797a3e..899a0750a 100644 --- a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/PublishLock.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/PublishLock.java @@ -22,7 +22,7 @@ public class PublishLock { public final static String TIMESTAMP = "timestamp"; public final static String ACTION = "action"; public final static String ERROR = "error"; - private static PublishLock instance = new PublishLock(); + private static PublishLock instance = new PublishLock(); private PublishLock() { } @@ -57,7 +57,9 @@ public class PublishLock { if (!collection.isEmpty()) { collection.next(); final DataObject lock = collection.getDataObject(); - lock.delete(); + if (!(ERROR.equals(lock.get(ACTION)))) { + lock.delete(); + } } collection.close(); SessionManager.getSession().getTransactionContext().commitTxn(); @@ -94,7 +96,7 @@ public class PublishLock { collection.close(); SessionManager.getSession().getTransactionContext().commitTxn(); } - + protected synchronized boolean hasError(final ContentItem item) { final DataCollection collection = SessionManager.getSession().retrieve( LOCK_OBJECT_TYPE); @@ -105,7 +107,7 @@ public class PublishLock { return false; } else { collection.next(); - + final DataObject lock = collection.getDataObject(); if (ERROR.equals(lock.get(ACTION).toString())) { collection.close(); diff --git a/ccm-navigation/src/com/arsdigita/navigation/cms/CMSDataCollectionRenderer.java b/ccm-navigation/src/com/arsdigita/navigation/cms/CMSDataCollectionRenderer.java index ecedc1222..7b000afb7 100755 --- a/ccm-navigation/src/com/arsdigita/navigation/cms/CMSDataCollectionRenderer.java +++ b/ccm-navigation/src/com/arsdigita/navigation/cms/CMSDataCollectionRenderer.java @@ -19,6 +19,7 @@ package com.arsdigita.navigation.cms; import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentItemXMLRenderer; +import com.arsdigita.cms.ExtraXMLGenerator; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.kernel.ACSObject; import com.arsdigita.navigation.DataCollectionRenderer; @@ -29,10 +30,20 @@ import com.arsdigita.xml.Element; public class CMSDataCollectionRenderer extends DataCollectionRenderer { + private boolean useExtraXml = true; + public CMSDataCollectionRenderer() { addAttribute("masterVersion.id"); } + public boolean getUseExtraXml() { + return useExtraXml; + } + + public void setUseExtraXml(final boolean useExtraXml) { + this.useExtraXml = useExtraXml; + } + protected String getStableURL(DataObject dobj, ACSObject obj) { if (obj == null) { @@ -64,6 +75,15 @@ public class CMSDataCollectionRenderer extends DataCollectionRenderer { * using DataCollectionRenderer#setSpecializeObjectsContext(String). */ renderer.walk(obj, getSpecializeObjectsContext()); + + if ((obj instanceof ContentItem) && useExtraXml) { + final ContentItem contentItem = (ContentItem) obj; + + for(ExtraXMLGenerator generator : contentItem.getExtraListXMLGenerators()) { + generator.generateXML(contentItem, item, null); + } + + } } } }