From fa5898dbb21db0584a39bec27832b78ec84b7382 Mon Sep 17 00:00:00 2001 From: Mark Czotter Date: Wed, 10 Aug 2022 10:32:02 +0200 Subject: [PATCH] feat(core): allow querying draft resources with LATEST... ...using their current HEAD branch --- .../core/rest/codesystem/CodeSystemApiTest.java | 16 ++++++++++++++-- .../b2international/snowowl/core/Resource.java | 1 + .../core/uri/DefaultResourceURIPathResolver.java | 12 ++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/core/com.b2international.snowowl.core.rest.tests/src/com/b2international/snowowl/core/rest/codesystem/CodeSystemApiTest.java b/core/com.b2international.snowowl.core.rest.tests/src/com/b2international/snowowl/core/rest/codesystem/CodeSystemApiTest.java index f2b5ea84933..50f42ea5ecf 100644 --- a/core/com.b2international.snowowl.core.rest.tests/src/com/b2international/snowowl/core/rest/codesystem/CodeSystemApiTest.java +++ b/core/com.b2international.snowowl.core.rest.tests/src/com/b2international/snowowl/core/rest/codesystem/CodeSystemApiTest.java @@ -25,8 +25,7 @@ import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.iterableWithSize; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import java.time.LocalDate; import java.util.List; @@ -45,6 +44,7 @@ import com.b2international.snowowl.core.branch.Branch; import com.b2international.snowowl.core.branch.Branches; import com.b2international.snowowl.core.codesystem.CodeSystem; +import com.b2international.snowowl.core.codesystem.CodeSystemRequests; import com.b2international.snowowl.core.date.EffectiveTimes; import com.b2international.snowowl.core.domain.IComponent; import com.b2international.snowowl.core.id.IDs; @@ -624,6 +624,18 @@ public void codesystem32_NonexistentBundleErrorShouldNotCreateUnderlyingBranchAs assertThat(branches).isEmpty(); } + @Test + public void codesystem33_AllowDraftResourcesToBeQueriedWithLATEST() throws Exception { + assertCodeSystemCreate(prepareCodeSystemCreateRequestBody("cs33").with("status", "draft")).statusCode(201); + // this should proceed without any errors from now on, if it throws an error then that is a failure of the test + CodeSystemRequests.prepareSearchConcepts() + .setLimit(0) + .filterByCodeSystemUri(CodeSystem.uri("cs33", ResourceURI.LATEST)) + .buildAsync() + .execute(Services.bus()) + .getSync(); + } + private long getCodeSystemCreatedAt(final String id) { return assertCodeSystemGet(id) .statusCode(200) diff --git a/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/Resource.java b/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/Resource.java index 07f73a51062..200e58aee7c 100644 --- a/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/Resource.java +++ b/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/Resource.java @@ -36,6 +36,7 @@ public abstract class Resource implements Serializable { // known retired status value from FHIR, TODO make it configurable when needed public static final String RETIRED_STATUS = "retired"; + public static final String DRAFT_STATUS = "draft"; /** * @since 8.0 diff --git a/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/uri/DefaultResourceURIPathResolver.java b/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/uri/DefaultResourceURIPathResolver.java index 1ca8fd3d195..cac7fedd0ad 100644 --- a/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/uri/DefaultResourceURIPathResolver.java +++ b/core/com.b2international.snowowl.core/src/com/b2international/snowowl/core/uri/DefaultResourceURIPathResolver.java @@ -68,8 +68,7 @@ public PathWithVersion resolveWithVersion(ServiceProvider context, ResourceURI u TerminologyResource terminologyResource = (TerminologyResource) resource; if (uriToResolve.isHead()) { // use code system working branch directly when HEAD is specified - final String workingBranchPath = terminologyResource.getBranchPath() + uriToResolve.getTimestampPart(); - return new PathWithVersion(workingBranchPath); + return getResourceHeadBranch(uriToResolve, terminologyResource); } // prevent running version search if path does not look like a versionId (single path segment) @@ -103,6 +102,10 @@ public PathWithVersion resolveWithVersion(ServiceProvider context, ResourceURI u return new PathWithVersion(versionBranchPath, versionResourceURI); }) .orElseGet(() -> { + // for draft resources allow HEAD to be queried via LATEST + if (uriToResolve.isLatest() && Resource.DRAFT_STATUS.equals(terminologyResource.getStatus())) { + return getResourceHeadBranch(uriToResolve, terminologyResource); + } if (uriToResolve.isLatest() || !allowBranches) { throw new BadRequestException("No Resource version is present in '%s'. Explicit '%s' can be used to retrieve the latest work in progress version of the Resource.", terminologyResource.getId(), terminologyResource.getId()); @@ -114,4 +117,9 @@ public PathWithVersion resolveWithVersion(ServiceProvider context, ResourceURI u return new PathWithVersion(""); } + + private PathWithVersion getResourceHeadBranch(ResourceURI uriToResolve, TerminologyResource terminologyResource) { + final String workingBranchPath = terminologyResource.getBranchPath() + uriToResolve.getTimestampPart(); + return new PathWithVersion(workingBranchPath); + } }