diff --git a/src/main/java/org/gitlab4j/api/ProjectApi.java b/src/main/java/org/gitlab4j/api/ProjectApi.java
index 1183103ad68dfc15a4fb4c045ea6b43bc160aae4..848f6bdca2394f4000ec574b86da34d8bf2529d5 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 0000000000000000000000000000000000000000..ac990e89736811f8a82f8871e701d8a7258c2fb6
--- /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 21209d6dfabdfa0d33e4e38376779160c51b06ec..d7d4d056086f6112dcdbb1f71ffc55c3f37141b1 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 0000000000000000000000000000000000000000..b918d411c2852feb8a04ddf898ec10081215b23c
--- /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 0000000000000000000000000000000000000000..fec744748fee6c6d4fcada179f960969dd34e088
--- /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 e57743850951a4e3498a4498afeb3c4ecff84f18..0afb446e5e4554e98ccb092945b4163d9380f68d 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 0000000000000000000000000000000000000000..bdea9c542a630f791ed0297f0c9d5b4380dc66de
--- /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"
+ }
+]