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.collect.Maps;
023 import org.apache.commons.lang.ObjectUtils;
024 import org.apache.commons.lang.StringUtils;
025 import org.sonar.api.BatchExtension;
026 import org.sonar.api.database.DatabaseSession;
027 import org.sonar.api.database.model.Snapshot;
028 import org.sonar.api.measures.Metric;
029 import org.sonar.api.measures.MetricFinder;
030 import org.sonar.api.resources.Qualifiers;
031 import org.sonar.api.resources.Resource;
032
033 import javax.annotation.Nullable;
034 import javax.persistence.Query;
035
036 import java.util.Collection;
037 import java.util.Collections;
038 import java.util.List;
039 import java.util.Map;
040
041 public class PastMeasuresLoader implements BatchExtension {
042
043 private Map<Integer, Metric> metricByIds;
044 private DatabaseSession session;
045
046 public PastMeasuresLoader(DatabaseSession session, MetricFinder metricFinder) {
047 this(session, metricFinder.findAll());
048 }
049
050 PastMeasuresLoader(DatabaseSession session, Collection<Metric> metrics) {
051 this.session = session;
052 this.metricByIds = Maps.newHashMap();
053 for (Metric metric : metrics) {
054 if (metric.isNumericType()) {
055 metricByIds.put(metric.getId(), metric);
056 }
057 }
058 }
059
060 public Collection<Metric> getMetrics() {
061 return metricByIds.values();
062 }
063
064 public List<Object[]> getPastMeasures(Resource resource, PastSnapshot projectPastSnapshot) {
065 if (projectPastSnapshot != null && projectPastSnapshot.getProjectSnapshot() != null) {
066 return getPastMeasures(resource.getEffectiveKey(), resource.getPath(), projectPastSnapshot.getProjectSnapshot());
067 }
068 return Collections.emptyList();
069 }
070
071 public List<Object[]> getPastMeasures(String resourceKey, Snapshot projectPastSnapshot) {
072 return getPastMeasures(resourceKey, null, projectPastSnapshot);
073 }
074
075 public List<Object[]> getPastMeasures(String resourceKey, @Nullable String path, Snapshot projectPastSnapshot) {
076 String sql = "select m.metric_id, m.characteristic_id, m.person_id, m.rule_id, m.value from project_measures m, snapshots s" +
077 " where m.snapshot_id=s.id and m.metric_id in (:metricIds) " +
078 " and (s.root_snapshot_id=:rootSnapshotId or s.id=:rootSnapshotId) " +
079 " and s.status=:status and s.project_id=(select p.id from projects p where p.kee=:resourceKey and p.qualifier<>:lib"
080 + (StringUtils.isNotBlank(path) ? " and p.path=:path" : "")
081 + ")";
082 Query q = session.createNativeQuery(sql)
083 .setParameter("metricIds", metricByIds.keySet())
084 .setParameter("rootSnapshotId", ObjectUtils.defaultIfNull(projectPastSnapshot.getRootId(), projectPastSnapshot.getId()))
085 .setParameter("resourceKey", resourceKey)
086 .setParameter("lib", Qualifiers.LIBRARY)
087 .setParameter("status", Snapshot.STATUS_PROCESSED);
088 if (StringUtils.isNotBlank(path)) {
089 q.setParameter("path", path);
090 }
091 return q.getResultList();
092 }
093
094 public static int getMetricId(Object[] row) {
095 // can be BigDecimal on Oracle
096 return ((Number) row[0]).intValue();
097 }
098
099 public static Integer getCharacteristicId(Object[] row) {
100 // can be BigDecimal on Oracle
101 Number number = (Number) row[1];
102 return number != null ? number.intValue() : null;
103 }
104
105 public static Integer getPersonId(Object[] row) {
106 // can be BigDecimal on Oracle
107 Number number = (Number) row[2];
108 return number != null ? number.intValue() : null;
109 }
110
111 public static Integer getRuleId(Object[] row) {
112 // can be BigDecimal on Oracle
113 Number number = (Number) row[3];
114 return number != null ? number.intValue() : null;
115 }
116
117 public static boolean hasValue(Object[] row) {
118 return row[4] != null;
119 }
120
121 public static double getValue(Object[] row) {
122 return ((Number) row[4]).doubleValue();
123 }
124
125 }