001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube 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     * SonarQube 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 License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    
021    package org.sonar.batch.issue.ignore.pattern;
022    
023    import com.google.common.collect.Sets;
024    import org.apache.commons.lang.builder.ToStringBuilder;
025    import org.apache.commons.lang.builder.ToStringStyle;
026    import org.sonar.api.issue.Issue;
027    import org.sonar.api.rule.RuleKey;
028    import org.sonar.api.utils.WildcardPattern;
029    
030    import java.util.Set;
031    
032    public class IssuePattern {
033    
034      private WildcardPattern resourcePattern;
035      private WildcardPattern rulePattern;
036      private Set<Integer> lines = Sets.newLinkedHashSet();
037      private Set<LineRange> lineRanges = Sets.newLinkedHashSet();
038      private String beginBlockRegexp;
039      private String endBlockRegexp;
040      private String allFileRegexp;
041      private boolean checkLines = true;
042    
043      public IssuePattern() {
044      }
045    
046      public IssuePattern(String resourcePattern, String rulePattern) {
047        this.resourcePattern = WildcardPattern.create(resourcePattern);
048        this.rulePattern = WildcardPattern.create(rulePattern);
049      }
050    
051      public IssuePattern(String resourcePattern, String rulePattern, Set<LineRange> lineRanges) {
052        this(resourcePattern, rulePattern);
053        this.lineRanges = lineRanges;
054      }
055    
056      public WildcardPattern getResourcePattern() {
057        return resourcePattern;
058      }
059    
060      public WildcardPattern getRulePattern() {
061        return rulePattern;
062      }
063    
064      public String getBeginBlockRegexp() {
065        return beginBlockRegexp;
066      }
067    
068      public String getEndBlockRegexp() {
069        return endBlockRegexp;
070      }
071    
072      public String getAllFileRegexp() {
073        return allFileRegexp;
074      }
075    
076      IssuePattern addLineRange(int fromLineId, int toLineId) {
077        lineRanges.add(new LineRange(fromLineId, toLineId));
078        return this;
079      }
080    
081      IssuePattern addLine(int lineId) {
082        lines.add(lineId);
083        return this;
084      }
085    
086      boolean isCheckLines() {
087        return checkLines;
088      }
089    
090      IssuePattern setCheckLines(boolean b) {
091        this.checkLines = b;
092        return this;
093      }
094    
095      IssuePattern setBeginBlockRegexp(String beginBlockRegexp) {
096        this.beginBlockRegexp = beginBlockRegexp;
097        return this;
098      }
099    
100      IssuePattern setEndBlockRegexp(String endBlockRegexp) {
101        this.endBlockRegexp = endBlockRegexp;
102        return this;
103      }
104    
105      IssuePattern setAllFileRegexp(String allFileRegexp) {
106        this.allFileRegexp = allFileRegexp;
107        return this;
108      }
109    
110      Set<Integer> getAllLines() {
111        Set<Integer> allLines = Sets.newLinkedHashSet(lines);
112        for (LineRange lineRange : lineRanges) {
113          allLines.addAll(lineRange.toLines());
114        }
115        return allLines;
116      }
117    
118      public boolean match(Issue issue) {
119        boolean match = matchResource(issue.componentKey())
120          && matchRule(issue.ruleKey());
121        if (checkLines) {
122          Integer line = issue.line();
123          if (line == null) {
124            match = false;
125          } else {
126            match = match && matchLine(line);
127          }
128        }
129        return match;
130      }
131    
132      boolean matchLine(int lineId) {
133        if (lines.contains(lineId)) {
134          return true;
135        }
136    
137        for (LineRange range : lineRanges) {
138          if (range.in(lineId)) {
139            return true;
140          }
141        }
142    
143        return false;
144      }
145    
146      boolean matchRule(RuleKey rule) {
147        if (rule == null) {
148          return false;
149        }
150    
151        String key = new StringBuilder().append(rule.repository()).append(':').append(rule.rule()).toString();
152        return rulePattern.match(key);
153      }
154    
155      boolean matchResource(String resource) {
156        return resource != null && resourcePattern.match(resource);
157      }
158    
159      public IssuePattern forResource(String resource) {
160        return new IssuePattern(resource, rulePattern.toString(), lineRanges).setCheckLines(isCheckLines());
161      }
162    
163      @Override
164      public String toString() {
165        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
166      }
167    }