Skip to content

Commit 69c7096

Browse files
NadeoWolfjmini
andauthored
Add TopicsApi (#1012)
--------- Co-authored-by: Jeremie Bresson <[email protected]>
1 parent 32d00b1 commit 69c7096

File tree

11 files changed

+489
-3
lines changed

11 files changed

+489
-3
lines changed

src/main/java/org/gitlab4j/api/GitLabApi.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public String getApiNamespace() {
9797
private SystemHooksApi systemHooksApi;
9898
private TagsApi tagsApi;
9999
private TodosApi todosApi;
100+
private TopicsApi topicsApi;
100101
private UserApi userApi;
101102
private UncyclosApi wikisApi;
102103
private KeysApi keysApi;
@@ -1670,6 +1671,25 @@ public TagsApi getTagsApi() {
16701671
return (tagsApi);
16711672
}
16721673

1674+
/**
1675+
* Gets the TagsApi instance owned by this GitLabApi instance. The TagsApi is used
1676+
* to perform all tag and release related API calls.
1677+
*
1678+
* @return the TagsApi instance owned by this GitLabApi instance
1679+
*/
1680+
public TopicsApi getTopicsApi() {
1681+
1682+
if (topicsApi == null) {
1683+
synchronized (this) {
1684+
if (topicsApi == null) {
1685+
topicsApi = new TopicsApi(this);
1686+
}
1687+
}
1688+
}
1689+
1690+
return (topicsApi);
1691+
}
1692+
16731693
/**
16741694
* Gets the SnippetsApi instance owned by this GitLabApi instance. The SnippetsApi is used
16751695
* to perform all snippet related API calls.

src/main/java/org/gitlab4j/api/GitLabApiClient.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.glassfish.jersey.jackson.JacksonFeature;
4242
import org.glassfish.jersey.media.multipart.BodyPart;
4343
import org.glassfish.jersey.media.multipart.Boundary;
44+
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
4445
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
4546
import org.glassfish.jersey.media.multipart.MultiPart;
4647
import org.glassfish.jersey.media.multipart.MultiPartFeature;
@@ -264,7 +265,7 @@ public void close() {
264265
*
265266
* @param logger the Logger instance to log to
266267
* @param level the logging level (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST)
267-
* @param maxEntitySize maximum number of entity bytes to be logged. When logging if the maxEntitySize
268+
* @param maxEntityLength maximum number of entity bytes to be logged. When logging if the maxEntitySize
268269
* is reached, the entity logging will be truncated at maxEntitySize and "...more..." will be added at
269270
* the end of the log entry. If maxEntitySize is <= 0, entity logging will be disabled
270271
* @param maskedHeaderNames a list of header names that should have the values masked
@@ -691,7 +692,11 @@ protected Response putUpload(String name, File fileToUpload, Object... pathArgs)
691692
protected Response putUpload(String name, File fileToUpload, URL url) throws IOException {
692693

693694
try (MultiPart multiPart = new FormDataMultiPart()) {
694-
multiPart.bodyPart(new FileDataBodyPart(name, fileToUpload, MediaType.APPLICATION_OCTET_STREAM_TYPE));
695+
if(fileToUpload == null) {
696+
multiPart.bodyPart(new FormDataBodyPart(name, "", MediaType.APPLICATION_OCTET_STREAM_TYPE));
697+
} else {
698+
multiPart.bodyPart(new FileDataBodyPart(name, fileToUpload, MediaType.APPLICATION_OCTET_STREAM_TYPE));
699+
}
695700
final Entity<?> entity = Entity.entity(multiPart, Boundary.addBoundary(multiPart.getMediaType()));
696701
return (invocation(url, null).put(entity));
697702
}

src/main/java/org/gitlab4j/api/ProjectApi.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,10 @@ public Project createProject(Project project, String importUrl) throws GitLabApi
10441044
if (project.getTagList() != null && !project.getTagList().isEmpty()) {
10451045
throw new IllegalArgumentException("GitLab API v3 does not support tag lists when creating projects");
10461046
}
1047+
1048+
if (project.getTopics() != null && !project.getTopics().isEmpty()) {
1049+
throw new IllegalArgumentException("GitLab API v3 does not support topics when creating projects");
1050+
}
10471051
} else {
10481052
Visibility visibility = (project.getVisibility() != null ? project.getVisibility() :
10491053
project.getPublic() == Boolean.TRUE ? Visibility.PUBLIC : null);
@@ -1052,6 +1056,10 @@ public Project createProject(Project project, String importUrl) throws GitLabApi
10521056
if (project.getTagList() != null && !project.getTagList().isEmpty()) {
10531057
formData.withParam("tag_list", String.join(",", project.getTagList()));
10541058
}
1059+
1060+
if (project.getTopics() != null && !project.getTopics().isEmpty()) {
1061+
formData.withParam("topics", String.join(",", project.getTopics()));
1062+
}
10551063
}
10561064

10571065
Response response = post(Response.Status.CREATED, formData, "projects");
@@ -1315,6 +1323,10 @@ public Project updateProject(Project project) throws GitLabApiException {
13151323
if (project.getTagList() != null && !project.getTagList().isEmpty()) {
13161324
throw new IllegalArgumentException("GitLab API v3 does not support tag lists when updating projects");
13171325
}
1326+
1327+
if (project.getTopics() != null && !project.getTopics().isEmpty()) {
1328+
throw new IllegalArgumentException("GitLab API v3 does not support topics when updating projects");
1329+
}
13181330
} else {
13191331
Visibility visibility = (project.getVisibility() != null ? project.getVisibility() :
13201332
project.getPublic() == Boolean.TRUE ? Visibility.PUBLIC : null);
@@ -1323,6 +1335,10 @@ public Project updateProject(Project project) throws GitLabApiException {
13231335
if (project.getTagList() != null && !project.getTagList().isEmpty()) {
13241336
formData.withParam("tag_list", String.join(",", project.getTagList()));
13251337
}
1338+
1339+
if (project.getTopics() != null && !project.getTopics().isEmpty()) {
1340+
formData.withParam("topics", String.join(",", project.getTopics()));
1341+
}
13261342
}
13271343

13281344
Response response = putWithFormData(Response.Status.OK, formData, "projects", projectIdentifier);
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package org.gitlab4j.api;
2+
3+
import org.gitlab4j.api.models.Topic;
4+
import org.gitlab4j.api.models.TopicParams;
5+
6+
import javax.ws.rs.core.GenericType;
7+
import javax.ws.rs.core.Response;
8+
import java.io.File;
9+
import java.util.List;
10+
import java.util.Optional;
11+
import java.util.stream.Stream;
12+
13+
public class TopicsApi extends AbstractApi{
14+
15+
public TopicsApi(GitLabApi gitLabApi) {
16+
super(gitLabApi);
17+
}
18+
19+
/**
20+
* <p>Get a list of Topics. </p>
21+
*
22+
* <strong>WARNING:</strong> Do not use this method to fetch Topics from https://gitlab.com,
23+
* gitlab.com has many 1,000's of public topics and it will a long time to fetch all of them.
24+
* Instead use {@link #getTopics(int itemsPerPage)} which will return a Pager of Topic instances.
25+
*
26+
* <pre><code>GitLab Endpoint: GET /topics</code></pre>
27+
*
28+
* @return the list of topics viewable by the authenticated user
29+
* @throws GitLabApiException if any exception occurs
30+
*/
31+
public List<Topic> getTopics() throws GitLabApiException {
32+
return (getTopics(getDefaultPerPage()).all());
33+
}
34+
35+
/**
36+
* Get a list of topics in the specified page range.
37+
*
38+
* <pre><code>GitLab Endpoint: GET /topics</code></pre>
39+
*
40+
* @param page the page to get
41+
* @param perPage the number of Topic instances per page
42+
* @return the list of topics
43+
* @throws GitLabApiException if any exception occurs
44+
*/
45+
public List<Topic> getTopics(int page, int perPage) throws GitLabApiException {
46+
Response response = get(Response.Status.OK, getPageQueryParams(page, perPage), "topics");
47+
return (response.readEntity(new GenericType<List<Topic>>() {}));
48+
}
49+
50+
/**
51+
* Get a Pager of topics.
52+
*
53+
* <pre><code>GitLab Endpoint: GET /topics</code></pre>
54+
*
55+
* @param itemsPerPage the number of Topic instances that will be fetched per page
56+
* @return the pager of topics
57+
* @throws GitLabApiException if any exception occurs
58+
*/
59+
public Pager<Topic> getTopics(int itemsPerPage) throws GitLabApiException {
60+
return (new Pager<Topic>(this, Topic.class, itemsPerPage, null, "topics"));
61+
}
62+
63+
/**
64+
* Get a Stream of topics.
65+
*
66+
* <pre><code>GitLab Endpoint: GET /topics</code></pre>
67+
*
68+
* @return the stream of topics
69+
* @throws GitLabApiException if any exception occurs
70+
*/
71+
public Stream<Topic> getTopicsStream() throws GitLabApiException {
72+
return (getTopics(getDefaultPerPage()).stream());
73+
}
74+
75+
/**
76+
* Get all details of a topic.
77+
*
78+
* <pre><code>GitLab Endpoint: GET /topics/:id</code></pre>
79+
*
80+
* @param id the topic ID
81+
* @return the topic for the specified topic id
82+
* @throws GitLabApiException if any exception occurs
83+
*/
84+
public Topic getTopic(Integer id) throws GitLabApiException {
85+
Response response = get(Response.Status.OK, null, "topics", id);
86+
return (response.readEntity(Topic.class));
87+
}
88+
89+
/**
90+
* Get all details of a topic as an Optional instance.
91+
*
92+
* <pre><code>GitLab Endpoint: GET /topics/:id</code></pre>
93+
*
94+
* @param id the topic ID
95+
* @return the Topic for the specified topic id as an Optional instance
96+
*/
97+
public Optional<Topic> getOptionalTopic(Integer id) {
98+
try {
99+
return (Optional.ofNullable(getTopic(id)));
100+
} catch (GitLabApiException glae) {
101+
return (GitLabApi.createOptionalFromException(glae));
102+
}
103+
}
104+
105+
/**
106+
* Creates a new Topic. Available only for users who can create topics.
107+
*
108+
* <pre><code>GitLab Endpoint: POST /topics</code></pre>
109+
*
110+
* @param params a TopicParams instance holding the parameters for the topic creation
111+
* @return the created Topic instance
112+
* @throws GitLabApiException if any exception occurs
113+
*/
114+
public Topic createTopic(TopicParams params) throws GitLabApiException {
115+
Response response = post(Response.Status.CREATED, params.getForm(true), "topics");
116+
return (response.readEntity(Topic.class));
117+
}
118+
119+
/**
120+
* Update a project topic.
121+
*
122+
* <pre><code>GitLab Endpoint: PUT /topics/:id</code></pre>
123+
*
124+
* @param id the topic id
125+
* @param params a TopicParams instance holding the properties to Update
126+
* @return the updated Topic instance
127+
* @throws GitLabApiException at any exception
128+
*/
129+
public Topic updateTopic(Integer id, TopicParams params) throws GitLabApiException {
130+
Response response = putWithFormData(Response.Status.OK,
131+
params.getForm(false), "topics", id);
132+
return (response.readEntity(Topic.class));
133+
}
134+
135+
/**
136+
* Uploads and sets the topic's avatar for the specified topic.
137+
*
138+
* <pre><code>GitLab Endpoint: PUT /topics/:id</code></pre>
139+
*
140+
* @param id the topic in the form of an Integer
141+
* @param avatarFile the File instance of the avatar file to upload
142+
* @return the updated Topic instance
143+
* @throws GitLabApiException if any exception occurs
144+
*/
145+
public Topic updateTopicAvatar(final Integer id, File avatarFile) throws GitLabApiException {
146+
Response response = putUpload(Response.Status.OK, "avatar", avatarFile, "topics", id);
147+
return (response.readEntity(Topic.class));
148+
}
149+
150+
/**
151+
* Delete the topic's avatar for the specified topic.
152+
*
153+
* <pre><code>GitLab Endpoint: PUT /topics/:id</code></pre>
154+
*
155+
* @param id the topic in the form of an Integer
156+
* @return the updated Topic instance
157+
* @throws GitLabApiException if any exception occurs
158+
*/
159+
public Topic deleteTopicAvatar(final Integer id) throws GitLabApiException {
160+
Response response = putUpload(Response.Status.OK, "avatar", null, "topics", id);
161+
return (response.readEntity(Topic.class));
162+
}
163+
164+
/**
165+
* Delete a topic. You must be an administrator to delete a project topic. When you delete a project topic, you also delete the topic assignment for projects.
166+
*
167+
* <pre><code>GitLab Endpoint: DELETE /topics/:id</code></pre>
168+
*
169+
* @param id the topic to deleted in the form of an Integer
170+
* @throws GitLabApiException if any exception occurs
171+
*/
172+
public void deleteTopic(Integer id) throws GitLabApiException {
173+
if(isApiVersion(GitLabApi.ApiVersion.V3)){
174+
throw new GitLabApiException("Topics need api v4+");
175+
}
176+
delete(Response.Status.NO_CONTENT,null, "topics", id);
177+
}
178+
179+
/**
180+
* Merge two topics together. You must be an administrator to merge a source topic into a target topic. When you merge topics, you delete the source topic and move all assigned projects to the target topic.
181+
*
182+
* <pre><code>GitLab Endpoint: POST /topics/merge</code></pre>
183+
*
184+
* @param sourceTopicId ID of source project topic
185+
* @param targetTopicId ID of target project topic
186+
* @return the merged Topic instance
187+
* @throws GitLabApiException if any exception occurs
188+
*/
189+
public Topic mergeTopics(Integer sourceTopicId, Integer targetTopicId) throws GitLabApiException {
190+
Response response = post(Response.Status.OK,new GitLabApiForm().withParam("source_topic_id",sourceTopicId).withParam("target_topic_id",targetTopicId),"topics/merge");
191+
return (response.readEntity(Topic.class));
192+
}
193+
}

src/main/java/org/gitlab4j/api/models/Project.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ public String toString() {
8080
private Boolean snippetsEnabled;
8181
private String sshUrlToRepo;
8282
private Integer starCount;
83+
8384
private List<String> tagList;
85+
private List<String> topics;
8486
private Integer visibilityLevel;
8587
private Visibility visibility;
8688
private Boolean wallEnabled;
@@ -542,19 +544,44 @@ public void setStarCount(Integer starCount) {
542544
this.starCount = starCount;
543545
}
544546

547+
/**
548+
* Tags will be removed in API v5
549+
*/
550+
@Deprecated
545551
public List<String> getTagList() {
546552
return tagList;
547553
}
548554

555+
/**
556+
* Tags will be removed in API v5
557+
*/
558+
@Deprecated
549559
public void setTagList(List<String> tagList) {
550560
this.tagList = tagList;
551561
}
552562

563+
/**
564+
* Tags will be removed in API v5
565+
*/
566+
@Deprecated
553567
public Project withTagList(List<String> tagList) {
554568
this.tagList = tagList;
555569
return (this);
556570
}
557571

572+
public List<String> getTopics() {
573+
return topics;
574+
}
575+
576+
public void setTopics(List<String> topics) {
577+
this.topics = topics;
578+
}
579+
580+
public Project withTopics(List<String> topics) {
581+
this.topics = topics;
582+
return (this);
583+
}
584+
558585
public Visibility getVisibility() {
559586
return visibility;
560587
}
@@ -733,7 +760,7 @@ public String toString() {
733760
* Formats a fully qualified project path based on the provided namespace and project path.
734761
*
735762
* @param namespace the namespace, either a user name or group name
736-
* @param path the project path
763+
* @param path the project path
737764
* @return a fully qualified project path based on the provided namespace and project path
738765
*/
739766
public static final String getPathWithNammespace(String namespace, String path) {

0 commit comments

Comments
 (0)