ItemVisitor. *
* Level 1 and 2 * *TraversingItemVisitor
is an abstract utility class
* which allows to easily traverse an Item
hierarchy.
*
* TraversingItemVisitor
makes use of the Visitor Pattern
* as described in the book 'Design Patterns' by the Gang Of Four
* (Gamma et al.).
*
Tree traversal is done observing the left-to-right order of
* child Item
s if such an order is supported and exists.
*
* @author Markus Nix breadthFirst
is true then traversal
* is done in a breadth-first manner; otherwise it is done in a
* depth-first manner (which is the default behaviour).
*/
public function __construct( $breadthFirst = false, $maxLevel = -1 ) {
$this->breadthFirst = $breadthFirst;
if ( $this->breadthFirst === true ) {
$this->currentQueue = array();
$this->nextQueue = array();
}
$this->currentLevel = 0;
$this->maxLevel = $maxLevel;
}
/**
* Implement this method to add behaviour performed before a
* Property
or Node
is visited.
*
* @param entry that is accepting this visitor.
* @param level hierarchy level of this property (the root node starts at level 0)
* @throws RepositoryException if an error occurrs
*/
protected abstract function entering( $entry, $level );
/**
* Implement this method to add behaviour performed after a
* Property
is visited.
*
* @param entry the Property
that is accepting this visitor.
* @param level hierarchy level of this property (the root node starts at level 0)
* @throws RepositoryException if an error occurrs
*/
protected abstract function leaving( $entry, $level );
/**
* Called when the Visitor is passed to a Node
.
*
* It calls TraversingItemVisitor.entering(Node, int)
followed by
* TraversingItemVisitor.leaving(Node, int)
. Implement these abstract methods to
* specify behaviour on 'arrival at' and 'after leaving' the Node
.
*
* If this method throws, the visiting process is aborted.
*
* @param Either Node or Property that is accepting this visitor.
* @throws RepositoryException if an error occurrs
*/
public function visit( $entry ) {
if ( $entry instanceof Property ) {
$this->entering( $entry, $this->currentLevel );
$this->leaving( $entry, $this->currentLevel );
} else {
try {
if ( !$this->breadthFirst ) {
// depth-first traversal
$this->entering( $entry, $this->currentLevel );
if ( $this->maxLevel == -1 || $this->currentLevel < $this->maxLevel ) {
$this->currentLevel++;
$nodeIter = $entry->getNodes();
while ( $nodeIter->hasNext() ) {
$nodeIter->nextNode()->accept( $this );
}
$propIter = $entry->getProperties();
while ( $propIter->hasNext()) {
$propIter->nextProperty()->accept( $this );
}
$currentLevel--;
}
$this->leaving( $entry, $this->currentLevel );
} else {
// breadth-first traversal
$this->entering( $entry, $this->currentLevel );
$this->leaving( $entry, $this->currentLevel );
if ( $this->maxLevel == -1 || $this->currentLevel < $this->maxLevel ) {
$nodeIter = $entry->getNodes();
while ( $nodeIter->hasNext() ) {
$this->nextQueue[] = $nodeIter->nextNode();
}
$propIter = $entry->getProperties();
while ( $propIter->hasNext() ) {
$this->nextQueue[] = $propIter->nextProperty();
}
}
while ( !empty( $this->currentQueue ) || !empty( $this->nextQueue ) ) {
if ( empty( $this->currentQueue ) ) {
$this->currentLevel++;
$this->currentQueue = $this->nextQueue;
$this->nextQueue = array();
}
$this->currentQueue = array_shift( $this->currentQueue );
}
$this->currentLevel = 0;
}
} catch ( RepositoryException $re ) {
$this->currentLevel = 0;
throw $re;
}
}
}
}
?>