001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 SonarSource
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.plugins.findbugs.xml;
021    
022    import com.thoughtworks.xstream.XStream;
023    import com.thoughtworks.xstream.annotations.XStreamAlias;
024    import com.thoughtworks.xstream.annotations.XStreamImplicit;
025    import org.apache.commons.lang.StringUtils;
026    import org.sonar.api.rules.RulePriority;
027    import org.sonar.plugins.findbugs.FindbugsLevelUtils;
028    
029    import java.util.*;
030    
031    @XStreamAlias("FindBugsFilter")
032    public class FindBugsFilter {
033    
034      private static final String PATTERN_SEPARATOR = ",";
035      private static final String CODE_SEPARATOR = ",";
036      private static final String CATEGORY_SEPARATOR = ",";
037    
038      @XStreamImplicit
039      private List<Match> matchs;
040    
041      public FindBugsFilter() {
042        matchs = new ArrayList<Match>();
043      }
044    
045      public String toXml() {
046        XStream xstream = createXStream();
047        return xstream.toXML(this);
048      }
049    
050      public List<Match> getMatchs() {
051        return matchs;
052      }
053    
054      public List<Match> getChildren() {
055        return matchs;
056      }
057    
058      public void setMatchs(List<Match> matchs) {
059        this.matchs = matchs;
060      }
061    
062      public void addMatch(Match child) {
063        matchs.add(child);
064      }
065    
066      public Map<String, RulePriority> getPatternLevels(FindbugsLevelUtils priorityMapper) {
067        BugInfoSplitter splitter = new BugInfoSplitter() {
068          public String getSeparator() {
069            return PATTERN_SEPARATOR;
070          }
071    
072          public String getVar(Bug bug) {
073            return bug.getPattern();
074          }
075        };
076        return processMatches(priorityMapper, splitter);
077      }
078    
079      public Map<String, RulePriority> getCodeLevels(FindbugsLevelUtils priorityMapper) {
080        BugInfoSplitter splitter = new BugInfoSplitter() {
081          public String getSeparator() {
082            return CODE_SEPARATOR;
083          }
084    
085          public String getVar(Bug bug) {
086            return bug.getCode();
087          }
088        };
089        return processMatches(priorityMapper, splitter);
090      }
091    
092      public Map<String, RulePriority> getCategoryLevels(FindbugsLevelUtils priorityMapper) {
093        BugInfoSplitter splitter = new BugInfoSplitter() {
094          public String getSeparator() {
095            return CATEGORY_SEPARATOR;
096          }
097    
098          public String getVar(Bug bug) {
099            return bug.getCategory();
100          }
101        };
102        return processMatches(priorityMapper, splitter);
103      }
104    
105      private RulePriority getRulePriority(Priority priority, FindbugsLevelUtils priorityMapper) {
106        return priority != null ? priorityMapper.from(priority.getValue()) : null;
107      }
108    
109      private Map<String, RulePriority> processMatches(FindbugsLevelUtils priorityMapper, BugInfoSplitter splitter) {
110        Map<String, RulePriority> result = new HashMap<String, RulePriority>();
111        for (Match child : getChildren()) {
112          if (child.getOrs() != null) {
113            for (OrFilter orFilter : child.getOrs()) {
114              completeLevels(result, orFilter.getBugs(), child.getPriority(), priorityMapper, splitter);
115            }
116          }
117          if (child.getBug() != null) {
118            completeLevels(result, Arrays.asList(child.getBug()), child.getPriority(), priorityMapper, splitter);
119          }
120        }
121        return result;
122      }
123    
124      private void completeLevels(Map<String, RulePriority> result, List<Bug> bugs, Priority priority, FindbugsLevelUtils priorityMapper, BugInfoSplitter splitter) {
125        if (bugs == null) {
126          return;
127        }
128        RulePriority rulePriority = getRulePriority(priority, priorityMapper);
129        for (Bug bug : bugs) {
130          String varToSplit = splitter.getVar(bug);
131          if (!StringUtils.isBlank(varToSplit)) {
132            String[] splitted = StringUtils.split(varToSplit, splitter.getSeparator());
133            for (String code : splitted) {
134              mapRulePriority(result, rulePriority, code);
135            }
136          }
137        }
138      }
139    
140      private interface BugInfoSplitter {
141        String getVar(Bug bug);
142    
143        String getSeparator();
144      }
145    
146      private void mapRulePriority(Map<String, RulePriority> prioritiesByRule, RulePriority priority, String key) {
147        if (prioritiesByRule.containsKey(key) && prioritiesByRule.get(key) != null) {
148          if (prioritiesByRule.get(key).compareTo(priority) < 0) {
149            prioritiesByRule.put(key, priority);
150          }
151        } else {
152          prioritiesByRule.put(key, priority);
153        }
154      }
155    
156      public static XStream createXStream() {
157        XStream xstream = new XStream();
158        xstream.setClassLoader(FindBugsFilter.class.getClassLoader());
159        xstream.processAnnotations(FindBugsFilter.class);
160        xstream.processAnnotations(Match.class);
161        xstream.processAnnotations(Bug.class);
162        xstream.processAnnotations(Priority.class);
163        xstream.processAnnotations(ClassFilter.class);
164        xstream.processAnnotations(PackageFilter.class);
165        xstream.processAnnotations(MethodFilter.class);
166        xstream.processAnnotations(FieldFilter.class);
167        xstream.processAnnotations(LocalFilter.class);
168        xstream.processAnnotations(OrFilter.class);
169        return xstream;
170      }
171    }