Package com.buschmais.jqassistant.sonar.plugin.profile

Source Code of com.buschmais.jqassistant.sonar.plugin.profile.JQAssistantProfileExporter

package com.buschmais.jqassistant.sonar.plugin.profile;

import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.checks.AnnotationCheckFactory;
import org.sonar.api.checks.CheckFactory;
import org.sonar.api.profiles.ProfileExporter;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RuleParam;
import org.sonar.api.utils.SonarException;

import com.buschmais.jqassistant.core.analysis.api.RuleSetWriter;
import com.buschmais.jqassistant.core.analysis.api.rule.*;
import com.buschmais.jqassistant.core.analysis.impl.RuleSetWriterImpl;
import com.buschmais.jqassistant.sonar.plugin.JQAssistant;
import com.buschmais.jqassistant.sonar.plugin.rule.*;

/**
* A {@link ProfileExporter} implementation which provides rules as permalink
* for direct usage by the jQAssistant analyzer.
*/
public class JQAssistantProfileExporter extends ProfileExporter {

    private final static Logger LOGGER = LoggerFactory.getLogger(JQAssistantProfileExporter.class);

    private final RuleFinder ruleFinder;

    /**
     * Constructor.
     *
     * @param ruleFinder
     *            The {@link org.sonar.api.rules.RuleFinder} to use.
     */
    public JQAssistantProfileExporter(RuleFinder ruleFinder) {
        super(JQAssistant.KEY, JQAssistant.NAME);
        this.ruleFinder = ruleFinder;
        super.setMimeType("application/xml");
    }

    @Override
    public void exportProfile(RulesProfile profile, Writer writer) {
        @SuppressWarnings("unchecked")
        CheckFactory<AbstractTemplateRule> annotationCheckFactory = AnnotationCheckFactory.create(profile, JQAssistant.KEY,
                JQAssistantRuleRepository.RULE_CLASSES);
        Map<String, Concept> concepts = new HashMap<String, Concept>();
        Map<AbstractRule, String> executables = new HashMap<AbstractRule, String>();
        for (ActiveRule activeRule : profile.getActiveRulesByRepository(JQAssistant.KEY)) {
            AbstractTemplateRule check = annotationCheckFactory.getCheck(activeRule);
            AbstractRule executable;
            String requiresConcepts;
            if (check == null) {
                executable = createExecutableFromActiveRule(activeRule);
                requiresConcepts = activeRule.getParameter(RuleParameter.RequiresConcepts.getName());
            } else {
                executable = createExecutableFromTemplate(activeRule, check);
                requiresConcepts = check.getRequiresConcepts();
            }
            executables.put(executable, requiresConcepts);
            if (executable instanceof Concept) {
                concepts.put(executable.getId(), (Concept) executable);
            }
        }
        Group group = new Group();
        group.setId(profile.getName());
        for (Map.Entry<AbstractRule, String> executableEntry : executables.entrySet()) {
            AbstractRule executable = executableEntry.getKey();
            String requiresConcepts = executableEntry.getValue();
            addRequiredConcepts(executable, requiresConcepts, concepts);
            if (executable instanceof Concept) {
                group.getConcepts().add((Concept) executable);
            } else if (executable instanceof Constraint) {
                group.getConstraints().add((Constraint) executable);
            }
        }
        RuleSet ruleSet = new RuleSet();
        ruleSet.getGroups().put(group.getId(), group);
        RuleSetWriter ruleSetWriter = new RuleSetWriterImpl();
        LOGGER.debug("Exporting rule set " + ruleSet.toString());
        ruleSetWriter.write(ruleSet, writer);
    }

    /**
     * Resolves and adds required concepts for an executable.
     *
     * @param executable
     *            The executable.
     * @param requiresConcepts
     *            The string containing the comma separated is of required
     *            concepts.
     * @param concepts
     *            The map of already resolved concepts.
     */
    private void addRequiredConcepts(AbstractRule executable, String requiresConcepts, Map<String, Concept> concepts) {
        LOGGER.debug("Adding required concepts for " + executable.getId());
        if (!StringUtils.isEmpty(requiresConcepts)) {
            for (String requiresConceptId : StringUtils.splitByWholeSeparator(requiresConcepts, ",")) {
                LOGGER.debug("Required concept: " + requiresConceptId);
                Concept requiredConcept = concepts.get(requiresConceptId);
                if (requiredConcept == null) {
                    LOGGER.debug("Finding rule for concept : " + requiresConceptId);
                    Rule rule = ruleFinder.findByKey(JQAssistant.KEY, requiresConceptId);
                    requiredConcept = (Concept) createExecutableFromRule(rule);
                    concepts.put(requiresConceptId, requiredConcept);
                    RuleParam requiresConceptsParam = rule.getParam(RuleParameter.RequiresConcepts.getName());
                    if (requiresConceptsParam != null) {
                        addRequiredConcepts(requiredConcept, requiresConceptsParam.getDefaultValue(), concepts);
                    }
                }
                if (requiredConcept != null) {
                    LOGGER.debug("Adding required concept with id " + requiresConceptId + " to " + executable.getId());
                    executable.getRequiresConcepts().add(requiredConcept);
                } else {
                    LOGGER.warn("Cannot resolve required concept with id " + requiresConceptId);
                }
            }
        }
    }

    /**
     * Creates an executable from an active rule and its parameters.
     *
     * @param activeRule
     *            The active rule.
     * @return The executable.
     */
    private AbstractRule createExecutableFromActiveRule(ActiveRule activeRule) {
        String cypher = activeRule.getParameter(RuleParameter.Cypher.getName());
        Rule rule = activeRule.getRule();
        return createExecutableFromRule(rule, cypher);
    }

    /**
     * Creates an executable from a rule.
     *
     * @param rule
     *            The rule.
     * @return The executable.
     */
    private AbstractRule createExecutableFromRule(Rule rule) {
        RuleParam cypherParam = rule.getParam(RuleParameter.Cypher.getName());
        if (cypherParam == null) {
            throw new SonarException("Cannot determine cypher for " + rule);
        }
        String cypher = cypherParam.getDefaultValue();
        return createExecutableFromRule(rule, cypher);
    }

    /**
     * Creates an executable from a rule.
     *
     * @param rule
     *            The rule.
     * @param cypher
     *            The cypher expression.
     * @return The executable.
     */
    private AbstractRule createExecutableFromRule(Rule rule, String cypher) {
        RuleParam typeParam = rule.getParam(RuleParameter.Type.getName());
        if (typeParam == null) {
            throw new SonarException("Cannot determine type of rule for " + rule);
        }
        AbstractRule executable;
        String type = typeParam.getDefaultValue();
        RuleType ruleType = RuleType.valueOf(type);
        switch (ruleType) {
        case Concept:
            executable = new Concept();
            break;
        case Constraint:
            executable = new Constraint();
            break;
        default:
            throw new SonarException("Rule type is not supported " + ruleType);
        }
        createExecutable(executable, rule.getName(), rule.getDescription(), cypher);
        return executable;
    }

    /**
     * Creates an executable from a check based on a template.
     *
     * @param activeRule
     *            The active rule.
     * @param check
     *            The check.
     * @return The executable.
     */
    private AbstractRule createExecutableFromTemplate(ActiveRule activeRule, AbstractTemplateRule check) {
        AbstractRule executable;
        if (check instanceof ConceptTemplateRule) {
            executable = new Concept();
        } else if (check instanceof ConstraintTemplateRule) {
            executable = new Constraint();
        } else {
            throw new SonarException("Unknown type " + check.getClass());
        }
        createExecutable(executable, activeRule.getRule().getName(), activeRule.getRule().getDescription(), check.getCypher());
        return executable;
    }

    /**
     * Sets the given parameters for an executable.
     *
     * @param executable
     *            The executable.
     * @param id
     *            The id.
     * @param description
     *            The description.
     * @param cypher
     *            The cypher expression.
     */
    private void createExecutable(AbstractRule executable, String id, String description, String cypher) {
        executable.setId(id);
        executable.setDescription(description);
        Query query = new Query();
        query.setCypher(cypher);
        executable.setQuery(query);
    }
}
TOP

Related Classes of com.buschmais.jqassistant.sonar.plugin.profile.JQAssistantProfileExporter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.