All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.projectnessie.api.v2.http.HttpTreeApi Maven / Gradle / Ivy

There is a newer version: 0.97.1
Show newest version
/*
 * Copyright (C) 2022 Dremio
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.projectnessie.api.v2.http;

import static org.projectnessie.api.v2.doc.ApiDoc.CHECKED_REF_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.CHECKED_REF_INFO;
import static org.projectnessie.api.v2.doc.ApiDoc.COMMIT_BRANCH_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.FOR_WRITE_PARAMETER_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.KEY_PARAMETER_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.MERGE_TRANSPLANT_BRANCH_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.PAGING_INFO;
import static org.projectnessie.api.v2.doc.ApiDoc.REF_NAME_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.REF_PARAMETER_DESCRIPTION;
import static org.projectnessie.api.v2.doc.ApiDoc.WITH_DOC_PARAMETER_DESCRIPTION;
import static org.projectnessie.model.Validation.REF_NAME_PATH_ELEMENT_REGEX;

import com.fasterxml.jackson.annotation.JsonView;
import java.util.List;
import javax.validation.constraints.Pattern;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.projectnessie.api.v2.TreeApi;
import org.projectnessie.api.v2.params.CommitLogParams;
import org.projectnessie.api.v2.params.DiffParams;
import org.projectnessie.api.v2.params.EntriesParams;
import org.projectnessie.api.v2.params.GetReferenceParams;
import org.projectnessie.api.v2.params.Merge;
import org.projectnessie.api.v2.params.ReferenceHistoryParams;
import org.projectnessie.api.v2.params.ReferencesParams;
import org.projectnessie.api.v2.params.Transplant;
import org.projectnessie.error.NessieConflictException;
import org.projectnessie.error.NessieNotFoundException;
import org.projectnessie.model.CommitResponse;
import org.projectnessie.model.ContentKey;
import org.projectnessie.model.ContentResponse;
import org.projectnessie.model.DiffResponse;
import org.projectnessie.model.EntriesResponse;
import org.projectnessie.model.GetMultipleContentsRequest;
import org.projectnessie.model.GetMultipleContentsResponse;
import org.projectnessie.model.LogResponse;
import org.projectnessie.model.MergeResponse;
import org.projectnessie.model.Operations;
import org.projectnessie.model.Reference;
import org.projectnessie.model.ReferenceHistoryResponse;
import org.projectnessie.model.ReferencesResponse;
import org.projectnessie.model.SingleReferenceResponse;
import org.projectnessie.model.Validation;
import org.projectnessie.model.ser.Views;

@Consumes(MediaType.APPLICATION_JSON)
@jakarta.ws.rs.Consumes(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
@Path("v2/trees")
@jakarta.ws.rs.Path("v2/trees")
@Tag(name = "v2")
public interface HttpTreeApi extends TreeApi {

  @Override
  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Operation(
      summary = "Get information about all branches and tags",
      operationId = "getAllReferencesV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Returned references.",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = {
                  @ExampleObject(ref = "referencesResponse"),
                  @ExampleObject(ref = "referencesResponseWithMetadata")
                },
                schema = @Schema(implementation = ReferencesResponse.class))),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
  })
  @JsonView(Views.V2.class)
  ReferencesResponse getAllReferences(@BeanParam @jakarta.ws.rs.BeanParam ReferencesParams params);

  @Override
  @POST
  @jakarta.ws.rs.POST
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Operation(
      summary = "Create a new branch or tag",
      description =
          "The name and type query parameters define the kind of reference to be created. "
              + "The payload object defines the new reference's origin in the commit history. "
              + "\n"
              + "Only branches and tags can be created by this method, but the payload object may be any"
              + " valid reference, including a detached commit."
              + "\n"
              + "If the payload reference object does not define a commit hash, the HEAD of that reference "
              + "will be used.",
      operationId = "createReferenceV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Created successfully.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {@ExampleObject(ref = "singleReferenceResponse")},
              schema = @Schema(implementation = SingleReferenceResponse.class))
        }),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(responseCode = "403", description = "Not allowed to create reference"),
    @APIResponse(
        responseCode = "409",
        description = "Another reference with the same name already exists"),
  })
  @JsonView(Views.V2.class)
  SingleReferenceResponse createReference(
      @Parameter(required = true, description = REF_NAME_DESCRIPTION)
          @QueryParam("name")
          @jakarta.ws.rs.QueryParam("name")
          String name,
      @Parameter(
              required = true,
              description = "Type of the reference to be created",
              examples = {@ExampleObject(ref = "referenceType")})
          @QueryParam("type")
          @jakarta.ws.rs.QueryParam("type")
          String type,
      @RequestBody(
              required = true,
              description = "Source reference data from which the new reference is to be created.",
              content = {
                @Content(
                    mediaType = MediaType.APPLICATION_JSON,
                    examples = {@ExampleObject(ref = "refObjNew")})
              })
          Reference reference)
      throws NessieNotFoundException, NessieConflictException;

  @Override
  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}")
  @Operation(summary = "Fetch details of a reference", operationId = "getReferenceByNameV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Found and returned reference.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {
                @ExampleObject(ref = "singleReferenceResponse"),
                @ExampleObject(ref = "singleReferenceResponseWithMetadata")
              },
              schema = @Schema(implementation = SingleReferenceResponse.class))
        }),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(responseCode = "403", description = "Not allowed to view the given reference"),
    @APIResponse(responseCode = "404", description = "Ref not found")
  })
  @JsonView(Views.V2.class)
  SingleReferenceResponse getReferenceByName(
      @BeanParam @jakarta.ws.rs.BeanParam GetReferenceParams params) throws NessieNotFoundException;

  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/recent-changes")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/recent-changes")
  @Operation(
      summary = "Fetch recent pointer changes of a reference",
      operationId = "getReferenceHistory",
      description =
          "Retrieve the recorded recent history of a reference.\n"
              + "\n"
              + "A reference's history is a size and time limited record of changes of the reference's "
              + "current pointer, aka HEAD. The size and time limits are configured in the Nessie server "
              + "configuration.\n"
              + "\n"
              + "This function is only useful for deployments using replicating multi-zone/region database "
              + "setups. If the \"primary write target\" fails and cannot be recovered, replicas might not "
              + "have all written records (data loss scenario). This function helps identifying whether "
              + "the commits of a reference that were written within the configured \"replication lag\" are "
              + "present and consistent. A reference might then be deleted or re-assigned to a consistent commit.")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Found and returned reference.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {@ExampleObject(ref = "referenceHistoryResponse")},
              schema = @Schema(implementation = ReferenceHistoryResponse.class))
        }),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(responseCode = "403", description = "Not allowed to view the given reference"),
    @APIResponse(responseCode = "404", description = "Reference not found")
  })
  @JsonView(Views.V2.class)
  @Override
  ReferenceHistoryResponse getReferenceHistory(
      @BeanParam @jakarta.ws.rs.BeanParam ReferenceHistoryParams params)
      throws NessieNotFoundException;

  @Override
  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/entries")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/entries")
  @Operation(
      summary = "Fetch all entries for a given reference",
      description =
          "Retrieves objects for a ref, potentially truncated by the backend.\n"
              + "\n"
              + "Retrieves up to 'maxRecords' entries for the "
              + "given named reference (tag or branch) or the given hash. "
              + "The backend may respect the given 'max' records hint, but return less or more entries. "
              + "Backends may also cap the returned entries at a hard-coded limit, the default "
              + "REST server implementation has such a hard-coded limit.\n"
              + "\n"
              + PAGING_INFO
              + "\n"
              + "The 'filter' parameter allows for advanced filtering capabilities using the Common Expression Language (CEL).\n"
              + "An intro to CEL can be found at https://github.com/google/cel-spec/blob/master/doc/intro.md.\n",
      operationId = "getEntriesV2")
  @APIResponses({
    @APIResponse(
        description = "List names and object types in a contents tree",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {@ExampleObject(ref = "entriesResponseV2")},
              schema = @Schema(implementation = EntriesResponse.class))
        }),
    @APIResponse(responseCode = "200", description = "Returned successfully."),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or fetch entries for it"),
    @APIResponse(responseCode = "404", description = "Ref not found")
  })
  @JsonView(Views.V2.class)
  EntriesResponse getEntries(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = REF_PARAMETER_DESCRIPTION,
              examples = {
                @ExampleObject(ref = "ref"),
                @ExampleObject(ref = "refWithHash"),
                @ExampleObject(
                    ref = "refWithTimestampMillisSinceEpoch",
                    description =
                        "The commit 'valid for' the timestamp 1685185847230 in ms since epoch on main"),
                @ExampleObject(
                    ref = "refWithTimestampInstant",
                    description = "The commit 'valid for' the given ISO-8601 instant on main"),
                @ExampleObject(
                    ref = "refWithNthPredecessor",
                    description = "The 10th commit from HEAD of main"),
                @ExampleObject(
                    ref = "refWithMergeParent",
                    description =
                        "References the merge-parent of commit 2e1cfa82b035c26cbbbdae632cea070514eb8b773f616aaeaf668e2f0be8f10d on main"),
                @ExampleObject(ref = "refDefault"),
                @ExampleObject(ref = "refDetached"),
              })
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref,
      @BeanParam @jakarta.ws.rs.BeanParam EntriesParams params)
      throws NessieNotFoundException;

  @Override
  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history")
  @Operation(
      summary = "Get commit log for a particular reference",
      description =
          "Retrieve the commit log for a reference, potentially truncated by the backend.\n"
              + "\n"
              + "The backend may respect the given 'max-entries' records hint, or may return more or less entries. "
              + "Backends may also cap the returned entries at a hard-coded limit\n"
              + "\n"
              + PAGING_INFO
              + "\n"
              + "The 'filter' parameter allows for advanced filtering capabilities using the Common Expression Language (CEL).\n"
              + "An intro to CEL can be found at https://github.com/google/cel-spec/blob/master/doc/intro.md.\n"
              + "\n"
              + "The fetching of the log starts from the HEAD of the given ref (or a more specific commit, if provided "
              + "as part of the 'ref' path element) and proceeds until the 'root' commit or the 'limit-hash' commit "
              + "are encountered.",
      operationId = "getCommitLogV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Returned commits.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {
                @ExampleObject(ref = "logResponseAdditionalInfo"),
                @ExampleObject(ref = "logResponseSimple")
              },
              schema = @Schema(implementation = LogResponse.class))
        }),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or get commit log for it"),
    @APIResponse(responseCode = "404", description = "Ref doesn't exists")
  })
  @JsonView(Views.V2.class)
  LogResponse getCommitLog(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = REF_PARAMETER_DESCRIPTION,
              examples = {
                @ExampleObject(ref = "ref"),
                @ExampleObject(ref = "refWithHash"),
                @ExampleObject(
                    ref = "refWithTimestampMillisSinceEpoch",
                    description =
                        "The commit 'valid for' the timestamp 1685185847230 in ms since epoch on main"),
                @ExampleObject(
                    ref = "refWithTimestampInstant",
                    description = "The commit 'valid for' the given ISO-8601 instant on main"),
                @ExampleObject(
                    ref = "refWithNthPredecessor",
                    description = "The 10th commit from HEAD of main"),
                @ExampleObject(
                    ref = "refWithMergeParent",
                    description =
                        "References the merge-parent of commit 2e1cfa82b035c26cbbbdae632cea070514eb8b773f616aaeaf668e2f0be8f10d on main"),
                @ExampleObject(ref = "refDefault"),
                @ExampleObject(ref = "refDetached"),
              })
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref,
      @BeanParam @jakarta.ws.rs.BeanParam CommitLogParams params)
      throws NessieNotFoundException;

  @Override
  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path(
      "{from-ref:"
          + REF_NAME_PATH_ELEMENT_REGEX
          + "}/diff/{to-ref:"
          + REF_NAME_PATH_ELEMENT_REGEX
          + "}")
  @jakarta.ws.rs.Path(
      "{from-ref:"
          + REF_NAME_PATH_ELEMENT_REGEX
          + "}/diff/{to-ref:"
          + REF_NAME_PATH_ELEMENT_REGEX
          + "}")
  @Operation(
      summary = "Get contents that differ in the trees specified by the two given references",
      description =
          "The URL pattern is basically 'from' and 'to' reference specs separated by '/diff/'\n"
              + "\n"
              + "Examples: \n"
              + "- main/diff/myBranch\n"
              + "- main@1234567890123456/diff/myBranch\n"
              + "- main@1234567890123456/diff/myBranch@23445678\n"
              + "- main/diff/myBranch@23445678\n"
              + "- main/diff/myBranch@23445678\n"
              + "- my/branch@/diff/main\n"
              + "- myBranch/diff/-\n",
      operationId = "getDiffV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Returned diff for the given references.",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = {
                  @ExampleObject(ref = "diffResponseWithRef"),
                },
                schema = @Schema(implementation = DiffResponse.class))),
    @APIResponse(responseCode = "400", description = "Invalid input, fromRef/toRef name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(responseCode = "403", description = "Not allowed to view the given fromRef/toRef"),
    @APIResponse(responseCode = "404", description = "fromRef/toRef not found"),
  })
  @JsonView(Views.V2.class)
  DiffResponse getDiff(@BeanParam @jakarta.ws.rs.BeanParam DiffParams params)
      throws NessieNotFoundException;

  @Override
  @PUT
  @jakarta.ws.rs.PUT
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}")
  @Operation(
      summary = "Set a named reference to a specific hash via another reference.",
      description =
          "The 'ref' parameter identifies the branch or tag to be reassigned.\n"
              + CHECKED_REF_INFO
              + "\n"
              + "Only branches and tags may be reassigned."
              + "\n"
              + "The payload object identifies any reference visible to the current user whose 'hash' will be used to "
              + "define the new HEAD of the reference being reassigned. Detached hashes may be used in the payload.",
      operationId = "assignReferenceV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Assigned successfully.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {@ExampleObject(ref = "singleReferenceResponse")},
              schema = @Schema(implementation = SingleReferenceResponse.class))
        }),
    @APIResponse(responseCode = "400", description = "Invalid input, ref specification not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(responseCode = "403", description = "Not allowed to view or assign reference"),
    @APIResponse(responseCode = "404", description = "One or more references don't exist"),
    @APIResponse(
        responseCode = "409",
        description = "Update conflict or expected hash / type mismatch")
  })
  @JsonView(Views.V2.class)
  SingleReferenceResponse assignReference(
      @Parameter(
              description = "Optional expected type of the reference being reassigned",
              examples = {@ExampleObject(ref = "referenceType")})
          @QueryParam("type")
          @jakarta.ws.rs.QueryParam("type")
          String type,
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = CHECKED_REF_DESCRIPTION,
              examples = @ExampleObject(ref = "refWithHash"))
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref,
      @RequestBody(
              required = true,
              description =
                  "Reference to which the 'ref' (from the path parameter) shall be assigned. This must be either a "
                      + "'Detached' commit, 'Branch' or 'Tag' via which the hash is visible to the caller.",
              content =
                  @Content(
                      mediaType = MediaType.APPLICATION_JSON,
                      examples = {@ExampleObject(ref = "refObj"), @ExampleObject(ref = "tagObj")}))
          Reference assignTo)
      throws NessieNotFoundException, NessieConflictException;

  @Override
  @DELETE
  @jakarta.ws.rs.DELETE
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}")
  @Operation(
      summary = "Delete a reference",
      description =
          "The 'ref' parameter identifies the branch or tag to be deleted.\n"
              + CHECKED_REF_INFO
              + "\n"
              + "Only branches and tags can be deleted. However, deleting the default branch may be restricted.",
      operationId = "deleteReferenceV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Deleted successfully.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {@ExampleObject(ref = "singleReferenceResponse")},
              schema = @Schema(implementation = SingleReferenceResponse.class))
        }),
    @APIResponse(responseCode = "400", description = "Invalid input, ref/hash name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(responseCode = "403", description = "Not allowed to view or delete reference"),
    @APIResponse(responseCode = "404", description = "Ref doesn't exists"),
    @APIResponse(responseCode = "409", description = "update conflict"),
  })
  @JsonView(Views.V2.class)
  SingleReferenceResponse deleteReference(
      @Parameter(
              description = "Optional expected type of the reference being deleted",
              examples = {@ExampleObject(ref = "referenceType")})
          @QueryParam("type")
          @jakarta.ws.rs.QueryParam("type")
          String type,
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = CHECKED_REF_DESCRIPTION,
              examples = @ExampleObject(ref = "refWithHash"))
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref)
      throws NessieConflictException, NessieNotFoundException;

  @Override
  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/contents/{key}")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/contents/{key}")
  @Operation(
      summary = "Get the content object associated with a key.",
      description =
          "This operation returns the content value for a content key at a particular point in history as defined "
              + "by the 'ref' parameter.",
      operationId = "getContentV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Information for a table, view or another content object for the given key",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = {@ExampleObject(ref = "contentResponseIceberg")},
                schema = @Schema(implementation = ContentResponse.class))),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or read object content for a key"),
    @APIResponse(
        responseCode = "404",
        description = "Table not found on 'ref' or non-existent reference")
  })
  @JsonView(Views.V2.class)
  ContentResponse getContent(
      @Parameter(description = KEY_PARAMETER_DESCRIPTION)
          @PathParam("key")
          @jakarta.ws.rs.PathParam("key")
          ContentKey key,
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = REF_PARAMETER_DESCRIPTION,
              examples = {
                @ExampleObject(ref = "ref"),
                @ExampleObject(ref = "refWithHash"),
                @ExampleObject(
                    ref = "refWithTimestampMillisSinceEpoch",
                    description =
                        "The commit 'valid for' the timestamp 1685185847230 in ms since epoch on main"),
                @ExampleObject(
                    ref = "refWithTimestampInstant",
                    description = "The commit 'valid for' the given ISO-8601 instant on main"),
                @ExampleObject(
                    ref = "refWithNthPredecessor",
                    description = "The 10th commit from HEAD of main"),
                @ExampleObject(
                    ref = "refWithMergeParent",
                    description =
                        "References the merge-parent of commit 2e1cfa82b035c26cbbbdae632cea070514eb8b773f616aaeaf668e2f0be8f10d on main"),
                @ExampleObject(ref = "refDefault"),
                @ExampleObject(ref = "refDetached"),
              })
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref,
      @Parameter(description = WITH_DOC_PARAMETER_DESCRIPTION)
          @QueryParam("with-doc")
          @jakarta.ws.rs.QueryParam("with-doc")
          boolean withDocumentation,
      @Parameter(description = FOR_WRITE_PARAMETER_DESCRIPTION)
          @QueryParam("for-write")
          @jakarta.ws.rs.QueryParam("for-write")
          boolean forWrite)
      throws NessieNotFoundException;

  @GET
  @jakarta.ws.rs.GET
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/contents")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/contents")
  @Operation(
      summary = "Get multiple content objects.",
      description =
          "Similar to 'GET /trees/{ref}/content/{key}', but takes multiple 'key' query parameters and returns zero "
              + "or more content values in the same JSON structure as the 'POST /trees/{ref}/content' endpoint.\n"
              + "\n"
              + "This is a convenience method for fetching a small number of content objects. It is mostly intended "
              + "for human use. For automated use cases or when the number of keys is large the "
              + "'POST /trees/{ref}/content' method is preferred.")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Retrieved successfully.",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = @ExampleObject(ref = "multipleContentsResponse"),
                schema = @Schema(implementation = GetMultipleContentsResponse.class))),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or read object content for a key"),
    @APIResponse(responseCode = "404", description = "Provided ref doesn't exists")
  })
  @JsonView(Views.V2.class)
  GetMultipleContentsResponse getSeveralContents(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = REF_PARAMETER_DESCRIPTION,
              examples = {
                @ExampleObject(ref = "ref"),
                @ExampleObject(ref = "refWithHash"),
                @ExampleObject(
                    ref = "refWithTimestampMillisSinceEpoch",
                    description =
                        "The commit 'valid for' the timestamp 1685185847230 in ms since epoch on main"),
                @ExampleObject(
                    ref = "refWithTimestampInstant",
                    description = "The commit 'valid for' the given ISO-8601 instant on main"),
                @ExampleObject(
                    ref = "refWithNthPredecessor",
                    description = "The 10th commit from HEAD of main"),
                @ExampleObject(
                    ref = "refWithMergeParent",
                    description =
                        "References the merge-parent of commit 2e1cfa82b035c26cbbbdae632cea070514eb8b773f616aaeaf668e2f0be8f10d on main"),
                @ExampleObject(ref = "refDefault"),
                @ExampleObject(ref = "refDetached"),
              })
          @Pattern(
              regexp = Validation.REF_NAME_PATH_REGEX,
              message = Validation.REF_NAME_PATH_MESSAGE)
          @jakarta.validation.constraints.Pattern(
              regexp = Validation.REF_NAME_PATH_REGEX,
              message = Validation.REF_NAME_PATH_MESSAGE)
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref,
      @Parameter(description = KEY_PARAMETER_DESCRIPTION)
          @QueryParam("key")
          @jakarta.ws.rs.QueryParam("key")
          List keys,
      @Parameter(description = WITH_DOC_PARAMETER_DESCRIPTION)
          @QueryParam("with-doc")
          @jakarta.ws.rs.QueryParam("with-doc")
          boolean withDocumentation,
      @Parameter(description = FOR_WRITE_PARAMETER_DESCRIPTION)
          @QueryParam("for-write")
          @jakarta.ws.rs.QueryParam("for-write")
          boolean forWrite)
      throws NessieNotFoundException;

  @Override
  @POST
  @jakarta.ws.rs.POST
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Consumes(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/contents")
  @jakarta.ws.rs.Path("{ref:" + REF_NAME_PATH_ELEMENT_REGEX + "}/contents")
  @Operation(
      summary = "Get multiple content objects.",
      description =
          "Similar to 'GET /trees/{ref}/content/{key}', but takes multiple 'ContentKey's (in the JSON payload) and "
              + "returns zero or more content objects.\n"
              + "\n"
              + "Note that if some keys from the request do not have an associated content object at the point in "
              + "history defined by the 'ref' parameter, the response will be successful, but no data will be "
              + "returned for the missing keys.",
      operationId = "getMultipleContentsV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Retrieved successfully.",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = @ExampleObject(ref = "multipleContentsResponse"),
                schema = @Schema(implementation = GetMultipleContentsResponse.class))),
    @APIResponse(responseCode = "400", description = "Invalid input, ref name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or read object content for a key"),
    @APIResponse(responseCode = "404", description = "Provided ref doesn't exists")
  })
  @JsonView(Views.V2.class)
  GetMultipleContentsResponse getMultipleContents(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = REF_PARAMETER_DESCRIPTION,
              examples = {
                @ExampleObject(ref = "ref"),
                @ExampleObject(ref = "refWithHash"),
                @ExampleObject(
                    ref = "refWithTimestampMillisSinceEpoch",
                    description =
                        "The commit 'valid for' the timestamp 1685185847230 in ms since epoch on main"),
                @ExampleObject(
                    ref = "refWithTimestampInstant",
                    description = "The commit 'valid for' the given ISO-8601 instant on main"),
                @ExampleObject(
                    ref = "refWithNthPredecessor",
                    description = "The 10th commit from HEAD of main"),
                @ExampleObject(
                    ref = "refWithMergeParent",
                    description =
                        "References the merge-parent of commit 2e1cfa82b035c26cbbbdae632cea070514eb8b773f616aaeaf668e2f0be8f10d on main"),
                @ExampleObject(ref = "refDefault"),
                @ExampleObject(ref = "refDetached"),
              })
          @PathParam("ref")
          @jakarta.ws.rs.PathParam("ref")
          String ref,
      @RequestBody(
              description = "Keys to retrieve.",
              content = @Content(examples = @ExampleObject(ref = "multiGetRequest")))
          GetMultipleContentsRequest request,
      @Parameter(description = WITH_DOC_PARAMETER_DESCRIPTION)
          @QueryParam("with-doc")
          @jakarta.ws.rs.QueryParam("with-doc")
          boolean withDocumentation,
      @Parameter(description = FOR_WRITE_PARAMETER_DESCRIPTION)
          @QueryParam("for-write")
          @jakarta.ws.rs.QueryParam("for-write")
          boolean forWrite)
      throws NessieNotFoundException;

  @Override
  @POST
  @jakarta.ws.rs.POST
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{branch:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history/transplant")
  @jakarta.ws.rs.Path("{branch:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history/transplant")
  @Operation(
      summary =
          "Transplant commits specified by the 'Transplant' payload object onto the given 'branch'",
      description =
          "This is done as an atomic operation such that only the last of the sequence is ever "
              + "visible to concurrent readers/writers. The sequence to transplant must be "
              + "contiguous and in order.\n"
              + "\n"
              + "The state of contents specified by the 'branch' reference will be used for detecting conflicts with "
              + "the commits being transplanted.",
      operationId = "transplantV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = @ExampleObject(ref = "mergeResponseSuccess"),
                schema = @Schema(implementation = MergeResponse.class)),
        description =
            "Transplant operation completed. "
                + "The actual transplant might have failed and reported as successful=false, "
                + "if the client asked to return a conflict as a result instead of returning an error. "
                + "Note: the 'commonAncestor' field in a response will always be null for a transplant."),
    @APIResponse(responseCode = "400", description = "Invalid input, ref/hash name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or transplant commits"),
    @APIResponse(responseCode = "404", description = "Ref doesn't exists"),
    @APIResponse(
        responseCode = "409",
        description = "Transplant conflict",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = @ExampleObject(ref = "mergeResponseFail"),
                schema = @Schema(implementation = MergeResponse.class)))
  })
  @JsonView(Views.V2.class)
  MergeResponse transplantCommitsIntoBranch(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = MERGE_TRANSPLANT_BRANCH_DESCRIPTION,
              examples = @ExampleObject(ref = "refWithHash"))
          @PathParam("branch")
          @jakarta.ws.rs.PathParam("branch")
          String branch,
      @RequestBody(
              required = true,
              description = "Commits to transplant",
              content =
                  @Content(
                      mediaType = MediaType.APPLICATION_JSON,
                      examples = {@ExampleObject(ref = "transplant")}))
          Transplant transplant)
      throws NessieNotFoundException, NessieConflictException;

  @Override
  @POST
  @jakarta.ws.rs.POST
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Path("{branch:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history/merge")
  @jakarta.ws.rs.Path("{branch:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history/merge")
  @Operation(
      summary = "Merge commits from another reference onto 'branch'.",
      description =
          "Merge commits referenced by the 'mergeRefName' and 'fromHash' parameters of the payload object into the "
              + "requested 'branch'.\n"
              + "\n"
              + "The state of contents specified by the 'branch' reference will be used for detecting conflicts with "
              + "the commits being transplanted.\n"
              + "\n"
              + "The merge is committed if it is free from conflicts. The set of commits merged into the target branch "
              + "will be all of those starting at 'fromHash' on 'mergeRefName' until we arrive at the common ancestor. "
              + "Depending on the underlying implementation, the number of commits allowed as part of this operation "
              + "may be limited.",
      operationId = "mergeV2")
  @APIResponses({
    @APIResponse(
        responseCode = "204",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = @ExampleObject(ref = "mergeResponseSuccess"),
                schema = @Schema(implementation = MergeResponse.class)),
        description =
            "Merge operation completed. "
                + "The actual merge might have failed and reported as successful=false, "
                + "if the client asked to return a conflict as a result instead of returning an error."),
    @APIResponse(responseCode = "400", description = "Invalid input, ref/hash name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or merge commits"),
    @APIResponse(responseCode = "404", description = "Ref doesn't exists"),
    @APIResponse(
        responseCode = "409",
        description = "Merge conflict",
        content =
            @Content(
                mediaType = MediaType.APPLICATION_JSON,
                examples = @ExampleObject(ref = "mergeResponseFail"),
                schema = @Schema(implementation = MergeResponse.class)))
  })
  @JsonView(Views.V2.class)
  MergeResponse mergeRefIntoBranch(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = MERGE_TRANSPLANT_BRANCH_DESCRIPTION,
              examples = @ExampleObject(ref = "refWithHash"))
          @PathParam("branch")
          @jakarta.ws.rs.PathParam("branch")
          String branch,
      @RequestBody(
              required = true,
              description =
                  "Merge operation that defines the source reference name and an optional hash. "
                      + "If 'fromHash' is not present, the current 'sourceRef's HEAD will be used.",
              content =
                  @Content(
                      mediaType = MediaType.APPLICATION_JSON,
                      examples = {@ExampleObject(ref = "merge")}))
          Merge merge)
      throws NessieNotFoundException, NessieConflictException;

  @Override
  @POST
  @jakarta.ws.rs.POST
  @Path("{branch:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history/commit")
  @jakarta.ws.rs.Path("{branch:" + REF_NAME_PATH_ELEMENT_REGEX + "}/history/commit")
  @Produces(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  @jakarta.ws.rs.Consumes(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
  @Operation(
      summary = "Commit one or more operations against the given 'branch'.",
      description =
          "The state of contents specified by the 'branch' reference will be used for detecting conflicts with "
              + "the operation being committed.\n"
              + "\n"
              + "The hash in the successful response will be the hash of the commit that contains the requested "
              + "operations, whose immediate parent commit will be the current HEAD of the specified branch.",
      operationId = "commitV2")
  @APIResponses({
    @APIResponse(
        responseCode = "200",
        description = "Updated successfully.",
        content = {
          @Content(
              mediaType = MediaType.APPLICATION_JSON,
              examples = {@ExampleObject(ref = "commitResponse")},
              schema = @Schema(implementation = CommitResponse.class))
        }),
    @APIResponse(responseCode = "400", description = "Invalid input, ref/hash name not valid"),
    @APIResponse(responseCode = "401", description = "Invalid credentials provided"),
    @APIResponse(
        responseCode = "403",
        description = "Not allowed to view the given reference or perform commits"),
    @APIResponse(responseCode = "404", description = "Provided ref doesn't exist"),
    @APIResponse(responseCode = "409", description = "Update conflict")
  })
  @JsonView(Views.V2.class)
  CommitResponse commitMultipleOperations(
      @Parameter(
              schema = @Schema(pattern = REF_NAME_PATH_ELEMENT_REGEX),
              description = COMMIT_BRANCH_DESCRIPTION,
              examples = @ExampleObject(ref = "refWithHash"))
          @PathParam("branch")
          @jakarta.ws.rs.PathParam("branch")
          String branch,
      @RequestBody(
              required = true,
              description = "Operations to commit",
              content =
                  @Content(
                      mediaType = MediaType.APPLICATION_JSON,
                      examples = {@ExampleObject(ref = "operations")}))
          Operations operations)
      throws NessieNotFoundException, NessieConflictException;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy