Skip to content

Commit 2d0664f

Browse files
keerthi-blGMishx
authored andcommitted
feat(rest) : Advanced Search for project page
Signed-off-by: Keerthi B L <keerthi.bl@siemens.com>
1 parent 9dd4ff4 commit 2d0664f

File tree

5 files changed

+172
-43
lines changed

5 files changed

+172
-43
lines changed

rest/resource-server/src/docs/asciidoc/projects.adoc

+19
Original file line numberDiff line numberDiff line change
@@ -1233,3 +1233,22 @@ include::{snippets}/should_document_get_export_project_create_clearing_request/c
12331233

12341234
===== Example response
12351235
include::{snippets}/should_document_get_export_project_create_clearing_request/http-response.adoc[]
1236+
1237+
[[resources-projects-list-by-search]]
1238+
==== Filtering with more fields
1239+
1240+
A `GET` request to fetch filtered list of projects.
1241+
1242+
Note : send query parameter's value in encoded format. (Reference: `https://datatracker.ietf.org/doc/html/rfc3986`)
1243+
1244+
===== Response structure
1245+
include::{snippets}/should_document_get_projects_by_advance_search/response-fields.adoc[]
1246+
1247+
===== Example request
1248+
include::{snippets}/should_document_get_projects_by_advance_search/curl-request.adoc[]
1249+
1250+
===== Example response
1251+
include::{snippets}/should_document_get_projects_by_advance_search/http-response.adoc[]
1252+
1253+
===== Links
1254+
include::{snippets}/should_document_get_projects_by_advance_search/links.adoc[]

rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/ProjectController.java

+103-41
Original file line numberDiff line numberDiff line change
@@ -69,27 +69,15 @@
6969
import org.eclipse.sw360.datahandler.thrift.attachments.AttachmentUsage;
7070
import org.eclipse.sw360.datahandler.thrift.attachments.CheckStatus;
7171
import org.eclipse.sw360.datahandler.thrift.attachments.UsageData;
72-
import org.eclipse.sw360.datahandler.thrift.components.ClearingState;
73-
import org.eclipse.sw360.datahandler.thrift.components.Release;
74-
import org.eclipse.sw360.datahandler.thrift.components.ReleaseClearingStateSummary;
75-
import org.eclipse.sw360.datahandler.thrift.components.ReleaseLink;
76-
import org.eclipse.sw360.datahandler.thrift.components.ReleaseNode;
72+
import org.eclipse.sw360.datahandler.thrift.components.*;
7773
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfo;
7874
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoFile;
7975
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoParsingResult;
8076
import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseNameWithText;
8177
import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatInfo;
8278
import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatVariant;
8379
import org.eclipse.sw360.datahandler.thrift.licenses.License;
84-
import org.eclipse.sw360.datahandler.thrift.projects.ObligationList;
85-
import org.eclipse.sw360.datahandler.thrift.projects.ObligationStatusInfo;
86-
import org.eclipse.sw360.datahandler.thrift.projects.Project;
87-
import org.eclipse.sw360.datahandler.thrift.projects.ProjectClearingState;
88-
import org.eclipse.sw360.datahandler.thrift.projects.ProjectLink;
89-
import org.eclipse.sw360.datahandler.thrift.projects.ProjectProjectRelationship;
90-
import org.eclipse.sw360.datahandler.thrift.projects.ProjectRelationship;
91-
import org.eclipse.sw360.datahandler.thrift.projects.ProjectDTO;
92-
import org.eclipse.sw360.datahandler.thrift.projects.ClearingRequest;
80+
import org.eclipse.sw360.datahandler.thrift.projects.*;
9381
import org.eclipse.sw360.datahandler.thrift.users.User;
9482
import org.eclipse.sw360.datahandler.thrift.users.UserGroup;
9583
import org.eclipse.sw360.datahandler.thrift.vendors.Vendor;
@@ -259,6 +247,16 @@ public ResponseEntity<CollectionModel<EntityModel<Project>>> getProjectsForUser(
259247
@RequestParam(value = "tag", required = false) String tag,
260248
@Parameter(description = "Flag to get projects with all details.")
261249
@RequestParam(value = "allDetails", required = false) boolean allDetails,
250+
@Parameter(description = "The version of the project")
251+
@RequestParam(value = "version", required = false) String version,
252+
@Parameter(description = "The projectResponsible of the project")
253+
@RequestParam(value = "projectResponsible", required = false) String projectResponsible,
254+
@Parameter(description = "The state of the project")
255+
@RequestParam(value = "state", required = false) ProjectState projectState,
256+
@Parameter(description = "The clearingStatus of the project")
257+
@RequestParam(value = "clearingStatus", required = false) ProjectClearingState projectClearingState,
258+
@Parameter(description = "The additionalData of the project")
259+
@RequestParam(value = "additionalData", required = false) String additionalData,
262260
@Parameter(description = "List project by lucene search")
263261
@RequestParam(value = "luceneSearch", required = false) boolean luceneSearch,
264262
HttpServletRequest request) throws TException, URISyntaxException, PaginationParameterException, ResourceClassNotFoundException {
@@ -269,23 +267,13 @@ public ResponseEntity<CollectionModel<EntityModel<Project>>> getProjectsForUser(
269267
boolean isSearchByType = CommonUtils.isNotNullEmptyOrWhitespace(projectType);
270268
boolean isSearchByGroup = CommonUtils.isNotNullEmptyOrWhitespace(group);
271269
boolean isNoFilter = false;
270+
boolean isAllProjectAdded=false;
272271
String queryString = request.getQueryString();
273272
Map<String, String> params = restControllerHelper.parseQueryString(queryString);
274273
List<Project> sw360Projects = new ArrayList<>();
275-
Map<String, Set<String>> filterMap = new HashMap<>();
276274
if (luceneSearch) {
277-
if (CommonUtils.isNotNullEmptyOrWhitespace(projectType)) {
278-
Set<String> values = CommonUtils.splitToSet(projectType);
279-
filterMap.put(Project._Fields.PROJECT_TYPE.getFieldName(), values);
280-
}
281-
if (CommonUtils.isNotNullEmptyOrWhitespace(group)) {
282-
Set<String> values = CommonUtils.splitToSet(group);
283-
filterMap.put(Project._Fields.BUSINESS_UNIT.getFieldName(), values);
284-
}
285-
if (CommonUtils.isNotNullEmptyOrWhitespace(tag)) {
286-
Set<String> values = CommonUtils.splitToSet(tag);
287-
filterMap.put(Project._Fields.TAG.getFieldName(), values);
288-
}
275+
Map<String, Set<String>> filterMap = getFilterMap(tag, projectType, group, version, projectResponsible, projectState, projectClearingState,
276+
additionalData);
289277

290278
if (CommonUtils.isNotNullEmptyOrWhitespace(name)) {
291279
Set<String> values = CommonUtils.splitToSet(name);
@@ -298,24 +286,56 @@ public ResponseEntity<CollectionModel<EntityModel<Project>>> getProjectsForUser(
298286
} else {
299287
if (isSearchByName) {
300288
sw360Projects.addAll(projectService.searchProjectByName(params.get("name"), sw360User));
301-
} else if (isSearchByGroup) {
302-
sw360Projects.addAll(projectService.searchProjectByGroup(group, sw360User));
303-
} else if (isSearchByTag) {
304-
sw360Projects.addAll(projectService.searchProjectByTag(params.get("tag"), sw360User));
305-
} else if (isSearchByType) {
306-
sw360Projects.addAll(projectService.searchProjectByType(projectType, sw360User));
307289
} else {
308-
sw360Projects.addAll(projectService.getProjectsForUser(sw360User, pageable));
290+
isAllProjectAdded=true;
291+
sw360Projects.addAll(projectService.getProjectsSummaryForUserWithoutPagination(sw360User));
292+
}
293+
Map<String, Set<String>> restrictions = getFilterMap(tag, projectType, group, version, projectResponsible, projectState, projectClearingState,
294+
additionalData);
295+
if (!restrictions.isEmpty()) {
296+
sw360Projects = new ArrayList<>(sw360Projects.stream()
297+
.filter(filterProjectMap(restrictions)).toList());
298+
}else if(isAllProjectAdded){
309299
isNoFilter = true;
310300
}
311301
}
312-
return getProjectResponse(pageable, projectType, group, tag, allDetails, luceneSearch, request, sw360User,
302+
return getProjectResponse(pageable, allDetails, luceneSearch, request, sw360User,
313303
mapOfProjects, isSearchByName, sw360Projects, isNoFilter);
314304
}
315305

306+
private Map<String, Set<String>> getFilterMap(String tag, String projectType, String group, String version, String projectResponsible,
307+
ProjectState projectState, ProjectClearingState projectClearingState, String additionalData) {
308+
Map<String, Set<String>> filterMap = new HashMap<>();
309+
if (CommonUtils.isNotNullEmptyOrWhitespace(tag)) {
310+
filterMap.put(Project._Fields.TAG.getFieldName(), CommonUtils.splitToSet(tag));
311+
}
312+
if (CommonUtils.isNotNullEmptyOrWhitespace(projectType)) {
313+
filterMap.put(Project._Fields.PROJECT_TYPE.getFieldName(), CommonUtils.splitToSet(projectType));
314+
}
315+
if (CommonUtils.isNotNullEmptyOrWhitespace(group)) {
316+
filterMap.put(Project._Fields.BUSINESS_UNIT.getFieldName(), CommonUtils.splitToSet(group));
317+
}
318+
if (CommonUtils.isNotNullEmptyOrWhitespace(version)) {
319+
filterMap.put(Project._Fields.VERSION.getFieldName(), CommonUtils.splitToSet(version));
320+
}
321+
if (CommonUtils.isNotNullEmptyOrWhitespace(projectResponsible)) {
322+
filterMap.put(Project._Fields.PROJECT_RESPONSIBLE.getFieldName(), CommonUtils.splitToSet(projectResponsible));
323+
}
324+
if (projectState!=null && CommonUtils.isNotNullEmptyOrWhitespace(projectState.name())) {
325+
filterMap.put(Project._Fields.STATE.getFieldName(), CommonUtils.splitToSet(projectState.name()));
326+
}
327+
if (projectClearingState!=null && CommonUtils.isNotNullEmptyOrWhitespace(projectClearingState.name())) {
328+
filterMap.put(Project._Fields.CLEARING_STATE.getFieldName(), CommonUtils.splitToSet(projectClearingState.name()));
329+
}
330+
if (CommonUtils.isNotNullEmptyOrWhitespace(additionalData)) {
331+
filterMap.put(Project._Fields.ADDITIONAL_DATA.getFieldName(), CommonUtils.splitToSet(additionalData));
332+
}
333+
return filterMap;
334+
}
335+
316336
@NotNull
317337
private ResponseEntity<CollectionModel<EntityModel<Project>>> getProjectResponse(Pageable pageable,
318-
String projectType, String group, String tag, boolean allDetails, boolean luceneSearch,
338+
boolean allDetails, boolean luceneSearch,
319339
HttpServletRequest request, User sw360User, Map<String, Project> mapOfProjects, boolean isSearchByName,
320340
List<Project> sw360Projects, boolean isNoFilter) throws ResourceClassNotFoundException, PaginationParameterException, URISyntaxException, TException {
321341
sw360Projects.stream().forEach(prj -> mapOfProjects.put(prj.getId(), prj));
@@ -347,11 +367,9 @@ private ResponseEntity<CollectionModel<EntityModel<Project>>> getProjectResponse
347367
if (luceneSearch) {
348368
paginationResult.getResources().stream().forEach(consumer);
349369
} else {
350-
paginationResult.getResources().stream()
351-
.filter(project -> projectType == null || projectType.equals(project.projectType.name()))
352-
.filter(project -> group == null || group.isEmpty() || group.equals(project.getBusinessUnit()))
353-
.filter(project -> tag == null || tag.isEmpty() || tag.equals(project.getTag())).forEach(consumer);
370+
paginationResult.getResources().stream().forEach(consumer);
354371
}
372+
355373
CollectionModel resources;
356374
if (projectResources.size() == 0) {
357375
resources = restControllerHelper.emptyPageResource(Project.class, paginationResult);
@@ -415,7 +433,7 @@ public ResponseEntity<CollectionModel<EntityModel<Project>>> getProjectsFiltered
415433
List<Project> sw360Projects = projectService.getMyProjects(sw360User, userRoles);
416434
sw360Projects = projectService.getWithFilledClearingStatus(sw360Projects, clearingState);
417435

418-
return getProjectResponse(pageable, null, null, null, allDetails, true, request, sw360User,
436+
return getProjectResponse(pageable, allDetails, true, request, sw360User,
419437
mapOfProjects, true, sw360Projects, false);
420438
}
421439

@@ -3418,4 +3436,48 @@ public ResponseEntity<?> createDuplicateProjectWithDependencyNetwork(
34183436

34193437
return ResponseEntity.created(location).body(projectDTOHalResource);
34203438
}
3439+
3440+
/**
3441+
* Create a filter predicate to remove all projects which do not satisfy the restriction set.
3442+
* @param restrictions Restrictions set to filter projects on
3443+
* @return Filter predicate for stream.
3444+
*/
3445+
private static @NonNull Predicate<Project> filterProjectMap(Map<String, Set<String>> restrictions) {
3446+
return project -> {
3447+
for (Map.Entry<String, Set<String>> restriction : restrictions.entrySet()) {
3448+
final Set<String> filterSet = restriction.getValue();
3449+
Project._Fields field = Project._Fields.findByName(restriction.getKey());
3450+
Object fieldValue = project.getFieldValue(field);
3451+
if (fieldValue == null) {
3452+
return false;
3453+
}
3454+
if (field == Project._Fields.PROJECT_TYPE && !filterSet.contains(project.projectType.name())) {
3455+
return false;
3456+
} else if (field == Project._Fields.VERSION && !filterSet.contains(project.version)) {
3457+
return false;
3458+
} else if (field == Project._Fields.PROJECT_RESPONSIBLE && !filterSet.contains(project.projectResponsible)) {
3459+
return false;
3460+
} else if (field == Project._Fields.STATE && !filterSet.contains(project.state.name())) {
3461+
return false;
3462+
} else if (field == Project._Fields.CLEARING_STATE && !filterSet.contains(project.clearingState.name())) {
3463+
return false;
3464+
} else if ((field == Project._Fields.CREATED_BY || field == Project._Fields.CREATED_ON)
3465+
&& !fieldValue.toString().equalsIgnoreCase(filterSet.iterator().next())) {
3466+
return false;
3467+
} else if (fieldValue instanceof Set) {
3468+
if (Sets.intersection(filterSet, (Set<String>) fieldValue).isEmpty()) {
3469+
return false;
3470+
}
3471+
} else if (fieldValue instanceof Map<?,?>) {
3472+
Map<?, ?> fieldValueMap = (Map<?, ?>) fieldValue;
3473+
boolean hasIntersection = fieldValueMap.keySet().stream()
3474+
.anyMatch(filterSet::contains);
3475+
if (!hasIntersection) {
3476+
return false;
3477+
}
3478+
}
3479+
}
3480+
return true;
3481+
};
3482+
}
34213483
}

rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/Sw360ProjectService.java

+5
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ public Set<Project> getProjectsForUser(User sw360User, Pageable pageable) throws
147147
return new HashSet<>(pageDtToProjects.entrySet().iterator().next().getValue());
148148
}
149149

150+
public List<Project> getProjectsSummaryForUserWithoutPagination(User sw360User) throws TException {
151+
ProjectService.Iface sw360ProjectClient = getThriftProjectClient();
152+
return sw360ProjectClient.getAccessibleProjectsSummary(sw360User);
153+
}
154+
150155
public Project getProjectForUserById(String projectId, User sw360User) throws TException {
151156
ProjectService.Iface sw360ProjectClient = getThriftProjectClient();
152157
try {

rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/integration/ProjectTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public void before() throws TException {
5151
projectList.add(project);
5252

5353
given(this.projectServiceMock.getProjectsForUser(any(), any())).willReturn(projectList);
54+
given(this.projectServiceMock.getProjectsSummaryForUserWithoutPagination(any())).willReturn(projectList.stream().toList());
5455

5556
User user = new User();
5657
user.setId("123456789");

0 commit comments

Comments
 (0)