These tutorials build upon the discussion in Chapter 4 WAF Component: Services.
This section presents an overview of using the categorization layer within WAF. The focus in this section is on describing the main concepts, classes, and interfaces that a programmer uses to work with the categorization API.
This section partially overlaps with and elaborates on the material presented in http://rhea.redhat.com/documentation/api/ccm-core-6.1.0/com/arsdigita/categorization/package-summary.html.
A category is a class of objects or things that share something in common within a conceptual scheme. It has a short name and an optional description. Each category also has a unique identity. Two distinct categories may happen to have the same name. They are treated as two different categories, if their identities are different. This abstraction is represented by the Category class.
There are two kinds of things that can be placed in a category. Firstly, a category may contain other categories within it. Such categories are called subcategories or child categories. The enclosing category is referred to as the parent category. Category Y is said to be a descendant of category X if either Y is a child of X, or the parent of Y is a descendant of X. If Y is a descendant of X, then X is called an ancestor category or ascendant category of X.
Secondly, a category may contain objects other than categories. In our system, a category may contain any ACSObject. Note that the Category class is itself an ACSObject, but one that has a special status in the categorization service. If ACSObject A is placed into category X, then we say that A is a child object of X and X is a parent category of A. We say that object B is a descendant object of category X, if either B is a child object of X, or the parent category of B is a descendant of X.
Let us first concentrate on the category-subcategory relationship. A category cannot contain two identically named subcategories.
We also require that there be no cycles. In other words, A must not be its own descendant. As an edge case of this general rule, A cannot contain itself as a subcategory.
A category may have more than one parent. By allowing this, we make possible categorization schemes that do not look like trees (see below). This complicates matters slightly, insofar as trees are easier to deal with than the more general structure known as directed acyclic graphs. To restore the ability to treat categorization schemes as trees, we allow some category-subcategory links to be marked as "default". We require that each category have no more than one default parent. A default parent is also sometimes referred to as a primary parent. Non-default parents are called secondary parents.
A category with no parents is called a root category. This category and its descendants are referred to as a category scheme. By disregarding non-default parent-child links, we can obtain a subset of the categorization scheme that forms a proper rooted tree. The following diagram shows a simple categorization scheme.
In the above diagram, the default parent of Televised Events is TV Shows. Its secondary parent is Sports. Once we have a categorization scheme, we can start categorizing objects.
The following diagram shows three objects placed in the above categorization scheme.
Note that an object can be categorized under more than one category. In the above example, the movie The Natural belongs to two categories.
It is possible to have two or more separate categorization schemes within the same application. Suppose the Legal and Marketing departments each need their own independent categorization scheme. This is supported through the notion of categorization contexts. Each categorization scheme is uniquely identified by its root category. Each root category is tied to an application that owns it. An application may own more than one category root. Each association may be labeled with a unique string, called a context.
In the above example, the application name is Content Section. It has two categorization schemes identified by the contexts legal and marketing, respectively.
To use the categorization layer, you should become familiar with the following classes.
A Category encapsulates a persistent category object. This object contains the name and description for the category, as well as information about whether the category is enabled. It also provides an API for placing objects within this category, creating subcategories under the instance category, and retrieving parent and child categories and objects.
This class has several notable methods that you should understand before beginning work with categorization. The URLs have been line broken with a "\" for printing purposes:
addChild(ACSObject acsObject) is used to create subcategories under the instance Category and to categorize objects within the instance Category.
addRelatedCategory(Category category) is used to specify a related category, that is, a category that is not necessarily a parent or a child, but is related in nature.
removeChild(ACSObject object) is used to delete a mapping with a child.
getChildren() returns all subcategories for the given category. See CategoryCollection.
getObjects() returns all objects categorized within the instance Category.
A collection of categories, e.g. children of the same parent category.
A collection of (non-category) objects, e.g. child objects of a category.
A convenience wrapper for working with the leaf nodes of a category scheme. Methods within CategorizedObject can be used to retrieve the parent categories or default ancestors of the object.
These classes work together to provide access to a Bebop Tree that can be used to display the category tree:
com.arsdigita.categorization.CategoryTreeModelLite — http://rhea.redhat.com/documentation/api/ccm-core-6.1.0/com/arsdigita/categorization/CategoryTreeModelLite.html
com.arsdigita.categorization.CategoryTreeNodeLite — http://rhea.redhat.com/documentation/api/ccm-core-6.1.0/com/arsdigita/categorization/CategoryTreeNodeLite.html
These classes are not of much importance to you unless you want to change the way the tree appears. Displaying a category hierarchy is a multiple-step process. First, create a TreeModelBuilder that will instantiate a CategoryTreeModelLite (based either on a query or some other external data source). This TreeModelBuilder is passed to the Tree, which uses your builder to create its TreeModel. This process is necessary since a DataObject cannot be used across connections.