Home | History | Annotate | Download | only in nodeTypes
      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&lt;Integer,String&gt;","int" to match<br>
    233      *            void foo(Map&lt;Integer,String&gt; 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&lt;Integer,String&gt;","int" to match<br>
    248      *            void foo(Map&lt;Integer,String&gt; 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