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.utils.AnnotationUtils; 027 import org.sonar.check.Check; 028 029 import java.lang.reflect.Field; 030 import java.util.Collection; 031 import java.util.List; 032 033 /** 034 * @since 2.3 035 */ 036 public final class AnnotationRuleRepository extends RuleRepository { 037 038 private static final Logger LOG = LoggerFactory.getLogger(AnnotationRuleRepository.class); 039 040 private Collection<Class> annotatedClasses; 041 042 /** 043 * Use the factory method create() 044 */ 045 private AnnotationRuleRepository(String key, String language, String name, Collection<Class> annotatedClasses) { 046 super(key, language); 047 setName(name); 048 this.annotatedClasses = annotatedClasses; 049 } 050 051 public static AnnotationRuleRepository create(String key, String language, String name, Collection<Class> annotatedClasses) { 052 return new AnnotationRuleRepository(key, language, name, annotatedClasses); 053 } 054 055 @Override 056 public List<Rule> createRules() { 057 List<Rule> rules = Lists.newArrayList(); 058 for (Class annotatedClass : annotatedClasses) { 059 rules.add(create(annotatedClass)); 060 } 061 return rules; 062 } 063 064 private Rule create(Class annotatedClass) { 065 org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getClassAnnotation(annotatedClass, org.sonar.check.Rule.class); 066 if (ruleAnnotation != null) { 067 return toRule(annotatedClass, ruleAnnotation); 068 } 069 Check checkAnnotation = AnnotationUtils.getClassAnnotation(annotatedClass, Check.class); 070 if (checkAnnotation != null) { 071 return toRule(annotatedClass, checkAnnotation); 072 } 073 LOG.warn("The class " + annotatedClass.getCanonicalName() + " is not a check template. It should be annotated with " + Rule.class); 074 return null; 075 } 076 077 private Rule toRule(Class clazz, org.sonar.check.Rule ruleAnnotation) { 078 String key = StringUtils.defaultIfEmpty(ruleAnnotation.key(), clazz.getCanonicalName()); 079 Rule rule = Rule.create(getKey(), key, ruleAnnotation.name()); 080 rule.setDescription(ruleAnnotation.description()); 081 rule.setRulesCategory(RulesCategory.fromIsoCategory(ruleAnnotation.isoCategory())); 082 rule.setPriority(RulePriority.fromCheckPriority(ruleAnnotation.priority())); 083 084 Field[] fields = clazz.getDeclaredFields(); 085 if (fields != null) { 086 for (Field field : fields) { 087 addRuleProperty(rule, field); 088 } 089 } 090 091 return rule; 092 } 093 094 private Rule toRule(Class clazz, Check checkAnnotation) { 095 String key = StringUtils.defaultIfEmpty(checkAnnotation.key(), clazz.getCanonicalName()); 096 Rule rule = Rule.create(getKey(), key, checkAnnotation.title()); 097 rule.setDescription(checkAnnotation.description()); 098 rule.setRulesCategory(RulesCategory.fromIsoCategory(checkAnnotation.isoCategory())); 099 rule.setPriority(RulePriority.fromCheckPriority(checkAnnotation.priority())); 100 101 Field[] fields = clazz.getDeclaredFields(); 102 if (fields != null) { 103 for (Field field : fields) { 104 addCheckProperty(rule, field); 105 } 106 } 107 return rule; 108 } 109 110 private void addRuleProperty(Rule rule, Field field) { 111 org.sonar.check.RuleProperty propertyAnnotation = field.getAnnotation(org.sonar.check.RuleProperty.class); 112 if (propertyAnnotation != null) { 113 String fieldKey = StringUtils.defaultIfEmpty(propertyAnnotation.key(), field.getName()); 114 RuleParam param = rule.createParameter(fieldKey); 115 param.setDescription(propertyAnnotation.description()); 116 param.setDefaultValue(propertyAnnotation.defaultValue()); 117 } 118 } 119 120 private void addCheckProperty(Rule rule, Field field) { 121 org.sonar.check.CheckProperty propertyAnnotation = field.getAnnotation(org.sonar.check.CheckProperty.class); 122 if (propertyAnnotation != null) { 123 String fieldKey = StringUtils.defaultIfEmpty(propertyAnnotation.key(), field.getName()); 124 RuleParam param = rule.createParameter(fieldKey); 125 param.setDescription(propertyAnnotation.description()); 126 } 127 } 128 }