
com.atlan.model.search.SearchLogResponse Maven / Gradle / Ivy
// Generated by delombok at Thu Oct 10 18:56:33 UTC 2024
/* SPDX-License-Identifier: Apache-2.0
Copyright 2022 Atlan Pte. Ltd. */
package com.atlan.model.search;
import com.atlan.AtlanClient;
import com.atlan.exception.AtlanException;
import com.atlan.net.ApiResource;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* Captures the response from a search against Atlan's search log. Also provides the ability to iteratively
* page through results, without needing to track or re-run the original query using {@link #getNextPage()}.
*/
public class SearchLogResponse extends ApiResource implements Iterable {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SearchLogResponse.class);
private static final long serialVersionUID = 2L;
private static final int CHARACTERISTICS = Spliterator.NONNULL | Spliterator.IMMUTABLE | Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
/**
* Connectivity to the Atlan tenant where the search was run.
*/
@JsonIgnore
AtlanClient client;
/**
* Parameters for the search.
*/
SearchLogRequest searchParameters;
/**
* List of results from the search.
*/
@JsonProperty("logs")
List logEntries;
/**
* Approximate number of total results.
*/
Long approximateCount;
/**
* Map of results for the requested aggregations.
*/
Map aggregations;
/**
* Retrieve the next page of results from this response.
*
* @return next page of results from this response
* @throws AtlanException on any API interaction problem
*/
@JsonIgnore
public SearchLogResponse getNextPage() throws AtlanException {
IndexSearchDSL dsl = getSearchParameters().getDsl();
int from = dsl.getFrom() == null ? 0 : dsl.getFrom();
int page = dsl.getSize() == null ? 10 : dsl.getSize();
dsl = dsl.toBuilder().from(from + page).build();
SearchLogRequest.SearchLogRequestBuilder, ?> next = SearchLogRequest.builder(dsl);
return next.build().search(client);
}
/**
* Retrieve a specific page of results using the same query used to produce this response.
*
* @param offset starting point for the specific page
* @param pageSize maximum number of results beyond the starting point to retrieve
* @return specific page of results from this response
* @throws AtlanException on any API interaction problem
*/
@JsonIgnore
public List getSpecificPage(int offset, int pageSize) throws AtlanException {
IndexSearchDSL dsl = getSearchParameters().getDsl().toBuilder().from(offset).size(pageSize).build();
SearchLogRequest.SearchLogRequestBuilder, ?> next = SearchLogRequest.builder(dsl);
SearchLogResponse response = next.build().search(client);
if (response != null && response.getLogEntries() != null) {
return response.getLogEntries();
} else {
return Collections.emptyList();
}
}
/**
* {@inheritDoc}
*/
@Override
public Iterator iterator() {
return new SearchLogResponseIterator(this);
}
/**
* {@inheritDoc}
*/
@Override
public Spliterator spliterator() {
Integer pageSize = getSearchParameters().getDsl().getSize();
if (pageSize == null) {
pageSize = 50;
}
SearchLogResponseSpliterator spliterator = new SearchLogResponseSpliterator(this, 0, this.getApproximateCount(), pageSize);
List entries = getLogEntries() == null ? Collections.emptyList() : getLogEntries();
spliterator.firstPage = entries.spliterator();
return spliterator;
}
/**
* Stream the results (lazily) for processing without needing to manually manage paging.
* @return a lazily-loaded stream of results from the search
*/
public Stream stream() {
return StreamSupport.stream(Spliterators.spliterator(iterator(), approximateCount, CHARACTERISTICS), false);
}
/**
* Stream the results in parallel across all pages (may do more than limited to in a request).
* @return a lazily-loaded stream of results from the search
*/
public Stream parallelStream() {
return StreamSupport.stream(this::spliterator, CHARACTERISTICS, true);
}
/**
* Allow results to be iterated through in parallel without managing paging retrievals.
* With inspiration from: https://stackoverflow.com/questions/38128274/how-can-i-create-a-general-purpose-paging-spliterator
*/
private static class SearchLogResponseSpliterator implements Spliterator {
private final SearchLogResponse response;
private long start;
private final long end;
private final long pageSize;
private Spliterator firstPage;
private Spliterator currentPage;
SearchLogResponseSpliterator(SearchLogResponse response, long start, long end, long pageSize) {
this.response = response;
this.start = start;
this.end = end;
this.pageSize = pageSize;
}
/**
* {@inheritDoc}
*/
@Override
public boolean tryAdvance(Consumer super SearchLogEntry> action) {
while (true) {
if (ensurePage().tryAdvance(action)) {
// If we're able to advance the page we're on, go for it
return true;
} else if (start >= end) {
// Alternatively, if we're at the end, we can stop now
return false;
} else {
// Otherwise, reset the current page to empty and try
// to advance again
currentPage = null;
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void forEachRemaining(Consumer super SearchLogEntry> action) {
do {
ensurePage().forEachRemaining(action);
currentPage = null;
} while (start < end);
}
/**
* {@inheritDoc}
*/
@Override
public Spliterator trySplit() {
if (firstPage != null) {
// If we have a first page already fetched, use it
Spliterator fp = firstPage;
firstPage = null; // clear it once we've used it
start = fp.getExactSizeIfKnown();
return fp;
} else if (currentPage != null) {
// Otherwise, if we have a current page already fetched, use that
return currentPage.trySplit();
} else if (end - start > pageSize) {
// Otherwise, if we know there are remaining elements that we have not yet fetched...
// Calculate a new split-point midway between them (shift rather than divide, to avoid overflow)
long mid = (start + end) >>> 1;
// Round the mid-point to a multiple of the pageSize
mid = mid / pageSize * pageSize;
if (mid == start) {
mid += pageSize;
}
// Create a new spliterator with the new mid-point, while resetting this existing
// spliterator's end-point to the midpoint
return new SearchLogResponseSpliterator(response, start, start = mid, pageSize);
}
return ensurePage().trySplit();
}
/**
* Only fetch data immediately before traversing or sub-page splitting.
*/
private Spliterator ensurePage() {
if (firstPage != null) {
// If we already have a first page fetched, use it
Spliterator fp = firstPage;
firstPage = null; // clear it once we've used it
currentPage = fp;
start = fp.getExactSizeIfKnown();
return fp;
} else {
// Otherwise, try to use the current page (if any)
Spliterator sp = currentPage;
if (sp == null) {
// ... and if there is no current page...
if (start >= end) {
// Return an empty spliterator if we're at the end
return Spliterators.emptySpliterator();
} else {
// Otherwise (only NOW), go fetch the next specific page of results needed
List entries;
try {
entries = response.getSpecificPage((int) start, (int) Math.min(end - start, pageSize));
} catch (AtlanException e) {
log.warn("Unable to fetch the specific page from {} to {}", start, Math.min(end - start, pageSize), e);
entries = Collections.emptyList();
}
// And update this spliterator's starting point accordingly
sp = entries.spliterator();
if (sp.getExactSizeIfKnown() > 0) {
// If there are any results in the page, increment the start by the size
start += sp.getExactSizeIfKnown();
} else {
// Otherwise, increment the start by the page size (so we skip over this "page"
// entirely rather than attempting to re-retrieve it endlessly)
start += pageSize;
}
currentPage = sp;
}
}
return sp;
}
}
/**
* {@inheritDoc}
*/
@Override
public long estimateSize() {
if (currentPage != null) {
return currentPage.estimateSize();
}
return end - start;
}
/**
* {@inheritDoc}
*/
@Override
public int characteristics() {
return CHARACTERISTICS;
}
}
/**
* Allow results to be iterated through without managing paging retrievals.
*/
private static class SearchLogResponseIterator implements Iterator {
private SearchLogResponse response;
private int i;
public SearchLogResponseIterator(SearchLogResponse response) {
this.response = response;
this.i = 0;
}
/** {@inheritDoc} */
@Override
public boolean hasNext() {
if (response.getLogEntries() != null && response.getLogEntries().size() > i) {
return true;
} else {
try {
response = response.getNextPage();
i = 0;
return response.getLogEntries() != null && response.getLogEntries().size() > i;
} catch (AtlanException e) {
throw new RuntimeException("Unable to iterate through all pages of search results.", e);
}
}
}
/** {@inheritDoc} */
@Override
public SearchLogEntry next() {
return response.getLogEntries().get(i++);
}
}
/**
* Connectivity to the Atlan tenant where the search was run.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public AtlanClient getClient() {
return this.client;
}
/**
* Parameters for the search.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public SearchLogRequest getSearchParameters() {
return this.searchParameters;
}
/**
* List of results from the search.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public List getLogEntries() {
return this.logEntries;
}
/**
* Approximate number of total results.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public Long getApproximateCount() {
return this.approximateCount;
}
/**
* Map of results for the requested aggregations.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public Map getAggregations() {
return this.aggregations;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof SearchLogResponse)) return false;
final SearchLogResponse other = (SearchLogResponse) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$approximateCount = this.getApproximateCount();
final java.lang.Object other$approximateCount = other.getApproximateCount();
if (this$approximateCount == null ? other$approximateCount != null : !this$approximateCount.equals(other$approximateCount)) return false;
final java.lang.Object this$client = this.getClient();
final java.lang.Object other$client = other.getClient();
if (this$client == null ? other$client != null : !this$client.equals(other$client)) return false;
final java.lang.Object this$searchParameters = this.getSearchParameters();
final java.lang.Object other$searchParameters = other.getSearchParameters();
if (this$searchParameters == null ? other$searchParameters != null : !this$searchParameters.equals(other$searchParameters)) return false;
final java.lang.Object this$logEntries = this.getLogEntries();
final java.lang.Object other$logEntries = other.getLogEntries();
if (this$logEntries == null ? other$logEntries != null : !this$logEntries.equals(other$logEntries)) return false;
final java.lang.Object this$aggregations = this.getAggregations();
final java.lang.Object other$aggregations = other.getAggregations();
if (this$aggregations == null ? other$aggregations != null : !this$aggregations.equals(other$aggregations)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected boolean canEqual(final java.lang.Object other) {
return other instanceof SearchLogResponse;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $approximateCount = this.getApproximateCount();
result = result * PRIME + ($approximateCount == null ? 43 : $approximateCount.hashCode());
final java.lang.Object $client = this.getClient();
result = result * PRIME + ($client == null ? 43 : $client.hashCode());
final java.lang.Object $searchParameters = this.getSearchParameters();
result = result * PRIME + ($searchParameters == null ? 43 : $searchParameters.hashCode());
final java.lang.Object $logEntries = this.getLogEntries();
result = result * PRIME + ($logEntries == null ? 43 : $logEntries.hashCode());
final java.lang.Object $aggregations = this.getAggregations();
result = result * PRIME + ($aggregations == null ? 43 : $aggregations.hashCode());
return result;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "SearchLogResponse(super=" + super.toString() + ", client=" + this.getClient() + ", searchParameters=" + this.getSearchParameters() + ", logEntries=" + this.getLogEntries() + ", approximateCount=" + this.getApproximateCount() + ", aggregations=" + this.getAggregations() + ")";
}
/**
* Connectivity to the Atlan tenant where the search was run.
*/
@JsonIgnore
@java.lang.SuppressWarnings("all")
@lombok.Generated
public void setClient(final AtlanClient client) {
this.client = client;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy