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

spoon.processing.AbstractAnnotationProcessor Maven / Gradle / Ivy

/*
 * Spoon - http://spoon.gforge.inria.fr/
 * Copyright (C) 2006 INRIA Futurs 
 *
 * This software is governed by the CeCILL-C License under French law and
 * abiding by the rules of distribution of free software. You can use, modify
 * and/or redistribute the software under the terms of the CeCILL-C license as
 * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
 *
 * This program 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 CeCILL-C License for more details.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C license and that you accept its terms.
 */

package spoon.processing;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import spoon.Launcher;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtElement;

/**
 * This class defines an abstract annotation processor to be subclassed by the
 * user for defining new annotation processors.
 */
public abstract class AbstractAnnotationProcessor
		extends AbstractProcessor implements AnnotationProcessor {

	Map> consumedAnnotationTypes = new TreeMap>();

	Map> processedAnnotationTypes = new TreeMap>();

	/**
	 * Empty constructor only for all processors (invoked by Spoon).
	 */
	@SuppressWarnings("unchecked")
	public AbstractAnnotationProcessor() {
		super();
		clearProcessedElementType();

		for (Method m : getClass().getMethods()) {
			if (m.getName().equals("process")
					&& (m.getParameterTypes().length == 2)) {
				Class c = m.getParameterTypes()[0];
				if (inferConsumedAnnotationType() && (Annotation.class != c)) {
					addConsumedAnnotationType((Class) c);
				}
				c = m.getParameterTypes()[1];
				if (CtElement.class != c) {
					addProcessedElementType((Class) c);
				}
			}
		}
		if (inferConsumedAnnotationType() && processedAnnotationTypes.isEmpty()) {
			addProcessedAnnotationType((Class) Annotation.class);
		}
		if (processedElementTypes.isEmpty()) {
			addProcessedElementType(CtElement.class);
		}
	}

	/**
	 * Adds a consumed annotation type (to be used in subclasses constructors).
	 * A consumed annotation type is also part of the processed annotation
	 * types.
	 */
	final protected void addConsumedAnnotationType(
			Class annotationType) {
		addProcessedAnnotationType(annotationType);
		consumedAnnotationTypes.put(annotationType.getName(), annotationType);
	}

	/**
	 * Adds a processed annotation type (to be used in subclasses constructors).
	 */
	final protected void addProcessedAnnotationType(
			Class annotationType) {
		processedAnnotationTypes.put(annotationType.getName(), annotationType);
	}

	/**
	 * Removes a processed annotation type.
	 */
	final protected void removeProcessedAnnotationType(
			Class annotationType) {
		processedAnnotationTypes.remove(annotationType.getName());
	}

	/**
	 * Clears the processed annotation types.
	 */
	final protected void clearProcessedAnnotationTypes() {
		processedAnnotationTypes.clear();
	}

	/**
	 * Clears the consumed annotation types.
	 */
	final protected void clearConsumedAnnotationTypes() {
		consumedAnnotationTypes.clear();
	}

	/**
	 * Removes a processed annotation type.
	 */
	final protected void removeConsumedAnnotationType(
			Class annotationType) {
		consumedAnnotationTypes.remove(annotationType.getName());
	}

	final public Set> getConsumedAnnotationTypes() {
		return new TreeSet>(consumedAnnotationTypes.values());
	}

	final public Set> getProcessedAnnotationTypes() {
		return new TreeSet>(
				processedAnnotationTypes.values());
	}

	public boolean inferConsumedAnnotationType() {
		return true;
	}

	/**
	 * Returns true if the element is annotated with an annotation whose type is
	 * processed.
	 */
	@Override
	final public boolean isToBeProcessed(E element) {
		if ((element != null) && (element.getAnnotations() != null)) {
			for (CtAnnotation a : element
					.getAnnotations()) {
				if (shoudBeProcessed(a)) {
					return true;
				}
			}
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	final public void process(E element) {
		for (CtAnnotation annotation : new ArrayList>(
				element.getAnnotations())) {
			if (shoudBeProcessed(annotation)) {
				try {
					process((A) annotation.getActualAnnotation(), element);
				} catch (Exception e) {
					Launcher.logger.error(e.getMessage(), e);
				}
				if (shoudBeConsumed(annotation)) {
					element.getAnnotations().remove(annotation);
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * Removes all annotations A on elements E.
	 */
	@Override
	public boolean shoudBeConsumed(CtAnnotation annotation) {
		if (consumedAnnotationTypes.containsKey(annotation.getAnnotationType()
				.getQualifiedName())) {
			return true;
		}
		return false;
	}

	private boolean shoudBeProcessed(
			CtAnnotation annotation) {
		if (processedAnnotationTypes.containsKey(annotation.getAnnotationType()
				.getQualifiedName())) {
			return true;
		}
		return false;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy