com.atlan.model.search.CompoundQuery Maven / Gradle / Ivy
// Generated by delombok at Thu Oct 10 18:56:33 UTC 2024
/* SPDX-License-Identifier: Apache-2.0
Copyright 2023 Atlan Pte. Ltd. */
package com.atlan.model.search;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.SpanQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.SpanTermQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.SpanWithinQuery;
import com.atlan.AtlanClient;
import com.atlan.exception.AtlanException;
import com.atlan.model.assets.Asset;
import com.atlan.model.assets.ITag;
import com.atlan.model.enums.AtlanStatus;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Class to compose compound queries combining various conditions.
* (Along with some static factory methods for some of the most common queries.)
*/
public abstract class CompoundQuery {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CompoundQuery.class);
/**
* Client through which to run the search.
*/
AtlanClient client;
/**
* Criteria that must be present on every search result. (Translated to filters.)
*/
private List wheres;
/**
* Criteria that must not be present on any search result.
*/
private List whereNots;
/**
* A collection of criteria at least some of which should be present on each search result.
* You can control "how many" of the criteria are a minimum for each search result to match
* through the `minimum` parameter.
* @see #minSomes
*/
private List whereSomes;
/**
* The minimum number of criteria in the "whereSomes" that must match on each search result. (Defaults to 1.)
*/
private int minSomes;
/**
* Translate the Atlan compound query into an Elastic Query object.
*
* @return an Elastic Query object that represents the compound query
*/
public Query toQuery() {
return toQuery(true);
}
/**
* Translate the Atlan compound query into an Elastic Query object, with an outer
* bool query and inner filtered bool query (necessary for some UI elements).
*
* @return the Elastic Query object that represents the compound query
*/
public Query toUnfilteredQuery() {
return toQuery(false);
}
private Query toQuery(boolean filter) {
BoolQuery.Builder builder = new BoolQuery.Builder();
if (wheres != null && !wheres.isEmpty()) {
if (filter) {
builder.filter(wheres);
} else {
builder.must(wheres);
}
}
if (whereNots != null && !whereNots.isEmpty()) {
builder.mustNot(whereNots);
}
if (whereSomes != null && !whereSomes.isEmpty()) {
builder.should(whereSomes).minimumShouldMatch("" + minSomes);
}
return builder.build()._toQuery();
}
public static abstract class CompoundQueryBuilder> {
@java.lang.SuppressWarnings("all")
@lombok.Generated
private AtlanClient client;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private java.util.ArrayList wheres;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private java.util.ArrayList whereNots;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private java.util.ArrayList whereSomes;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private boolean minSomes$set;
@java.lang.SuppressWarnings("all")
@lombok.Generated
private int minSomes$value;
/**
* Returns a query that will only match assets that have at least one of the Atlan tags
* provided. This will match irrespective of the Atlan tag being directly applied to the
* asset, or if it was propagated to the asset.
*
* @param atlanTagNames human-readable names of the Atlan tags
* @return a query that will only match assets that have at least one of the Atlan tags provided
* @throws AtlanException on any error communicating with the API to refresh the Atlan tag cache
*/
public B tagged(Collection atlanTagNames) throws AtlanException {
List values = new ArrayList<>();
for (String name : atlanTagNames) {
values.add(client.getAtlanTagCache().getIdForName(name));
}
return // direct Atlan tags
// propagated Atlan tags
whereSome(Asset.ATLAN_TAGS.in(values)).whereSome(Asset.PROPAGATED_ATLAN_TAGS.in(values)).minSomes(1);
}
/**
* Returns a query that will only match assets that have at least one Atlan tag assigned.
*
* @param directly when true, the asset must have at least one Atlan tag directly assigned (otherwise even propagated tags will suffice)
* @return a query that will only match assets that have at least one Atlan tag directly assigned
*/
public B tagged(boolean directly) {
if (directly) {
return where(Asset.ATLAN_TAGS.hasAnyValue());
} else {
return whereSome(Asset.ATLAN_TAGS.hasAnyValue()).whereSome(Asset.PROPAGATED_ATLAN_TAGS.hasAnyValue()).minSomes(1);
}
}
/**
* Returns a query that will match assets that have a specific value for the specified tag
* (for source-synced tags).
*
* @param atlanTagName human-readable name of the Atlan tag
* @param value the tag should have to match the query
* @return a query that will only match assets that have a particular value assigned for the given Atlan tag
* @throws AtlanException on any error communicating with the API to refresh the Atlan tag cache
*/
public B taggedWithValue(String atlanTagName, String value) throws AtlanException {
return taggedWithValue(atlanTagName, value, false);
}
/**
* Returns a query that will match assets that have a specific value for the specified tag
* (for source-synced tags).
*
* @param atlanTagName human-readable name of the Atlan tag
* @param value the tag should have to match the query
* @param directly when true, the asset must have the tag and value directly assigned (otherwise even propagated tags with the value will suffice)
* @return a query that will only match assets that have a particular value assigned for the given Atlan tag
* @throws AtlanException on any error communicating with the API to refresh the Atlan tag cache
*/
public B taggedWithValue(String atlanTagName, String value, boolean directly) throws AtlanException {
String tagId = client.getAtlanTagCache().getIdForName(atlanTagName);
List syncedTags = client.assets.select().where(ITag.MAPPED_ATLAN_TAG_NAME.eq(tagId)).stream().toList();
String syncedTagQN;
if (syncedTags.size() > 1) {
syncedTagQN = syncedTags.get(0).getQualifiedName();
log.warn("Multiple mapped source-synced tags found for tag {} -- using only the first: {}", atlanTagName, syncedTagQN);
} else if (!syncedTags.isEmpty()) {
syncedTagQN = syncedTags.get(0).getQualifiedName();
} else {
syncedTagQN = "NON_EXISTENT";
}
List littleSpans = new ArrayList<>();
littleSpans.add(SpanTermQuery.of(t -> t.field("__classificationsText.text").value("tagAttachmentValue"))._toSpanQuery());
for (String token : value.split(" ")) {
littleSpans.add(SpanTermQuery.of(t -> t.field("__classificationsText.text").value(token))._toSpanQuery());
}
littleSpans.add(SpanTermQuery.of(t -> t.field("__classificationsText.text").value("tagAttachmentKey"))._toSpanQuery());
List bigSpans = new ArrayList<>();
bigSpans.add(SpanTermQuery.of(t -> t.field("__classificationsText.text").value(tagId))._toSpanQuery());
bigSpans.add(SpanTermQuery.of(t -> t.field("__classificationsText.text").value(syncedTagQN))._toSpanQuery());
Query span = SpanWithinQuery.of(s -> s.little(l -> l.spanNear(n -> n.clauses(littleSpans).slop(0).inOrder(true))).big(b -> b.spanNear(n -> n.clauses(bigSpans).slop(10000000).inOrder(true))))._toQuery();
if (directly) {
return where(Asset.ATLAN_TAGS.eq(tagId)).where(span);
} else {
return whereSome(Asset.ATLAN_TAGS.eq(tagId)).whereSome(Asset.PROPAGATED_ATLAN_TAGS.eq(tagId)).minSomes(1).where(span);
}
}
/**
* Adds a condition that matches only active assets.
* Note: this is mutually-exclusive with {@link #archived()} -- if you want both, specify neither.
*
* @return the search builder with a condition that will only match assets that are active
*/
public B active() {
return where(Asset.STATUS.eq(AtlanStatus.ACTIVE));
}
/**
* Adds a condition that matches only archived assets.
* Note: this is mutually-exclusive with {@link #active()} -- if you want both, specify neither.
*
* @return the search builder with a condition that will only match assets that are active
*/
public B archived() {
return where(Asset.STATUS.eq(AtlanStatus.DELETED));
}
/**
* Adds a condition that matches only assets with lineage.
* Note: this is mutually-exclusive with {@link #withoutLineage()} -- if you want both, specify neither.
*
* @return the search builder with a condition that will only match assets that have lineage
*/
public B withLineage() {
return where(Asset.HAS_LINEAGE.eq(true));
}
/**
* Adds a condition that matches only assets without lineage.
* Note: this is mutually-exclusive with {@link #withLineage()} -- if you want both, specify neither.
*
* @return the search builder with a condition that will only match assets that do NOT have lineage
*/
public B withoutLineage() {
return whereNot(withLineage().build().toQuery());
}
/**
* Client through which to run the search.
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B client(final AtlanClient client) {
this.client = client;
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B where(final Query where) {
if (this.wheres == null) this.wheres = new java.util.ArrayList();
this.wheres.add(where);
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B wheres(final java.util.Collection extends Query> wheres) {
if (wheres == null) {
throw new java.lang.NullPointerException("wheres cannot be null");
}
if (this.wheres == null) this.wheres = new java.util.ArrayList();
this.wheres.addAll(wheres);
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B clearWheres() {
if (this.wheres != null) this.wheres.clear();
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B whereNot(final Query whereNot) {
if (this.whereNots == null) this.whereNots = new java.util.ArrayList();
this.whereNots.add(whereNot);
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B whereNots(final java.util.Collection extends Query> whereNots) {
if (whereNots == null) {
throw new java.lang.NullPointerException("whereNots cannot be null");
}
if (this.whereNots == null) this.whereNots = new java.util.ArrayList();
this.whereNots.addAll(whereNots);
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B clearWhereNots() {
if (this.whereNots != null) this.whereNots.clear();
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B whereSome(final Query whereSome) {
if (this.whereSomes == null) this.whereSomes = new java.util.ArrayList();
this.whereSomes.add(whereSome);
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B whereSomes(final java.util.Collection extends Query> whereSomes) {
if (whereSomes == null) {
throw new java.lang.NullPointerException("whereSomes cannot be null");
}
if (this.whereSomes == null) this.whereSomes = new java.util.ArrayList();
this.whereSomes.addAll(whereSomes);
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B clearWhereSomes() {
if (this.whereSomes != null) this.whereSomes.clear();
return self();
}
/**
* The minimum number of criteria in the "whereSomes" that must match on each search result. (Defaults to 1.)
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@lombok.Generated
public B minSomes(final int minSomes) {
this.minSomes$value = minSomes;
minSomes$set = true;
return self();
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected abstract B self();
@java.lang.SuppressWarnings("all")
@lombok.Generated
public abstract C build();
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public java.lang.String toString() {
return "CompoundQuery.CompoundQueryBuilder(client=" + this.client + ", wheres=" + this.wheres + ", whereNots=" + this.whereNots + ", whereSomes=" + this.whereSomes + ", minSomes$value=" + this.minSomes$value + ")";
}
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
private static int $default$minSomes() {
return 1;
}
@java.lang.SuppressWarnings("all")
@lombok.Generated
protected CompoundQuery(final CompoundQuery.CompoundQueryBuilder, ?> b) {
this.client = b.client;
java.util.List wheres;
switch (b.wheres == null ? 0 : b.wheres.size()) {
case 0:
wheres = java.util.Collections.emptyList();
break;
case 1:
wheres = java.util.Collections.singletonList(b.wheres.get(0));
break;
default:
wheres = java.util.Collections.unmodifiableList(new java.util.ArrayList(b.wheres));
}
this.wheres = wheres;
java.util.List whereNots;
switch (b.whereNots == null ? 0 : b.whereNots.size()) {
case 0:
whereNots = java.util.Collections.emptyList();
break;
case 1:
whereNots = java.util.Collections.singletonList(b.whereNots.get(0));
break;
default:
whereNots = java.util.Collections.unmodifiableList(new java.util.ArrayList(b.whereNots));
}
this.whereNots = whereNots;
java.util.List whereSomes;
switch (b.whereSomes == null ? 0 : b.whereSomes.size()) {
case 0:
whereSomes = java.util.Collections.emptyList();
break;
case 1:
whereSomes = java.util.Collections.singletonList(b.whereSomes.get(0));
break;
default:
whereSomes = java.util.Collections.unmodifiableList(new java.util.ArrayList(b.whereSomes));
}
this.whereSomes = whereSomes;
if (b.minSomes$set) this.minSomes = b.minSomes$value;
else this.minSomes = CompoundQuery.$default$minSomes();
}
}