diff --git a/src/main/java/org/qortal/api/resource/ArbitraryResource.java b/src/main/java/org/qortal/api/resource/ArbitraryResource.java index 8031bf83..ba39825c 100644 --- a/src/main/java/org/qortal/api/resource/ArbitraryResource.java +++ b/src/main/java/org/qortal/api/resource/ArbitraryResource.java @@ -432,14 +432,23 @@ public class ArbitraryResource { @HeaderParam(Security.API_KEY_HEADER) String apiKey, @Parameter(description = "Include status") @QueryParam("includestatus") Boolean includeStatus, @Parameter(ref = "limit") @QueryParam("limit") Integer limit, - @Parameter(ref = "offset") @QueryParam("offset") Integer offset) { + @Parameter(ref = "offset") @QueryParam("offset") Integer offset, + @QueryParam("query") String query) { + Security.checkApiCallAllowed(request); List resources = new ArrayList<>(); try (final Repository repository = RepositoryManager.getRepository()) { + + List transactionDataList; + + if (query == null || query.equals("")) { + transactionDataList = ArbitraryDataStorageManager.getInstance().listAllHostedTransactions(repository, limit, offset); + } else { + transactionDataList = ArbitraryDataStorageManager.getInstance().searchHostedTransactions(repository,query, limit, offset); + } - List transactionDataList = ArbitraryDataStorageManager.getInstance().listAllHostedTransactions(repository, limit, offset); for (ArbitraryTransactionData transactionData : transactionDataList) { ArbitraryResourceInfo arbitraryResourceInfo = new ArbitraryResourceInfo(); arbitraryResourceInfo.name = transactionData.getName(); @@ -461,6 +470,8 @@ public class ArbitraryResource { } } + + @DELETE @Path("/resource/{service}/{name}/{identifier}") @Operation( diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataStorageManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataStorageManager.java index e2649cbe..4b975b40 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataStorageManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataStorageManager.java @@ -47,6 +47,9 @@ public class ArbitraryDataStorageManager extends Thread { private List hostedTransactions; + private String searchQuery; + private List searchResultsTransactions; + private static final long DIRECTORY_SIZE_CHECK_INTERVAL = 10 * 60 * 1000L; // 10 minutes /** Treat storage as full at 90% usage, to reduce risk of going over the limit. @@ -258,14 +261,8 @@ public class ArbitraryDataStorageManager extends Thread { } - // Hosted data - - public List listAllHostedTransactions(Repository repository, Integer limit, Integer offset) { - // Load from cache if we can, to avoid disk reads - if (this.hostedTransactions != null) { - return ArbitraryTransactionUtils.limitOffsetTransactions(this.hostedTransactions, limit, offset); - } - + public List loadAllHostedTransactions(Repository repository){ + List arbitraryTransactionDataList = new ArrayList<>(); // Find all hosted paths @@ -296,10 +293,69 @@ public class ArbitraryDataStorageManager extends Thread { // Sort by newest first arbitraryTransactionDataList.sort(Comparator.comparingLong(ArbitraryTransactionData::getTimestamp).reversed()); - // Update cache - this.hostedTransactions = arbitraryTransactionDataList; + return arbitraryTransactionDataList; + } + // Hosted data - return ArbitraryTransactionUtils.limitOffsetTransactions(arbitraryTransactionDataList, limit, offset); + public List listAllHostedTransactions(Repository repository, Integer limit, Integer offset) { + // Load from cache if we can, to avoid disk reads + + if (this.hostedTransactions != null) { + return ArbitraryTransactionUtils.limitOffsetTransactions(this.hostedTransactions, limit, offset); + } + + this.hostedTransactions = this.loadAllHostedTransactions(repository); + + return ArbitraryTransactionUtils.limitOffsetTransactions(this.hostedTransactions, limit, offset); + } + + /** + * searchHostedTransactions + * Allow to run a query against hosted data names and return matches if there are any + * @param repository + * @param query + * @param limit + * @param offset + * @return + */ + + public List searchHostedTransactions(Repository repository, String query, Integer limit, Integer offset) { + // Load from results cache if we can (results that exists for the same query), to avoid disk reads + if (this.searchResultsTransactions != null && this.searchQuery.equals(query.toLowerCase())) { + return ArbitraryTransactionUtils.limitOffsetTransactions(this.searchResultsTransactions, limit, offset); + } + + // Using cache if we can, to avoid disk reads + if (this.hostedTransactions == null) { + this.hostedTransactions = this.loadAllHostedTransactions(repository); + } + + this.searchQuery = query.toLowerCase(); //set the searchQuery so that it can be checked on the next call + + List searchResultsList = new ArrayList<>(); + + // Loop through cached hostedTransactions + for (ArbitraryTransactionData atd : this.hostedTransactions) { + try { + if (atd.getName() != null && atd.getName().toLowerCase().contains(this.searchQuery)) { + searchResultsList.add(atd); + } + else if (atd.getIdentifier() != null && atd.getIdentifier().toLowerCase().contains(this.searchQuery)) { + searchResultsList.add(atd); + } + + } catch (Exception e) { + continue; + } + } + + // Sort by newest first + searchResultsList.sort(Comparator.comparingLong(ArbitraryTransactionData::getTimestamp).reversed()); + + // Update cache + this.searchResultsTransactions = searchResultsList; + + return ArbitraryTransactionUtils.limitOffsetTransactions(this.searchResultsTransactions, limit, offset); } /**