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.checks.templates;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.slf4j.Logger;
024    import org.slf4j.LoggerFactory;
025    import org.sonar.check.AnnotationIntrospector;
026    
027    import java.lang.reflect.Field;
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.List;
031    
032    /**
033     * Load templates from class annotations (see the library sonar-check-api)
034     */
035    public class AnnotationCheckTemplateFactory {
036    
037      private static final Logger LOG = LoggerFactory.getLogger(AnnotationCheckTemplateFactory.class);
038    
039      private Collection<Class> annotatedClasses;
040    
041      public AnnotationCheckTemplateFactory(Collection<Class> annotatedClasses) {
042        this.annotatedClasses = annotatedClasses;
043      }
044    
045      public List<CheckTemplate> create() {
046        List<CheckTemplate> templates = new ArrayList<CheckTemplate>();
047        for (Class annotatedClass : annotatedClasses) {
048          BundleCheckTemplate template = create(annotatedClass);
049          if (template != null) {
050            templates.add(template);
051          }
052        }
053        return templates;
054      }
055    
056    
057      protected BundleCheckTemplate create(Class annotatedClass) {
058        org.sonar.check.Check checkAnnotation = AnnotationIntrospector.getCheckAnnotation(annotatedClass);
059        if (checkAnnotation == null) {
060          LOG.warn("The class " + annotatedClass.getCanonicalName() + " is not a check template. It should be annotated with " + CheckTemplate.class);
061          return null;
062        }
063    
064        BundleCheckTemplate check = toTemplate(annotatedClass, checkAnnotation);
065        Field[] fields = annotatedClass.getDeclaredFields();
066        if (fields != null) {
067          for (Field field : fields) {
068            BundleCheckTemplateProperty property = toProperty(check, field);
069            if (property != null) {
070              check.addProperty(property);
071            }
072          }
073        }
074        return check;
075      }
076    
077      private static BundleCheckTemplate toTemplate(Class annotatedClass, org.sonar.check.Check checkAnnotation) {
078        String key = AnnotationIntrospector.getCheckKey(annotatedClass);
079        String bundle = getBundleBaseName(checkAnnotation, annotatedClass);
080    
081        BundleCheckTemplate check = new BundleCheckTemplate(key, bundle);
082        check.setDefaultDescription(checkAnnotation.description());
083        check.setDefaultTitle(checkAnnotation.title());
084        check.setIsoCategory(checkAnnotation.isoCategory());
085        check.setPriority(checkAnnotation.priority());
086    
087        return check;
088      }
089    
090      private static String getBundleBaseName(org.sonar.check.Check checkAnnotation, Class annotatedClass) {
091        String bundle = checkAnnotation.bundle();
092        if (StringUtils.isBlank(bundle)) {
093          bundle = annotatedClass.getCanonicalName();
094        }
095        return bundle;
096      }
097    
098      private static BundleCheckTemplateProperty toProperty(BundleCheckTemplate check, Field field) {
099        org.sonar.check.CheckProperty propertyAnnotation = field.getAnnotation(org.sonar.check.CheckProperty.class);
100        if (propertyAnnotation != null) {
101          String fieldKey = propertyAnnotation.key();
102          if (fieldKey==null || "".equals(fieldKey)) {
103            fieldKey = field.getName();
104          }
105          BundleCheckTemplateProperty property = new BundleCheckTemplateProperty(check, fieldKey);
106          property.setDefaultTitle(propertyAnnotation.title());
107          property.setDefaultDescription(propertyAnnotation.description());
108          return property;
109        }
110        return null;
111      }
112    }