A Complex Decorator Example
In order to understand the point of this example, you need to know what collection content items are.
A collection content item is a content type (defined in the
content-type
resource) that has one or more
relations, but no ordinary fields. It is not intended for display in a
publication, but is created for internal use by editorial staff as a
container for relations. Imagine, for example a group of background
articles on a particular subject that all need to be added as related
content items to any new article written on the same subject. Instead
of requiring editorial staff to individually add each related content
item, a manager can create a collection content item and add all the
related content items to this one content item. Editorial staff can
then add all the relations in one go by simply adding the collection
content item to their new content items.
The catch, of course, is that the template programmer must then "unpack" these collection content items, converting the single related collection content item back into a series of ordinary related content items in order to display them properly. This could be done using custom tags or in-line Java, but this example shows how it can be done using a decorator class.
package com.mycompany.decorators; import neo.xredsys.presentation.*; import java.util.*; public class UnpackCollectionArticles extends PresentationArticleDecorator { /* to hold the names of all "collection" content types */ private Set articleTypeNames; public UnpackCollectionArticles(PresentationArticle pa) { super(pa); articleTypeNames = new HashSet(); /* add the content type names (only one in this case) */ articleTypeNames.add("collection"); } public List getArticles() { /* get all of this article's related articles */ List relatedArticles = new ArrayList(super.getArticles()); /* get this article's related collection articles WHY IS THIS DIFFERENT */ List collectionArticles = super.getArticles(articleTypeNames); /* remove the collection articles from the list of related articles */ relatedArticles.removeAll(collectionArticles); /* for each related collection article... */ Iterator i = collectionArticles.iterator(); while(i.hasNext()) { PresentationArticle a = (PresentationArticle)i.next(); /* ...add all the collection article's related articles to THIS article's related articles list */ relatedArticles.addAll(a.getArticles()); } return relatedArticles; }
You can use a single decorator class to modify more than one
method. It might be the case, for example, that your collection
content items are used to hold lists of related images as well as
lists of related content items. In this case you would want to
override the getImages()
method as well as
getArticles()
:
public List getImages() { List relatedImages = new ArrayList(super.getImages()); List collectionArticles=super.getArticles(articleTypeNames); Iterator i = collectionArticles.iterator(); while(i.hasNext()) { PresentationArticle a = (PresentationArticle)i.next(); relatedImages.addAll(a.getImages()); } return relatedImages; } }