org.eclipse.ajdt.core.model.AJModelChecker.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ajdt.core.model.AJModelChecker.java

Source

/*******************************************************************************
 * Copyright (c) 2009 SpringSource and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Andrew Eisenberg - initial API and implementation
 *******************************************************************************/

package org.eclipse.ajdt.core.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.ajdt.internal.core.builder.AjState;
import org.aspectj.asm.IRelationship;
import org.aspectj.asm.IRelationshipMap;
import org.eclipse.ajdt.core.AJLog;
import org.eclipse.ajdt.core.javaelements.DeclareElement;
import org.eclipse.ajdt.core.javaelements.IntertypeElement;
import org.eclipse.jdt.core.IJavaElement;

/**
 * @author Andrew Eisenberg
 * @created Feb 3, 2009
 *
 * Performs sanity checking on the crosscutting model.
 * 
 * The following rules are checked:
 * 
 * 1. Advice relationships target only methods, fields, and AJCodeElements
 * 2. Aspect Declarations (ITDs) target only types
 * 
 */
public class AJModelChecker {
    private AJModelChecker() {
        // not instantiable
    }

    public static void doModelCheckIfRequired(AJProjectModelFacade model) {
        if (shouldCheckModel()) {
            AJLog.logStart("Model sanity check for: " + model.getProject().getName());
            List<String> problems = internalCheckModel(model);
            logProblems(problems);
            AJLog.logEnd(AJLog.MODEL, "Model sanity check for: " + model.getProject().getName());
        }
    }

    public static boolean shouldCheckModel() {
        // if the state listener is not null, this means that debug tracing is enabled.
        return AjState.stateListener != null;
    }

    private static void logProblems(List<String> problems) {
        if (problems.size() == 0) {
            AJLog.log(AJLog.MODEL, "Crosscutting model sanity checked with no problems");
            return;
        }

        AJLog.log(AJLog.MODEL, "Crosscutting model sanity checked.  The following problems found:");
        for (Iterator<String> probIter = problems.iterator(); probIter.hasNext();) {
            String problem = probIter.next();
            AJLog.log(AJLog.MODEL, problem);
        }
        AJLog.log(AJLog.MODEL, "");
    }

    /**
     * iterates through all relationships and checks to see that it passes all rules
     * 
     * returns list of questionable relationships as strings.  An empty list is returned if the
     * model is OK. 
     */
    private static List<String> internalCheckModel(AJProjectModelFacade model) {
        IRelationshipMap relationships = model.getAllRelationships();
        List<String> problems = new ArrayList<String>();
        if (relationships != null) {
            for (Iterator<String> relIter = relationships.getEntries().iterator(); relIter.hasNext();) {
                String handle = (String) relIter.next();
                List<IRelationship> relsForHandle = relationships.get(handle);
                for (Iterator<IRelationship> relIter2 = relsForHandle.iterator(); relIter2.hasNext();) {
                    IRelationship rel = (IRelationship) relIter2.next();
                    List<String> res = invalidAdviceRelationsip(rel, model);
                    problems.addAll(res);
                    res = itdsNotOnType(rel, model);
                    problems.addAll(res);
                }
            }
        } else {
            problems.add("No relationshipes found");
        }

        return problems;
    }

    private static List<String> invalidAdviceRelationsip(IRelationship rel, AJProjectModelFacade model) {
        List<String> problems = new ArrayList<String>();
        if (rel.getKind() == IRelationship.Kind.ADVICE || rel.getKind() == IRelationship.Kind.ADVICE_AFTER
                || rel.getKind() == IRelationship.Kind.ADVICE_AFTERRETURNING
                || rel.getKind() == IRelationship.Kind.ADVICE_AFTERTHROWING
                || rel.getKind() == IRelationship.Kind.ADVICE_BEFORE
                || rel.getKind() == IRelationship.Kind.ADVICE_AROUND) {

            IJavaElement elt = model.programElementToJavaElement(rel.getSourceHandle());
            if (!elt.exists()) {
                problems.add("Java Element does not exist: " + rel.getSourceHandle()
                        + "\n\tIt is the source relationship of " + toRelString(rel)
                        + "\n\tThis may not actually be a problem if compiling broken code or advising static initializers.");
            }
            if (elt.getElementType() == IJavaElement.COMPILATION_UNIT
                    || elt.getElementType() == IJavaElement.CLASS_FILE) {
                problems.add(
                        "Java Element is wrong type (advice relationships should not contain any types or compilation units): "
                                + rel.getSourceHandle() + "\n\tIt is the source relationship of "
                                + toRelString(rel));
            }

            for (Iterator<String> targetIter = rel.getTargets().iterator(); targetIter.hasNext();) {
                String target = targetIter.next();
                elt = model.programElementToJavaElement(target);
                if (!elt.exists()) {
                    problems.add("Java Element does not exist: " + target + "\n\tIt is the source relationship of "
                            + toRelString(rel)
                            + "\n\tThis may not actually be a problem if compiling broken code or advising static initializers.");
                }
                if (elt != AJProjectModelFacade.ERROR_JAVA_ELEMENT
                        && (elt.getElementType() == IJavaElement.COMPILATION_UNIT
                                || elt.getElementType() == IJavaElement.CLASS_FILE)) {
                    problems.add(
                            "Java Element is wrong type (advice relationships should not contain any types or compilation units): "
                                    + target + "\n\tIt is the source relationship of " + toRelString(rel));
                }
            }

        }
        return problems;
    }

    private static List<String> itdsNotOnType(IRelationship rel, AJProjectModelFacade model) {
        List<String> problems = new ArrayList<String>();
        if (rel.getKind() == IRelationship.Kind.DECLARE_INTER_TYPE) {

            IJavaElement elt = model.programElementToJavaElement(rel.getSourceHandle());
            if (!elt.exists()) {
                problems.add("Java Element does not exist: " + rel.getSourceHandle()
                        + "\n\tIt is the source relationship of " + toRelString(rel)
                        + "\n\tThis may not actually be a problem if compiling broken code.");
            }
            if (elt != AJProjectModelFacade.ERROR_JAVA_ELEMENT
                    && (elt.getElementType() == IJavaElement.FIELD || elt.getElementType() == IJavaElement.METHOD
                            || elt.getElementType() == IJavaElement.LOCAL_VARIABLE
                            || elt.getElementType() == IJavaElement.INITIALIZER
                            || elt.getElementType() == IJavaElement.COMPILATION_UNIT
                            || elt.getElementType() == IJavaElement.CLASS_FILE)
                    && !(elt instanceof IntertypeElement || elt instanceof DeclareElement)) {
                problems.add(
                        "Java Element is wrong type (ITD relationships should only contain types and intertype elements): "
                                + rel.getSourceHandle() + "\n\tIt is the source relationship of "
                                + toRelString(rel));
            }

            for (Iterator<String> targetIter = rel.getTargets().iterator(); targetIter.hasNext();) {
                String target = targetIter.next();
                elt = model.programElementToJavaElement(target);
                if (!elt.exists()) {
                    problems.add("Java Element does not exist: " + target + "\n\tIt is the source relationship of "
                            + toRelString(rel)
                            + "\n\tThis may not actually be a problem if compiling broken code.");
                }
                if (elt != AJProjectModelFacade.ERROR_JAVA_ELEMENT
                        && (elt.getElementType() == IJavaElement.FIELD
                                || elt.getElementType() == IJavaElement.METHOD
                                || elt.getElementType() == IJavaElement.LOCAL_VARIABLE
                                || elt.getElementType() == IJavaElement.INITIALIZER
                                || elt.getElementType() == IJavaElement.COMPILATION_UNIT
                                || elt.getElementType() == IJavaElement.CLASS_FILE)
                        && !(elt instanceof IntertypeElement || elt instanceof DeclareElement)) {
                    problems.add(
                            "Java Element is wrong type (ITD relationships should only contain types and intertype elements): "
                                    + target + "\n\tIt is the source relationship of " + toRelString(rel));
                }
            }

        }
        return problems;
    }

    private static String toRelString(IRelationship rel) {
        StringBuffer sb = new StringBuffer();
        sb.append(rel.getSourceHandle());
        sb.append(" --");
        sb.append(rel.getName());
        sb.append("--> ");
        for (Iterator<String> targetIter = rel.getTargets().iterator(); targetIter.hasNext();) {
            String target = targetIter.next();
            sb.append(target);
            if (targetIter.hasNext()) {
                sb.append(",   ");
            }
        }
        return sb.toString();
    }
}