diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/TagDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/TagDao.java index c2b18796..cf7ff8a0 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/TagDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/TagDao.java @@ -11,6 +11,7 @@ import javax.persistence.NoResultException; import javax.persistence.Query; import com.sismics.docs.core.dao.jpa.dto.TagDto; +import com.sismics.docs.core.dao.jpa.dto.TagStatDto; import com.sismics.docs.core.model.jpa.DocumentTag; import com.sismics.docs.core.model.jpa.Tag; import com.sismics.util.context.ThreadLocalContext; @@ -84,6 +85,7 @@ public class TagDao { StringBuilder sb = new StringBuilder("select t.TAG_ID_C, t.TAG_NAME_C from T_DOCUMENT_TAG dt "); sb.append(" join T_TAG t on t.TAG_ID_C = dt.DOT_IDTAG_C "); sb.append(" where dt.DOT_IDDOCUMENT_C = :documentId and t.TAG_DELETEDATE_D is null "); + sb.append(" order by t.TAG_NAME_C "); // Perform the query Query q = em.createNativeQuery(sb.toString()); @@ -102,6 +104,39 @@ public class TagDao { return tagDtoList; } + /** + * Returns stats on tags. + * @param documentId + * @return + */ + @SuppressWarnings("unchecked") + public List getStats(String userId) { + EntityManager em = ThreadLocalContext.get().getEntityManager(); + StringBuilder sb = new StringBuilder("select t.TAG_ID_C, t.TAG_NAME_C, count(d.DOC_ID_C) "); + sb.append(" from T_DOCUMENT_TAG dt "); + sb.append(" join T_TAG t on t.TAG_ID_C = dt.DOT_IDTAG_C "); + sb.append(" join T_DOCUMENT d on d.DOC_ID_C = dt.DOT_IDDOCUMENT_C "); + sb.append(" where d.DOC_IDUSER_C = :userId and t.TAG_DELETEDATE_D is null and d.DOC_DELETEDATE_D is null "); + sb.append(" group by t.TAG_ID_C "); + + // Perform the query + Query q = em.createNativeQuery(sb.toString()); + q.setParameter("userId", userId); + List l = q.getResultList(); + + // Assemble results + List tagStatDtoList = new ArrayList(); + for (Object[] o : l) { + int i = 0; + TagStatDto tagDto = new TagStatDto(); + tagDto.setId((String) o[i++]); + tagDto.setName((String) o[i++]); + tagDto.setCount(((Number) o[i++]).intValue()); + tagStatDtoList.add(tagDto); + } + return tagStatDtoList; + } + /** * Creates a new tag. * diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/TagStatDto.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/TagStatDto.java new file mode 100644 index 00000000..cb54a7d7 --- /dev/null +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/TagStatDto.java @@ -0,0 +1,30 @@ +package com.sismics.docs.core.dao.jpa.dto; + + +/** + * Tag DTO. + * + * @author bgamard + */ +public class TagStatDto extends TagDto { + + private int count; + + /** + * Getter of count. + * + * @return the count + */ + public int getCount() { + return count; + } + + /** + * Setter of count. + * + * @param count count + */ + public void setCount(int count) { + this.count = count; + } +} diff --git a/docs-parent/TODO b/docs-parent/TODO index 6f626eec..6b39fea8 100644 --- a/docs-parent/TODO +++ b/docs-parent/TODO @@ -1,2 +1,2 @@ -- Tag stats (client/server) +- Tag stats (client) - Users administration (client) \ No newline at end of file diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java index 32e4755c..aed64ff8 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java @@ -19,6 +19,7 @@ import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import com.sismics.docs.core.dao.jpa.TagDao; +import com.sismics.docs.core.dao.jpa.dto.TagStatDto; import com.sismics.docs.core.model.jpa.Tag; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; @@ -59,6 +60,35 @@ public class TagResource extends BaseResource { return Response.ok().entity(response).build(); } + /** + * Returns stats on tags. + * + * @return Response + * @throws JSONException + */ + @GET + @Path("/stats") + @Produces(MediaType.APPLICATION_JSON) + public Response stats() throws JSONException { + if (!authenticate()) { + throw new ForbiddenClientException(); + } + + TagDao tagDao = new TagDao(); + List tagStatDtoList = tagDao.getStats(principal.getId()); + JSONObject response = new JSONObject(); + List items = new ArrayList(); + for (TagStatDto tagStatDto : tagStatDtoList) { + JSONObject item = new JSONObject(); + item.put("id", tagStatDto.getId()); + item.put("name", tagStatDto.getName()); + item.put("count", tagStatDto.getCount()); + items.add(item); + } + response.put("stats", items); + return Response.ok().entity(response).build(); + } + /** * Creates a new tag. * diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java index c157adc0..37747d91 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java @@ -7,7 +7,6 @@ import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.junit.Test; -import com.sismics.docs.rest.BaseJerseyTest; import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse.Status; @@ -42,6 +41,48 @@ public class TestTagResource extends BaseJerseyTest { String tag3Id = json.optString("id"); Assert.assertNotNull(tag3Id); + // Create a tag + tagResource = resource().path("/tag"); + tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); + postParams = new MultivaluedMapImpl(); + postParams.add("name", "Tag 4"); + response = tagResource.put(ClientResponse.class, postParams); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + String tag4Id = json.optString("id"); + Assert.assertNotNull(tag4Id); + + // Create a document + WebResource documentResource = resource().path("/document"); + documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); + postParams = new MultivaluedMapImpl(); + postParams.add("title", "My super document 1"); + postParams.add("tags", tag3Id); + response = documentResource.put(ClientResponse.class, postParams); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + + // Create a document + documentResource = resource().path("/document"); + documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); + postParams = new MultivaluedMapImpl(); + postParams.add("title", "My super document 1"); + postParams.add("tags", tag4Id); + response = documentResource.put(ClientResponse.class, postParams); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + + // Get tag stats + tagResource = resource().path("/tag/stats"); + tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); + response = tagResource.get(ClientResponse.class); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + JSONArray stats = json.getJSONArray("stats"); + Assert.assertTrue(stats.length() == 2); + Assert.assertEquals(1, stats.getJSONObject(0).getInt("count")); + Assert.assertEquals(1, stats.getJSONObject(1).getInt("count")); + // Get all tags tagResource = resource().path("/tag/list"); tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); @@ -51,15 +92,15 @@ public class TestTagResource extends BaseJerseyTest { JSONArray tags = json.getJSONArray("tags"); Assert.assertTrue(tags.length() > 0); - // Update a document - tagResource = resource().path("/tag/" + tag3Id); + // Update a tag + tagResource = resource().path("/tag/" + tag4Id); tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); postParams = new MultivaluedMapImpl(); postParams.add("name", "Updated name"); response = tagResource.post(ClientResponse.class, postParams); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); json = response.getEntity(JSONObject.class); - Assert.assertEquals(tag3Id, json.getString("id")); + Assert.assertEquals(tag4Id, json.getString("id")); // Get all tags tagResource = resource().path("/tag/list"); @@ -72,7 +113,7 @@ public class TestTagResource extends BaseJerseyTest { Assert.assertEquals("Updated name", tags.getJSONObject(0).getString("name")); // Deletes a tag - tagResource = resource().path("/tag/" + tag3Id); + tagResource = resource().path("/tag/" + tag4Id); tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); response = tagResource.delete(ClientResponse.class); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); @@ -86,6 +127,6 @@ public class TestTagResource extends BaseJerseyTest { Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); json = response.getEntity(JSONObject.class); tags = json.getJSONArray("tags"); - Assert.assertTrue(tags.length() == 0); + Assert.assertTrue(tags.length() == 1); } } \ No newline at end of file