blob: a628ac0a01a0a5866225936dcaed2666a5c34206 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.camel.model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Helper class for ProcessorDefinition and the other model classes.
*/
public final class ProcessorDefinitionHelper {
private ProcessorDefinitionHelper() {
}
/**
* Looks for the given type in the list of outputs and recurring all the children as well.
*
* @param outputs list of outputs, can be null or empty.
* @param type the type to look for
* @return the found definitions, or <tt>null</tt> if not found
*/
public static <T> Iterator<T> filterTypeInOutputs(List<ProcessorDefinition> outputs, Class<T> type) {
List<T> found = new ArrayList<T>();
doFindType(outputs, type, found);
return found.iterator();
}
/**
* Looks for the given type in the list of outputs and recurring all the children as well.
* Will stop at first found and return it.
*
* @param outputs list of outputs, can be null or empty.
* @param type the type to look for
* @return the first found type, or <tt>null</tt> if not found
*/
public static <T> T findFirstTypeInOutputs(List<ProcessorDefinition> outputs, Class<T> type) {
List<T> found = new ArrayList<T>();
doFindType(outputs, type, found);
if (found.isEmpty()) {
return null;
}
return found.iterator().next();
}
/**
* Is the given child the first in the outputs from the parent?
*
* @param parentType the type the parent must be
* @param node the node
* @return <tt>true</tt> if first child, <tt>false</tt> otherwise
*/
public static boolean isFirstChildOfType(Class<?> parentType, ProcessorDefinition<?> node) {
if (node == null || node.getParent() == null) {
return false;
}
if (node.getParent().getOutputs().isEmpty()) {
return false;
}
if (!(node.getParent().getClass().equals(parentType))) {
return false;
}
return node.getParent().getOutputs().get(0).equals(node);
}
/**
* Is the given node parent(s) of the given type
* @param parentType the parent type
* @param node the current node
* @param recursive whether or not to check grand parent(s) as well
* @return <tt>true</tt> if parent(s) is of given type, <tt>false</tt> otherwise
*/
public static boolean isParentOfType(Class<?> parentType, ProcessorDefinition<?> node, boolean recursive) {
if (node == null || node.getParent() == null) {
return false;
}
if (parentType.isAssignableFrom(node.getParent().getClass())) {
return true;
} else if (recursive) {
// recursive up the tree of parents
return isParentOfType(parentType, node.getParent(), true);
} else {
// no match
return false;
}
}
/**
* Gets the route definition the given node belongs to.
*
* @param node the node
* @return the route, or <tt>null</tt> if not possible to find
*/
public static RouteDefinition getRoute(ProcessorDefinition<?> node) {
if (node == null) {
return null;
}
ProcessorDefinition def = node;
// drill to the top
while (def != null && def.getParent() != null) {
def = def.getParent();
}
if (def instanceof RouteDefinition) {
return (RouteDefinition) def;
} else {
// not found
return null;
}
}
@SuppressWarnings("unchecked")
private static <T> void doFindType(List<ProcessorDefinition> outputs, Class<T> type, List<T> found) {
if (outputs == null || outputs.isEmpty()) {
return;
}
for (ProcessorDefinition out : outputs) {
if (type.isInstance(out)) {
found.add((T)out);
}
// send is much common
if (out instanceof SendDefinition) {
SendDefinition send = (SendDefinition) out;
List<ProcessorDefinition> children = send.getOutputs();
doFindType(children, type, found);
}
// special for choice
if (out instanceof ChoiceDefinition) {
ChoiceDefinition choice = (ChoiceDefinition) out;
for (WhenDefinition when : choice.getWhenClauses()) {
List<ProcessorDefinition> children = when.getOutputs();
doFindType(children, type, found);
}
// otherwise is optional
if (choice.getOtherwise() != null) {
List<ProcessorDefinition> children = choice.getOtherwise().getOutputs();
doFindType(children, type, found);
}
}
// try children as well
List<ProcessorDefinition> children = out.getOutputs();
doFindType(children, type, found);
}
}
/**
* Is there any outputs in the given list.
* <p/>
* Is used for check if the route output has any real outputs (non abstracts)
*
* @param outputs the outputs
* @param excludeAbstract whether or not to exclude abstract outputs (e.g. skip onException etc.)
* @return <tt>true</tt> if has outputs, otherwise <tt>false</tt> is returned
*/
@SuppressWarnings("unchecked")
public static boolean hasOutputs(List<ProcessorDefinition> outputs, boolean excludeAbstract) {
if (outputs == null || outputs.isEmpty()) {
return false;
}
if (!excludeAbstract) {
return !outputs.isEmpty();
}
for (ProcessorDefinition output : outputs) {
if (output instanceof TransactedDefinition || output instanceof PolicyDefinition) {
// special for those as they wrap entire output, so we should just check its output
return hasOutputs(output.getOutputs(), excludeAbstract);
}
if (!output.isAbstract()) {
return true;
}
}
return false;
}
}