Skip to content

Commit 32b41d5

Browse files
authored
Merge pull request #9 from mcanoy/types-sort
api to get distinct types and api to get counts per type. add sort
2 parents 11f0a2f + 8d75b1b commit 32b41d5

File tree

9 files changed

+161
-44
lines changed

9 files changed

+161
-44
lines changed

src/main/java/com/redhat/labs/lodestar/model/Artifact.java

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.redhat.labs.lodestar.model;
22

3+
import java.util.ArrayList;
34
import java.util.List;
45
import java.util.Optional;
56

67
import javax.json.bind.annotation.JsonbProperty;
78
import javax.json.bind.annotation.JsonbTransient;
89
import javax.validation.constraints.NotBlank;
910

11+
import com.mongodb.client.model.Filters;
1012
import org.bson.codecs.pojo.annotations.BsonId;
13+
import org.bson.conversions.Bson;
1114
import org.bson.types.ObjectId;
1215
import org.javers.core.metamodel.annotation.DiffIgnore;
1316
import org.javers.core.metamodel.annotation.Id;
@@ -21,6 +24,12 @@
2124
import lombok.EqualsAndHashCode;
2225
import lombok.NoArgsConstructor;
2326

27+
import static com.mongodb.client.model.Accumulators.sum;
28+
import static com.mongodb.client.model.Aggregates.*;
29+
import static com.mongodb.client.model.Aggregates.sort;
30+
import static com.mongodb.client.model.Projections.*;
31+
import static com.mongodb.client.model.Sorts.*;
32+
2433
@Data
2534
@Builder
2635
@NoArgsConstructor
@@ -70,19 +79,19 @@ public static ArtifactCount countAllArtifacts() {
7079
* Returns an {@link ArtifactCount} containing the count for the number of
7180
* {@link Artifact} matching the engagement uuid.
7281
*
73-
* @param engagementUuid
74-
* @return
82+
* @param engagementUuid - uuid
83+
* @return count - number of artifacts for engagement
7584
*/
7685
public static ArtifactCount countArtifactsByEngagementUuid(String engagementUuid) {
7786
return ArtifactCount.builder().count(count("engagementUuid", engagementUuid)).build();
7887
}
7988

8089
/**
8190
* Returns an {@link ArtifactCount} containing the count for the number of
82-
* {@link Artifact} matching the typegit.
91+
* {@link Artifact} matching the type.
8392
*
84-
* @param engagementUuid
85-
* @return
93+
* @param type - type of artifact
94+
* @return count
8695
*/
8796
public static ArtifactCount countArtifactsByType(String type) {
8897
return ArtifactCount.builder().count(count("type", type)).build();
@@ -96,6 +105,21 @@ public static ArtifactCount countArtifactsByRegionAndType(String type, List<Stri
96105
return ArtifactCount.builder().count(count("{ $and: [ {'type':?1}, {'region':{'$in':[?2]}} ] }", type, regions)).build();
97106
}
98107

108+
public static List<ArtifactCount> countArtifactsForEachRegionAndType(List<String> regions) {
109+
String count = "count";
110+
List<Bson> bson = new ArrayList<>();
111+
112+
if(!regions.isEmpty()) {
113+
bson.add(match(Filters.in("region", regions)));
114+
}
115+
116+
bson.add(group("$type", sum(count, 1)));
117+
bson.add(project(fields(include(count), computed("type", "$_id"))));
118+
bson.add(sort(orderBy(descending(count), ascending("type"))));
119+
120+
return mongoCollection().aggregate(bson, ArtifactCount.class).into(new ArrayList<>());
121+
}
122+
99123
/**
100124
* Returns {@link List} of {@link Artifact}s sorted descending on modified
101125
* timestamp using the page specified.
@@ -104,8 +128,8 @@ public static ArtifactCount countArtifactsByRegionAndType(String type, List<Stri
104128
* @param pageSize
105129
* @return
106130
*/
107-
public static List<Artifact> pagedArtifacts(int page, int pageSize) {
108-
return findAll(Sort.descending(MODIFIED)).page(page, pageSize).list();
131+
public static List<Artifact> pagedArtifacts(int page, int pageSize, Sort sort) {
132+
return findAll(sort).page(page, pageSize).list();
109133
}
110134

111135
/**
@@ -116,18 +140,18 @@ public static List<Artifact> pagedArtifacts(int page, int pageSize) {
116140
* @param pageSize
117141
* @return
118142
*/
119-
public static List<Artifact> pagedArtifactsByType(String type, int page, int pageSize) {
120-
return find("type", Sort.descending(MODIFIED), type).page(page, pageSize).list();
143+
public static List<Artifact> pagedArtifactsByType(String type, int page, int pageSize, Sort sort) {
144+
return find("type", sort, type).page(page, pageSize).list();
121145
}
122146

123-
public static List<Artifact> pagedArtifactsByRegion(List<String> regions, int page, int pageSize) {
124-
return find("region in ?1", Sort.descending(MODIFIED), regions).page(page, pageSize).list();
147+
public static List<Artifact> pagedArtifactsByRegion(List<String> regions, int page, int pageSize, Sort sort) {
148+
return find("region in ?1", sort, regions).page(page, pageSize).list();
125149
}
126150

127-
public static List<Artifact> pagedArtifactsByRegionAndType(String type, List<String> regions, int page, int pageSize) {
151+
public static List<Artifact> pagedArtifactsByRegionAndType(String type, List<String> regions, int page, int pageSize, Sort sort) {
128152
//not sure why the commented query doesn't work but keep seeing this error - no viable alternative at input 'type='
129153
//return find("type = ?1 and region in ?2", Sort.descending(MODIFIED), type, regions).page(page, pageSize).list();
130-
return find("{ $and: [ {'type':?1}, {'region':{'$in':[?2]}} ] }", Sort.descending(MODIFIED), type, regions).page(page, pageSize).list();
154+
return find("{ $and: [ {'type':?1}, {'region':{'$in':[?2]}} ] }", sort, type, regions).page(page, pageSize).list();
131155
}
132156

133157
/**

src/main/java/com/redhat/labs/lodestar/model/ArtifactCount.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@
22

33
import java.util.Optional;
44

5+
import lombok.AllArgsConstructor;
56
import lombok.Builder;
67
import lombok.Data;
8+
import lombok.NoArgsConstructor;
79

810
@Data
911
@Builder
12+
@NoArgsConstructor
13+
@AllArgsConstructor
1014
public class ArtifactCount {
1115

1216
@Builder.Default
1317
private Long count = 0l;
18+
private String type;
1419
@Builder.Default
1520
private Optional<String> engagementId = Optional.empty();
1621

src/main/java/com/redhat/labs/lodestar/model/GetListOptions.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.redhat.labs.lodestar.model;
22

3-
import javax.ws.rs.QueryParam;
3+
import javax.ws.rs.*;
44

5+
import io.quarkus.panache.common.*;
56
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
67

78
import lombok.AllArgsConstructor;
@@ -15,14 +16,19 @@
1516
@EqualsAndHashCode(callSuper = true)
1617
public class GetListOptions extends GetOptions {
1718

18-
@Parameter(name = "page", required = false, description = "0 based index of page of results to return")
19+
@Parameter(name = "page", description = "0 based index of page of results to return")
1920
@QueryParam("page")
2021
private int page;
2122

22-
@Parameter(name = "pageSize", required = false, description = "number of results to return per page")
23+
@Parameter(name = "pageSize", description = "number of results to return per page")
2324
@QueryParam("pageSize")
2425
private int pageSize;
2526

27+
@DefaultValue("updated|DESC")
28+
@Parameter(name = "sort", description = "Sort. Comma separated list field|direction,field|direction. UUID will always be added at the end. Default direction is ASC")
29+
@QueryParam("sort")
30+
private String sort;
31+
2632
public int getPage() {
2733
return page < 0 ? 0 : page;
2834
}
@@ -31,4 +37,39 @@ public int getPageSize() {
3137
return pageSize < 1 ? 20 : pageSize;
3238
}
3339

40+
public Sort getQuerySort() {
41+
return getQuerySort(Sort.by("uuid"));
42+
}
43+
44+
public Sort getQuerySort(Sort defaultSort) {
45+
if(sort == null) {
46+
return defaultSort;
47+
}
48+
String[] sortAll = sort.split(",");
49+
Sort sort = null;
50+
String direction;
51+
52+
for (String s : sortAll) {
53+
String[] sortFields = s.split("\\|");
54+
direction = sortFields.length == 2 ? sortFields[1] : "";
55+
if (sort == null) {
56+
sort = Sort.by(sortFields[0], getDirection(direction));
57+
} else {
58+
sort.and(sortFields[0], getDirection(direction));
59+
}
60+
}
61+
62+
sort.and("uuid");
63+
64+
return sort;
65+
}
66+
67+
private Sort.Direction getDirection(String dir) {
68+
if("DESC".equals(dir)) {
69+
return Sort.Direction.Descending;
70+
}
71+
72+
return Sort.Direction.Ascending;
73+
}
74+
3475
}

src/main/java/com/redhat/labs/lodestar/resource/ArtifactResource.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.util.List;
44
import java.util.Optional;
5+
import java.util.Set;
6+
import java.util.TreeSet;
57

68
import javax.inject.Inject;
79
import javax.validation.Valid;
@@ -75,6 +77,22 @@ public ArtifactCount countArtifacts(@BeanParam GetOptions options) {
7577
return service.countArtifacts(options);
7678
}
7779

80+
@GET
81+
@Path("/types/count")
82+
public List<ArtifactCount> countArtifactsByType(@QueryParam("regions") List<String> regions) {
83+
return service.getArtifactTypeSummary(regions);
84+
}
85+
86+
@GET
87+
@Path("/types")
88+
public Set<String> getAllTypes(@QueryParam("regions") List<String> regions) {
89+
List<ArtifactCount> counts = service.getArtifactTypeSummary(regions);
90+
Set<String> types = new TreeSet<>();
91+
counts.forEach(type -> types.add(type.getType()));
92+
93+
return types;
94+
}
95+
7896
@PUT
7997
@Path("/refresh")
8098
@APIResponses(value = {

src/main/java/com/redhat/labs/lodestar/rest/client/EngagementApiRestClient.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
@Produces("application/json")
1717
@RegisterRestClient(configKey = "engagement.api")
1818
@RegisterProvider(value = GitLabApiExceptionMapper.class, priority = 50)
19+
@Path("/api/v2/engagements")
1920
public interface EngagementApiRestClient {
2021

2122
@GET
22-
@Path("/api/v1/engagements/projects/{uuid}")
23-
Engagement getEngagementProjectByUuid(@PathParam("uuid") String engagementUuid, @QueryParam("mini") boolean mini);
23+
@Path("{uuid}")
24+
Engagement getEngagementByUuid(@PathParam("uuid") String engagementUuid);
2425

2526
@GET
26-
@Path("/api/v1/engagements/projects")
27-
List<Engagement> getAllEngagementProjects();
27+
List<Engagement> getAllEngagements();
2828

2929
}

src/main/java/com/redhat/labs/lodestar/service/ArtifactService.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import javax.json.bind.Jsonb;
1313
import javax.ws.rs.WebApplicationException;
1414

15+
import io.quarkus.panache.common.Sort;
1516
import org.eclipse.microprofile.config.inject.ConfigProperty;
1617
import org.eclipse.microprofile.rest.client.inject.RestClient;
1718
import org.javers.core.ChangesByObject;
@@ -76,7 +77,7 @@ public void purge() {
7677
* and inserts into the database.
7778
*/
7879
public long refresh() {
79-
engagementRestClient.getAllEngagementProjects().parallelStream().forEach(this::reloadFromGitlabByEngagement);
80+
engagementRestClient.getAllEngagements().parallelStream().forEach(this::reloadFromGitlabByEngagement);
8081
return countArtifacts(new GetOptions()).getCount();
8182
}
8283

@@ -85,7 +86,7 @@ public long refresh() {
8586
* empty {@link List} is returned if {@link File} or its contents are null or
8687
* blank.
8788
*
88-
* @param projectId
89+
* @param engagement engagement to reload artifacts
8990
* @return
9091
*/
9192
void reloadFromGitlabByEngagement(Engagement engagement) {
@@ -170,26 +171,31 @@ public void updateArtifacts(String engagementUuid, String region, List<Artifact>
170171
public List<Artifact> getArtifacts(GetListOptions options) {
171172

172173
if(!options.getRegion().isEmpty() && options.getType().isPresent()) { //by region and type
173-
return Artifact.pagedArtifactsByRegionAndType(options.getType().get(), options.getRegion(), options.getPage(), options.getPageSize());
174+
return Artifact.pagedArtifactsByRegionAndType(options.getType().get(), options.getRegion(), options.getPage(),
175+
options.getPageSize(), options.getQuerySort());
174176
}
175177

176178
if(!options.getRegion().isEmpty()) { //by region
177-
return Artifact.pagedArtifactsByRegion(options.getRegion(), options.getPage(), options.getPageSize());
179+
return Artifact.pagedArtifactsByRegion(options.getRegion(), options.getPage(), options.getPageSize(), options.getQuerySort());
178180
}
179181

180182
if(options.getType().isPresent()) { //by type
181183
checkEngagementUuid(options.getEngagementUuid());
182-
return Artifact.pagedArtifactsByType(options.getType().get(), options.getPage(), options.getPageSize());
184+
return Artifact.pagedArtifactsByType(options.getType().get(), options.getPage(), options.getPageSize(), options.getQuerySort());
183185
}
184186

185187
Optional<String> engagementUuid = options.getEngagementUuid();
186188

187189
return engagementUuid.isPresent()
188190
? Artifact.pagedArtifactsByEngagementUuid(engagementUuid.get(), options.getPage(),
189191
options.getPageSize()) //by uuid
190-
: Artifact.pagedArtifacts(options.getPage(), options.getPageSize()); //all
192+
: Artifact.pagedArtifacts(options.getPage(), options.getPageSize(), options.getQuerySort(Sort.descending("modified").and("engagementUuid"))); //all
191193

192194
}
195+
196+
public List<ArtifactCount> getArtifactTypeSummary(List<String> regions) {
197+
return Artifact.countArtifactsForEachRegionAndType(regions);
198+
}
193199

194200
private void checkEngagementUuid(Optional<String> engagementUuid) {
195201

@@ -231,8 +237,8 @@ public ArtifactCount countArtifacts(GetOptions options) {
231237
* Removes the {@link Artifact} from the database if the object has been
232238
* removed. Otherwise, creates or updates the {@link Artifact}.
233239
*
234-
* @param cbo
235-
* @param incoming
240+
* @param cbo changes
241+
* @param incoming update artifacts
236242
*/
237243
void processObjectChange(ChangesByObject cbo, List<Artifact> incoming) {
238244

@@ -258,7 +264,6 @@ void processObjectChange(ChangesByObject cbo, List<Artifact> incoming) {
258264
* Creates or updates the {@link Artifact} in the database.
259265
*
260266
* @param artifact
261-
* @return
262267
*/
263268
void createOrUpdateArtifact(Artifact artifact) {
264269

@@ -318,7 +323,6 @@ void updateArtifact(Artifact artifact, Artifact existing) {
318323
* {@link Artifact}s.
319324
*
320325
* @param engagementUuid
321-
* @param artifacts
322326
* @param authorEmail
323327
* @param authorName
324328
* @param commitMessage
@@ -327,7 +331,7 @@ public void updateArtifactsFile(String engagementUuid, Optional<String> authorEm
327331
Optional<String> authorName, Optional<String> commitMessage) {
328332

329333
// find project by engagement
330-
Engagement project = engagementRestClient.getEngagementProjectByUuid(engagementUuid, true);
334+
Engagement project = engagementRestClient.getEngagementByUuid(engagementUuid);
331335

332336
List<Artifact> artifacts = Artifact.findAllByEngagementUuid(engagementUuid);
333337
String content = jsonb.toJson(artifacts);

src/test/java/com/redhat/labs/mock/ExternalApiWireMock.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ public Map<String, String> start() {
2626
// get engagement projects
2727
String body = ResourceLoader.load("engagement-projects.json");
2828

29-
stubFor(get(urlEqualTo("/api/v1/engagements/projects"))
29+
stubFor(get(urlEqualTo("/api/v2/engagements"))
3030
.willReturn(aResponse().withHeader("Content-Type", "application/json").withBody(body)));
3131

3232
body = ResourceLoader.load("engagement-project-1.json");
3333

34-
stubFor(get(urlEqualTo("/api/v1/engagements/projects/1111?mini=true"))
34+
stubFor(get(urlEqualTo("/api/v2/engagements/1111"))
3535
.willReturn(aResponse().withHeader("Content-Type", "application/json").withBody(body)));
3636

3737
body = ResourceLoader.load("engagement-project-2.json");
3838

39-
stubFor(get(urlEqualTo("/api/v1/engagements/projects/2222?mini=true"))
39+
stubFor(get(urlEqualTo("/api/v2/engagements/2222"))
4040
.willReturn(aResponse().withHeader("Content-Type", "application/json").withBody(body)));
4141

4242
// stubFor(get(urlEqualTo("/api/v1/engagements/projects/2222"))

src/test/java/com/redhat/labs/model/ArtifactTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import javax.inject.Inject;
99

10+
import io.quarkus.panache.common.Sort;
1011
import org.junit.jupiter.api.BeforeEach;
1112
import org.junit.jupiter.api.Test;
1213

@@ -42,7 +43,7 @@ void testCountArtifactsByEngagementUuid() {
4243

4344
@Test
4445
void testPagedArtifacts() {
45-
assertEquals(1, Artifact.pagedArtifacts(0, 1).size());
46+
assertEquals(1, Artifact.pagedArtifacts(0, 1, Sort.by("uuid")).size());
4647
}
4748

4849
@Test

0 commit comments

Comments
 (0)