From c262345c32fbb44428b643107083adb801a3bc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 30 Mar 2023 15:57:37 +0200 Subject: [PATCH] Add getProjectGroups() methods in the projects api (#909) --- .../java/org/gitlab4j/api/ProjectApi.java | 88 ++++++++++++++- .../gitlab4j/api/models/AbstractGroup.java | 106 ++++++++++++++++++ .../java/org/gitlab4j/api/models/Group.java | 86 +------------- .../org/gitlab4j/api/models/ProjectGroup.java | 4 + .../api/models/ProjectGroupsFilter.java | 87 ++++++++++++++ .../org/gitlab4j/api/TestGitLabApiBeans.java | 7 ++ .../org/gitlab4j/api/project-groups.json | 18 +++ 7 files changed, 310 insertions(+), 86 deletions(-) create mode 100644 src/main/java/org/gitlab4j/api/models/AbstractGroup.java create mode 100644 src/main/java/org/gitlab4j/api/models/ProjectGroup.java create mode 100644 src/main/java/org/gitlab4j/api/models/ProjectGroupsFilter.java create mode 100644 src/test/resources/org/gitlab4j/api/project-groups.json diff --git a/src/main/java/org/gitlab4j/api/ProjectApi.java b/src/main/java/org/gitlab4j/api/ProjectApi.java index 1183103a..848f6bdc 100644 --- a/src/main/java/org/gitlab4j/api/ProjectApi.java +++ b/src/main/java/org/gitlab4j/api/ProjectApi.java @@ -54,6 +54,8 @@ import org.gitlab4j.api.models.Project; import org.gitlab4j.api.models.ProjectApprovalsConfig; import org.gitlab4j.api.models.ProjectFetches; import org.gitlab4j.api.models.ProjectFilter; +import org.gitlab4j.api.models.ProjectGroupsFilter; +import org.gitlab4j.api.models.ProjectGroup; import org.gitlab4j.api.models.ProjectHook; import org.gitlab4j.api.models.ProjectUser; import org.gitlab4j.api.models.PushRules; @@ -1624,7 +1626,7 @@ public class ProjectApi extends AbstractApi implements Constants { * @throws GitLabApiException if any exception occurs */ public Member getMember(Object projectIdOrPath, Long userId) throws GitLabApiException { - return (getMember(projectIdOrPath, userId, false)); + return (getMember(projectIdOrPath, userId, false)); } /** @@ -1926,6 +1928,90 @@ public class ProjectApi extends AbstractApi implements Constants { return (getProjectUsers(projectIdOrPath, search, getDefaultPerPage()).stream()); } + /** + * Get a list of the ancestor groups for a given project. + * + *
GitLab Endpoint: GET /projects/:id/groups
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance, required + * @return the ancestor groups for a given project + * @throws GitLabApiException if any exception occurs + */ + public List getProjectGroups(Object projectIdOrPath) throws GitLabApiException { + return (getProjectGroups(projectIdOrPath, new ProjectGroupsFilter(), getDefaultPerPage()).all()); + } + + /** + * Get a Pager of the ancestor groups for a given project. + * + *
GitLab Endpoint: GET /projects/:id/groups
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param itemsPerPage the number of Project instances that will be fetched per page + * @return a Pager of the ancestor groups for a given project + * @throws GitLabApiException if any exception occurs + */ + public Pager getProjectGroups(Object projectIdOrPath, int itemsPerPage) throws GitLabApiException { + return (getProjectGroups(projectIdOrPath, new ProjectGroupsFilter(), itemsPerPage)); + } + + /** + * Get a Stream of the ancestor groups for a given project. + * + *
GitLab Endpoint: GET /projects/:id/groups
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance, required + * @return a Stream of the ancestor groups for a given project + * @throws GitLabApiException if any exception occurs + */ + public Stream getProjectGroupsStream(Object projectIdOrPath) throws GitLabApiException { + return (getProjectGroups(projectIdOrPath, new ProjectGroupsFilter(), getDefaultPerPage()).stream()); + } + + /** + * Get a list of the ancestor groups for a given project matching the specified filter. + * + *
GitLab Endpoint: GET /projects/:id/groups
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance, required + * @param filter the ProjectGroupsFilter to match against + * @return the ancestor groups for a given project + * @throws GitLabApiException if any exception occurs + */ + public List getProjectGroups(Object projectIdOrPath, ProjectGroupsFilter filter) throws GitLabApiException { + return (getProjectGroups(projectIdOrPath, filter, getDefaultPerPage()).all()); + } + + /** + * Get a Pager of the ancestor groups for a given project matching the specified filter. + * + *
GitLab Endpoint: GET /projects/:id/groups
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param filter the ProjectGroupsFilter to match against + * @param itemsPerPage the number of Project instances that will be fetched per page + * @return a Pager of the ancestor groups for a given project + * @throws GitLabApiException if any exception occurs + */ + public Pager getProjectGroups(Object projectIdOrPath, ProjectGroupsFilter filter, int itemsPerPage) throws GitLabApiException { + GitLabApiForm formData = filter.getQueryParams(); + return (new Pager(this, ProjectGroup.class, itemsPerPage, formData.asMap(), "projects", getProjectIdOrPath(projectIdOrPath), "groups")); + } + + /** + * Get a Stream of the ancestor groups for a given project matching the specified filter. + * + *
GitLab Endpoint: GET /projects/:id/groups
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance, required + * @param filter the ProjectGroupsFilter to match against + * @return a Stream of the ancestor groups for a given project + * @throws GitLabApiException if any exception occurs + */ + public Stream getProjectGroupsStream(Object projectIdOrPath, ProjectGroupsFilter filter) throws GitLabApiException { + return (getProjectGroups(projectIdOrPath, filter, getDefaultPerPage()).stream()); + } + /** * Get the project events for specific project. Sorted from newest to latest. * diff --git a/src/main/java/org/gitlab4j/api/models/AbstractGroup.java b/src/main/java/org/gitlab4j/api/models/AbstractGroup.java new file mode 100644 index 00000000..ac990e89 --- /dev/null +++ b/src/main/java/org/gitlab4j/api/models/AbstractGroup.java @@ -0,0 +1,106 @@ + +package org.gitlab4j.api.models; + +import org.gitlab4j.api.utils.JacksonJson; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public abstract class AbstractGroup> { + + private Long id; + private String name; + private String avatarUrl; + private String webUrl; + private String fullName; + private String fullPath; + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAvatarUrl() { + return avatarUrl; + } + + public void setAvatarUrl(String avatarUrl) { + this.avatarUrl = avatarUrl; + } + + public String getWebUrl() { + return webUrl; + } + + public void setWebUrl(String webUrl) { + this.webUrl = webUrl; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getFullPath() { + return fullPath; + } + + public void setFullPath(String fullPath) { + this.fullPath = fullPath; + } + + @SuppressWarnings("unchecked") + public G withId(Long id) { + this.id = id; + return (G)this; + } + + @SuppressWarnings("unchecked") + public G withName(String name) { + this.name = name; + return (G)this; + } + + @SuppressWarnings("unchecked") + public G withAvatarUrl(String avatarUrl) { + this.avatarUrl = avatarUrl; + return (G)this; + } + + @SuppressWarnings("unchecked") + public G withWebUrl(String url) { + this.webUrl = url; + return (G)this; + } + + @SuppressWarnings("unchecked") + public G withFullName(String fullName) { + this.fullName = fullName; + return (G)this; + } + + @SuppressWarnings("unchecked") + public G withFullPath(String fullPath) { + this.fullPath = fullPath; + return (G)this; + } + + @Override + public String toString() { + return (JacksonJson.toJsonString(this)); + } +} diff --git a/src/main/java/org/gitlab4j/api/models/Group.java b/src/main/java/org/gitlab4j/api/models/Group.java index 21209d6d..d7d4d056 100644 --- a/src/main/java/org/gitlab4j/api/models/Group.java +++ b/src/main/java/org/gitlab4j/api/models/Group.java @@ -7,7 +7,7 @@ import org.gitlab4j.api.utils.JacksonJson; import java.util.Date; import java.util.List; -public class Group { +public class Group extends AbstractGroup { public class Statistics { private Long storageSize; @@ -49,17 +49,11 @@ public class Group { } - private Long id; - private String name; private String path; private String description; private Visibility visibility; private Boolean lfsEnabled; - private String avatarUrl; - private String webUrl; private Boolean requestAccessEnabled; - private String fullName; - private String fullPath; private Long parentId; private Integer sharedRunnersMinutesLimit; private Statistics statistics; @@ -71,22 +65,6 @@ public class Group { @JsonSerialize(using = JacksonJson.DateOnlySerializer.class) private Date markedForDeletionOn; - public Long getId() { - return this.id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - public String getPath() { return this.path; } @@ -119,22 +97,6 @@ public class Group { this.lfsEnabled = lfsEnabled; } - public String getAvatarUrl() { - return avatarUrl; - } - - public void setAvatarUrl(String avatarUrl) { - this.avatarUrl = avatarUrl; - } - - public String getWebUrl() { - return webUrl; - } - - public void setWebUrl(String webUrl) { - this.webUrl = webUrl; - } - public Boolean getRequestAccessEnabled() { return requestAccessEnabled; } @@ -143,22 +105,6 @@ public class Group { this.requestAccessEnabled = requestAccessEnabled; } - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public String getFullPath() { - return fullPath; - } - - public void setFullPath(String fullPath) { - this.fullPath = fullPath; - } - public Long getParentId() { return parentId; } @@ -223,16 +169,6 @@ public class Group { this.runnersToken = runnersToken; } - public Group withId(Long id) { - this.id = id; - return this; - } - - public Group withName(String name) { - this.name = name; - return this; - } - public Group withPath(String path) { this.path = path; return this; @@ -253,31 +189,11 @@ public class Group { return this; } - public Group withAvatarUrl(String avatarUrl) { - this.avatarUrl = avatarUrl; - return this; - } - - public Group withWebUrl(String url) { - this.webUrl = url; - return this; - } - public Group withRequestAccessEnabled(boolean requestAccessEnabled) { this.requestAccessEnabled = requestAccessEnabled; return this; } - public Group withFullName(String fullName) { - this.fullName = fullName; - return this; - } - - public Group withFullPath(String fullPath) { - this.fullPath = fullPath; - return this; - } - public Group withParentId(Long parentId) { this.parentId = parentId; return this; diff --git a/src/main/java/org/gitlab4j/api/models/ProjectGroup.java b/src/main/java/org/gitlab4j/api/models/ProjectGroup.java new file mode 100644 index 00000000..b918d411 --- /dev/null +++ b/src/main/java/org/gitlab4j/api/models/ProjectGroup.java @@ -0,0 +1,4 @@ +package org.gitlab4j.api.models; + +public class ProjectGroup extends AbstractGroup { +} diff --git a/src/main/java/org/gitlab4j/api/models/ProjectGroupsFilter.java b/src/main/java/org/gitlab4j/api/models/ProjectGroupsFilter.java new file mode 100644 index 00000000..fec74474 --- /dev/null +++ b/src/main/java/org/gitlab4j/api/models/ProjectGroupsFilter.java @@ -0,0 +1,87 @@ +package org.gitlab4j.api.models; + +import java.util.List; + +import org.gitlab4j.api.GitLabApiForm; + +/** + * This class is used to filter Groups when getting lists of groups for a specified project. + */ +public class ProjectGroupsFilter { + + private String search; + private AccessLevel sharedMinAccessLevel; + private Boolean sharedVisibleOnly; + private List skipGroups; + private Boolean withShared; + + /** + * Search for specific groups. + * + * @param search the search criteria + * @return the reference to this ProjectGroupsFilter instance + */ + public ProjectGroupsFilter withSearch(String search) { + this.search = search; + return (this); + } + + /** + * Limit to shared groups with at least this role. + * + * @param sharedMinAccessLevel the minimal role + * @return the reference to this ProjectGroupsFilter instance + */ + public ProjectGroupsFilter withSharedMinAccessLevel(AccessLevel sharedMinAccessLevel) { + this.sharedMinAccessLevel = sharedMinAccessLevel; + return (this); + } + + /** + * Limit to shared groups user has access to. + * + * @param sharedVisibleOnly if true limit to the shared groups user has access to. + * @return the reference to this ProjectGroupsFilter instance + */ + public ProjectGroupsFilter withSharedVisibleOnly(Boolean sharedVisibleOnly) { + this.sharedVisibleOnly = sharedVisibleOnly; + return (this); + } + + /** + * Do not include the provided groups IDs. + * + * @param skipGroups List of group IDs to not include in the search + * @return the reference to this ProjectGroupsFilter instance + */ + public ProjectGroupsFilter withSkipGroups(List skipGroups) { + this.skipGroups = skipGroups; + return (this); + } + + /** + * Include projects shared with this group. + * + * @param withShared if true include projects shared with this group. + * @return the reference to this ProjectGroupsFilter instance + */ + public ProjectGroupsFilter withWithShared(Boolean withShared) { + this.withShared = withShared; + return (this); + } + + /** + * Get the query params specified by this filter. + * + * @return a GitLabApiForm instance holding the query parameters for this ProjectGroupsFilter instance + */ + public GitLabApiForm getQueryParams() { + return (new GitLabApiForm() + .withParam("search", search) + .withParam("shared_min_access_level", sharedMinAccessLevel) + .withParam("shared_visible_only", sharedVisibleOnly) + .withParam("skip_groups", skipGroups) + .withParam("with_shared", withShared) + ); + } +} diff --git a/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java b/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java index e5774385..0afb446e 100644 --- a/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java +++ b/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java @@ -90,6 +90,7 @@ import org.gitlab4j.api.models.PackageFile; import org.gitlab4j.api.models.Pipeline; import org.gitlab4j.api.models.PipelineSchedule; import org.gitlab4j.api.models.Project; +import org.gitlab4j.api.models.ProjectGroup; import org.gitlab4j.api.models.ProjectApprovalsConfig; import org.gitlab4j.api.models.ProjectFetches; import org.gitlab4j.api.models.ProjectHook; @@ -456,6 +457,12 @@ public class TestGitLabApiBeans { assertTrue(compareJson(artifactFile, "artifacts-file.json")); } + @Test + public void testProjectGroups() throws Exception { + List projectGroups = unmarshalResourceList(ProjectGroup.class, "project-groups.json"); + assertTrue(compareJson(projectGroups, "project-groups.json")); + } + @Test public void testProjectLanguages() throws Exception { Map projectLanguages = unmarshalResourceMap(Float.class, "project-languages.json"); diff --git a/src/test/resources/org/gitlab4j/api/project-groups.json b/src/test/resources/org/gitlab4j/api/project-groups.json new file mode 100644 index 00000000..bdea9c54 --- /dev/null +++ b/src/test/resources/org/gitlab4j/api/project-groups.json @@ -0,0 +1,18 @@ +[ + { + "id": 1, + "name": "Foobar Group", + "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg", + "web_url": "http://localhost:3000/groups/foo-bar", + "full_name": "Foobar Group", + "full_path": "foo-bar" + }, + { + "id": 2, + "name": "Shared Group", + "avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/bar.jpg", + "web_url": "http://gitlab.example.com/groups/foo/bar", + "full_name": "Shared Group", + "full_path": "foo/shared" + } +] -- GitLab