Skip to content

Commit

Permalink
Merge pull request #15 from protegeproject/6-change-history-for-a-sin…
Browse files Browse the repository at this point in the history
…gle-entity

added handler for GetEntityHistorySummaryRequest
  • Loading branch information
alexsilaghi authored Nov 21, 2024
2 parents 22105fc + a6d1435 commit c7af8b6
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto;

import edu.stanford.protege.webprotege.common.UserId;

import java.time.LocalDateTime;

public record EntityChange(String changeSummary,
UserId userId,
LocalDateTime dateTime) {

public static EntityChange create(String changeSummary,
UserId userId,
LocalDateTime dateTime){
return new EntityChange(changeSummary,userId,dateTime);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto;

import java.util.List;

public record EntityHistorySummary(List<EntityChange> changes) {
public static EntityHistorySummary create(List<EntityChange> changes) {
return new EntityHistorySummary(changes);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.handlers;

import edu.stanford.protege.webprotege.common.ProjectId;
import edu.stanford.protege.webprotege.ipc.*;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto.EntityHistorySummary;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.services.NewRevisionsEventService;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.Nonnull;

@Component
public class GetEntityHistorySummaryCommandHandler implements CommandHandler<GetEntityHistorySummaryRequest, GetEntityHistorySummaryResponse> {

private final NewRevisionsEventService service;

public GetEntityHistorySummaryCommandHandler(NewRevisionsEventService service) {
this.service = service;
}


@Nonnull
@Override
public String getChannelName() {
return GetEntityHistorySummaryRequest.CHANNEL;
}

@Override
public Class<GetEntityHistorySummaryRequest> getRequestClass() {
return GetEntityHistorySummaryRequest.class;
}

@Override
public Mono<GetEntityHistorySummaryResponse> handleRequest(GetEntityHistorySummaryRequest request, ExecutionContext executionContext) {
EntityHistorySummary entityHistorySummary = service.getEntityHistorySummary(ProjectId.valueOf(request.projectId()), request.entityIri());
return Mono.just(GetEntityHistorySummaryResponse.create(entityHistorySummary));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.handlers;

import com.fasterxml.jackson.annotation.*;
import edu.stanford.protege.webprotege.common.Request;

@JsonTypeName(GetEntityHistorySummaryRequest.CHANNEL)
public record GetEntityHistorySummaryRequest(
@JsonProperty("projectId") String projectId,
@JsonProperty("entityIri") String entityIri
) implements Request<GetEntityHistorySummaryResponse> {

public static final String CHANNEL = "webprotege.history.GetEntityHistorySummary";

public static GetEntityHistorySummaryRequest create(String projectId,
String entityIri) {
return new GetEntityHistorySummaryRequest(projectId, entityIri);
}

@Override
public String getChannel() {
return CHANNEL;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.handlers;

import com.fasterxml.jackson.annotation.*;
import edu.stanford.protege.webprotege.common.Response;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto.EntityHistorySummary;

import static edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.handlers.GetEntityHistorySummaryRequest.CHANNEL;

@JsonTypeName(CHANNEL)
public record GetEntityHistorySummaryResponse(
@JsonProperty("entityHistorySummary") EntityHistorySummary entityHistorySummary
) implements Response {
public static GetEntityHistorySummaryResponse create(EntityHistorySummary entityHistorySummary) {
return new GetEntityHistorySummaryResponse(entityHistorySummary);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.repositories;

import edu.stanford.protege.webprotege.common.ProjectId;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.events.RevisionsEvent;
import org.springframework.data.mongodb.repository.*;

Expand All @@ -8,4 +9,7 @@
public interface RevisionsEventRepository extends MongoRepository<RevisionsEvent, String> {
@Query("{ 'projectId.id': ?0, 'timestamp': { $gt: ?1 } }")
List<RevisionsEvent> findByProjectIdAndTimestampAfter(String projectId, long timestamp);

List<RevisionsEvent> findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(ProjectId projectId, String whoficEntityIri);

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import edu.stanford.protege.webprotege.change.ProjectChange;
import edu.stanford.protege.webprotege.common.*;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto.ChangedEntities;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto.*;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.events.NewRevisionsEvent;
import org.semanticweb.owlapi.model.OWLEntity;

Expand All @@ -16,4 +16,6 @@ public interface NewRevisionsEventService {
Page<ProjectChange> fetchPaginatedProjectChanges(ProjectId projectId, Optional<OWLEntity> subject, int pageNumber, int pageSize);

ChangedEntities getChangedEntitiesAfterTimestamp(ProjectId projectId, Timestamp timestamp);

EntityHistorySummary getEntityHistorySummary(ProjectId projectId, String entityIri);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -99,4 +100,20 @@ private static List<String> groupByChangeType(List<RevisionsEvent> revisionsEven
.distinct()
.collect(Collectors.toList());
}

@Override
public EntityHistorySummary getEntityHistorySummary(ProjectId projectId, String entityIri) {
List<RevisionsEvent> revisionsForEntity = repository.findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri);
List<EntityChange> entityChanges = revisionsForEntity.stream()
.map(revisionEvent -> {
ProjectChange projectChange = projectChangeMapper.mapProjectChangeDocumentToProjectChange(revisionEvent.projectChange());
Instant instant = Instant.ofEpochMilli(projectChange.getTimestamp());
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC"));
return EntityChange.create(projectChange.getSummary(), projectChange.getAuthor(), localDateTime);
}
).toList();


return EntityHistorySummary.create(entityChanges);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import edu.stanford.protege.webprotege.change.ProjectChange;
import edu.stanford.protege.webprotege.common.Page;
import edu.stanford.protege.webprotege.common.*;
import edu.stanford.protege.webprotege.revision.RevisionNumber;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.dto.*;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.events.*;
import edu.stanford.protege.webprotegeeventshistory.uiHistoryConcern.mappers.*;
Expand All @@ -17,6 +18,7 @@
import org.springframework.data.domain.*;

import java.sql.Timestamp;
import java.time.*;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;
Expand Down Expand Up @@ -183,4 +185,92 @@ public void GIVEN_multipleEntitiesChangedAfterTimestamp_WHEN_getChangedEntitiesA

verify(repository).findByProjectIdAndTimestampAfter(projectId.id(), timestamp.getTime());
}

@Test
public void GIVEN_noHistoryForEntity_WHEN_getEntityHistorySummaryCalled_THEN_returnEmptyHistorySummary() {
String entityIri = "http://example.com/entity1";

when(repository.findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri))
.thenReturn(Collections.emptyList());

EntityHistorySummary result = service.getEntityHistorySummary(projectId, entityIri);

assertNotNull(result);
assertTrue(result.changes().isEmpty());

verify(repository).findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri);
}

@Test
public void GIVEN_validHistoryForEntity_WHEN_getEntityHistorySummaryCalled_THEN_returnMappedHistorySummary() {
String entityIri = "http://example.com/entity1";
long timestamp1 = 1234567890123L;
long timestamp2 = 1234567890124L;
UserId userId1 = UserId.valueOf("user1");
UserId userId2 = UserId.valueOf("user2");

Document document1 = new Document("a", "b");
Document document2 = new Document("c", "d");

RevisionsEvent eventCreate = RevisionsEvent.create(projectId, entityIri, ChangeType.CREATE_ENTITY, timestamp2, document2);
RevisionsEvent eventUpdate = RevisionsEvent.create(projectId, entityIri, ChangeType.UPDATE_ENTITY, timestamp1, document1);

ProjectChange changeCreate = ProjectChange.get(
RevisionNumber.getRevisionNumber(1),
userId1,
timestamp1,
"Create",
1,
Page.emptyPage()
);
ProjectChange changeUpdate = ProjectChange.get(
RevisionNumber.getRevisionNumber(2),
userId2,
timestamp2,
"Update",
1,
Page.emptyPage()
);

when(repository.findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri))
.thenReturn(List.of(eventUpdate, eventCreate));
when(projectChangeMapper.mapProjectChangeDocumentToProjectChange(eq(eventCreate.projectChange())))
.thenReturn(changeCreate);
when(projectChangeMapper.mapProjectChangeDocumentToProjectChange(eq(eventUpdate.projectChange())))
.thenReturn(changeUpdate);

EntityHistorySummary result = service.getEntityHistorySummary(projectId, entityIri);

assertNotNull(result);
assertEquals(2, result.changes().size());

EntityChange entityUpdate = result.changes().get(0);
assertEquals("Update", entityUpdate.changeSummary());
assertEquals(userId2, entityUpdate.userId());
assertEquals(LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp2), ZoneId.of("UTC")), entityUpdate.dateTime());

EntityChange entityCreate = result.changes().get(1);
assertEquals("Create", entityCreate.changeSummary());
assertEquals(userId1, entityCreate.userId());
assertEquals(LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp1), ZoneId.of("UTC")), entityCreate.dateTime());

verify(repository).findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri);
verify(projectChangeMapper).mapProjectChangeDocumentToProjectChange(eventCreate.projectChange());
verify(projectChangeMapper).mapProjectChangeDocumentToProjectChange(eventUpdate.projectChange());
}

@Test
public void GIVEN_emptyHistory_WHEN_getEntityHistorySummaryCalled_THEN_returnEmptySummary() {
String entityIri = "http://example.com/entity2";

when(repository.findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri))
.thenReturn(Collections.emptyList());

EntityHistorySummary result = service.getEntityHistorySummary(projectId, entityIri);

assertNotNull(result);
assertTrue(result.changes().isEmpty());

verify(repository).findByProjectIdAndWhoficEntityIriOrderByTimestampDesc(projectId, entityIri);
}
}

0 comments on commit c7af8b6

Please sign in to comment.