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