• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.github.javaparser.metamodel;
2 
3 import com.github.javaparser.ast.AllFieldsConstructor;
4 import com.github.javaparser.ast.Node;
5 import com.github.javaparser.ast.NodeList;
6 
7 import java.lang.reflect.Constructor;
8 import java.lang.reflect.InvocationTargetException;
9 import java.util.*;
10 
11 import static com.github.javaparser.utils.Utils.decapitalize;
12 
13 /**
14  * Meta-data about all classes in the AST. These are all Nodes, except NodeList.
15  */
16 public abstract class BaseNodeMetaModel {
17     private final Optional<BaseNodeMetaModel> superNodeMetaModel;
18     private final List<PropertyMetaModel> declaredPropertyMetaModels = new ArrayList<>();
19     private final List<PropertyMetaModel> derivedPropertyMetaModels = new ArrayList<>();
20     private final List<PropertyMetaModel> constructorParameters = new ArrayList<>();
21     private final Class<? extends Node> type;
22     private final String name;
23     private final String packageName;
24     private final boolean isAbstract;
25     private final boolean hasWildcard;
26 
BaseNodeMetaModel(Optional<BaseNodeMetaModel> superNodeMetaModel, Class<? extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard)27     public BaseNodeMetaModel(Optional<BaseNodeMetaModel> superNodeMetaModel, Class<? extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard) {
28         this.superNodeMetaModel = superNodeMetaModel;
29         this.type = type;
30         this.name = name;
31         this.packageName = packageName;
32         this.isAbstract = isAbstract;
33         this.hasWildcard = hasWildcard;
34     }
35 
36     /**
37      * @return is this the meta model for this node class?
38      */
is(Class<? extends Node> c)39     public boolean is(Class<? extends Node> c) {
40         return type.equals(c);
41     }
42 
43     /**
44      * @return package name + class name
45      */
getQualifiedClassName()46     public String getQualifiedClassName() {
47         return packageName + "." + name;
48     }
49 
50     /**
51      * @return the meta model for the node that this node extends. Note that this is to be used to find properties
52      * defined in superclasses of a Node.
53      */
getSuperNodeMetaModel()54     public Optional<BaseNodeMetaModel> getSuperNodeMetaModel() {
55         return superNodeMetaModel;
56     }
57 
58     /**
59      * @return a list of all properties declared directly in this node (not its parent nodes.) These are also available
60      * as fields.
61      */
getDeclaredPropertyMetaModels()62     public List<PropertyMetaModel> getDeclaredPropertyMetaModels() {
63         return declaredPropertyMetaModels;
64     }
65 
getDerivedPropertyMetaModels()66     public List<PropertyMetaModel> getDerivedPropertyMetaModels() {
67         return derivedPropertyMetaModels;
68     }
69 
70     /**
71      * @return a list of all properties that describe the parameters to the all-fields (but not "range" and "comment")
72      * constructor, in the order of appearance in the constructor parameter list.
73      */
getConstructorParameters()74     public List<PropertyMetaModel> getConstructorParameters() {
75         return constructorParameters;
76     }
77 
78     /**
79      * @return a list of all properties in this node and its parents. Note that a new list is created every time this
80      * method is called.
81      */
getAllPropertyMetaModels()82     public List<PropertyMetaModel> getAllPropertyMetaModels() {
83         List<PropertyMetaModel> allPropertyMetaModels = new ArrayList<>(getDeclaredPropertyMetaModels());
84         BaseNodeMetaModel walkNode = this;
85         while (walkNode.getSuperNodeMetaModel().isPresent()) {
86             walkNode = walkNode.getSuperNodeMetaModel().get();
87             allPropertyMetaModels.addAll(walkNode.getDeclaredPropertyMetaModels());
88         }
89         return allPropertyMetaModels;
90     }
91 
isInstanceOfMetaModel(BaseNodeMetaModel baseMetaModel)92     public boolean isInstanceOfMetaModel(BaseNodeMetaModel baseMetaModel) {
93         if (this == baseMetaModel) {
94             return true;
95         }
96         if (isRootNode()) {
97             return false;
98         }
99         return getSuperNodeMetaModel().get().isInstanceOfMetaModel(baseMetaModel);
100     }
101 
102     /**
103      * @return the class for this AST node type.
104      */
getType()105     public Class<? extends Node> getType() {
106         return type;
107     }
108 
109     /**
110      * @return the package containing this AST node class.
111      */
getPackageName()112     public String getPackageName() {
113         return packageName;
114     }
115 
116     /**
117      * @return whether this AST node is abstract.
118      */
isAbstract()119     public boolean isAbstract() {
120         return isAbstract;
121     }
122 
123     /**
124      * @return whether this AST node has a &lt;?&gt; at the end of its type.
125      */
hasWildcard()126     public boolean hasWildcard() {
127         return hasWildcard;
128     }
129 
130     /**
131      * @return whether this AST node is the root node, meaning that it is the meta model for "Node": "NodeMetaModel".
132      */
isRootNode()133     public boolean isRootNode() {
134         return !superNodeMetaModel.isPresent();
135     }
136 
137     @Override
equals(Object o)138     public boolean equals(Object o) {
139         if (this == o) return true;
140         if (o == null || getClass() != o.getClass()) return false;
141 
142         BaseNodeMetaModel classMetaModel = (BaseNodeMetaModel) o;
143 
144         if (!type.equals(classMetaModel.type)) return false;
145 
146         return true;
147     }
148 
149     @Override
hashCode()150     public int hashCode() {
151         return type.hashCode();
152     }
153 
154     @Override
toString()155     public String toString() {
156         return name;
157     }
158 
159     /**
160      * @return the type name, with generics.
161      */
getTypeNameGenerified()162     public String getTypeNameGenerified() {
163         if (hasWildcard) {
164             return getTypeName() + "<?>";
165         }
166         return getTypeName();
167     }
168 
169     /**
170      * @return the raw type name, so nothing but the name.
171      */
getTypeName()172     public String getTypeName() {
173         return type.getSimpleName();
174     }
175 
176     /**
177      * The name of the field in JavaParserMetaModel for this node meta model.
178      */
getMetaModelFieldName()179     public String getMetaModelFieldName() {
180         return decapitalize(getClass().getSimpleName());
181     }
182 
183     /**
184      * Creates a new node of this type.
185      *
186      * @param parameters a map of propertyName -> value.
187      * This should at least contain a pair for every required property for this node.
188      */
construct(Map<String, Object> parameters)189     public Node construct(Map<String, Object> parameters) {
190         for (Constructor<?> constructor : getType().getConstructors()) {
191             if (constructor.getAnnotation(AllFieldsConstructor.class) != null) {
192                 try {
193                     Object[] paramArray = new Object[constructor.getParameterCount()];
194                     int i = 0;
195                     for (PropertyMetaModel constructorParameter : getConstructorParameters()) {
196                         paramArray[i] = parameters.get(constructorParameter.getName());
197                         if (paramArray[i] == null && constructorParameter.isRequired()) {
198                             if (constructorParameter.isNodeList()) {
199                                 paramArray[i] = new NodeList<>();
200                             }
201                             // We could have more defaults here.
202                         }
203                         i++;
204                     }
205                     return (Node) constructor.newInstance(paramArray);
206                 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
207                     throw new RuntimeException(e);
208                 }
209             }
210         }
211         throw new IllegalStateException();
212     }
213 }
214