Commit d798c903 authored by Greg Messner's avatar Greg Messner
Browse files

Mods to support project and issues statistics (#424).

parent 6d1aa4cd
...@@ -13,6 +13,8 @@ import org.gitlab4j.api.models.Duration; ...@@ -13,6 +13,8 @@ import org.gitlab4j.api.models.Duration;
import org.gitlab4j.api.models.Issue; import org.gitlab4j.api.models.Issue;
import org.gitlab4j.api.models.IssueFilter; import org.gitlab4j.api.models.IssueFilter;
import org.gitlab4j.api.models.IssueLink; import org.gitlab4j.api.models.IssueLink;
import org.gitlab4j.api.models.IssuesStatistics;
import org.gitlab4j.api.models.IssuesStatisticsFilter;
import org.gitlab4j.api.models.MergeRequest; import org.gitlab4j.api.models.MergeRequest;
import org.gitlab4j.api.models.Participant; import org.gitlab4j.api.models.Participant;
import org.gitlab4j.api.models.TimeStats; import org.gitlab4j.api.models.TimeStats;
...@@ -22,6 +24,7 @@ import org.gitlab4j.api.utils.DurationUtils; ...@@ -22,6 +24,7 @@ import org.gitlab4j.api.utils.DurationUtils;
* This class provides an entry point to all the GitLab API Issue calls. * This class provides an entry point to all the GitLab API Issue calls.
* @see <a href="https://docs.gitlab.com/ce/api/issues.html">Issues API at GitLab</a> * @see <a href="https://docs.gitlab.com/ce/api/issues.html">Issues API at GitLab</a>
* @see <a href="https://docs.gitlab.com/ce/api/issue_links.html">Issue Links API at GitLab</a> * @see <a href="https://docs.gitlab.com/ce/api/issue_links.html">Issue Links API at GitLab</a>
* @see <a href="https://docs.gitlab.com/ce/api/issues_statistics.html">Issues Statistics API at GitLab</a>
*/ */
public class IssuesApi extends AbstractApi implements Constants { public class IssuesApi extends AbstractApi implements Constants {
...@@ -839,4 +842,52 @@ public class IssuesApi extends AbstractApi implements Constants { ...@@ -839,4 +842,52 @@ public class IssuesApi extends AbstractApi implements Constants {
public Stream<Participant> getParticipantsStream(Object projectIdOrPath, Integer issueIid) throws GitLabApiException { public Stream<Participant> getParticipantsStream(Object projectIdOrPath, Integer issueIid) throws GitLabApiException {
return (getParticipants(projectIdOrPath, issueIid, getDefaultPerPage()).stream()); return (getParticipants(projectIdOrPath, issueIid, getDefaultPerPage()).stream());
} }
/**
* Gets issues count statistics on all issues the authenticated user has access to. By default it returns
* only issues created by the current user. To get all issues, use parameter scope=all.
*
* <pre><code>GitLab Endpoint: GET /issues_statistics</code></pre>
*
* @param filter {@link IssuesStatisticsFilter} a IssuesStatisticsFilter instance with the filter settings.
* @return an IssuesStatistics instance with the statistics for the matched issues.
* @throws GitLabApiException if any exception occurs
*/
public IssuesStatistics getIssuesStatistics(IssuesStatisticsFilter filter) throws GitLabApiException {
GitLabApiForm formData = filter.getQueryParams();
Response response = get(Response.Status.OK, formData.asMap(), "issues_statistics");
return (response.readEntity(IssuesStatistics.class));
}
/**
* Gets issues count statistics for given group.
*
* <pre><code>GitLab Endpoint: GET /groups/:groupId/issues_statistics</code></pre>
*
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path, required
* @param filter {@link IssuesStatisticsFilter} a IssuesStatisticsFilter instance with the filter settings
* @return an IssuesStatistics instance with the statistics for the matched issues
* @throws GitLabApiException if any exception occurs
*/
public IssuesStatistics getGroupIssuesStatistics(Object groupIdOrPath, IssuesStatisticsFilter filter) throws GitLabApiException {
GitLabApiForm formData = filter.getQueryParams();
Response response = get(Response.Status.OK, formData.asMap(), "groups", this.getGroupIdOrPath(groupIdOrPath), "issues_statistics");
return (response.readEntity(IssuesStatistics.class));
}
/**
* Gets issues count statistics for given group.
*
* <pre><code>GitLab Endpoint: GET /projects/:projectId/issues_statistics</code></pre>
*
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
* @param filter {@link IssuesStatisticsFilter} a IssuesStatisticsFilter instance with the filter settings.
* @return an IssuesStatistics instance with the statistics for the matched issues
* @throws GitLabApiException if any exception occurs
*/
public IssuesStatistics geProjectIssuesStatistics(Object projectIdOrPath, IssuesStatisticsFilter filter) throws GitLabApiException {
GitLabApiForm formData = filter.getQueryParams();
Response response = get(Response.Status.OK, formData.asMap(), "projects", this.getProjectIdOrPath(projectIdOrPath), "issues_statistics");
return (response.readEntity(IssuesStatistics.class));
}
} }
...@@ -46,6 +46,7 @@ import org.gitlab4j.api.models.Issue; ...@@ -46,6 +46,7 @@ import org.gitlab4j.api.models.Issue;
import org.gitlab4j.api.models.Member; import org.gitlab4j.api.models.Member;
import org.gitlab4j.api.models.Namespace; import org.gitlab4j.api.models.Namespace;
import org.gitlab4j.api.models.Project; import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.ProjectFetches;
import org.gitlab4j.api.models.ProjectFilter; import org.gitlab4j.api.models.ProjectFilter;
import org.gitlab4j.api.models.ProjectHook; import org.gitlab4j.api.models.ProjectHook;
import org.gitlab4j.api.models.ProjectUser; import org.gitlab4j.api.models.ProjectUser;
...@@ -57,8 +58,9 @@ import org.gitlab4j.api.models.Visibility; ...@@ -57,8 +58,9 @@ import org.gitlab4j.api.models.Visibility;
/** /**
* This class provides an entry point to all the GitLab API project calls. * This class provides an entry point to all the GitLab API project calls.
* @see <a href="https://docs.gitlab.com/ce/api/projects.html">Projects API at GitLab</a> * @see <a href="https://docs.gitlab.com/ce/api/projects.html">Projects API at GitLab</a>
* @see <a href="https://docs.gitlab.com/ee/api/members.html">Group and project members API at GitLab</a> * @see <a href="https://docs.gitlab.com/ce/api/project_statistics.html">Project statistics API</a>
* @see <a href="https://docs.gitlab.com/ee/api/access_requests.html#group-and-project-access-requests-api">Group and project access requests API</a> * @see <a href="https://docs.gitlab.com/ce/api/members.html">Group and project members API at GitLab</a>
* @see <a href="https://docs.gitlab.com/ce/api/access_requests.html#group-and-project-access-requests-api">Group and project access requests API</a>
*/ */
public class ProjectApi extends AbstractApi implements Constants { public class ProjectApi extends AbstractApi implements Constants {
...@@ -66,6 +68,40 @@ public class ProjectApi extends AbstractApi implements Constants { ...@@ -66,6 +68,40 @@ public class ProjectApi extends AbstractApi implements Constants {
super(gitLabApi); super(gitLabApi);
} }
/**
* Get the project fetch statistics for the last 30 days. Retrieving the statistics requires
* write access to the repository. Currently only HTTP fetches statistics are returned.
* Fetches statistics includes both clones and pulls count and are HTTP only,
* SSH fetches are not included.
*
* <pre><code>GitLab Endpoint: GET /project/:id/statistics</code></pre>
*
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
* @return a ProjectFetches instance with the project fetch statistics for the last 30 days
* @throws GitLabApiException if any exception occurs during execution
*/
public ProjectFetches getProjectStatistics(Object projectIdOrPath) throws GitLabApiException {
Response response = get(Response.Status.OK, null, "projects", getProjectIdOrPath(projectIdOrPath), "statistics");
return (response.readEntity(ProjectFetches.class));
}
/**
* Get an Optional instance with the value for the project fetch statistics for the last 30 days.
*
* <pre><code>GitLab Endpoint: GET /project/:id/statistics</code></pre>
*
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required
* @return an Optional instance with the value for the project fetch statistics for the last 30 day
* @throws GitLabApiException if any exception occurs during execution
*/
public Optional<ProjectFetches> getOptionalProjectStatistics(Object projectIdOrPath) throws GitLabApiException {
try {
return (Optional.ofNullable(getProjectStatistics(projectIdOrPath)));
} catch (GitLabApiException glae) {
return (GitLabApi.createOptionalFromException(glae));
}
}
/** /**
* <p>Get a list of projects accessible by the authenticated user.</p> * <p>Get a list of projects accessible by the authenticated user.</p>
* *
......
...@@ -12,8 +12,6 @@ import org.gitlab4j.api.GitLabApiForm; ...@@ -12,8 +12,6 @@ import org.gitlab4j.api.GitLabApiForm;
import org.gitlab4j.api.utils.ISO8601; import org.gitlab4j.api.utils.ISO8601;
/** /**
* Created by zhengrenjie on 2018/09/11 12:31
*
* This class is used to filter issues when getting lists of them. * This class is used to filter issues when getting lists of them.
*/ */
public class IssueFilter { public class IssueFilter {
......
...@@ -26,6 +26,7 @@ public class ISO8601 { ...@@ -26,6 +26,7 @@ public class ISO8601 {
public static final String OUTPUT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; public static final String OUTPUT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
public static final String OUTPUT_MSEC_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; public static final String OUTPUT_MSEC_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
public static final String UTC_PATTERN = "yyyy-MM-dd HH:mm:ss 'UTC'"; public static final String UTC_PATTERN = "yyyy-MM-dd HH:mm:ss 'UTC'";
public static final String DATE_ONLY_PATTERN = "yyyy-MM-dd";
private static final DateTimeFormatter ODT_WITH_MSEC_PARSER = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd[['T'][ ]HH:mm:ss.SSS[ ][XXXXX][XXXX]]").toFormatter(); private static final DateTimeFormatter ODT_WITH_MSEC_PARSER = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd[['T'][ ]HH:mm:ss.SSS[ ][XXXXX][XXXX]]").toFormatter();
private static final DateTimeFormatter ODT_PARSER = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd[['T'][ ]HH:mm:ss[.SSS][ ][XXX][X]]") private static final DateTimeFormatter ODT_PARSER = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd[['T'][ ]HH:mm:ss[.SSS][ ][XXX][X]]")
...@@ -116,6 +117,21 @@ public class ISO8601 { ...@@ -116,6 +117,21 @@ public class ISO8601 {
SafeDateFormatter.getDateFormat(OUTPUT_PATTERN).format(date)); SafeDateFormatter.getDateFormat(OUTPUT_PATTERN).format(date));
} }
/**
* Get a string that includes the date only in yyyy-mm-ss format.
*
* @param date the Date instance to get the date only formatted string for
* @return a string that includes the date only in yyyy-mm-ss format, or null if date is null
*/
public static String dateOnly(Date date) {
if (date == null) {
return (null);
}
return SafeDateFormatter.getDateFormat(DATE_ONLY_PATTERN).format(date);
}
/** /**
* Get a ISO8601 formatted string for the provided Date instance. * Get a ISO8601 formatted string for the provided Date instance.
* *
......
...@@ -257,6 +257,18 @@ public class JacksonJson extends JacksonJaxbJsonProvider implements ContextResol ...@@ -257,6 +257,18 @@ public class JacksonJson extends JacksonJaxbJsonProvider implements ContextResol
return (results); return (results);
} }
/**
* JsonSerializer for serializing dates s yyyy-mm-dd in UTC timezone.
*/
public static class DateOnlySerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {
String dateString = ISO8601.dateOnly(date);
gen.writeString(dateString);
}
}
/** /**
* JsonSerializer for serializing ISO8601 formatted dates. * JsonSerializer for serializing ISO8601 formatted dates.
*/ */
......
...@@ -52,6 +52,7 @@ import org.gitlab4j.api.models.Epic; ...@@ -52,6 +52,7 @@ import org.gitlab4j.api.models.Epic;
import org.gitlab4j.api.models.EpicIssue; import org.gitlab4j.api.models.EpicIssue;
import org.gitlab4j.api.models.Event; import org.gitlab4j.api.models.Event;
import org.gitlab4j.api.models.ExportStatus; import org.gitlab4j.api.models.ExportStatus;
import org.gitlab4j.api.models.ProjectFetches;
import org.gitlab4j.api.models.FileUpload; import org.gitlab4j.api.models.FileUpload;
import org.gitlab4j.api.models.Group; import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.HealthCheckInfo; import org.gitlab4j.api.models.HealthCheckInfo;
...@@ -59,6 +60,7 @@ import org.gitlab4j.api.models.ImpersonationToken; ...@@ -59,6 +60,7 @@ import org.gitlab4j.api.models.ImpersonationToken;
import org.gitlab4j.api.models.ImportStatus; import org.gitlab4j.api.models.ImportStatus;
import org.gitlab4j.api.models.Issue; import org.gitlab4j.api.models.Issue;
import org.gitlab4j.api.models.IssueLink; import org.gitlab4j.api.models.IssueLink;
import org.gitlab4j.api.models.IssuesStatistics;
import org.gitlab4j.api.models.Job; import org.gitlab4j.api.models.Job;
import org.gitlab4j.api.models.Key; import org.gitlab4j.api.models.Key;
import org.gitlab4j.api.models.Label; import org.gitlab4j.api.models.Label;
...@@ -208,6 +210,18 @@ public class TestGitLabApiBeans { ...@@ -208,6 +210,18 @@ public class TestGitLabApiBeans {
assertTrue(compareJson(fileUpload, "file-upload.json")); assertTrue(compareJson(fileUpload, "file-upload.json"));
} }
@Test
public void testIssuesStatistics() throws Exception {
IssuesStatistics statistics = unmarshalResource(IssuesStatistics.class, "issues-statistics.json");
assertTrue(compareJson(statistics, "issues-statistics.json"));
}
@Test
public void testProjectFetches() throws Exception {
ProjectFetches fetches = unmarshalResource(ProjectFetches.class, "project-fetches.json");
assertTrue(compareJson(fetches, "project-fetches.json"));
}
@Test @Test
public void testGroup() throws Exception { public void testGroup() throws Exception {
Group group = unmarshalResource(Group.class, "group.json"); Group group = unmarshalResource(Group.class, "group.json");
......
...@@ -44,6 +44,7 @@ import org.gitlab4j.api.models.AccessRequest; ...@@ -44,6 +44,7 @@ import org.gitlab4j.api.models.AccessRequest;
import org.gitlab4j.api.models.Group; import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Member; import org.gitlab4j.api.models.Member;
import org.gitlab4j.api.models.Project; import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.ProjectFetches;
import org.gitlab4j.api.models.ProjectFilter; import org.gitlab4j.api.models.ProjectFilter;
import org.gitlab4j.api.models.User; import org.gitlab4j.api.models.User;
import org.gitlab4j.api.models.Variable; import org.gitlab4j.api.models.Variable;
...@@ -847,4 +848,11 @@ public class TestProjectApi extends AbstractIntegrationTest { ...@@ -847,4 +848,11 @@ public class TestProjectApi extends AbstractIntegrationTest {
} }
} }
} }
@Test
public void testGetProjectStatistics() throws GitLabApiException {
assertNotNull(testProject);
Optional<ProjectFetches> statistics = gitLabApi.getProjectApi().getOptionalProjectStatistics(testProject);
assertTrue(statistics.isPresent());
}
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment