Skip to content

Commit 4a3d40f

Browse files
committed
Design progress and working search implemented, more todo
1 parent 75dbf36 commit 4a3d40f

8 files changed

Lines changed: 356 additions & 31 deletions

File tree

src/main/java/org/pwss/controller/HomeController.java

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
11
package org.pwss.controller;
22

3-
import java.awt.event.MouseAdapter;
4-
import java.awt.event.MouseEvent;
5-
import java.util.List;
6-
import java.util.Optional;
7-
import java.util.concurrent.ExecutionException;
8-
9-
import javax.swing.*;
10-
113
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import org.pwss.controller.util.NavigationContext;
125
import org.pwss.exception.monitored_directory.MonitoredDirectoryGetAllException;
136
import org.pwss.exception.scan.*;
7+
import org.pwss.exception.scan_summary.GetSearchFilesException;
148
import org.pwss.model.entity.Diff;
9+
import org.pwss.model.entity.File;
1510
import org.pwss.model.entity.MonitoredDirectory;
1611
import org.pwss.model.entity.Scan;
1712
import org.pwss.model.service.MonitoredDirectoryService;
1813
import org.pwss.model.service.ScanService;
14+
import org.pwss.model.service.ScanSummaryService;
1915
import org.pwss.model.service.response.LiveFeedResponse;
2016
import org.pwss.model.table.DiffTableModel;
17+
import org.pwss.model.table.FileTableModel;
2118
import org.pwss.model.table.MonitoredDirectoryTableModel;
2219
import org.pwss.model.table.ScanTableModel;
2320
import org.pwss.navigation.NavigationEvents;
2421
import org.pwss.navigation.Screen;
25-
import org.pwss.view.popup_menu.MonitoredDirectoryPopupFactory;
26-
import org.pwss.view.popup_menu.listener.MonitoredDirectoryPopupListenerImpl;
27-
import org.pwss.controller.util.NavigationContext;
2822
import org.pwss.utils.LiveFeedUtils;
2923
import org.pwss.utils.ReportUtils;
3024
import org.pwss.utils.StringConstants;
25+
import org.pwss.view.popup_menu.MonitoredDirectoryPopupFactory;
26+
import org.pwss.view.popup_menu.listener.MonitoredDirectoryPopupListenerImpl;
3127
import org.pwss.view.screen.HomeScreen;
3228

29+
import javax.swing.*;
30+
import java.awt.event.MouseAdapter;
31+
import java.awt.event.MouseEvent;
32+
import java.util.List;
33+
import java.util.Optional;
34+
import java.util.concurrent.ExecutionException;
35+
3336
public class HomeController extends BaseController<HomeScreen> {
3437
private final ScanService scanService;
3538
private final MonitoredDirectoryService monitoredDirectoryService;
39+
private final ScanSummaryService scanSummaryService;
3640
private final MonitoredDirectoryPopupFactory monitoredDirectoryPopupFactory;
3741

3842
private List<MonitoredDirectory> allMonitoredDirectories;
3943
private List<Scan> recentScans;
4044
private List<Diff> recentDiffs;
45+
private List<File> fileResults;
4146

4247
private boolean scanRunning;
4348
private long totalDiffCount = 0;
@@ -47,6 +52,7 @@ public HomeController(HomeScreen view) {
4752
super(view);
4853
this.scanService = new ScanService();
4954
this.monitoredDirectoryService = new MonitoredDirectoryService();
55+
scanSummaryService = new ScanSummaryService();
5056
this.monitoredDirectoryPopupFactory = new MonitoredDirectoryPopupFactory(new MonitoredDirectoryPopupListenerImpl(this, monitoredDirectoryService));
5157
}
5258

@@ -174,6 +180,7 @@ public void mouseClicked(MouseEvent e) {
174180
}
175181
});
176182
screen.getClearFeedButton().addActionListener(e -> clearLiveFeed());
183+
screen.getFileSearchField().addActionListener(e -> searchForFiles());
177184
}
178185

179186
@Override
@@ -191,14 +198,17 @@ protected void refreshView() {
191198
screen.getLiveFeedDiffCount().setVisible(showLiveFeed);
192199
screen.getClearFeedButton().setVisible(showClearLiveFeed);
193200

194-
ScanTableModel mostRecentScansListModel = new ScanTableModel(recentScans);
201+
ScanTableModel mostRecentScansListModel = new ScanTableModel(recentScans != null ? recentScans : List.of());
195202
screen.getRecentScanTable().setModel(mostRecentScansListModel);
196203

197-
MonitoredDirectoryTableModel monitoredDirectoryTableModel = new MonitoredDirectoryTableModel(allMonitoredDirectories);
204+
MonitoredDirectoryTableModel monitoredDirectoryTableModel = new MonitoredDirectoryTableModel(allMonitoredDirectories != null ? allMonitoredDirectories : List.of());
198205
screen.getMonitoredDirectoriesTable().setModel(monitoredDirectoryTableModel);
199206

200-
DiffTableModel diffTableModel = new DiffTableModel(recentDiffs);
207+
DiffTableModel diffTableModel = new DiffTableModel(recentDiffs != null ? recentDiffs : List.of());
201208
screen.getDiffTable().setModel(diffTableModel);
209+
210+
FileTableModel fileTableModel = new FileTableModel(fileResults != null ? fileResults : List.of());
211+
screen.getFilesTable().setModel(fileTableModel);
202212
}
203213

204214
/**
@@ -374,4 +384,22 @@ private void startPollingScanLiveFeed(boolean singleDirectory) {
374384
});
375385
scanStatusTimer.start();
376386
}
387+
388+
private void searchForFiles() {
389+
String query = screen.getFileSearchField().getText().trim();
390+
boolean searchContainingInput = screen.getSearchContainingCheckBox().isSelected();
391+
boolean descendingOrder = screen.getDescendingCheckBox().isSelected();
392+
if (query.isEmpty()) {
393+
screen.showError("Please enter a search query.");
394+
return;
395+
}
396+
397+
try {
398+
String searchQuery = searchContainingInput ? "%" + query + "%" : query;
399+
fileResults = scanSummaryService.searchFiles(searchQuery, !descendingOrder);
400+
refreshView();
401+
} catch (GetSearchFilesException | ExecutionException | InterruptedException | JsonProcessingException e) {
402+
SwingUtilities.invokeLater(() -> screen.showError(e.getMessage()));
403+
}
404+
}
377405
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.pwss.exception.scan_summary;
2+
3+
public final class GetSearchFilesException extends Exception {
4+
5+
/**
6+
* Constructs a `GetSearchFilesException` with no detail message or cause.
7+
*/
8+
public GetSearchFilesException() {
9+
super();
10+
}
11+
12+
/**
13+
* Constructs a `GetSearchFilesException` with the specified detail message.
14+
* The message is appended with " \nPWSS @Exception".
15+
*
16+
* @param message The detail message to be included in the exception.
17+
*/
18+
public GetSearchFilesException(String message) {
19+
super(message + " \nPWSS-FE @Exception");
20+
}
21+
22+
/**
23+
* Constructs a `GetSearchFilesException` with the specified cause.
24+
*
25+
* @param cause The cause of the exception.
26+
*/
27+
public GetSearchFilesException(Throwable cause) {
28+
super(cause);
29+
}
30+
31+
/**
32+
* Constructs a `GetSearchFilesException` with the specified detail message and cause.
33+
*
34+
* @param message The detail message to be included in the exception.
35+
* @param cause The cause of the exception.
36+
*/
37+
public GetSearchFilesException(String message, Throwable cause) {
38+
super(message, cause);
39+
}
40+
}

src/main/java/org/pwss/model/service/ScanSummaryService.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import com.fasterxml.jackson.core.JsonProcessingException;
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import org.pwss.exception.scan_summary.GetMostRecentSummaryException;
6+
import org.pwss.exception.scan_summary.GetSearchFilesException;
67
import org.pwss.exception.scan_summary.GetSummaryForFileException;
78
import org.pwss.exception.scan_summary.GetSummaryForScanException;
9+
import org.pwss.model.entity.File;
810
import org.pwss.model.entity.ScanSummary;
911
import org.pwss.model.service.network.Endpoint;
1012
import org.pwss.model.service.network.PwssHttpClient;
13+
import org.pwss.model.service.request.scan_summary.GetFilesSearchRequest;
1114
import org.pwss.model.service.request.scan_summary.GetSummaryForFileRequest;
1215
import org.pwss.model.service.request.scan_summary.GetSummaryForScanRequest;
1316

@@ -46,6 +49,16 @@ public List<ScanSummary> getMostRecentSummary() throws GetMostRecentSummaryExcep
4649
};
4750
}
4851

52+
/**
53+
* Retrieves scan summaries for a specific file by sending a request to the SUMMARY_FILE endpoint.
54+
*
55+
* @param fileId The ID of the file for which to retrieve scan summaries.
56+
* @return A list of ScanSummary objects associated with the specified file ID if the request is successful.
57+
* @throws GetSummaryForFileException If the attempt to retrieve scan summaries for the specified file fails due to various reasons such as invalid credentials, no scan summaries found, invalid file ID, or server error.
58+
* @throws ExecutionException If an error occurs during the asynchronous execution of the request.
59+
* @throws InterruptedException If the thread executing the request is interrupted.
60+
* @throws JsonProcessingException If an error occurs while processing JSON data.
61+
*/
4962
public List<ScanSummary> getSummaryForFile(long fileId) throws GetSummaryForFileException, ExecutionException, InterruptedException, JsonProcessingException {
5063
String body = objectMapper.writeValueAsString(new GetSummaryForFileRequest(fileId));
5164
HttpResponse<String> response = PwssHttpClient.getInstance().request(Endpoint.SUMMARY_FILE, body);
@@ -60,6 +73,34 @@ public List<ScanSummary> getSummaryForFile(long fileId) throws GetSummaryForFile
6073
};
6174
}
6275

76+
/**
77+
* Searches for files based on a query string by sending a request to the SUMMARY_FILE_SEARCH endpoint.
78+
*
79+
* @param queryString The search query string used to find files.
80+
* @param ascending A boolean indicating whether the search results should be sorted in ascending order.
81+
* @return A list of File objects that match the search criteria if the request is successful.
82+
* @throws GetSearchFilesException If the attempt to search for files fails due to various reasons such as invalid credentials, invalid search parameters, or server error.
83+
* @throws ExecutionException If an error occurs during the asynchronous execution of the request.
84+
* @throws InterruptedException If the thread executing the request is interrupted.
85+
* @throws JsonProcessingException If an error occurs while processing JSON data.
86+
*/
87+
public List<File> searchFiles(String queryString, boolean ascending) throws GetSearchFilesException, ExecutionException, InterruptedException, JsonProcessingException {
88+
String body = objectMapper.writeValueAsString(new GetFilesSearchRequest(queryString, 1000, "basename", ascending));
89+
HttpResponse<String> response = PwssHttpClient.getInstance().request(Endpoint.SUMMARY_FILE_SEARCH, body);
90+
91+
return switch (response.statusCode()) {
92+
case 200 -> List.of(objectMapper.readValue(response.body(), File[].class));
93+
case 401 ->
94+
throw new GetSearchFilesException("Search files failed: User not authorized to perform this action.");
95+
case 404 -> List.of();
96+
case 422 ->
97+
throw new GetSearchFilesException("Search files failed: The provided search parameters are invalid.");
98+
case 500 ->
99+
throw new GetSearchFilesException("Search files failed: An error occurred on the server while attempting to search for files.");
100+
default -> null;
101+
};
102+
}
103+
63104
public List<ScanSummary> getScanSummaryForScan(long scanId) throws GetSummaryForScanException, ExecutionException, InterruptedException, JsonProcessingException {
64105
String body = objectMapper.writeValueAsString(new GetSummaryForScanRequest(scanId));
65106
HttpResponse<String> response = PwssHttpClient.getInstance().request(Endpoint.SUMMARY_SCAN, body);

src/main/java/org/pwss/model/service/network/Endpoint.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ public enum Endpoint {
8787
* Endpoint for retrieving the scan summaries for a specific file.
8888
*/
8989
SUMMARY_FILE(HTTP_Method.POST, A.BASE_URL + A.SCAN_SUMMARY + "file"),
90+
/**
91+
* Endpoint for searching files based on a query string.
92+
*/
93+
SUMMARY_FILE_SEARCH(HTTP_Method.POST, A.BASE_URL + A.SCAN_SUMMARY + "file/search"),
9094
/**
9195
* Endpoint for retrieving the most recent scan summary.
9296
*/
@@ -155,4 +159,8 @@ final class A {
155159
* Path segment for user-related endpoints.
156160
*/
157161
static final String USER = "user/";
162+
/**
163+
* Path segment for note-related endpoints.
164+
*/
165+
static final String NOTE = "note/";
158166
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.pwss.model.service.request.scan_summary;
2+
3+
/**
4+
* Record representing a request to search for files with specific parameters.
5+
*
6+
* @param searchQuery The search query string to filter files.
7+
* @param limit The maximum number of results to return.
8+
* @param sortField The field by which to sort the results.
9+
* @param ascending Whether the sorting should be in ascending order.
10+
*/
11+
public record GetFilesSearchRequest(String searchQuery, int limit, String sortField, boolean ascending) {
12+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.pwss.model.table;
2+
3+
import org.pwss.model.entity.File;
4+
5+
import javax.swing.table.AbstractTableModel;
6+
import java.util.List;
7+
import java.util.Optional;
8+
9+
public class FileTableModel extends AbstractTableModel {
10+
private final List<File> data;
11+
private final String[] columns = {"\uD83D\uDEA6 Basename", "Size (bytes)"};
12+
13+
public FileTableModel(List<File> data) {
14+
this.data = data;
15+
}
16+
17+
@Override
18+
public int getRowCount() {
19+
return data.size();
20+
}
21+
22+
@Override
23+
public int getColumnCount() {
24+
return columns.length;
25+
}
26+
27+
@Override
28+
public String getColumnName(int column) {
29+
return columns[column];
30+
}
31+
32+
@Override
33+
public Object getValueAt(int rowIndex, int columnIndex) {
34+
File file = data.get(rowIndex);
35+
return switch (columnIndex) {
36+
case 0 -> file.basename();
37+
case 1 -> file.size();
38+
default -> null;
39+
};
40+
}
41+
42+
/**
43+
* Retrieves the File object at the specified row index.
44+
*
45+
* @param rowIndex The index of the row for which to retrieve the File object.
46+
* @return An Optional containing the File object if the index is valid, or an empty Optional if the index is out of bounds.
47+
*/
48+
public Optional<File> getFileAt(int rowIndex) {
49+
if (rowIndex >= 0 && rowIndex < data.size()) {
50+
return Optional.of(data.get(rowIndex));
51+
}
52+
return Optional.empty();
53+
}
54+
}

0 commit comments

Comments
 (0)