1package com.github.javaparser.generator.core.node; 2 3import com.github.javaparser.ast.CompilationUnit; 4import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 5import com.github.javaparser.ast.body.MethodDeclaration; 6import com.github.javaparser.generator.NodeGenerator; 7import com.github.javaparser.metamodel.BaseNodeMetaModel; 8import com.github.javaparser.metamodel.JavaParserMetaModel; 9import com.github.javaparser.utils.Pair; 10import com.github.javaparser.utils.SourceRoot; 11 12import java.util.Optional; 13import java.util.Set; 14import java.util.function.Consumer; 15 16import static com.github.javaparser.JavaParser.parseBodyDeclaration; 17import static com.github.javaparser.utils.CodeGenerationUtils.f; 18import static com.github.javaparser.utils.Utils.set; 19 20public class TypeCastingGenerator extends NodeGenerator { 21 private final Set<BaseNodeMetaModel> baseNodes = set( 22 JavaParserMetaModel.statementMetaModel, 23 JavaParserMetaModel.expressionMetaModel, 24 JavaParserMetaModel.typeMetaModel, 25 JavaParserMetaModel.moduleStmtMetaModel, 26 JavaParserMetaModel.bodyDeclarationMetaModel, 27 JavaParserMetaModel.commentMetaModel 28 ); 29 30 public TypeCastingGenerator(SourceRoot sourceRoot) { 31 super(sourceRoot); 32 } 33 34 @Override 35 protected void generateNode(BaseNodeMetaModel nodeMetaModel, CompilationUnit nodeCu, ClassOrInterfaceDeclaration nodeCoid) throws Exception { 36 Pair<CompilationUnit, ClassOrInterfaceDeclaration> baseCode = null; 37 for (BaseNodeMetaModel baseNode : baseNodes) { 38 if(nodeMetaModel == baseNode) { 39 // We adjust the base models from the child nodes, 40 // so we don't do anything when we *are* the base model. 41 return; 42 } 43 if (nodeMetaModel.isInstanceOfMetaModel(baseNode)) { 44 baseCode = parseNode(baseNode); 45 } 46 } 47 48 if (baseCode == null) { 49 // Node is not a child of one of the base nodes, so we don't want to generate this method for it. 50 return; 51 } 52 53 final String typeName = nodeMetaModel.getTypeName(); 54 final ClassOrInterfaceDeclaration baseCoid = baseCode.b; 55 final CompilationUnit baseCu = baseCode.a; 56 57 generateIsType(baseCu, nodeCoid, baseCoid, typeName); 58 generateAsType(baseCu, nodeCoid, baseCoid, typeName); 59 generateToType(nodeCu, baseCu, nodeCoid, baseCoid, typeName); 60 generateIfType(nodeCu, baseCu, nodeCoid, baseCoid, typeName); 61 } 62 63 private void generateAsType(CompilationUnit baseCu, ClassOrInterfaceDeclaration nodeCoid, ClassOrInterfaceDeclaration baseCoid, String typeName) { 64 final MethodDeclaration asTypeBaseMethod = (MethodDeclaration) parseBodyDeclaration(f("public %s as%s() { throw new IllegalStateException(f(\"%%s is not an %s\", this)); }", typeName, typeName, typeName)); 65 final MethodDeclaration asTypeNodeMethod = (MethodDeclaration) parseBodyDeclaration(f("@Override public %s as%s() { return this; }", typeName, typeName)); 66 addOrReplaceWhenSameSignature(baseCoid, asTypeBaseMethod); 67 addOrReplaceWhenSameSignature(nodeCoid, asTypeNodeMethod); 68 baseCu.addImport("com.github.javaparser.utils.CodeGenerationUtils.f", true, false); 69 } 70 71 private void generateToType(CompilationUnit nodeCu, CompilationUnit baseCu, ClassOrInterfaceDeclaration nodeCoid, ClassOrInterfaceDeclaration baseCoid, String typeName) { 72 baseCu.addImport(Optional.class); 73 nodeCu.addImport(Optional.class); 74 final MethodDeclaration asTypeBaseMethod = (MethodDeclaration) parseBodyDeclaration(f("public Optional<%s> to%s() { return Optional.empty(); }", typeName, typeName, typeName)); 75 final MethodDeclaration asTypeNodeMethod = (MethodDeclaration) parseBodyDeclaration(f("@Override public Optional<%s> to%s() { return Optional.of(this); }", typeName, typeName)); 76 addOrReplaceWhenSameSignature(baseCoid, asTypeBaseMethod); 77 addOrReplaceWhenSameSignature(nodeCoid, asTypeNodeMethod); 78 } 79 80 private void generateIfType(CompilationUnit nodeCu, CompilationUnit baseCu, ClassOrInterfaceDeclaration nodeCoid, ClassOrInterfaceDeclaration baseCoid, String typeName) { 81 final MethodDeclaration ifTypeBaseMethod = (MethodDeclaration) parseBodyDeclaration(f("public void if%s(Consumer<%s> action) { }", typeName, typeName)); 82 final MethodDeclaration ifTypeNodeMethod = (MethodDeclaration) parseBodyDeclaration(f("public void if%s(Consumer<%s> action) { action.accept(this); }", typeName, typeName)); 83 addOrReplaceWhenSameSignature(baseCoid, ifTypeBaseMethod); 84 addOrReplaceWhenSameSignature(nodeCoid, ifTypeNodeMethod); 85 86 baseCu.addImport(Consumer.class); 87 nodeCu.addImport(Consumer.class); 88 } 89 90 private void generateIsType(CompilationUnit baseCu, ClassOrInterfaceDeclaration nodeCoid, ClassOrInterfaceDeclaration baseCoid, String typeName) { 91 final MethodDeclaration baseIsTypeMethod = (MethodDeclaration) parseBodyDeclaration(f("public boolean is%s() { return false; }", typeName)); 92 final MethodDeclaration overriddenIsTypeMethod = (MethodDeclaration) parseBodyDeclaration(f("@Override public boolean is%s() { return true; }", typeName)); 93 94 addOrReplaceWhenSameSignature(nodeCoid, overriddenIsTypeMethod); 95 addOrReplaceWhenSameSignature(baseCoid, baseIsTypeMethod); 96 } 97} 98