1 /* 2 * Copyright (C) 2007-2010 Jlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2016 The JavaParser Team. 4 * 5 * This file is part of JavaParser. 6 * 7 * JavaParser can be used either under the terms of 8 * a) the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * b) the terms of the Apache License 12 * 13 * You should have received a copy of both licenses in LICENCE.LGPL and 14 * LICENCE.APACHE. Please refer to those files for details. 15 * 16 * JavaParser is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Lesser General Public License for more details. 20 */ 21 package com.github.javaparser.ast.nodeTypes; 22 23 import com.github.javaparser.ast.Modifier; 24 import com.github.javaparser.ast.Node; 25 import com.github.javaparser.ast.NodeList; 26 import com.github.javaparser.ast.body.*; 27 import com.github.javaparser.ast.expr.Expression; 28 import com.github.javaparser.ast.stmt.BlockStmt; 29 import com.github.javaparser.ast.type.Type; 30 import com.github.javaparser.ast.type.VoidType; 31 32 import java.util.Arrays; 33 import java.util.EnumSet; 34 import java.util.List; 35 import java.util.Optional; 36 37 import static com.github.javaparser.JavaParser.parseType; 38 import static java.util.Collections.unmodifiableList; 39 import static java.util.stream.Collectors.toCollection; 40 import static java.util.stream.Collectors.toList; 41 42 /** 43 * A node having members. 44 * <p> 45 * The main reason for this interface is to permit users to manipulate homogeneously all nodes with a getMembers 46 * method. 47 */ 48 public interface NodeWithMembers<N extends Node> { 49 /** 50 * @return all members inside the braces of this node, 51 * like fields, methods, nested types, etc. 52 */ 53 NodeList<BodyDeclaration<?>> getMembers(); 54 55 void tryAddImportToParentCompilationUnit(Class<?> clazz); 56 57 default BodyDeclaration<?> getMember(int i) { 58 return getMembers().get(i); 59 } 60 61 @SuppressWarnings("unchecked") 62 default N setMember(int i, BodyDeclaration<?> member) { 63 getMembers().set(i, member); 64 return (N) this; 65 } 66 67 @SuppressWarnings("unchecked") 68 default N addMember(BodyDeclaration<?> member) { 69 getMembers().add(member); 70 return (N) this; 71 } 72 73 N setMembers(NodeList<BodyDeclaration<?>> members); 74 75 /** 76 * Add a field to this and automatically add the import of the type if needed 77 * 78 * @param typeClass the type of the field 79 * @param name the name of the field 80 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 81 * @return the {@link FieldDeclaration} created 82 */ 83 default FieldDeclaration addField(Class<?> typeClass, String name, Modifier... modifiers) { 84 tryAddImportToParentCompilationUnit(typeClass); 85 return addField(typeClass.getSimpleName(), name, modifiers); 86 } 87 88 /** 89 * Add a field to this. 90 * 91 * @param type the type of the field 92 * @param name the name of the field 93 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 94 * @return the {@link FieldDeclaration} created 95 */ 96 default FieldDeclaration addField(String type, String name, Modifier... modifiers) { 97 return addField(parseType(type), name, modifiers); 98 } 99 100 /** 101 * Add a field to this. 102 * 103 * @param type the type of the field 104 * @param name the name of the field 105 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 106 * @return the {@link FieldDeclaration} created 107 */ 108 default FieldDeclaration addField(Type type, String name, Modifier... modifiers) { 109 FieldDeclaration fieldDeclaration = new FieldDeclaration(); 110 VariableDeclarator variable = new VariableDeclarator(type, name); 111 fieldDeclaration.getVariables().add(variable); 112 fieldDeclaration.setModifiers(Arrays.stream(modifiers) 113 .collect(toCollection(() -> EnumSet.noneOf(Modifier.class)))); 114 getMembers().add(fieldDeclaration); 115 return fieldDeclaration; 116 } 117 118 /** 119 * Add a field to this. 120 * 121 * @param type the type of the field 122 * @param name the name of the field 123 * @param initializer the initializer of the field 124 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 125 * @return the {@link FieldDeclaration} created 126 */ 127 default FieldDeclaration addFieldWithInitializer(Type type, String name, Expression initializer, Modifier... modifiers) { 128 FieldDeclaration declaration = addField(type, name, modifiers); 129 declaration.getVariables().iterator().next().setInitializer(initializer); 130 return declaration; 131 } 132 133 /** 134 * Add a private field to this. 135 * 136 * @param typeClass the type of the field 137 * @param name the name of the field 138 * @return the {@link FieldDeclaration} created 139 */ 140 default FieldDeclaration addPrivateField(Class<?> typeClass, String name) { 141 return addField(typeClass, name, Modifier.PRIVATE); 142 } 143 144 /** 145 * Add a private field to this and automatically add the import of the type if 146 * needed. 147 * 148 * @param type the type of the field 149 * @param name the name of the field 150 * @return the {@link FieldDeclaration} created 151 */ 152 default FieldDeclaration addPrivateField(String type, String name) { 153 return addField(type, name, Modifier.PRIVATE); 154 } 155 156 /** 157 * Add a public field to this. 158 * 159 * @param typeClass the type of the field 160 * @param name the name of the field 161 * @return the {@link FieldDeclaration} created 162 */ 163 default FieldDeclaration addPublicField(Class<?> typeClass, String name) { 164 return addField(typeClass, name, Modifier.PUBLIC); 165 } 166 167 /** 168 * Add a public field to this and automatically add the import of the type if 169 * needed. 170 * 171 * @param type the type of the field 172 * @param name the name of the field 173 * @return the {@link FieldDeclaration} created 174 */ 175 default FieldDeclaration addPublicField(String type, String name) { 176 return addField(type, name, Modifier.PUBLIC); 177 } 178 179 /** 180 * Add a protected field to this. 181 * 182 * @param typeClass the type of the field 183 * @param name the name of the field 184 * @return the {@link FieldDeclaration} created 185 */ 186 default FieldDeclaration addProtectedField(Class<?> typeClass, String name) { 187 return addField(typeClass, name, Modifier.PROTECTED); 188 } 189 190 /** 191 * Add a protected field to this and automatically add the import of the type 192 * if needed. 193 * 194 * @param type the type of the field 195 * @param name the name of the field 196 * @return the {@link FieldDeclaration} created 197 */ 198 default FieldDeclaration addProtectedField(String type, String name) { 199 return addField(type, name, Modifier.PROTECTED); 200 } 201 202 /** 203 * Adds a methods with void return by default to this. 204 * 205 * @param methodName the method name 206 * @param modifiers the modifiers like {@link Modifier#PUBLIC} 207 * @return the {@link MethodDeclaration} created 208 */ 209 default MethodDeclaration addMethod(String methodName, Modifier... modifiers) { 210 MethodDeclaration methodDeclaration = new MethodDeclaration(); 211 methodDeclaration.setName(methodName); 212 methodDeclaration.setType(new VoidType()); 213 methodDeclaration.setModifiers(Arrays.stream(modifiers) 214 .collect(toCollection(() -> EnumSet.noneOf(Modifier.class)))); 215 getMembers().add(methodDeclaration); 216 return methodDeclaration; 217 } 218 219 /** 220 * Add an initializer block ({@link InitializerDeclaration}) to this. 221 */ 222 default BlockStmt addInitializer() { 223 BlockStmt block = new BlockStmt(); 224 InitializerDeclaration initializerDeclaration = new InitializerDeclaration(false, block); 225 getMembers().add(initializerDeclaration); 226 return block; 227 } 228 229 /** 230 * Add a static initializer block ({@link InitializerDeclaration}) to this. 231 */ 232 default BlockStmt addStaticInitializer() { 233 BlockStmt block = new BlockStmt(); 234 InitializerDeclaration initializerDeclaration = new InitializerDeclaration(true, block); 235 getMembers().add(initializerDeclaration); 236 return block; 237 } 238 239 /** 240 * Try to find a {@link MethodDeclaration} by its name 241 * 242 * @param name the name of the method 243 * @return the methods found (multiple in case of overloading) 244 */ 245 default List<MethodDeclaration> getMethodsByName(String name) { 246 return unmodifiableList(getMethods().stream() 247 .filter(m -> m.getNameAsString().equals(name)) 248 .collect(toList())); 249 } 250 251 /** 252 * Find all methods in the members of this node. 253 * 254 * @return the methods found. This list is immutable. 255 */ 256 default List<MethodDeclaration> getMethods() { 257 return unmodifiableList(getMembers().stream() 258 .filter(m -> m instanceof MethodDeclaration) 259 .map(m -> (MethodDeclaration) m) 260 .collect(toList())); 261 } 262 263 /** 264 * Try to find a {@link MethodDeclaration} by its parameters types 265 * 266 * @param paramTypes the types of parameters like "Map<Integer,String>","int" to match<br> void 267 * foo(Map<Integer,String> myMap,int number) 268 * @return the methods found (multiple in case of overloading) 269 */ 270 default List<MethodDeclaration> getMethodsByParameterTypes(String... paramTypes) { 271 return unmodifiableList(getMethods().stream() 272 .filter(m -> m.hasParametersOfType(paramTypes)) 273 .collect(toList())); 274 } 275 276 /** 277 * Try to find {@link MethodDeclaration}s by their name and parameters types 278 * 279 * @param paramTypes the types of parameters like "Map<Integer,String>","int" to match<br> void 280 * foo(Map<Integer,String> myMap,int number) 281 * @return the methods found (multiple in case of overloading) 282 */ 283 default List<MethodDeclaration> getMethodsBySignature(String name, String... paramTypes) { 284 return unmodifiableList(getMethodsByName(name).stream() 285 .filter(m -> m.hasParametersOfType(paramTypes)) 286 .collect(toList())); 287 } 288 289 /** 290 * Try to find a {@link MethodDeclaration} by its parameters types 291 * 292 * @param paramTypes the types of parameters like "Map<Integer,String>","int" to match<br> void 293 * foo(Map<Integer,String> myMap,int number) 294 * @return the methods found (multiple in case of overloading) 295 */ 296 default List<MethodDeclaration> getMethodsByParameterTypes(Class<?>... paramTypes) { 297 return unmodifiableList(getMethods().stream() 298 .filter(m -> m.hasParametersOfType(paramTypes)) 299 .collect(toList())); 300 } 301 302 /** 303 * Try to find a {@link FieldDeclaration} by its name 304 * 305 * @param name the name of the field 306 * @return null if not found, the FieldDeclaration otherwise 307 */ 308 default Optional<FieldDeclaration> getFieldByName(String name) { 309 return getMembers().stream() 310 .filter(m -> m instanceof FieldDeclaration) 311 .map(f -> (FieldDeclaration) f) 312 .filter(f -> f.getVariables().stream() 313 .anyMatch(var -> var.getNameAsString().equals(name))) 314 .findFirst(); 315 } 316 317 /** 318 * Find all fields in the members of this node. 319 * 320 * @return the fields found. This list is immutable. 321 */ 322 default List<FieldDeclaration> getFields() { 323 return unmodifiableList(getMembers().stream() 324 .filter(m -> m instanceof FieldDeclaration) 325 .map(m -> (FieldDeclaration) m) 326 .collect(toList())); 327 } 328 } 329