com.github.javaparser.metamodel.BaseNodeMetaModel Maven / Gradle / Ivy
/*
* Copyright (C) 2007-2010 Júlio Vilmar Gesser.
* Copyright (C) 2011, 2013-2021 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
package com.github.javaparser.metamodel;
import com.github.javaparser.ast.AllFieldsConstructor;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import static com.github.javaparser.utils.Utils.decapitalize;
/**
* Meta-data about all classes in the AST. These are all Nodes, except NodeList.
*/
public abstract class BaseNodeMetaModel {
private final Optional superNodeMetaModel;
private final List declaredPropertyMetaModels = new ArrayList<>();
private final List derivedPropertyMetaModels = new ArrayList<>();
private final List constructorParameters = new ArrayList<>();
private final Class extends Node> type;
private final String name;
private final String packageName;
private final boolean isAbstract;
private final boolean hasWildcard;
public BaseNodeMetaModel(Optional superNodeMetaModel, Class extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard) {
this.superNodeMetaModel = superNodeMetaModel;
this.type = type;
this.name = name;
this.packageName = packageName;
this.isAbstract = isAbstract;
this.hasWildcard = hasWildcard;
}
/**
* @return is this the meta model for this node class?
*/
public boolean is(Class extends Node> c) {
return type.equals(c);
}
/**
* @return package name + class name
*/
public String getQualifiedClassName() {
return packageName + "." + name;
}
/**
* @return the meta model for the node that this node extends. Note that this is to be used to find properties
* defined in superclasses of a Node.
*/
public Optional getSuperNodeMetaModel() {
return superNodeMetaModel;
}
/**
* @return a list of all properties declared directly in this node (not its parent nodes.) These are also available
* as fields.
*/
public List getDeclaredPropertyMetaModels() {
return declaredPropertyMetaModels;
}
public List getDerivedPropertyMetaModels() {
return derivedPropertyMetaModels;
}
/**
* @return a list of all properties that describe the parameters to the all-fields (but not "range" and "comment")
* constructor, in the order of appearance in the constructor parameter list.
*/
public List getConstructorParameters() {
return constructorParameters;
}
/**
* @return a list of all properties in this node and its parents. Note that a new list is created every time this
* method is called.
*/
public List getAllPropertyMetaModels() {
List allPropertyMetaModels = new ArrayList<>(getDeclaredPropertyMetaModels());
BaseNodeMetaModel walkNode = this;
while (walkNode.getSuperNodeMetaModel().isPresent()) {
walkNode = walkNode.getSuperNodeMetaModel().get();
allPropertyMetaModels.addAll(walkNode.getDeclaredPropertyMetaModels());
}
return allPropertyMetaModels;
}
public boolean isInstanceOfMetaModel(BaseNodeMetaModel baseMetaModel) {
if (this == baseMetaModel) {
return true;
}
if (isRootNode()) {
return false;
}
return getSuperNodeMetaModel().get().isInstanceOfMetaModel(baseMetaModel);
}
/**
* @return the class for this AST node type.
*/
public Class extends Node> getType() {
return type;
}
/**
* @return the package containing this AST node class.
*/
public String getPackageName() {
return packageName;
}
/**
* @return whether this AST node is abstract.
*/
public boolean isAbstract() {
return isAbstract;
}
/**
* @return whether this AST node has a <?> at the end of its type.
*/
public boolean hasWildcard() {
return hasWildcard;
}
/**
* @return whether this AST node is the root node, meaning that it is the meta model for "Node": "NodeMetaModel".
*/
public boolean isRootNode() {
return !superNodeMetaModel.isPresent();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BaseNodeMetaModel classMetaModel = (BaseNodeMetaModel) o;
if (!type.equals(classMetaModel.type)) return false;
return true;
}
@Override
public int hashCode() {
return type.hashCode();
}
@Override
public String toString() {
return name;
}
/**
* @return the type name, with generics.
*/
public String getTypeNameGenerified() {
if (hasWildcard) {
return getTypeName() + ">";
}
return getTypeName();
}
/**
* @return the raw type name, so nothing but the name.
*/
public String getTypeName() {
return type.getSimpleName();
}
/**
* The name of the field in JavaParserMetaModel for this node meta model.
*/
public String getMetaModelFieldName() {
return decapitalize(getClass().getSimpleName());
}
/**
* Creates a new node of this type.
*
* @param parameters a map of propertyName -> value.
* This should at least contain a pair for every required property for this node.
*/
public Node construct(Map parameters) {
for (Constructor> constructor : getType().getConstructors()) {
if (constructor.getAnnotation(AllFieldsConstructor.class) != null) {
try {
Object[] paramArray = new Object[constructor.getParameterCount()];
int i = 0;
for (PropertyMetaModel constructorParameter : getConstructorParameters()) {
paramArray[i] = parameters.get(constructorParameter.getName());
if (paramArray[i] == null && constructorParameter.isRequired()) {
if (constructorParameter.isNodeList()) {
paramArray[i] = new NodeList<>();
}
// We could have more defaults here.
}
i++;
}
return (Node) constructor.newInstance(paramArray);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
throw new IllegalStateException();
}
}