001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.api.rules;
021
022 import com.google.common.collect.Lists;
023 import org.apache.commons.lang.StringUtils;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026 import org.sonar.api.ServerComponent;
027 import org.sonar.api.utils.AnnotationUtils;
028 import org.sonar.check.Check;
029
030 import java.lang.reflect.Field;
031 import java.util.Collection;
032 import java.util.List;
033
034 /**
035 * @since 2.3
036 */
037 public final class AnnotationRuleParser implements ServerComponent {
038
039 private static final Logger LOG = LoggerFactory.getLogger(AnnotationRuleParser.class);
040
041 public List<Rule> parse(String repositoryKey, Collection<Class> annotatedClasses) {
042 List<Rule> rules = Lists.newArrayList();
043 for (Class annotatedClass : annotatedClasses) {
044 rules.add(create(repositoryKey, annotatedClass));
045 }
046 return rules;
047 }
048
049 private Rule create(String repositoryKey, Class annotatedClass) {
050 org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getClassAnnotation(annotatedClass, org.sonar.check.Rule.class);
051 if (ruleAnnotation != null) {
052 return toRule(repositoryKey, annotatedClass, ruleAnnotation);
053 }
054 Check checkAnnotation = AnnotationUtils.getClassAnnotation(annotatedClass, Check.class);
055 if (checkAnnotation != null) {
056 return toRule(repositoryKey, annotatedClass, checkAnnotation);
057 }
058 LOG.warn("The class " + annotatedClass.getCanonicalName() + " should be annotated with " + Rule.class);
059 return null;
060 }
061
062 private Rule toRule(String repositoryKey, Class clazz, org.sonar.check.Rule ruleAnnotation) {
063 String ruleKey = StringUtils.defaultIfEmpty(ruleAnnotation.key(), clazz.getCanonicalName());
064 String ruleName = StringUtils.defaultIfEmpty(ruleAnnotation.name(), ruleKey);
065 Rule rule = Rule.create(repositoryKey, ruleKey, ruleName);
066 rule.setDescription(ruleAnnotation.description());
067 rule.setSeverity(RulePriority.fromCheckPriority(ruleAnnotation.priority()));
068 rule.setCardinality(ruleAnnotation.cardinality());
069
070 Field[] fields = clazz.getDeclaredFields();
071 if (fields != null) {
072 for (Field field : fields) {
073 addRuleProperty(rule, field);
074 }
075 }
076
077 return rule;
078 }
079
080 private Rule toRule(String repositoryKey, Class clazz, Check checkAnnotation) {
081 String ruleKey = StringUtils.defaultIfEmpty(checkAnnotation.key(), clazz.getCanonicalName());
082 String ruleName = StringUtils.defaultIfEmpty(checkAnnotation.title(), ruleKey);
083 Rule rule = Rule.create(repositoryKey, ruleKey, ruleName);
084 rule.setDescription(checkAnnotation.description());
085 rule.setSeverity(RulePriority.fromCheckPriority(checkAnnotation.priority()));
086
087 Field[] fields = clazz.getDeclaredFields();
088 if (fields != null) {
089 for (Field field : fields) {
090 addCheckProperty(rule, field);
091 }
092 }
093 return rule;
094 }
095
096 private void addRuleProperty(Rule rule, Field field) {
097 org.sonar.check.RuleProperty propertyAnnotation = field.getAnnotation(org.sonar.check.RuleProperty.class);
098 if (propertyAnnotation != null) {
099 String fieldKey = StringUtils.defaultIfEmpty(propertyAnnotation.key(), field.getName());
100 RuleParam param = rule.createParameter(fieldKey);
101 param.setDescription(propertyAnnotation.description());
102 param.setDefaultValue(propertyAnnotation.defaultValue());
103 }
104 }
105
106 private void addCheckProperty(Rule rule, Field field) {
107 org.sonar.check.CheckProperty propertyAnnotation = field.getAnnotation(org.sonar.check.CheckProperty.class);
108 if (propertyAnnotation != null) {
109 String fieldKey = StringUtils.defaultIfEmpty(propertyAnnotation.key(), field.getName());
110 RuleParam param = rule.createParameter(fieldKey);
111 param.setDescription(propertyAnnotation.description());
112 }
113 }
114 }