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.batch; 021 022 import com.google.common.collect.Lists; 023 import com.google.common.collect.Maps; 024 import org.sonar.api.batch.TimeMachine; 025 import org.sonar.api.batch.TimeMachineQuery; 026 import org.sonar.api.database.DatabaseSession; 027 import org.sonar.api.database.model.MeasureModel; 028 import org.sonar.api.database.model.Snapshot; 029 import org.sonar.api.measures.Measure; 030 import org.sonar.api.measures.Metric; 031 import org.sonar.api.measures.MetricFinder; 032 import org.sonar.api.resources.Qualifiers; 033 import org.sonar.api.resources.Resource; 034 import org.sonar.batch.index.DefaultIndex; 035 036 import javax.persistence.Query; 037 038 import java.util.*; 039 040 public class DefaultTimeMachine implements TimeMachine { 041 042 private DatabaseSession session; 043 private DefaultIndex index; 044 private MetricFinder metricFinder; 045 046 public DefaultTimeMachine(DatabaseSession session, DefaultIndex index, MetricFinder metricFinder) { 047 this.session = session; 048 this.index = index; 049 this.metricFinder = metricFinder; 050 } 051 052 public List<Measure> getMeasures(TimeMachineQuery query) { 053 Map<Integer, Metric> metricById = getMetricsById(query); 054 055 List<Object[]> objects = execute(query, true, metricById.keySet()); 056 List<Measure> result = Lists.newArrayList(); 057 058 for (Object[] object : objects) { 059 MeasureModel model = (MeasureModel) object[0]; 060 Measure measure = toMeasure(model, metricById.get(model.getMetricId())); 061 measure.setDate((Date) object[1]); 062 result.add(measure); 063 } 064 return result; 065 } 066 067 public List<Object[]> getMeasuresFields(TimeMachineQuery query) { 068 Map<Integer, Metric> metricById = getMetricsById(query); 069 List<Object[]> rows = execute(query, false, metricById.keySet()); 070 for (Object[] fields : rows) { 071 fields[1] = metricById.get(fields[1]); 072 } 073 return rows; 074 } 075 076 protected List execute(TimeMachineQuery query, boolean selectAllFields, Set<Integer> metricIds) { 077 Resource resource = query.getResource(); 078 if (resource != null && resource.getId() == null) { 079 resource = index.getResource(query.getResource()); 080 } 081 if (resource == null) { 082 return Collections.emptyList(); 083 } 084 085 StringBuilder sb = new StringBuilder(); 086 Map<String, Object> params = Maps.newHashMap(); 087 088 if (selectAllFields) { 089 sb.append("SELECT m, s.createdAt "); 090 } else { 091 sb.append("SELECT s.createdAt, m.metricId, m.value "); 092 } 093 sb.append(" FROM ") 094 .append(MeasureModel.class.getSimpleName()) 095 .append(" m, ") 096 .append(Snapshot.class.getSimpleName()) 097 .append(" s WHERE m.snapshotId=s.id AND s.resourceId=:resourceId AND s.status=:status AND s.qualifier<>:lib"); 098 params.put("resourceId", resource.getId()); 099 params.put("status", Snapshot.STATUS_PROCESSED); 100 params.put("lib", Qualifiers.LIBRARY); 101 102 sb.append(" AND m.characteristic IS NULL"); 103 sb.append(" AND m.personId IS NULL"); 104 sb.append(" AND m.ruleId IS NULL AND m.rulePriority IS NULL"); 105 if (!metricIds.isEmpty()) { 106 sb.append(" AND m.metricId IN (:metricIds) "); 107 params.put("metricIds", metricIds); 108 } 109 if (query.isFromCurrentAnalysis()) { 110 sb.append(" AND s.createdAt>=:from "); 111 params.put("from", index.getProject().getAnalysisDate()); 112 113 } else if (query.getFrom() != null) { 114 sb.append(" AND s.createdAt>=:from "); 115 params.put("from", query.getFrom()); 116 } 117 if (query.isToCurrentAnalysis()) { 118 sb.append(" AND s.createdAt<=:to "); 119 params.put("to", index.getProject().getAnalysisDate()); 120 121 } else if (query.getTo() != null) { 122 sb.append(" AND s.createdAt<=:to "); 123 params.put("to", query.getTo()); 124 } 125 if (query.isOnlyLastAnalysis()) { 126 sb.append(" AND s.last=:last "); 127 params.put("last", Boolean.TRUE); 128 } 129 sb.append(" ORDER BY s.createdAt "); 130 131 Query jpaQuery = session.createQuery(sb.toString()); 132 133 for (Map.Entry<String, Object> entry : params.entrySet()) { 134 jpaQuery.setParameter(entry.getKey(), entry.getValue()); 135 } 136 return jpaQuery.getResultList(); 137 } 138 139 public Map<Integer, Metric> getMetricsById(TimeMachineQuery query) { 140 Collection<Metric> metrics = metricFinder.findAll(query.getMetricKeys()); 141 Map<Integer, Metric> result = Maps.newHashMap(); 142 for (Metric metric : metrics) { 143 result.put(metric.getId(), metric); 144 } 145 return result; 146 } 147 148 static Measure toMeasure(MeasureModel model, Metric metric) { 149 // NOTE: measures on rule are not supported 150 Measure measure = new Measure(metric); 151 measure.setId(model.getId()); 152 measure.setDescription(model.getDescription()); 153 measure.setValue(model.getValue()); 154 measure.setData(model.getData(metric)); 155 measure.setAlertStatus(model.getAlertStatus()); 156 measure.setAlertText(model.getAlertText()); 157 measure.setTendency(model.getTendency()); 158 measure.setVariation1(model.getVariationValue1()); 159 measure.setVariation2(model.getVariationValue2()); 160 measure.setVariation3(model.getVariationValue3()); 161 measure.setVariation4(model.getVariationValue4()); 162 measure.setVariation5(model.getVariationValue5()); 163 measure.setUrl(model.getUrl()); 164 measure.setCharacteristic(model.getCharacteristic()); 165 measure.setPersonId(model.getPersonId()); 166 return measure; 167 } 168 }