All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spoon.metamodel.MetamodelConcept Maven / Gradle / Ivy

Go to download

Spoon is a tool for meta-programming, analysis and transformation of Java programs.

There is a newer version: 11.1.1-beta-14
Show newest version
/*
 * SPDX-License-Identifier: (MIT OR CECILL-C)
 *
 * Copyright (C) 2006-2023 INRIA and contributors
 *
 * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) or the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon.
 */
package spoon.metamodel;

import static spoon.metamodel.Metamodel.addUniqueObject;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import spoon.SpoonException;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtInterface;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.path.CtRole;
import spoon.support.adaption.TypeAdaptor;

/**
 * Represents a concept of the Spoon metamodel (eg {@link CtClass}).
 */
public class MetamodelConcept {
	/**
	 * Kind of this concept
	 */
	private ConceptKind kind;
	/**
	 * Name of the concept
	 */
	private final String name;
	/**
	 * Map of {@link CtRole} to {@link MetamodelProperty}s with values ordered same like CtScanner scans these properties when visiting this {@link MetamodelConcept}
	 */
	private final Map role2Property = new LinkedHashMap<>();

	/**
	 * List of super concepts of this concept
	 */
	private final List superConcepts = new ArrayList<>();

	/**
	 * The {@link CtClass} linked to this {@link MetamodelConcept}. Is null in case of class without interface
	 */
	private CtClass modelClass;
	/**
	 * The {@link CtInterface} linked to this {@link MetamodelConcept}. Is null in case of interface without class
	 */
	private CtInterface modelInterface;

	/**
	 * {@link TypeAdaptor} of this concept used to adapt methods from super type implementations to this {@link MetamodelConcept}
	 */
	private TypeAdaptor typeContext;

	/**
	 * own methods of {@link MetamodelConcept}, which does not belong to any role
	 */
	final List> otherMethods = new ArrayList<>();

	MetamodelConcept(String name) {
		this.name = name;
	}

	/**
	 * @return interface name of {@link MetamodelConcept}. For example CtClass, CtForEach, ...
	 * It is never followed by xxxImpl
	 */
	public String getName() {
		return name;
	}


	MetamodelProperty getOrCreateMMField(CtRole role) {
		return role2Property.computeIfAbsent(role, k -> new MetamodelProperty(k.getCamelCaseName(), k, this));
	}

	/**
	 * @return kind of this {@link MetamodelConcept}.
	 */
	public ConceptKind getKind() {
		if (kind == null) {
			if (modelClass == null && modelInterface == null) {
				return null;
			} else {
				// we first consider interface
				if (modelClass == null) {
					this.kind = ConceptKind.ABSTRACT;
				} else {
					if (modelClass.hasModifier(ModifierKind.ABSTRACT)) {
						this.kind = ConceptKind.ABSTRACT;
					} else {
						this.kind = ConceptKind.LEAF;
					}
				}
			}
		}
		return kind;
	}

	/**
	 * @return map of {@link MetamodelProperty}s by their {@link CtRole}
	 */
	public Map getRoleToProperty() {
		return Collections.unmodifiableMap(role2Property);
	}

	/**
	 * @return Collection of all {@link MetamodelProperty} of current {@link MetamodelConcept}
	 * Note: actually is the order undefined
	 * TODO: return List in the same order like it is scanned by CtScanner
	 */
	public Collection getProperties() {
		return Collections.unmodifiableCollection(role2Property.values());
	}

	/**
	 * @param role a {@link CtRole}
	 * @return {@link MetamodelProperty} for `role` of this concept
	 */
	public MetamodelProperty getProperty(CtRole role) {
		return role2Property.get(role);
	}

	/**
	 * @return super types
	 */
	public List getSuperConcepts() {
		return superConcepts;
	}

	void addSuperConcept(MetamodelConcept superType) {
		if (superType == this) {
			throw new SpoonException("Cannot add supertype to itself");
		}
		if (addUniqueObject(superConcepts, superType)) {
			superType.role2Property.forEach((role, superMMField) -> {
				MetamodelProperty mmField = getOrCreateMMField(role);
				mmField.addSuperField(superMMField);
			});
		}
	}

	/**
	 * @return {@link CtClass} which represents this {@link MetamodelConcept}
	 */
	public CtClass getImplementationClass() {
		return modelClass;
	}

	void setModelClass(CtClass modelClass) {
		this.modelClass = modelClass;
	}

	/**
	 * @return {@link CtInterface} which represents this {@link MetamodelConcept}
	 */
	public CtInterface getMetamodelInterface() {
		return modelInterface;
	}

	void setModelInterface(CtInterface modelInterface) {
		this.modelInterface = modelInterface;
	}

	/**
	 * @return {@link TypeAdaptor}, which can be used to adapt super type methods to this {@link MetamodelConcept}
	 *
	 * (package protected, not in the public API)
	 */
	TypeAdaptor getTypeContext() {
		if (typeContext == null) {
			typeContext = new TypeAdaptor(modelClass != null ? modelClass : modelInterface);
		}
		return typeContext;
	}

	@Override
	public String toString() {
		return getName();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy