From 348ec4e14aeaf4e98fcab96f0ae7242d178db69b Mon Sep 17 00:00:00 2001
From: Trygve Laugstøl <trygvis@inamo.no>
Date: Wed, 26 Dec 2012 13:30:42 +0100
Subject: o Starting on a better front page.

---
 .../esper/testing/core/badge/BadgeProgress.java    | 15 ++++
 .../esper/testing/core/badge/BadgeService.java     | 35 ++++++++
 .../core/badge/UnbreakableBadgeProgress.java       | 38 ++++++++-
 .../testing/core/badge/UnbreakablePoller.java      | 35 ++------
 .../esper/testing/core/db/PersonBadgeDto.java      |  6 +-
 .../trygvis/esper/testing/core/db/PersonDao.java   | 41 ++++++++--
 .../esper/testing/util/sql/PageRequest.java        | 23 ++++++
 .../io/trygvis/esper/testing/web/CoreResource.java | 92 ++++++++++++++++++++++
 .../trygvis/esper/testing/web/JenkinsResource.java |  6 +-
 .../esper/testing/web/JerseyApplication.java       | 16 ++--
 10 files changed, 257 insertions(+), 50 deletions(-)
 create mode 100644 src/main/java/io/trygvis/esper/testing/core/badge/BadgeProgress.java
 create mode 100644 src/main/java/io/trygvis/esper/testing/core/badge/BadgeService.java
 create mode 100644 src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java
 create mode 100644 src/main/java/io/trygvis/esper/testing/web/CoreResource.java

(limited to 'src/main/java/io')

diff --git a/src/main/java/io/trygvis/esper/testing/core/badge/BadgeProgress.java b/src/main/java/io/trygvis/esper/testing/core/badge/BadgeProgress.java
new file mode 100644
index 0000000..eb8d4bd
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/core/badge/BadgeProgress.java
@@ -0,0 +1,15 @@
+package io.trygvis.esper.testing.core.badge;
+
+import io.trygvis.esper.testing.core.db.PersonBadgeDto.*;
+
+public abstract class BadgeProgress {
+    public final BadgeType type;
+
+    protected BadgeProgress(BadgeType type) {
+        this.type = type;
+    }
+
+    public abstract int progression();
+    public abstract int goal();
+    public abstract int progressingAgainstLevel();
+}
diff --git a/src/main/java/io/trygvis/esper/testing/core/badge/BadgeService.java b/src/main/java/io/trygvis/esper/testing/core/badge/BadgeService.java
new file mode 100644
index 0000000..ea0c0dc
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/core/badge/BadgeService.java
@@ -0,0 +1,35 @@
+package io.trygvis.esper.testing.core.badge;
+
+import io.trygvis.esper.testing.core.db.*;
+import org.codehaus.jackson.map.*;
+import org.slf4j.*;
+
+import java.io.*;
+
+public class BadgeService {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    public UnbreakableBadgeProgress unbreakable(PersonBadgeProgressDto dto) {
+        String state = dto.state;
+
+        try {
+            return objectMapper.readValue(state, UnbreakableBadgeProgress.class);
+        } catch (IOException e) {
+            logger.error("Could not de-serialize badge state: {}", state);
+            throw new RuntimeException(e);
+        }
+    }
+
+    public String serialize(UnbreakableBadgeProgress badge) {
+        try {
+            CharArrayWriter writer = new CharArrayWriter();
+            objectMapper.writeValue(writer, badge);
+            return writer.toString();
+        } catch (IOException e) {
+            logger.error("Could not serialize badge.", e);
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakableBadgeProgress.java b/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakableBadgeProgress.java
index 871be25..dc9a5bc 100644
--- a/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakableBadgeProgress.java
+++ b/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakableBadgeProgress.java
@@ -1,25 +1,27 @@
 package io.trygvis.esper.testing.core.badge;
 
+import static fj.P.*;
 import fj.*;
 import fj.data.*;
+import static fj.data.Option.*;
 import io.trygvis.esper.testing.core.db.*;
+import io.trygvis.esper.testing.core.db.PersonBadgeDto.*;
 
 import java.util.*;
 
-import static fj.P.p;
-import static fj.data.Option.some;
-
-class UnbreakableBadgeProgress {
+public class UnbreakableBadgeProgress extends BadgeProgress {
     public final UUID person;
     public final int count;
 
     private UnbreakableBadgeProgress(UUID person, int count) {
+        super(BadgeType.UNBREAKABLE);
         this.person = person;
         this.count = count;
     }
 
     @SuppressWarnings("UnusedDeclaration")
     private UnbreakableBadgeProgress() {
+        super(BadgeType.UNBREAKABLE);
         person = null;
         count = -1;
     }
@@ -50,6 +52,34 @@ class UnbreakableBadgeProgress {
         return p(new UnbreakableBadgeProgress(person, count), Option.<UnbreakableBadge>none());
     }
 
+    public int progression() {
+        return count;
+    }
+
+    public int goal() {
+        if (count > UnbreakableBadge.LEVEL_2_COUNT) {
+            return UnbreakableBadge.LEVEL_3_COUNT;
+        }
+
+        if (count > UnbreakableBadge.LEVEL_1_COUNT) {
+            return UnbreakableBadge.LEVEL_2_COUNT;
+        }
+
+        return UnbreakableBadge.LEVEL_1_COUNT;
+    }
+
+    public int progressingAgainstLevel() {
+        if (count > UnbreakableBadge.LEVEL_2_COUNT) {
+            return 3;
+        }
+
+        if (count > UnbreakableBadge.LEVEL_1_COUNT) {
+            return 2;
+        }
+
+        return 1;
+    }
+
     @Override
     public String toString() {
         return "UnbreakableBadgeProgress{person=" + person + ", count=" + count + '}';
diff --git a/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakablePoller.java b/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakablePoller.java
index 16f8ee8..1d0a947 100644
--- a/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakablePoller.java
+++ b/src/main/java/io/trygvis/esper/testing/core/badge/UnbreakablePoller.java
@@ -7,21 +7,19 @@ import io.trygvis.esper.testing.*;
 import io.trygvis.esper.testing.core.*;
 import io.trygvis.esper.testing.core.db.*;
 import io.trygvis.esper.testing.util.sql.*;
-import org.codehaus.jackson.map.*;
 import org.slf4j.*;
 
-import java.io.*;
 import java.sql.*;
 import java.util.List;
 import java.util.*;
 
 import static io.trygvis.esper.testing.Config.*;
-import static io.trygvis.esper.testing.core.db.PersonBadgeDto.Type.*;
+import static io.trygvis.esper.testing.core.db.PersonBadgeDto.BadgeType.*;
 
 public class UnbreakablePoller implements TablePoller.NewRowCallback<BuildDto> {
-    Logger logger = LoggerFactory.getLogger(getClass());
+    private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private static final ObjectMapper objectMapper = new ObjectMapper();
+    private final BadgeService badgeService = new BadgeService();
 
     public static void main(String[] args) throws Exception {
         String pollerName = "unbreakable";
@@ -50,23 +48,15 @@ public class UnbreakablePoller implements TablePoller.NewRowCallback<BuildDto> {
 
             SqlOption<PersonBadgeProgressDto> o = daos.personDao.selectBadgeProgress(person, UNBREAKABLE);
 
-            UnbreakableBadgeProgress badge;
-
             if (o.isNone()) {
-                badge = UnbreakableBadgeProgress.initial(person);
+                UnbreakableBadgeProgress badge = UnbreakableBadgeProgress.initial(person);
                 logger.info("New badge progress");
-                String state = serialize(badge);
+                String state = badgeService.serialize(badge);
                 daos.personDao.insertBadgeProgress(person, UNBREAKABLE, state);
                 continue;
             }
 
-            String state = o.get().state;
-            try {
-                badge = objectMapper.readValue(state, UnbreakableBadgeProgress.class);
-            } catch (IOException e) {
-                logger.error("Could not de-serialize badge state: {}", state);
-                throw new RuntimeException(e);
-            }
+            UnbreakableBadgeProgress badge = badgeService.unbreakable(o.get());
 
             logger.info("Existing badge progress: count={}", badge.count);
 
@@ -90,20 +80,9 @@ public class UnbreakablePoller implements TablePoller.NewRowCallback<BuildDto> {
                 }
             }
 
-            state = serialize(badge);
+            String state = badgeService.serialize(badge);
 
             daos.personDao.updateBadgeProgress(person, UNBREAKABLE, state);
         }
     }
-
-    private String serialize(UnbreakableBadgeProgress badge) {
-        try {
-            CharArrayWriter writer = new CharArrayWriter();
-            objectMapper.writeValue(writer, badge);
-            return writer.toString();
-        } catch (IOException e) {
-            logger.error("Could not serialize badge.", e);
-            throw new RuntimeException(e);
-        }
-    }
 }
diff --git a/src/main/java/io/trygvis/esper/testing/core/db/PersonBadgeDto.java b/src/main/java/io/trygvis/esper/testing/core/db/PersonBadgeDto.java
index 5bbe159..463da9c 100644
--- a/src/main/java/io/trygvis/esper/testing/core/db/PersonBadgeDto.java
+++ b/src/main/java/io/trygvis/esper/testing/core/db/PersonBadgeDto.java
@@ -6,16 +6,16 @@ import org.joda.time.*;
 import java.util.*;
 
 public class PersonBadgeDto extends AbstractEntity {
-    public enum Type {
+    public enum BadgeType {
         UNBREAKABLE
     }
 
     public final UUID person;
-    public final Type type;
+    public final BadgeType type;
     public final int level;
     public final int count;
 
-    public PersonBadgeDto(UUID uuid, DateTime createdDate, UUID person, Type type, int level, int count) {
+    public PersonBadgeDto(UUID uuid, DateTime createdDate, UUID person, BadgeType type, int level, int count) {
         super(uuid, createdDate);
         this.person = person;
         this.type = type;
diff --git a/src/main/java/io/trygvis/esper/testing/core/db/PersonDao.java b/src/main/java/io/trygvis/esper/testing/core/db/PersonDao.java
index 2cb6e6a..6605999 100644
--- a/src/main/java/io/trygvis/esper/testing/core/db/PersonDao.java
+++ b/src/main/java/io/trygvis/esper/testing/core/db/PersonDao.java
@@ -1,5 +1,7 @@
 package io.trygvis.esper.testing.core.db;
 
+import static io.trygvis.esper.testing.Util.toList;
+import io.trygvis.esper.testing.core.db.PersonBadgeDto.*;
 import io.trygvis.esper.testing.util.sql.*;
 import org.joda.time.*;
 
@@ -33,7 +35,7 @@ public class PersonDao {
                     UUID.fromString(rs.getString(i++)),
                     new DateTime(rs.getTimestamp(i++).getTime()),
                     UUID.fromString(rs.getString(i++)),
-                    PersonBadgeDto.Type.valueOf(rs.getString(i++)),
+                    BadgeType.valueOf(rs.getString(i++)),
                     rs.getInt(i),
                     rs.getInt(i));
         }
@@ -69,6 +71,15 @@ public class PersonDao {
         }
     }
 
+    public List<PersonDto> selectPerson(PageRequest pageRequest) throws SQLException {
+        try (PreparedStatement s = c.prepareStatement("SELECT " + PERSON + " FROM person ORDER BY created_date LIMIT ? OFFSET ?")) {
+            int i = 1;
+            s.setInt(i++, pageRequest.count.orSome(10));
+            s.setInt(i, pageRequest.startIndex.orSome(0));
+            return toList(s, person);
+        }
+    }
+
     public SqlOption<PersonDto> selectPersonByJenkinsUuid(UUID jenkinsUser) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("SELECT " + PERSON + " FROM person WHERE uuid=(SELECT person FROM person_jenkins_user WHERE jenkins_user=?)")) {
             int i = 1;
@@ -81,7 +92,7 @@ public class PersonDao {
     // Badge
     // -----------------------------------------------------------------------
 
-    public UUID insertBadge(UUID person, PersonBadgeDto.Type type, int level, int count) throws SQLException {
+    public UUID insertBadge(UUID person, BadgeType type, int level, int count) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("INSERT INTO person_badge(" + PERSON_BADGE + ") VALUES(?, ?, ?, ?, ?, ?)")) {
             UUID uuid = UUID.randomUUID();
             int i = 1;
@@ -96,7 +107,7 @@ public class PersonDao {
         }
     }
 
-    public void incrementBadgeCount(UUID person, PersonBadgeDto.Type type, int level) throws SQLException {
+    public void incrementBadgeCount(UUID person, BadgeType type, int level) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("UPDATE person_badge SET count=count+1 WHERE person=? AND name=? AND level=?")) {
             int i = 1;
             s.setString(i++, person.toString());
@@ -106,7 +117,15 @@ public class PersonDao {
         }
     }
 
-    public SqlOption<PersonBadgeDto> selectBadge(UUID person, PersonBadgeDto.Type type, int level) throws SQLException {
+    public List<PersonBadgeDto> selectBadges(UUID person) throws SQLException {
+        try (PreparedStatement s = c.prepareStatement("SELECT " + PERSON_BADGE + " FROM person_badge WHERE person=? ORDER BY name, level DESC")) {
+            int i = 1;
+            s.setString(i, person.toString());
+            return toList(s, personBadge);
+        }
+    }
+
+    public SqlOption<PersonBadgeDto> selectBadge(UUID person, BadgeType type, int level) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("SELECT " + PERSON_BADGE + " FROM person_badge WHERE person=? AND name=? AND level=?")) {
             int i = 1;
             s.setString(i++, person.toString());
@@ -120,7 +139,7 @@ public class PersonDao {
     // Badge Progress
     // -----------------------------------------------------------------------
 
-    public SqlOption<PersonBadgeProgressDto> selectBadgeProgress(UUID person, PersonBadgeDto.Type type) throws SQLException {
+    public SqlOption<PersonBadgeProgressDto> selectBadgeProgress(UUID person, BadgeType type) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("SELECT " + PERSON_BADGE_PROGRESS + " FROM person_badge_progress WHERE person=? AND badge=?")) {
             int i = 1;
             s.setString(i++, person.toString());
@@ -129,7 +148,15 @@ public class PersonDao {
         }
     }
 
-    public void insertBadgeProgress(UUID person, PersonBadgeDto.Type type, String state) throws SQLException {
+    public List<PersonBadgeProgressDto> selectBadgeProgresses(UUID person) throws SQLException {
+        try (PreparedStatement s = c.prepareStatement("SELECT " + PERSON_BADGE_PROGRESS + " FROM person_badge_progress WHERE person=? ORDER BY badge")) {
+            int i = 1;
+            s.setString(i, person.toString());
+            return toList(s, personBadgeProgress);
+        }
+    }
+
+    public void insertBadgeProgress(UUID person, BadgeType type, String state) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("INSERT INTO person_badge_progress (" + PERSON_BADGE_PROGRESS + ") VALUES(?, ?, ?, ?, ?)")) {
             UUID uuid = UUID.randomUUID();
             int i = 1;
@@ -142,7 +169,7 @@ public class PersonDao {
         }
     }
 
-    public void updateBadgeProgress(UUID person, PersonBadgeDto.Type type, String state) throws SQLException {
+    public void updateBadgeProgress(UUID person, BadgeType type, String state) throws SQLException {
         try (PreparedStatement s = c.prepareStatement("UPDATE person_badge_progress SET state=? WHERE person=? AND badge=?")) {
             int i = 1;
             s.setString(i++, state);
diff --git a/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java b/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java
new file mode 100644
index 0000000..2d8edfe
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java
@@ -0,0 +1,23 @@
+package io.trygvis.esper.testing.util.sql;
+
+import fj.data.*;
+import static fj.data.Option.fromNull;
+import io.trygvis.esper.testing.*;
+
+import javax.servlet.http.*;
+
+public class PageRequest {
+    public final Option<Integer> startIndex;
+    public final Option<Integer> count;
+
+    public PageRequest(Option<Integer> startIndex, Option<Integer> count) {
+        this.startIndex = startIndex;
+        this.count = count;
+    }
+
+    public static PageRequest fromReq(HttpServletRequest req) {
+        return new PageRequest(
+            fromNull(req.getParameter("startIndex")).bind(Util.parseInt),
+            fromNull(req.getParameter("count")).bind(Util.parseInt));
+    }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/web/CoreResource.java b/src/main/java/io/trygvis/esper/testing/web/CoreResource.java
new file mode 100644
index 0000000..3132a62
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/web/CoreResource.java
@@ -0,0 +1,92 @@
+package io.trygvis.esper.testing.web;
+
+import io.trygvis.esper.testing.*;
+import io.trygvis.esper.testing.core.badge.*;
+import io.trygvis.esper.testing.core.db.*;
+import io.trygvis.esper.testing.util.sql.*;
+
+import javax.servlet.http.*;
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+import java.sql.*;
+import java.util.*;
+
+@Path("/resource/core")
+public class CoreResource {
+
+    private final DatabaseAccess da;
+    private final BadgeService badgeService;
+
+    public CoreResource(DatabaseAccess da, BadgeService badgeService) {
+        this.da = da;
+        this.badgeService = badgeService;
+    }
+
+    @GET
+    @Path("/person")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<PersonJson> getServers(@Context final HttpServletRequest req) throws Exception {
+        return da.inTransaction(new DatabaseAccess.DaosCallback<List<PersonJson>>() {
+            @Override
+            public List<PersonJson> run(Daos daos) throws SQLException {
+                List<PersonJson> list = new ArrayList<>();
+                for (PersonDto person : daos.personDao.selectPerson(PageRequest.fromReq(req))) {
+                    list.add(getPersonJson(daos, person));
+                }
+                return list;
+            }
+        });
+    }
+
+    private PersonJson getPersonJson(Daos daos, PersonDto person) throws SQLException {
+        List<BadgeJson> badges = new ArrayList<>();
+
+        for (PersonBadgeDto badge : daos.personDao.selectBadges(person.uuid)) {
+            badges.add(new BadgeJson(badge.type.name(), badge.level, badge.count, 100, 100));
+        }
+
+        for (PersonBadgeProgressDto badgeProgressDto : daos.personDao.selectBadgeProgresses(person.uuid)) {
+            UnbreakableBadgeProgress progress = badgeService.unbreakable(badgeProgressDto);
+            badges.add(new BadgeJson(progress.type.name(), progress.progressingAgainstLevel(), 0,
+                progress.progression(), progress.goal()));
+        }
+
+        return new PersonJson(
+            person.uuid,
+            person.name,
+            badges
+        );
+    }
+
+    public static class PersonJson {
+        public final UUID uuid;
+        public final String name;
+        public final List<BadgeJson> badges;
+
+        public PersonJson(UUID uuid, String name, List<BadgeJson> badges) {
+            this.uuid = uuid;
+            this.name = name;
+            this.badges = badges;
+        }
+    }
+
+    public static class BadgeJson {
+        public final String name;
+        public final int level;
+
+        /**
+         * Number of times this badge has been received.
+         */
+        public final int count;
+        public final int progress;
+        public final int goal;
+
+        public BadgeJson(String name, int level, int count, int progress, int goal) {
+            this.name = name;
+            this.level = level;
+            this.count = count;
+            this.progress = progress;
+            this.goal = goal;
+        }
+    }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java b/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java
index b9e997f..6551cea 100644
--- a/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java
+++ b/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java
@@ -14,7 +14,7 @@ import java.util.List;
 
 import static fj.data.Option.*;
 
-@Path("/")
+@Path("/resource/jenkins")
 public class JenkinsResource {
 
     private final DatabaseAccess da;
@@ -24,7 +24,7 @@ public class JenkinsResource {
     }
 
     @GET
-    @Path("/resource/jenkins/server")
+    @Path("/server")
     @Produces(MediaType.APPLICATION_JSON)
     public List<JenkinsServerJson> getServers() throws Exception {
         return da.inTransaction(new DatabaseAccess.DaosCallback<List<JenkinsServerJson>>() {
@@ -40,7 +40,7 @@ public class JenkinsResource {
     }
 
     @GET
-    @Path("/resource/jenkins/server/{uuid}")
+    @Path("/server/{uuid}")
     @Produces(MediaType.APPLICATION_JSON)
     public JenkinsServerJson getServer(@PathParam("uuid") String s) throws Exception {
         final UUID uuid = parseUuid(s);
diff --git a/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java b/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java
index 6937804..67fbf74 100644
--- a/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java
+++ b/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java
@@ -1,22 +1,28 @@
 package io.trygvis.esper.testing.web;
 
 import io.trygvis.esper.testing.*;
+import io.trygvis.esper.testing.core.badge.*;
 
 import javax.ws.rs.core.*;
 import java.util.*;
 
 public class JerseyApplication extends Application {
 
-    private final DatabaseAccess da;
+    private final HashSet<Object> singletons;
 
     public JerseyApplication() throws Exception {
-        this.da = new DatabaseAccess(WebConfig.config.createBoneCp());
+        DatabaseAccess da = new DatabaseAccess(WebConfig.config.createBoneCp());
+
+        BadgeService badgeService = new BadgeService();
+
+        singletons = new HashSet<>(Arrays.asList(
+            new CoreResource(da, badgeService),
+            new JenkinsResource(da)
+        ));
     }
 
     @Override
     public Set<Object> getSingletons() {
-        return new HashSet<Object>(Arrays.asList(
-                new JenkinsResource(da)
-        ));
+        return singletons;
     }
 }
-- 
cgit v1.2.3