org.camunda.bpm.engine.impl.tree.ReferenceWalker Maven / Gradle / Ivy
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.camunda.bpm.engine.impl.tree;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* A walker for walking through an object reference structure (e.g. an execution tree).
* Any visited element can have any number of following elements. The elements are visited
* with a breadth-first approach: The walker maintains a list of next elements to which it adds
* a new elements at the end whenever it has visited an element. The walker stops when it encounters
* an element that fulfills the given {@link WalkCondition}.
*
*
Subclasses define the type of objects and provide the walking behavior.
*
* @author Thorben Lindhauer
*/
public abstract class ReferenceWalker {
protected List currentElements;
protected List> preVisitor = new ArrayList>();
protected List> postVisitor = new ArrayList>();
protected abstract Collection nextElements();
public ReferenceWalker(T initialElement) {
currentElements = new LinkedList();
currentElements.add(initialElement);
}
public ReferenceWalker(List initialElements) {
currentElements = new LinkedList(initialElements);
}
public ReferenceWalker addPreVisitor(TreeVisitor collector) {
this.preVisitor.add(collector);
return this;
}
public ReferenceWalker addPostVisitor(TreeVisitor collector) {
this.postVisitor.add(collector);
return this;
}
public T walkWhile() {
return walkWhile(new ReferenceWalker.NullCondition());
}
public T walkUntil() {
return walkUntil(new ReferenceWalker.NullCondition());
}
public T walkWhile(ReferenceWalker.WalkCondition condition) {
while (!condition.isFulfilled(getCurrentElement())) {
for (TreeVisitor collector : preVisitor) {
collector.visit(getCurrentElement());
}
currentElements.addAll(nextElements());
currentElements.remove(0);
for (TreeVisitor collector : postVisitor) {
collector.visit(getCurrentElement());
}
}
return getCurrentElement();
}
public T walkUntil(ReferenceWalker.WalkCondition condition) {
do {
for (TreeVisitor collector : preVisitor) {
collector.visit(getCurrentElement());
}
currentElements.addAll(nextElements());
currentElements.remove(0);
for (TreeVisitor collector : postVisitor) {
collector.visit(getCurrentElement());
}
} while (!condition.isFulfilled(getCurrentElement()));
return getCurrentElement();
}
public T getCurrentElement() {
return currentElements.isEmpty() ? null : currentElements.get(0);
}
public interface WalkCondition {
boolean isFulfilled(S element);
}
public static class NullCondition implements ReferenceWalker.WalkCondition {
public boolean isFulfilled(S element) {
return element == null;
}
public static ReferenceWalker.WalkCondition notNull() {
return new NullCondition();
}
}
}