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    package org.sonar.batch.components;
021    
022    import com.google.common.base.Strings;
023    import org.apache.commons.configuration.Configuration;
024    import org.apache.commons.lang.StringUtils;
025    import org.slf4j.Logger;
026    import org.slf4j.LoggerFactory;
027    import org.sonar.api.BatchExtension;
028    import org.sonar.api.CoreProperties;
029    import org.sonar.api.config.Settings;
030    import org.sonar.api.database.model.Snapshot;
031    
032    import javax.annotation.Nullable;
033    import java.text.ParseException;
034    import java.text.SimpleDateFormat;
035    import java.util.Date;
036    
037    public class PastSnapshotFinder implements BatchExtension {
038    
039      private static final Logger LOG = LoggerFactory.getLogger(PastSnapshotFinder.class);
040    
041      private PastSnapshotFinderByDays finderByDays;
042      private PastSnapshotFinderByVersion finderByVersion;
043      private PastSnapshotFinderByDate finderByDate;
044      private PastSnapshotFinderByPreviousAnalysis finderByPreviousAnalysis;
045      private PastSnapshotFinderByPreviousVersion finderByPreviousVersion;
046    
047      public PastSnapshotFinder(PastSnapshotFinderByDays finderByDays, PastSnapshotFinderByVersion finderByVersion,
048                                PastSnapshotFinderByDate finderByDate, PastSnapshotFinderByPreviousAnalysis finderByPreviousAnalysis,
049                                PastSnapshotFinderByPreviousVersion finderByPreviousVersion) {
050        this.finderByDays = finderByDays;
051        this.finderByVersion = finderByVersion;
052        this.finderByDate = finderByDate;
053        this.finderByPreviousAnalysis = finderByPreviousAnalysis;
054        this.finderByPreviousVersion = finderByPreviousVersion;
055      }
056    
057      /**
058       * @deprecated since 3.6. Replaced by {@link #find(Snapshot projectSnapshot, String rootQualifier, Settings settings, int index) }
059       */
060      @Deprecated
061      public PastSnapshot find(Snapshot projectSnapshot, Configuration conf, int index) {
062        String propertyValue = getPropertyValue(conf, index);
063        PastSnapshot pastSnapshot = find(projectSnapshot, index, propertyValue);
064        if (pastSnapshot == null && StringUtils.isNotBlank(propertyValue)) {
065          LoggerFactory.getLogger(PastSnapshotFinder.class).debug("Property " + CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + " is not valid: " + propertyValue);
066        }
067        return pastSnapshot;
068      }
069    
070      /**
071       * @deprecated since 3.6. Replace by {@link #getPropertyValue(String rootQualifier, Settings settings, int index) }
072       */
073      @Deprecated
074      static String getPropertyValue(Configuration conf, int index) {
075        String defaultValue = null;
076        switch (index) {
077          case 1:
078            defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_1;
079            break;
080          case 2:
081            defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_2;
082            break;
083          case 3:
084            defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_3;
085            break;
086          case 4:
087            defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_4;
088            break;
089          case 5:
090            defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_5;
091            break;
092        }
093        return conf.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index, defaultValue);
094      }
095    
096      public PastSnapshot find(Snapshot projectSnapshot, @Nullable String rootQualifier, Settings settings, int index) {
097        String propertyValue = getPropertyValue(rootQualifier, settings, index);
098        PastSnapshot pastSnapshot = find(projectSnapshot, index, propertyValue);
099        if (pastSnapshot == null && StringUtils.isNotBlank(propertyValue)) {
100          LOG.debug("Property " + CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + " is not valid: " + propertyValue);
101        }
102        return pastSnapshot;
103      }
104    
105      public PastSnapshot find(Snapshot projectSnapshot, Settings settings, int index) {
106        return find(projectSnapshot, null, settings, index);
107      }
108    
109      static String getPropertyValue(@Nullable String rootQualifier, Settings settings, int index) {
110        String value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index);
111        // For periods 4 and 5 we're searching for a property prefixed by the qualifier
112        if (index > 3 && Strings.isNullOrEmpty(value)) {
113          value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + "." + rootQualifier);
114        }
115        return value;
116      }
117    
118      public PastSnapshot findPreviousAnalysis(Snapshot projectSnapshot) {
119        return finderByPreviousAnalysis.findByPreviousAnalysis(projectSnapshot);
120      }
121    
122      @Nullable
123      public PastSnapshot find(Snapshot projectSnapshot, int index, String property) {
124        if (StringUtils.isBlank(property)) {
125          return null;
126        }
127    
128        PastSnapshot result = findByDays(projectSnapshot, property);
129        if (result == null) {
130          result = findByDate(projectSnapshot, property);
131          if (result == null) {
132            result = findByPreviousAnalysis(projectSnapshot, property);
133            if (result == null) {
134              result = findByPreviousVersion(projectSnapshot, property);
135              if (result == null) {
136                result = findByVersion(projectSnapshot, property);
137              }
138            }
139          }
140        }
141    
142        if (result != null) {
143          result.setIndex(index);
144        }
145    
146        return result;
147      }
148    
149      @Nullable
150      private PastSnapshot findByPreviousAnalysis(Snapshot projectSnapshot, String property) {
151        PastSnapshot pastSnapshot = null;
152        if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, property)) {
153          pastSnapshot = finderByPreviousAnalysis.findByPreviousAnalysis(projectSnapshot);
154        }
155        return pastSnapshot;
156      }
157    
158      @Nullable
159      private PastSnapshot findByPreviousVersion(Snapshot projectSnapshot, String property) {
160        PastSnapshot pastSnapshot = null;
161        if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, property)) {
162          pastSnapshot = finderByPreviousVersion.findByPreviousVersion(projectSnapshot);
163        }
164        return pastSnapshot;
165      }
166    
167      @Nullable
168      private PastSnapshot findByDate(Snapshot projectSnapshot, String property) {
169        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
170        try {
171          Date date = format.parse(property);
172          return finderByDate.findByDate(projectSnapshot, date);
173    
174        } catch (ParseException e) {
175          return null;
176        }
177      }
178    
179      private PastSnapshot findByVersion(Snapshot projectSnapshot, String property) {
180        return finderByVersion.findByVersion(projectSnapshot, property);
181      }
182    
183      @Nullable
184      private PastSnapshot findByDays(Snapshot projectSnapshot, String property) {
185        try {
186          int days = Integer.parseInt(property);
187          return finderByDays.findFromDays(projectSnapshot, days);
188    
189        } catch (NumberFormatException e) {
190          return null;
191        }
192      }
193    
194    }