1 package com.github.javaparser.ast.nodeTypes; 2 3 import static com.github.javaparser.ast.type.VoidType.VOID_TYPE; 4 import static java.util.Collections.unmodifiableList; 5 import static java.util.stream.Collectors.toCollection; 6 import static java.util.stream.Collectors.toList; 7 import static java.util.stream.Collectors.toSet; 8 9 import java.util.Arrays; 10 import java.util.EnumSet; 11 import java.util.List; 12 import java.util.stream.Stream; 13 14 import com.github.javaparser.ast.Modifier; 15 import com.github.javaparser.ast.Node; 16 import com.github.javaparser.ast.body.BodyDeclaration; 17 import com.github.javaparser.ast.body.ConstructorDeclaration; 18 import com.github.javaparser.ast.body.FieldDeclaration; 19 import com.github.javaparser.ast.body.InitializerDeclaration; 20 import com.github.javaparser.ast.body.MethodDeclaration; 21 import com.github.javaparser.ast.body.TypeDeclaration; 22 import com.github.javaparser.ast.body.VariableDeclarator; 23 import com.github.javaparser.ast.body.VariableDeclaratorId; 24 import com.github.javaparser.ast.stmt.BlockStmt; 25 import com.github.javaparser.ast.type.ClassOrInterfaceType; 26 import com.github.javaparser.ast.type.Type; 27 28 /** 29 * A node having members. 30 * 31 * The main reason for this interface is to permit users to manipulate homogeneously all nodes with a getMembers 32 * method. 33 * 34 */ 35 public interface NodeWithMembers<T> { 36 List<BodyDeclaration<?>> getMembers(); 37 38 T setMembers(List<BodyDeclaration<?>> members); 39 40 /** 41 * Add a field to this and automatically add the import of the type if needed 42 * 43 * @param typeClass the type of the field 44 * @param name the name of the field 45 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 46 * @return the {@link FieldDeclaration} created 47 */ 48 default FieldDeclaration addField(Class<?> typeClass, String name, Modifier... modifiers) { 49 ((Node) this).tryAddImportToParentCompilationUnit(typeClass); 50 return addField(typeClass.getSimpleName(), name, modifiers); 51 } 52 53 /** 54 * Add a field to this 55 * 56 * @param type the type of the field 57 * @param name the name of the field 58 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 59 * @return the {@link FieldDeclaration} created 60 */ 61 default FieldDeclaration addField(String type, String name, Modifier... modifiers) { 62 return addField(new ClassOrInterfaceType(type), name, modifiers); 63 } 64 65 /** 66 * Add a field to this 67 * 68 * @param type the type of the field 69 * @param name the name of the field 70 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 71 * @return the {@link FieldDeclaration} created 72 */ 73 default FieldDeclaration addField(Type<?> type, String name, Modifier... modifiers) { 74 FieldDeclaration fieldDeclaration = new FieldDeclaration(); 75 fieldDeclaration.setParentNode((Node) this); 76 VariableDeclarator variable = new VariableDeclarator(new VariableDeclaratorId(name)); 77 fieldDeclaration.getVariables().add(variable); 78 variable.setParentNode(fieldDeclaration); 79 fieldDeclaration.setModifiers(Arrays.stream(modifiers) 80 .collect(toCollection(() -> EnumSet.noneOf(Modifier.class)))); 81 variable.setType(type); 82 getMembers().add(fieldDeclaration); 83 return fieldDeclaration; 84 } 85 86 /** 87 * Add a private field to this 88 * 89 * @param typeClass the type of the field 90 * @param name the name of the field 91 * @return the {@link FieldDeclaration} created 92 */ 93 default FieldDeclaration addPrivateField(Class<?> typeClass, String name) { 94 return addField(typeClass, name, Modifier.PRIVATE); 95 } 96 97 /** 98 * Add a private field to this and automatically add the import of the type if 99 * needed 100 * 101 * @param type the type of the field 102 * @param name the name of the field 103 * @return the {@link FieldDeclaration} created 104 */ 105 default FieldDeclaration addPrivateField(String type, String name) { 106 return addField(type, name, Modifier.PRIVATE); 107 } 108 109 /** 110 * Add a public field to this 111 * 112 * @param typeClass the type of the field 113 * @param name the name of the field 114 * @return the {@link FieldDeclaration} created 115 */ 116 default FieldDeclaration addPublicField(Class<?> typeClass, String name) { 117 return addField(typeClass, name, Modifier.PUBLIC); 118 } 119 120 /** 121 * Add a public field to this and automatically add the import of the type if 122 * needed 123 * 124 * @param type the type of the field 125 * @param name the name of the field 126 * @return the {@link FieldDeclaration} created 127 */ 128 default FieldDeclaration addPublicField(String type, String name) { 129 return addField(type, name, Modifier.PUBLIC); 130 } 131 132 /** 133 * Add a protected field to this 134 * 135 * @param typeClass the type of the field 136 * @param name the name of the field 137 * @return the {@link FieldDeclaration} created 138 */ 139 default FieldDeclaration addProtectedField(Class<?> typeClass, String name) { 140 return addField(typeClass, name, Modifier.PROTECTED); 141 } 142 143 /** 144 * Add a protected field to this and automatically add the import of the type 145 * if needed 146 * 147 * @param type the type of the field 148 * @param name the name of the field 149 * @return the {@link FieldDeclaration} created 150 */ 151 default FieldDeclaration addProtectedField(String type, String name) { 152 return addField(type, name, Modifier.PROTECTED); 153 } 154 155 /** 156 * Adds a methods with void return by default to this 157 * 158 * @param methodName the method name 159 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 160 * @return the {@link MethodDeclaration} created 161 */ 162 default MethodDeclaration addMethod(String methodName, Modifier... modifiers) { 163 MethodDeclaration methodDeclaration = new MethodDeclaration(); 164 methodDeclaration.setName(methodName); 165 methodDeclaration.setType(VOID_TYPE); 166 methodDeclaration.setModifiers(Arrays.stream(modifiers) 167 .collect(toCollection(() -> EnumSet.noneOf(Modifier.class)))); 168 getMembers().add(methodDeclaration); 169 methodDeclaration.setParentNode((Node) this); 170 return methodDeclaration; 171 } 172 173 /** 174 * Adds a constructor to this 175 * 176 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 177 * @return the {@link MethodDeclaration} created 178 */ 179 default ConstructorDeclaration addCtor(Modifier... modifiers) { 180 ConstructorDeclaration constructorDeclaration = new ConstructorDeclaration(); 181 constructorDeclaration.setModifiers(Arrays.stream(modifiers) 182 .collect(toCollection(() -> EnumSet.noneOf(Modifier.class)))); 183 constructorDeclaration.setName(((TypeDeclaration<?>) this).getName()); 184 getMembers().add(constructorDeclaration); 185 constructorDeclaration.setParentNode((Node) this); 186 return constructorDeclaration; 187 } 188 189 default BlockStmt addInitializer() { 190 BlockStmt block = new BlockStmt(); 191 InitializerDeclaration initializerDeclaration = new InitializerDeclaration(false, block); 192 getMembers().add(initializerDeclaration); 193 initializerDeclaration.setParentNode((Node) this); 194 return block; 195 } 196 197 default BlockStmt addStaticInitializer() { 198 BlockStmt block = new BlockStmt(); 199 InitializerDeclaration initializerDeclaration = new InitializerDeclaration(true, block); 200 getMembers().add(initializerDeclaration); 201 initializerDeclaration.setParentNode((Node) this); 202 return block; 203 } 204 205 /** 206 * Try to find a {@link MethodDeclaration} by its name 207 * 208 * @param name the name of the method 209 * @return the methods found (multiple in case of polymorphism) 210 */ 211 default List<MethodDeclaration> getMethodsByName(String name) { 212 return getMembers().stream() 213 .filter(m -> m instanceof MethodDeclaration && ((MethodDeclaration) m).getName().equals(name)) 214 .map(m -> (MethodDeclaration) m).collect(toList()); 215 } 216 217 /** 218 * Find all methods in the members of this node. 219 * 220 * @return the methods found. This list is immutable. 221 */ 222 default List<MethodDeclaration> getMethods() { 223 return unmodifiableList(getMembers().stream() 224 .filter(m -> m instanceof MethodDeclaration) 225 .map(m -> (MethodDeclaration) m) 226 .collect(toList())); 227 } 228 229 /** 230 * Try to find a {@link MethodDeclaration} by its parameters types 231 * 232 * @param paramTypes the types of parameters like "Map<Integer,String>","int" to match<br> 233 * void foo(Map<Integer,String> myMap,int number) 234 * @return the methods found (multiple in case of polymorphism) 235 */ 236 default List<MethodDeclaration> getMethodsByParameterTypes(String... paramTypes) { 237 return getMembers().stream() 238 .filter(m -> m instanceof MethodDeclaration 239 && ((MethodDeclaration) m).getParameters().stream().map(p -> p.getType().toString()) 240 .collect(toSet()).equals(Stream.of(paramTypes).collect(toSet()))) 241 .map(m -> (MethodDeclaration) m).collect(toList()); 242 } 243 244 /** 245 * Try to find a {@link MethodDeclaration} by its parameters types 246 * 247 * @param paramTypes the types of parameters like "Map<Integer,String>","int" to match<br> 248 * void foo(Map<Integer,String> myMap,int number) 249 * @return the methods found (multiple in case of polymorphism) 250 */ 251 default List<MethodDeclaration> getMethodsByParameterTypes(Class<?>... paramTypes) { 252 return getMembers().stream() 253 .filter(m -> m instanceof MethodDeclaration 254 && ((MethodDeclaration) m).getParameters().stream().map(p -> p.getType().toString()) 255 .collect(toSet()) 256 .equals(Stream.of(paramTypes).map(Class::getSimpleName).collect(toSet()))) 257 .map(m -> (MethodDeclaration) m).collect(toList()); 258 } 259 260 /** 261 * Try to find a {@link FieldDeclaration} by its name 262 * 263 * @param name the name of the field 264 * @return null if not found, the FieldDeclaration otherwise 265 */ 266 default FieldDeclaration getFieldByName(String name) { 267 return (FieldDeclaration) getMembers().stream() 268 .filter(m -> m instanceof FieldDeclaration && ((FieldDeclaration) m).getVariables().stream() 269 .anyMatch(var -> var.getId().getName().equals(name))) 270 .findFirst().orElse(null); 271 } 272 273 /** 274 * Find all fields in the members of this node. 275 * 276 * @return the fields found. This list is immutable. 277 */ 278 default List<FieldDeclaration> getFields() { 279 return unmodifiableList(getMembers().stream() 280 .filter(m -> m instanceof FieldDeclaration ) 281 .map(m -> (FieldDeclaration) m) 282 .collect(toList())); 283 } 284 } 285