Skip to content

Commit

Permalink
[#325] started backend implementation of readBy
Browse files Browse the repository at this point in the history
(markRead), updated liquibase and jooq classes
  • Loading branch information
mvanzalu committed Mar 12, 2020
1 parent 0e7471d commit de6d2ba
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ public interface Repository {
boolean star(User user, String documentId);
boolean unstar(User user, String documentId);
List<Document> getStarredDocuments(User user);
boolean markRead(User user, String documentId);
boolean unmarkRead(User user, String documentId);
List<String> getMarkedReadDocumentUsers(String documentId);

// project related
List<Document> getDocumentsNotTaggedWithPipeline(Project project, Pipeline.Type type);
// standalone (to remove later ?)
int star(Project project, User user, List<String> documentIds);
int unstar(Project project, User user, List<String> documentIds);
List<String> getStarredDocuments(Project project, User user);
int markRead(Project project, User user, List<String> documentIds);
int unmarkRead(Project project, User user, List<String> documentIds);
List<String> getMarkedReadDocumentUsers(Project project, String documentId);

boolean tag(Project prj, String documentId, Tag... tags);
boolean untag(Project prj, String documentId, Tag... tags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,75 @@ public Payload unstarDocument(final String docId, Context context) {
return repository.unstar((HashMapUser)context.currentUser(), docId) ? Payload.created(): Payload.ok();
}

/**
* Gets all the tags from a document with the user and timestamp.
* @param projectId
* @param docId
* @return 200 and the list of tags
*
* Example :
* $(curl http://localhost:8080/api/apigen-datashare/documents/tags/bd2ef02d39043cc5cd8c5050e81f6e73c608cafde339c9b7ed68b2919482e8dc7da92e33aea9cafec2419c97375f684f)
*/
@Get("/:project/documents/:docId/markedRead")
public List<String> getMarkedReadDocumentUsers(final String projectId,final String docId) {
return repository.getMarkedReadDocumentUsers(project(projectId),docId);
}

/**
* Group star the documents. The id list is passed in the request body as a json list.
*
* It answers 200 if the change as been done and the number of documents updated in the response body.
* @param projectId
* @param docIds as json
* @return 200 and the number of documents updated
*
* Example :
* $(curl -i -XPOST -H "Content-Type: application/json" localhost:8080/api/apigen-datashare/documents/batchUpdate/star -d '["bd2ef02d39043cc5cd8c5050e81f6e73c608cafde339c9b7ed68b2919482e8dc7da92e33aea9cafec2419c97375f684f"]')
*/
@Post("/:projectId/documents/batchUpdate/markRead")
public int groupMarkReadProject(final String projectId, final List<String> docIds, Context context) {
return repository.markRead(project(projectId), (HashMapUser)context.currentUser(), docIds);
}

/**
* Group unstar the documents. The id list is passed in the request body as a json list.
*
* It answers 200 if the change as been done and the number of documents updated in the response body.
*
* @param projectId
* @param docIds as json in body
* @return 200 and the number of documents unstarred
*
* Example :
* $(curl -i -XPOST -H "Content-Type: application/json" localhost:8080/api/apigen-datashare/documents/batchUpdate/unstar -d '["bd2ef02d39043cc5cd8c5050e81f6e73c608cafde339c9b7ed68b2919482e8dc7da92e33aea9cafec2419c97375f684f", "unknownId"]')
*/
@Post("/:project/documents/batchUpdate/unmarkRead")
public int groupUnmarkReadProject(final String projectId, final List<String> docIds, Context context) {
return repository.unmarkRead(project(projectId), (HashMapUser)context.currentUser(), docIds);
}

/**
* Mark the document read by the user with id docId
* @param docId
* @return 201 if the document has been marked else 200
* $(curl localhost:8080/api/document/markRead/bd2ef02d39043cc5cd8c5050e81f6e73c608cafde339c9b7ed68b2919482e8dc7da92e33aea9cafec2419c97375f684f)
*/
@Post("/documents/markRead/:docId")
public Payload markReadDocument(final String docId, Context context) {
return repository.markRead((HashMapUser)context.currentUser(), docId) ? Payload.created(): Payload.ok();
}

/**
* Unmark the document read by the user with id docId
* @param docId
* @return 201 if the document has been unmarked else 200
* $(curl localhost:8080/api/document/markRead/bd2ef02d39043cc5cd8c5050e81f6e73c608cafde339c9b7ed68b2919482e8dc7da92e33aea9cafec2419c97375f684f)
*/
@Post("/documents/unmarkRead/:docId")
public Payload unmarkReadDocument(final String docId, Context context) {
return repository.unmarkRead((HashMapUser)context.currentUser(), docId) ? Payload.created(): Payload.ok();
}

@NotNull
private Payload getPayload(Document doc, String index, boolean inline) throws IOException {
try (InputStream from = new SourceExtractor().getSource(project(index), doc)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,38 @@ public void testGroupUnstarDocumentWithProject() {
post("/api/prj1/documents/batchUpdate/unstar", "[\"id1\", \"id2\"]").should().respond(200);
}

@Test
public void testMarkReadDocument() {
when(repository.markRead(any(),any())).thenReturn(true).thenReturn(false);
post("/api/documents/markRead/doc_id").should().respond(201);
post("/api/documents/markRead/doc_id").should().respond(200);
}

@Test
public void testUnmarkReadDocument() {
when(repository.unmarkRead(any(),any())).thenReturn(true).thenReturn(false);
post("/api/documents/unmarkRead/doc_id").should().respond(201);
post("/api/documents/unmarkRead/doc_id").should().respond(200);
}

@Test
public void testGroupMarkReadDocumentWithProject() {
when(repository.markRead(project("prj1"), User.local(), asList("id1", "id2"))).thenReturn(2);
post("/api/prj1/documents/batchUpdate/markRead", "[\"id1\", \"id2\"]").should().respond(200);
}

@Test
public void testGroupUnmarkReadDocumentWithProject() {
when(repository.unmarkRead(project("prj1"), User.local(), asList("id1", "id2"))).thenReturn(2);
post("/api/prj1/documents/batchUpdate/unmarkRead", "[\"id1\", \"id2\"]").should().respond(200);
}

@Test
public void testGetMarkedReadDocumentUsers() {
when(repository.getMarkedReadDocumentUsers(eq(project("prj")), eq("docId"))).thenReturn(asList("user1", "user2"));
get("/api/prj/documents/docId/markedRead").should().respond(200).contain("user1").contain("user2");
}

@Test
public void testTagDocumentWithProject() throws Exception {
when(repository.tag(eq(project("prj1")), anyString(), eq(tag("tag1")), eq(tag("tag2")))).thenReturn(true).thenReturn(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.icij.datashare.db.tables.NamedEntity.NAMED_ENTITY;
import static org.icij.datashare.db.tables.Note.NOTE;
import static org.icij.datashare.db.tables.Project.PROJECT;
import static org.icij.datashare.db.tables.DocumentUserMarkRead.DOCUMENT_USER_MARK_READ;
import static org.icij.datashare.json.JsonObjectMapper.MAPPER;
import static org.icij.datashare.text.Document.Status.fromCode;
import static org.icij.datashare.text.Language.parse;
Expand Down Expand Up @@ -122,6 +123,32 @@ public List<Document> getStarredDocuments(User user) {
where(DOCUMENT_USER_STAR.USER_ID.eq(user.id)).fetch().stream().map(this::createDocumentFrom).collect(toList());
}

@Override
public boolean markRead(User user, String documentId) {
DSLContext create = DSL.using(connectionProvider, dialect);;
Result<Record1<Integer>> existResult = create.selectCount().from(DOCUMENT_USER_MARK_READ).
where(DOCUMENT_USER_MARK_READ.USER_ID.eq(user.id), DOCUMENT_USER_MARK_READ.DOC_ID.eq(documentId)).fetch();
if (existResult.get(0).value1() == 0) {
return create.insertInto(DOCUMENT_USER_MARK_READ, DOCUMENT_USER_MARK_READ.DOC_ID, DOCUMENT_USER_MARK_READ.USER_ID).
values(documentId, user.id).execute() > 0;
} else {
return false;
}
}

@Override
public boolean unmarkRead(User user, String documentId) {
return DSL.using(connectionProvider, dialect).deleteFrom(DOCUMENT_USER_MARK_READ).
where(DOCUMENT_USER_MARK_READ.DOC_ID.eq(documentId), DOCUMENT_USER_MARK_READ.USER_ID.eq(user.id)).execute() > 0;
}

@Override
public List<String> getMarkedReadDocumentUsers(String documentId) {
DSLContext create = DSL.using(connectionProvider, dialect);
return create.select(DOCUMENT_USER_MARK_READ.USER_ID).from(DOCUMENT_USER_MARK_READ).
where(DOCUMENT_USER_MARK_READ.DOC_ID.eq(documentId)).fetch().getValues(DOCUMENT_USER_MARK_READ.USER_ID);
}

// ------------- functions that don't need document migration/indexing
// they can use just the DOCUMENT_USER_STAR table thus denormalizing project information
// this could be removed later
Expand Down Expand Up @@ -150,6 +177,31 @@ public List<String> getStarredDocuments(Project project, User user) {
fetch().getValues(DOCUMENT_USER_STAR.DOC_ID);
}

@Override
public int markRead(Project project, User user, List<String> documentIds) {
InsertValuesStep3<DocumentUserMarkReadRecord, String, String, String> query = using(connectionProvider, dialect).
insertInto(DOCUMENT_USER_MARK_READ, DOCUMENT_USER_MARK_READ.DOC_ID, DOCUMENT_USER_MARK_READ.USER_ID, DOCUMENT_USER_MARK_READ.PRJ_ID);
documentIds.forEach(t -> query.values(t, user.id, project.getId()));
return query.execute();
}

@Override
public int unmarkRead(Project project, User user, List<String> documentIds) {
return DSL.using(connectionProvider, dialect).deleteFrom(DOCUMENT_USER_MARK_READ).
where(DOCUMENT_USER_MARK_READ.DOC_ID.in(documentIds),
DOCUMENT_USER_MARK_READ.USER_ID.eq(user.id),
DOCUMENT_USER_MARK_READ.PRJ_ID.eq(project.getId())).execute();
}

@Override
public List<String> getMarkedReadDocumentUsers(Project project, String documentId) {
DSLContext create = DSL.using(connectionProvider, dialect);
return create.select(DOCUMENT_USER_MARK_READ.USER_ID).from(DOCUMENT_USER_MARK_READ).
where(DOCUMENT_USER_MARK_READ.DOC_ID.eq(documentId)).
and(DOCUMENT_USER_MARK_READ.PRJ_ID.eq(project.getId())).
fetch().getValues(DOCUMENT_USER_MARK_READ.USER_ID);
}

@Override
public boolean tag(Project prj, String documentId, Tag... tags) {
InsertValuesStep5<DocumentTagRecord, String, String, String, Timestamp, String> query = using(connectionProvider, dialect).insertInto(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
databaseChangeLog:
- changeSet:
id: 25
author: mvanza
changes:
- createTable:
tableName: document_user_mark_read
columns:
- column:
name: doc_id
type: varchar(96)
constraints:
nullable: false
- column:
name: user_id
type: varchar(96)
constraints:
nullable: false
- column:
name: prj_id
type: varchar(96)

- createIndex:
indexName: document_user_mark_read_doc_id
tableName: document_user_mark_read
columns:
- column:
name: doc_id
type: varchar(96)

- createIndex:
indexName: document_user_mark_read_project_id
tableName: document_user_mark_read
columns:
- column:
name: prj_id
type: varchar(96)

- createIndex:
indexName: document_user_mark_read_user_id
tableName: document_user_mark_read
columns:
- column:
name: user_id
type: varchar(96)
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ databaseChangeLog:
- include:
file: changes/014-note.yml
relativeToChangelogFile: true
- include:
file: changes/015-markRead.yml
relativeToChangelogFile: true
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class DbSetupRule extends ExternalResource {
private final String dataSourceUrl;
private static final Operation DELETE_ALL = deleteAllFrom(
"document", "named_entity", "document_user_star", "document_tag", "batch_search",
"batch_search_query", "batch_search_result", "project", "note");
"batch_search_query", "batch_search_result", "project", "note","document_user_mark_read");

DbSetupRule(String dataSourceUrl) {
this.dataSource = createDatasource(dataSourceUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,23 @@ public void test_star_unstar_a_document_with_join() {
assertThat(repository.unstar(user, doc.getId())).isFalse();
}

@Test
public void test_markRead_unmarkRead_a_document_with_join() {
// we consider that this one is unmarked and become marked
Document doc = new Document("id", project("prj"), Paths.get("/path/to/docId"), "my doc",
FRENCH, Charset.defaultCharset(),
"text/plain", new HashMap<>(),
Document.Status.INDEXED, Pipeline.set(CORENLP, OPENNLP), 432L);
repository.create(doc);
User user = new User("userid");

assertThat(repository.markRead(user, doc.getId())).isTrue();
assertThat(repository.markRead(user, doc.getId())).isFalse();

assertThat(repository.unmarkRead(user, doc.getId())).isTrue();
assertThat(repository.unmarkRead(user, doc.getId())).isFalse();
}

@Test
public void test_save_read_project() {
assertThat(repository.save(new Project("prj", Paths.get("/source"), "10.0.*.*"))).isTrue();
Expand All @@ -134,7 +151,7 @@ public void test_get_unknown_project() {
}

@Test
public void test_group_star_unstar_a_document_without_documents() {
public void test_group_unstar_a_document_without_documents() {
User user = new User("userid");

assertThat(repository.star(project("prj"), user, asList("id1", "id2", "id3"))).isEqualTo(3);
Expand All @@ -146,6 +163,16 @@ public void test_group_star_unstar_a_document_without_documents() {
assertThat(repository.getStarredDocuments(project("prj"), user)).isEmpty();
}

@Test
public void test_group_markRead_unmarkRead_a_document_without_documents() {
User user = new User("userid");

assertThat(repository.markRead(project("prj"), user, asList("id1", "id2", "id3"))).isEqualTo(3);

assertThat(repository.unmarkRead(project("prj"), user,asList("id1", "id2"))).isEqualTo(2);
assertThat(repository.unmarkRead(project("prj"), user, singletonList("id3"))).isEqualTo(1);
}

@Test
public void test_tag_untag_a_document() {
assertThat(repository.tag(project("prj"), "doc_id", tag("tag1"), tag("tag2"))).isTrue();
Expand Down

0 comments on commit de6d2ba

Please sign in to comment.