/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 com.google.template.soy.basetree;
import java.util.ArrayList;
import java.util.List;
/**
* Base class for {@code AbstractXxxNodeVisitor} classes.
*
* <p>Same as {@link AbstractReturningNodeVisitor} except that in this class, internal {@code
* visit()} calls do not return a value.
*
* <p>Important: Do not use outside of Soy code (treat as superpackage-private).
*
* @param <N> A more specific subinterface of Node, or just Node if not applicable.
* @param <R> The return type of this visitor.
* @see AbstractReturningNodeVisitor
*/
public abstract class AbstractNodeVisitor<N extends Node, R> implements NodeVisitor<N, R> {
@Override
public R exec(N node) {
visit(node);
return null;
}
/**
* Visits the given node to execute the function defined by this visitor.
*
* @param node The node to visit.
*/
protected abstract void visit(N node);
/**
* Helper to visit all the children of a node, in order.
*
* @param node The parent node whose children to visit.
* @see #visitChildrenAllowingConcurrentModification
*/
protected void visitChildren(ParentNode<? extends N> node) {
visitAll(node.getChildren());
}
/**
* Helper to visit all the children of a node, in order.
*
* <p>This method differs from {@code visitChildren} in that we are iterating through a copy of
* the children. Thus, concurrent modification of the list of children is allowed.
*
* @param node The parent node whose children to visit.
* @see #visitChildren
*/
protected void visitChildrenAllowingConcurrentModification(ParentNode<? extends N> node) {
// TODO(lukes): consider using CopyOnWriteArrayList for .getChildre and we could avoid this
// or possibly introduce dedicated tree mutation apis to allow us to apply mutations after
// iteration
visitAll(new ArrayList<>(node.getChildren()));
}
private void visitAll(List<? extends N> children) {
int size = children.size();
for (int i = 0; i < size; i++) {
visit(children.get(i));
}
}
}