org.apache.camel.parser.helper.CamelJavaTreeParserHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-route-parser Show documentation
Show all versions of camel-route-parser Show documentation
Java and XML source code parser for Camel routes
/**
* 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.parser.helper;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.camel.catalog.CamelCatalog;
import org.apache.camel.catalog.DefaultCamelCatalog;
import org.apache.camel.catalog.JSonSchemaHelper;
import org.apache.camel.parser.model.CamelNodeDetails;
import org.apache.camel.parser.model.CamelNodeDetailsFactory;
import org.apache.camel.parser.roaster.StatementFieldSource;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.ASTNode;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.Block;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.BooleanLiteral;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.Expression;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.ExpressionStatement;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.FieldDeclaration;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.InfixExpression;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.MemberValuePair;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.MethodDeclaration;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.MethodInvocation;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.NormalAnnotation;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.NumberLiteral;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.QualifiedName;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.SimpleName;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.StringLiteral;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.Type;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.jboss.forge.roaster.model.Annotation;
import org.jboss.forge.roaster.model.source.FieldSource;
import org.jboss.forge.roaster.model.source.JavaClassSource;
import org.jboss.forge.roaster.model.source.MethodSource;
/**
* A Camel Java tree parser that only depends on the Roaster API.
*
* This implement is used for parsing the Camel routes and build a tree structure of the EIP nodes.
*
* @see CamelJavaParserHelper for parser that can discover endpoints and simple expressions
*/
public final class CamelJavaTreeParserHelper {
private final CamelCatalog camelCatalog = new DefaultCamelCatalog(true);
public List parseCamelRouteTree(JavaClassSource clazz, String baseDir, String fullyQualifiedFileName,
MethodSource configureMethod) {
// find any from which is the start of the route
CamelNodeDetailsFactory nodeFactory = CamelNodeDetailsFactory.newInstance();
CamelNodeDetails route = nodeFactory.newNode(null, "route");
if (configureMethod != null) {
MethodDeclaration md = (MethodDeclaration) configureMethod.getInternal();
Block block = md.getBody();
if (block != null) {
for (Object statement : md.getBody().statements()) {
// must be a method call expression
if (statement instanceof ExpressionStatement) {
ExpressionStatement es = (ExpressionStatement) statement;
Expression exp = es.getExpression();
boolean valid = isFromCamelRoute(exp);
if (valid) {
parseExpression(nodeFactory, fullyQualifiedFileName, clazz, configureMethod, block, exp, route);
}
}
}
}
}
List answer = new ArrayList<>();
if (route.getOutputs() == null || route.getOutputs().isEmpty()) {
// okay no routes found
return answer;
}
// now parse the route node and build the correct model/tree structure of the EIPs
// re-create factory as we rebuild the tree
nodeFactory = CamelNodeDetailsFactory.newInstance();
CamelNodeDetails parent = route.getOutputs().get(0);
for (int i = 0; i < route.getOutputs().size(); i++) {
CamelNodeDetails node = route.getOutputs().get(i);
String name = node.getName();
if ("from".equals(name)) {
CamelNodeDetails from = nodeFactory.copyNode(null, "from", node);
from.setFileName(fullyQualifiedFileName);
answer.add(from);
parent = from;
} else if ("routeId".equals(name)) {
// should be set on the parent
parent.setRouteId(node.getRouteId());
} else if ("end".equals(name) || "endParent".equals(name) || "endRest".equals(name)
|| "endDoTry".equals(name) || "endHystrix".equals(name)) {
// parent should be grand parent
if (parent.getParent() != null) {
parent = parent.getParent();
}
} else if ("endChoice".equals(name)) {
// we are in a choice block so parent should be the first choice up the parent tree
while (!"from".equals(parent.getName()) && !"choice".equals(parent.getName())) {
if (parent.getParent() != null) {
parent = parent.getParent();
} else {
break;
}
}
} else if ("choice".equals(name)) {
// special for some EIPs
CamelNodeDetails output = nodeFactory.copyNode(parent, name, node);
parent.addOutput(output);
parent = output;
} else if ("when".equals(name) || "otherwise".equals(name)) {
// we are in a choice block so parent should be the first choice up the parent tree
while (!"from".equals(parent.getName()) && !"choice".equals(parent.getName())) {
if (parent.getParent() != null) {
parent = parent.getParent();
} else {
break;
}
}
} else {
boolean hasOutput = hasOutput(name);
if (hasOutput) {
// has output so add as new child node
CamelNodeDetails output = nodeFactory.copyNode(parent, name, node);
parent.addOutput(output);
parent = output;
} else {
// add straight to itself
CamelNodeDetails output = nodeFactory.copyNode(parent, name, node);
parent.addOutput(output);
}
}
}
return answer;
}
private boolean isFromCamelRoute(Expression exp) {
String rootMethodName = null;
// find out if this is from a Camel route (eg from, route etc.)
Expression sub = exp;
while (sub instanceof MethodInvocation) {
sub = ((MethodInvocation) sub).getExpression();
if (sub instanceof MethodInvocation) {
Expression parent = ((MethodInvocation) sub).getExpression();
if (parent == null) {
break;
}
}
}
if (sub instanceof MethodInvocation) {
rootMethodName = ((MethodInvocation) sub).getName().getIdentifier();
} else if (sub instanceof SimpleName) {
rootMethodName = ((SimpleName) sub).getIdentifier();
}
// a route starts either via from or route
return "from".equals(rootMethodName) || "route".equals(rootMethodName);
}
private boolean hasOutput(String name) {
String json = camelCatalog.modelJSonSchema(name);
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy