001: /**
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use,
007: * modify and/or redistribute the software under the terms of the
008: * CeCILL-C
009: * license as circulated by CEA, CNRS and INRIA at the following URL:
010: * http://www.cecill.info.
011: *
012: * This program is distributed in the hope that it will be useful, but
013: * WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C
015: * License for more details.
016: *
017: * The fact that you are presently reading this means that you have had
018: * knowledge of the CeCILL-C license and that you accept its terms.
019: */package spoon.aval.support.validator;
020:
021: import java.lang.annotation.Annotation;
022: import java.util.HashMap;
023: import java.util.List;
024: import java.util.Map;
025:
026: import spoon.aval.Validator;
027: import spoon.aval.annotation.value.RefersTo;
028: import spoon.aval.processing.AValProcessor;
029: import spoon.aval.processing.ValidationPoint;
030: import spoon.processing.ProblemFixer;
031: import spoon.processing.Severity;
032: import spoon.reflect.Factory;
033: import spoon.reflect.declaration.CtAnnotation;
034: import spoon.reflect.declaration.CtElement;
035: import spoon.reflect.reference.CtFieldReference;
036: import spoon.reflect.visitor.Query;
037: import spoon.reflect.visitor.filter.AnnotationFilter;
038:
039: /**
040: * Implementation of the {@link RefersTo} validator
041: *
042: * <p>
043: * This class implements the {@link RefersTo} validator.
044: * It checks the complete metamodel to see if there are CtElements annotated with
045: * the refered annotation and value. If this is not the case, an ERROR is reported.
046: * An ERROR is also reported if the refered annotation does not contain
047: * the refered attribute
048: * <p>
049: * To avoid unnecesary (and maybe costly) traversals of the model, a cache is kept with
050: * the annotations and values found during the first traversal of the model.
051: *
052: */
053: public class RefersToValidator implements Validator<RefersTo> {
054:
055: static private Map<Class<? extends Annotation>, List<CtElement>> cache = new HashMap<Class<? extends Annotation>, List<CtElement>>();
056:
057: /**
058: * Implementation of the Validator interface. Called by {@link AValProcessor}
059: */
060: public void check(ValidationPoint<RefersTo> vp) {
061: Class<? extends Annotation> referedType = vp.getValAnnotation()
062: .value();
063: String referedAttributeName = vp.getValAnnotation().attribute();
064:
065: String dslAttributeName = ((CtFieldReference) vp
066: .getDslElement()).getSimpleName();
067: Object dslAttribute = vp.getDslAnnotation().getElementValue(
068: dslAttributeName);
069:
070: Factory f = vp.getProgramElement().getFactory();
071: List<CtElement> posibles = cache.get(referedType);
072:
073: if (posibles == null) {
074: posibles = Query.getElements(f,
075: new AnnotationFilter<CtElement>(referedType));
076: // cache.put(referedType,posibles);
077: }
078: CtAnnotation dslAnnotation = vp.getDslAnnotation();
079:
080: for (CtElement posible : posibles) {
081: CtAnnotation refered = posible.getAnnotation(f.Type()
082: .createReference(referedType));
083: Object referedVal = refered
084: .getElementValue(referedAttributeName);
085:
086: if (referedVal == null) {
087: CtElement dslElement = vp.getDslElement()
088: .getDeclaration();
089: String message = referedAttributeName
090: + " is not an attribute of the annotation "
091: + referedType;
092: if (dslElement != null)
093: ValidationPoint.report(Severity.ERROR, dslElement,
094: message);
095: return;
096: }
097:
098: if (referedVal.equals(dslAttribute)) {
099: return;
100: }
101: }
102:
103: String message = vp.getValAnnotation().message().replace(
104: "?val", dslAttribute.toString());
105: ProblemFixer[] fixerFactory = vp.fixerFactory(vp
106: .getValAnnotation().fixers());
107: ValidationPoint.report(vp.getValAnnotation().severity(),
108: dslAnnotation, message, fixerFactory);
109: }
110:
111: }
|