From bd7a95e4bf2489c64202694333f71fe989a246f9 Mon Sep 17 00:00:00 2001 From: simonbrandhof Date: Mon, 3 Jan 2011 17:41:19 +0000 Subject: [PATCH] period by number of days : search for the nearest snapshot, even if it's older than (analysis date - nb of days) --- .../sonar/batch/components/PastSnapshot.java | 8 +-- .../components/PastSnapshotFinderByDays.java | 32 ++++++++++-- .../PastSnapshotFinderByDaysTest.java | 51 ++++++++++++++++++- .../shouldNotFindSelf.xml | 34 +++++++++++++ 4 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/components/PastSnapshotFinderByDaysTest/shouldNotFindSelf.xml diff --git a/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshot.java b/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshot.java index 04140ae8c16..242b0def5dd 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshot.java +++ b/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshot.java @@ -90,16 +90,16 @@ public class PastSnapshot { @Override public String toString() { if (StringUtils.equals(mode, PastSnapshotFinderByVersion.MODE)) { - return String.format("Compare to version " + modeParameter + "(" + targetDate + ")"); + return String.format("Compare to version " + modeParameter + "(" + getDate() + ")"); } if (StringUtils.equals(mode, PastSnapshotFinderByDays.MODE)) { - return String.format("Compare over " + modeParameter + " days (" + targetDate + ")"); + return String.format("Compare over " + modeParameter + " days (" + getDate() + ")"); } if (StringUtils.equals(mode, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS)) { - return String.format("Compare to previous analysis " + " (" + targetDate + ")"); + return String.format("Compare to previous analysis " + " (" + getDate() + ")"); } if (StringUtils.equals(mode, PastSnapshotFinderByDate.MODE)) { - return String.format("Compare to date " + targetDate); + return String.format("Compare to date " + getDate()); } return ReflectionToStringBuilder.toString(this); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshotFinderByDays.java b/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshotFinderByDays.java index 6894a802ec1..3ab57983339 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshotFinderByDays.java +++ b/sonar-batch/src/main/java/org/sonar/batch/components/PastSnapshotFinderByDays.java @@ -39,18 +39,40 @@ public class PastSnapshotFinderByDays implements BatchExtension { PastSnapshot findFromDays(Snapshot projectSnapshot, int days) { Date targetDate = DateUtils.addDays(projectSnapshot.getCreatedAt(), -days); - String hql = "from " + Snapshot.class.getSimpleName() + " where resourceId=:resourceId AND status=:status AND createdAt>=:from AND createdAt<:to order by createdAt asc"; + String hql = "from " + Snapshot.class.getSimpleName() + " where resourceId=:resourceId AND status=:status AND createdAt<:date order by createdAt asc"; List snapshots = session.createQuery(hql) - .setParameter("from", targetDate) - .setParameter("to", projectSnapshot.getCreatedAt()) + .setParameter("date", projectSnapshot.getCreatedAt()) .setParameter("resourceId", projectSnapshot.getResourceId()) .setParameter("status", Snapshot.STATUS_PROCESSED) - .setMaxResults(1) .getResultList(); if (snapshots.isEmpty()) { return null; } - return new PastSnapshot(MODE, targetDate, snapshots.get(0)).setModeParameter(String.valueOf(days)); + + Snapshot snapshot = getNearestToTarget(snapshots, targetDate); + return new PastSnapshot(MODE, targetDate, snapshot).setModeParameter(String.valueOf(days)); + } + + static Snapshot getNearestToTarget(List snapshots, Date currentDate, int distanceInDays) { + Date targetDate = DateUtils.addDays(currentDate, -distanceInDays); + return getNearestToTarget(snapshots, targetDate); + } + + static Snapshot getNearestToTarget(List snapshots, Date targetDate) { + long bestDistance = Long.MAX_VALUE; + Snapshot nearest = null; + for (Snapshot snapshot : snapshots) { + long distance = distance(snapshot.getCreatedAt(), targetDate); + if (distance <= bestDistance) { + bestDistance = distance; + nearest = snapshot; + } + } + return nearest; + } + + static long distance(Date d1, Date d2) { + return Math.abs(d1.getTime() - d2.getTime()); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/components/PastSnapshotFinderByDaysTest.java b/sonar-batch/src/test/java/org/sonar/batch/components/PastSnapshotFinderByDaysTest.java index 6db32df71c7..06c1673e95f 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/components/PastSnapshotFinderByDaysTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/components/PastSnapshotFinderByDaysTest.java @@ -19,11 +19,17 @@ */ package org.sonar.batch.components; +import org.hamcrest.core.IsNull; import org.junit.Test; import org.sonar.api.database.model.Snapshot; import org.sonar.jpa.test.AbstractDbUnitTestCase; import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.nullValue; @@ -31,6 +37,8 @@ import static org.junit.Assert.assertThat; public class PastSnapshotFinderByDaysTest extends AbstractDbUnitTestCase { + private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + @Test public void shouldGetNextSnapshot() throws ParseException { setupData("shared"); @@ -53,7 +61,7 @@ public class PastSnapshotFinderByDaysTest extends AbstractDbUnitTestCase { @Test public void shouldNotFindSelf() throws ParseException { - setupData("shared"); + setupData("shouldNotFindSelf"); Snapshot projectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 1009); // 2008-11-16 PastSnapshotFinderByDays finder = new PastSnapshotFinderByDays(getSession()); @@ -61,4 +69,45 @@ public class PastSnapshotFinderByDaysTest extends AbstractDbUnitTestCase { assertThat(finder.findFromDays(projectSnapshot, 1), nullValue()); } + @Test + public void shouldLocateNearestSnapshotBefore() throws ParseException { + Date current = dateFormat.parse("2010-10-20"); + // distance: 15 => target is 2010-10-05 + + List snapshots = Arrays.asList( + newSnapshot(1, "2010-09-30"), + newSnapshot(2, "2010-10-03"),// -2 days + newSnapshot(3, "2010-10-08"),// +3 days + newSnapshot(4, "2010-10-12") // + 7 days + ); + assertThat(PastSnapshotFinderByDays.getNearestToTarget(snapshots, current, 15).getId(), is(2)); + } + + @Test + public void shouldLocateNearestSnapshotAfter() throws ParseException { + Date current = dateFormat.parse("2010-10-20"); + // distance: 15 => target is 2010-10-05 + + List snapshots = Arrays.asList( + newSnapshot(1, "2010-09-30"), + newSnapshot(2, "2010-10-01"),// -4 days + newSnapshot(3, "2010-10-08"),// +3 days + newSnapshot(4, "2010-10-12") // + 7 days + ); + assertThat(PastSnapshotFinderByDays.getNearestToTarget(snapshots, current, 15).getId(), is(3)); + } + + @Test + public void shouldReturnNullIfNoSnapshots() throws ParseException { + Date current = dateFormat.parse("2010-10-20"); + List snapshots = Collections.emptyList(); + assertThat(PastSnapshotFinderByDays.getNearestToTarget(snapshots, current, 15), IsNull.nullValue()); + } + + private Snapshot newSnapshot(int id, String date) throws ParseException { + Snapshot snapshot = new Snapshot(); + snapshot.setId(id); + snapshot.setCreatedAt(dateFormat.parse(date)); + return snapshot; + } } diff --git a/sonar-batch/src/test/resources/org/sonar/batch/components/PastSnapshotFinderByDaysTest/shouldNotFindSelf.xml b/sonar-batch/src/test/resources/org/sonar/batch/components/PastSnapshotFinderByDaysTest/shouldNotFindSelf.xml new file mode 100644 index 00000000000..35b1dc30300 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/components/PastSnapshotFinderByDaysTest/shouldNotFindSelf.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- 2.39.5