Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.wooteco.wiki.graph.repository;

import java.util.UUID;

public record CrewGraphNodeReadModel(
UUID documentUuid,
String title
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

public interface CrewGraphQueryRepository {

List<CrewGraphNodeReadModel> findAllGraphNodesByGenerationTitle(String generationTitle);

List<CrewGraphReadModel> findAllCrewDocumentsByGenerationTitle(String generationTitle);

List<UUID> findAllCrewDocumentUuidsByGenerationTitleAndOrganizationDocumentUuid(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.wooteco.wiki.graph.repository;

import java.util.UUID;

public record DocumentReferenceReadModel(
UUID sourceDocumentUuid,
UUID targetDocumentUuid
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,36 @@
import com.wooteco.wiki.graph.domain.DocumentReference;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface DocumentReferenceRepository extends JpaRepository<DocumentReference, Long> {

List<DocumentReference> findAllBySourceDocument(CrewDocument sourceDocument);

@Query("""
SELECT new com.wooteco.wiki.graph.repository.DocumentReferenceReadModel(
documentReference.sourceDocument.uuid,
documentReference.targetDocument.uuid
)
FROM DocumentReference documentReference
WHERE documentReference.sourceDocument IN (
SELECT sourceGenerationLink.crewDocument
FROM DocumentOrganizationLink sourceGenerationLink
WHERE sourceGenerationLink.organizationDocument.title = :generationTitle
)
AND documentReference.targetDocument IN (
SELECT targetGenerationLink.crewDocument
FROM DocumentOrganizationLink targetGenerationLink
WHERE targetGenerationLink.organizationDocument.title = :generationTitle
)
AND TYPE(documentReference.targetDocument) = CrewDocument
ORDER BY documentReference.sourceDocument.uuid, documentReference.targetDocument.uuid
""")
List<DocumentReferenceReadModel> findAllReadModelsByGenerationTitle(
@Param("generationTitle") String generationTitle
);

void deleteAllBySourceDocument(CrewDocument sourceDocument);

void deleteAllByTargetDocument(Document targetDocument);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.wooteco.wiki.document.domain.CrewDocument;
import com.wooteco.wiki.document.repository.GenerationCrewOrganizationReadModel;
import com.wooteco.wiki.document.repository.GenerationCrewQueryRepository;
import com.wooteco.wiki.graph.repository.CrewGraphNodeReadModel;
import com.wooteco.wiki.graph.repository.CrewGraphQueryRepository;
import com.wooteco.wiki.graph.repository.CrewGraphReadModel;
import com.wooteco.wiki.organizationdocument.domain.DocumentOrganizationLink;
Expand Down Expand Up @@ -57,6 +58,21 @@ List<GenerationCrewOrganizationReadModel> findAllByGenerationTitle(
@Param("generationTitle") String generationTitle
);

@Override
@Query("""
SELECT new com.wooteco.wiki.graph.repository.CrewGraphNodeReadModel(
crewDocument.uuid,
crewDocument.title
)
FROM DocumentOrganizationLink documentOrganizationLink
JOIN documentOrganizationLink.crewDocument crewDocument
WHERE documentOrganizationLink.organizationDocument.title = :generationTitle
ORDER BY crewDocument.title
""")
List<CrewGraphNodeReadModel> findAllGraphNodesByGenerationTitle(
@Param("generationTitle") String generationTitle
);

@Override
@Query("""
SELECT new com.wooteco.wiki.graph.repository.CrewGraphReadModel(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.wooteco.wiki.graph.repository;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;

import com.wooteco.wiki.document.domain.CrewDocument;
import com.wooteco.wiki.document.fixture.CrewDocumentFixture;
Expand Down Expand Up @@ -34,6 +35,38 @@ class CrewGraphQueryRepositoryTest {
@Autowired
private DocumentOrganizationLinkRepository documentOrganizationLinkRepository;

@Nested
@DisplayName("기수에 연결된 그래프 노드를 조회할 때")
class FindAllGraphNodesByGenerationTitle {

@Test
@DisplayName("해당 기수의 크루 문서만 title 순으로 반환한다.")
void findAllGraphNodesByGenerationTitle_success_byCrewDocumentsInGenerationSortedByTitle() {
// given
OrganizationDocument eighthGeneration = saveOrganizationDocument("8기");
OrganizationDocument seventhGeneration = saveOrganizationDocument("7기");
CrewDocument firstEighthCrew = saveCrewDocument("가람(8기)");
CrewDocument secondEighthCrew = saveCrewDocument("나래(8기)");
CrewDocument seventhCrew = saveCrewDocument("다온(7기)");
saveCrewDocument("라온(미연결)");
saveLink(firstEighthCrew, eighthGeneration);
saveLink(secondEighthCrew, eighthGeneration);
saveLink(seventhCrew, seventhGeneration);

// when
List<CrewGraphNodeReadModel> nodes = crewGraphQueryRepository
.findAllGraphNodesByGenerationTitle("8기");

// then
assertThat(nodes)
.extracting(CrewGraphNodeReadModel::documentUuid, CrewGraphNodeReadModel::title)
.containsExactly(
tuple(firstEighthCrew.getUuid(), "가람(8기)"),
tuple(secondEighthCrew.getUuid(), "나래(8기)")
);
}
}

@Nested
@DisplayName("기수와 조직에 모두 연결된 크루 문서 UUID를 조회할 때")
class FindAllCrewDocumentUuidsByGenerationTitleAndOrganizationDocumentUuid {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.wooteco.wiki.graph.repository;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.SoftAssertions.assertSoftly;
import static org.assertj.core.groups.Tuple.tuple;

import com.wooteco.wiki.document.domain.CrewDocument;
import com.wooteco.wiki.document.domain.Document;
Expand All @@ -11,8 +13,11 @@
import com.wooteco.wiki.document.repository.DocumentRepository;
import com.wooteco.wiki.graph.domain.DocumentReference;
import com.wooteco.wiki.graph.fixture.DocumentReferenceFixture;
import com.wooteco.wiki.organizationdocument.domain.DocumentOrganizationLink;
import com.wooteco.wiki.organizationdocument.domain.OrganizationDocument;
import com.wooteco.wiki.organizationdocument.fixture.DocumentOrganizationLinkFixture;
import com.wooteco.wiki.organizationdocument.fixture.OrganizationDocumentFixture;
import com.wooteco.wiki.organizationdocument.repository.DocumentOrganizationLinkRepository;
import com.wooteco.wiki.organizationdocument.repository.OrganizationDocumentRepository;
import jakarta.persistence.EntityManager;
import java.util.List;
Expand All @@ -35,6 +40,9 @@ class DocumentReferenceRepositoryTest {
@Autowired
private OrganizationDocumentRepository organizationDocumentRepository;

@Autowired
private DocumentOrganizationLinkRepository documentOrganizationLinkRepository;

@Autowired
private DocumentRepository documentRepository;

Expand Down Expand Up @@ -183,6 +191,75 @@ void findAllBySourceDocument_success_byExistingReferences() {
}
}

@Nested
class FindAllReadModelsByGenerationTitle {

@Test
void findAllReadModelsByGenerationTitle_success_byDirectionalReferencesSortedByUuid() {
// given
OrganizationDocument generation = saveOrganizationDocument("8기");
UUID firstSourceUuid = UUID.fromString("00000000-0000-0000-0000-000000000001");
UUID secondSourceUuid = UUID.fromString("00000000-0000-0000-0000-000000000002");
CrewDocument firstSourceDocument = saveCrewDocument("first-source", firstSourceUuid);
CrewDocument secondSourceDocument = saveCrewDocument("second-source", secondSourceUuid);
saveLink(firstSourceDocument, generation);
saveLink(secondSourceDocument, generation);
saveAndFlushReference(firstSourceDocument, secondSourceDocument);
saveAndFlushReference(secondSourceDocument, firstSourceDocument);

// when
List<DocumentReferenceReadModel> readModels = documentReferenceRepository
.findAllReadModelsByGenerationTitle("8기");

// then
assertThat(readModels)
.extracting(
DocumentReferenceReadModel::sourceDocumentUuid,
DocumentReferenceReadModel::targetDocumentUuid
)
.containsExactly(
tuple(firstSourceUuid, secondSourceUuid),
tuple(secondSourceUuid, firstSourceUuid)
);
}

@Test
void findAllReadModelsByGenerationTitle_success_bySameGenerationCrewMembership() {
// given
OrganizationDocument eighthGeneration = saveOrganizationDocument("8기");
OrganizationDocument seventhGeneration = saveOrganizationDocument("7기");
CrewDocument sourceDocument = saveCrewDocument("source");
CrewDocument otherGenerationSourceDocument = saveCrewDocument("other-generation-source");
CrewDocument sameGenerationTargetDocument = saveCrewDocument("same-generation-target");
CrewDocument otherGenerationTargetDocument = saveCrewDocument("other-generation-target");
CrewDocument unlinkedTargetDocument = saveCrewDocument("unlinked-target");
OrganizationDocument organizationTargetDocument = saveOrganizationDocument("organization-target");
saveLink(sourceDocument, eighthGeneration);
saveLink(otherGenerationSourceDocument, seventhGeneration);
saveLink(sameGenerationTargetDocument, eighthGeneration);
saveLink(otherGenerationTargetDocument, seventhGeneration);
saveAndFlushReference(sourceDocument, sameGenerationTargetDocument);
saveAndFlushReference(sourceDocument, otherGenerationTargetDocument);
saveAndFlushReference(otherGenerationSourceDocument, sameGenerationTargetDocument);
saveAndFlushReference(sourceDocument, unlinkedTargetDocument);
saveAndFlushReference(sourceDocument, organizationTargetDocument);

// when
List<DocumentReferenceReadModel> readModels = documentReferenceRepository
.findAllReadModelsByGenerationTitle("8기");

// then
assertThat(readModels)
.extracting(
DocumentReferenceReadModel::sourceDocumentUuid,
DocumentReferenceReadModel::targetDocumentUuid
)
.containsExactly(
tuple(sourceDocument.getUuid(), sameGenerationTargetDocument.getUuid())
);
}
}

@Nested
class DeleteAllBySourceDocument {

Expand Down Expand Up @@ -270,12 +347,16 @@ void delete_success_withoutDocumentCascade() {
}

private CrewDocument saveCrewDocument(String title) {
return saveCrewDocument(title, UUID.randomUUID());
}

private CrewDocument saveCrewDocument(String title, UUID uuid) {
CrewDocument crewDocument = CrewDocumentFixture.createCrewDocument(
title,
"contents",
"writer",
10L,
UUID.randomUUID()
uuid
);
return crewDocumentRepository.save(crewDocument);
}
Expand All @@ -291,6 +372,17 @@ private OrganizationDocument saveOrganizationDocument(String title) {
return organizationDocumentRepository.save(organizationDocument);
}

private void saveLink(
CrewDocument crewDocument,
OrganizationDocument organizationDocument
) {
DocumentOrganizationLink link = DocumentOrganizationLinkFixture.create(
crewDocument,
organizationDocument
);
documentOrganizationLinkRepository.save(link);
}

private DocumentReference saveReference(
CrewDocument sourceDocument,
Document targetDocument
Expand Down
Loading