• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.github.javaparser.metamodel;
2 
3 import com.github.javaparser.ast.Node;
4 
5 import java.lang.reflect.Field;
6 import java.util.Optional;
7 
8 import static com.github.javaparser.utils.CodeGenerationUtils.getterName;
9 import static com.github.javaparser.utils.CodeGenerationUtils.setterName;
10 
11 /**
12  * Meta-data about a property of a node in the AST.
13  */
14 public class PropertyMetaModel {
15     private final BaseNodeMetaModel containingNodeMetaModel;
16     private final String name;
17     private final Class<?> type;
18     private final Optional<BaseNodeMetaModel> nodeReference;
19     private final boolean isOptional;
20     private final boolean isNonEmpty;
21     private final boolean isNodeList;
22     private final boolean isEnumSet;
23     private final boolean hasWildcard;
24 
PropertyMetaModel(BaseNodeMetaModel containingNodeMetaModel, String name, Class<?> type, Optional<BaseNodeMetaModel> nodeReference, boolean isOptional, boolean isNonEmpty, boolean isNodeList, boolean isEnumSet, boolean hasWildcard)25     public PropertyMetaModel(BaseNodeMetaModel containingNodeMetaModel, String name, Class<?> type, Optional<BaseNodeMetaModel> nodeReference, boolean isOptional, boolean isNonEmpty, boolean isNodeList, boolean isEnumSet, boolean hasWildcard) {
26         this.containingNodeMetaModel = containingNodeMetaModel;
27         this.name = name;
28         this.type = type;
29         this.nodeReference = nodeReference;
30         this.isOptional = isOptional;
31         this.isNonEmpty = isNonEmpty;
32         this.isNodeList = isNodeList;
33         this.isEnumSet = isEnumSet;
34         this.hasWildcard = hasWildcard;
35     }
36 
37     /**
38      * @return is this the field fieldName on class c?
39      */
is(Class<? extends Node> c, String fieldName)40     public boolean is(Class<? extends Node> c, String fieldName) {
41         return containingNodeMetaModel.is(c) && name.equals(fieldName);
42     }
43 
44     /**
45      * @return is this fields called fieldName?
46      */
is(String fieldName)47     public boolean is(String fieldName) {
48         return name.equals(fieldName);
49     }
50 
51     /**
52      * @return the name used in the AST for the setter
53      */
getSetterMethodName()54     public String getSetterMethodName() {
55         return setterName(name);
56     }
57 
58     /**
59      * @return the name used in the AST for the getter
60      */
getGetterMethodName()61     public String getGetterMethodName() {
62         return getterName(type, name);
63     }
64 
65     /**
66      * @return the NodeMetaModel that "has" this property.
67      */
getContainingNodeMetaModel()68     public BaseNodeMetaModel getContainingNodeMetaModel() {
69         return containingNodeMetaModel;
70     }
71 
72     /**
73      * @return the name of the property. This is equal to the name of the field in the AST.
74      */
getName()75     public String getName() {
76         return name;
77     }
78 
79     /**
80      * @return if this property is a String or a NodeList: whether it may be empty.
81      */
isNonEmpty()82     public boolean isNonEmpty() {
83         return isNonEmpty;
84     }
85 
86     /**
87      * @return the class of the field.
88      */
getType()89     public Class<?> getType() {
90         return type;
91     }
92 
93     /**
94      * @return if this property is a Node, this will get the node meta model.
95      */
getNodeReference()96     public Optional<BaseNodeMetaModel> getNodeReference() {
97         return nodeReference;
98     }
99 
100     /**
101      * @return whether this property is optional.
102      */
isOptional()103     public boolean isOptional() {
104         return isOptional;
105     }
106 
107     /**
108      * @return whether this property is not optional.
109      */
isRequired()110     public boolean isRequired() {
111         return !isOptional;
112     }
113 
114     /**
115      * @return whether this property is contained in a NodeList.
116      */
isNodeList()117     public boolean isNodeList() {
118         return isNodeList;
119     }
120 
121     /**
122      * @return whether this property is contained in an EnumSet.
123      */
isEnumSet()124     public boolean isEnumSet() {
125         return isEnumSet;
126     }
127 
128     /**
129      * @return whether this property has a wildcard following it, like BodyDeclaration&lt;?&gt;.
130      */
hasWildcard()131     public boolean hasWildcard() {
132         return hasWildcard;
133     }
134 
135     /**
136      * @return whether this property is not a list or set.
137      */
isSingular()138     public boolean isSingular() {
139         return !(isNodeList || isEnumSet);
140     }
141 
142     @Override
toString()143     public String toString() {
144         return "(" + getTypeName() + ")\t" + containingNodeMetaModel + "#" + name;
145     }
146 
147     @Override
equals(Object o)148     public boolean equals(Object o) {
149         if (this == o) return true;
150         if (o == null || getClass() != o.getClass()) return false;
151 
152         PropertyMetaModel that = (PropertyMetaModel) o;
153 
154         if (!name.equals(that.name)) return false;
155         if (!type.equals(that.type)) return false;
156 
157         return true;
158     }
159 
160     @Override
hashCode()161     public int hashCode() {
162         int result = name.hashCode();
163         result = 31 * result + type.hashCode();
164         return result;
165     }
166 
167     /**
168      * @return the type of a single element of this property, so no Optional or NodeList or EnumSet.
169      */
getTypeNameGenerified()170     public String getTypeNameGenerified() {
171         if (hasWildcard) {
172             return getTypeName() + "<?>";
173         }
174         return getTypeName();
175     }
176 
177     /**
178      * @return the raw type of a single element of this property, so nothing but the name.
179      */
getTypeName()180     public String getTypeName() {
181         return type.getSimpleName();
182     }
183 
184     /**
185      * @return the type that is returned from getters in the AST.
186      */
getTypeNameForGetter()187     public String getTypeNameForGetter() {
188         if (isOptional) {
189             return "Optional<" + getTypeNameForSetter() + ">";
190         }
191         return getTypeNameForSetter();
192     }
193 
194     /**
195      * @return the type that is passed to setters in the AST.
196      */
getTypeNameForSetter()197     public String getTypeNameForSetter() {
198         if (isNodeList) {
199             return "NodeList<" + getTypeNameGenerified() + ">";
200         }
201         if (isEnumSet) {
202             return "EnumSet<" + getTypeNameGenerified() + ">";
203         }
204         return getTypeNameGenerified();
205     }
206 
207     /**
208      * @return is this property an AST Node?
209      */
isNode()210     public boolean isNode() {
211         return getNodeReference().isPresent();
212     }
213 
214     /**
215      * The name of the field in the containing BaseNodeMetaModel for this property meta model.
216      */
getMetaModelFieldName()217     public String getMetaModelFieldName() {
218         return getName() + "PropertyMetaModel";
219     }
220 
221     /**
222      * @return is this property an attribute, meaning: not a node?
223      */
isAttribute()224     public boolean isAttribute() {
225         return !isNode();
226     }
227 
228     /**
229      * Introspects the node to get the value from this field.
230      * Note that an optional empty field will return null here.
231      */
getValue(Node node)232     public Object getValue(Node node) {
233         try {
234             for (Class<?> c = node.getClass(); c != null; c = c.getSuperclass()) {
235                 Field[] fields = c.getDeclaredFields();
236                 for (Field classField : fields) {
237                     if (classField.getName().equals(getName())) {
238                         classField.setAccessible(true);
239                         return classField.get(node);
240                     }
241                 }
242             }
243             throw new NoSuchFieldError(getName());
244         } catch (IllegalAccessException e) {
245             throw new RuntimeException(e);
246         }
247     }
248 }
249