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