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;
  }
}