Introduction

Authors
This is a joint document between Jean Francois (Jeff) Roche and Russ Ferriday. It stems from collaboration that started at the Plone Multimedia Sprint in September 2005, immediately after the Vienna Plone Conference. Jeff was porting his famous ZPhotoSlides Product to create ATPhoto and ATPhotoAlbum for Plone. Russ gave a little help but Jeff did the bulk of the work, with the help of Gawel and others, and made a great job of the ATPhoto package. Now we are working together again to move the features into ATContentTypes (ATCT) using Five, ready for the eventual move to Zope 3. We can offer a useful perspective because Jeff had some experience of the Five interfaces, and Russ was a newbie to Five at the start of this. We hope to share our learning with you.
Assumptions
- You have some background in Plone Product development.
- You know about object oriented programming.
- You have a basic knowledge of UML.
- You are interested and have some basic knowledge in the Zope 3 Component Architecture.
Our Goals
More and more people are speaking about the Zope 3 Component Architecture (CA). We are for the moment in a transition period where people have to mix the Zope 2 and the Zope 3 concepts. We understand that it's not that easy to change your way of thinking to the component architecture, as it comes with many (really beautiful, interesting and useful) new concepts. There isn't much documentation and usage of the Zope 3 CA in Zope 2, so we will try here to make our contribution in the hope of helping your progress towards Zope 3.
If you consider that Zope 3 CA is a nice way to code/think when you have read this document then we will have reached our goal.
The pattern we are going to implement
We have been working on moving over to Five ATPhoto's Zip feature, which can archive a tree of objects to a Zip file. We had completed and tested a generic Archiver. And had even merged it into the ATContentTypes tree. But while documenting what we had done, we realized that we had missed an opportunity to decompose our design into more useful and reusable components. So we took a close look and decided to split out a general purpose iteration mechanism that can be used for traversing and operating on a wide variety of objects or object trees. This has delayed our original task a bit, but we think the learning value and reuse aspect were worth it. This tutorial describes what we have made. Beyond the tutorial value, you might find this a useful tool for your own projects. It will become part of ATContentTypes in Plone 2.5
Separation of concerns, testability, and easy maintenance are important factors in design. But we also wanted people to use our work, and that means being able to understand it, too! So we came up with three easy to define classes that implement our concept.
- An Operator that knows how to operate on nodes in a tree
- A Filter that knows how to filter items in a tree so that we only look at items that are interesting for our purpose
- A TreeWalker, that knows how to visit nodes in a tree, given a starting point, an Operator, and optionally a Filter.
The behaviour of the TreeWalker might never need to be changed, but the whole idea of the Operator and Filter is that they will be overridden by new classes, to achieve new functionality. So we introduce the concept of Interfaces. Interfaces are part of python. But in "plain" python they do not have the same power that they do in Java, C++, Delphi and other languages. Five and Zope 3 change all that with the interfaces package, which adds rigor to the definition and use of interfaces, and also enables the adapter concept. We needed to define interfaces for Filter and Operator, as you will see later. Though we did not need it, we also made an interface for TreeWalker to provide rigor now and more flexibility later.
In the UML diagram below, you can see the following interfaces:
- ITreeWalker
- IOperator
- IFilter
They define the interface contracts for the classes that implement them.
ITreeWalker is implemented in TreeWalker. And this is the same TreeWalker you will instantiate to do your recursive task.
IOperator is provided only as an interface. You will make an implementation of it to do your task. Just for example, we have shown the ArchivingOperator created for the Archiver for which we made the TreeWalker. You can provide any Operator you like to replace ArchivingOperator.
IFilterFolder is an Interface which you can re-implement as you wish, if you want to process only certain types while traversing the tree. We provide a default implementation called FolderFilter that might be all you ever need. FolderFilter, looks at all folders and items in those folders. We'll talk more about Filtering actions later.

The UML gives a very general overview of what we have done. The "Using Treewalker" section shows you how to use it, and later we get deeper to the implementation.

