argos/dmp-backend/core/src/main/java/eu/eudat/elastic/query/DescriptionElasticQuery.java

305 lines
14 KiB
Java

package eu.eudat.elastic.query;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.enums.DescriptionStatus;
import eu.eudat.commons.enums.DmpAccessType;
import eu.eudat.commons.enums.DmpStatus;
import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.service.elastic.AppElasticProperties;
import eu.eudat.elastic.data.DescriptionElasticEntity;
import eu.eudat.elastic.data.DmpElasticEntity;
import eu.eudat.elastic.data.nested.NestedDmpElasticEntity;
import eu.eudat.service.elastic.ElasticService;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.elastic.configuration.ElasticProperties;
import gr.cite.tools.elastic.mapper.FieldBasedMapper;
import gr.cite.tools.elastic.query.ElasticField;
import gr.cite.tools.elastic.query.ElasticFields;
import gr.cite.tools.elastic.query.ElasticNestedQuery;
import gr.cite.tools.elastic.query.ElasticQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.time.Instant;
import java.util.*;
@Component
//Like in C# make it Transient
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEntity, UUID> {
private Collection<UUID> ids;
private String like;
private InnerObjectDmpElasticQuery dmpSubQuery;
private Instant createdAfter;
private Instant createdBefore;
private Instant finalizedAfter;
private Instant finalizedBefore;
private Collection<UUID> excludedIds;
private Collection<DescriptionStatus> statuses;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public DescriptionElasticQuery like(String value) {
this.like = value;
return this;
}
public DescriptionElasticQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public DescriptionElasticQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public DescriptionElasticQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public DescriptionElasticQuery dmpSubQuery(InnerObjectDmpElasticQuery subQuery) {
this.dmpSubQuery = subQuery;
return this;
}
public DescriptionElasticQuery createdAfter(Instant value) {
this.createdAfter = value;
return this;
}
public DescriptionElasticQuery createdBefore(Instant value) {
this.createdBefore = value;
return this;
}
public DescriptionElasticQuery finalizedAfter(Instant value) {
this.finalizedAfter = value;
return this;
}
public DescriptionElasticQuery finalizedBefore(Instant value) {
this.finalizedBefore = value;
return this;
}
public DescriptionElasticQuery excludedIds(Collection<UUID> values) {
this.excludedIds = values;
return this;
}
public DescriptionElasticQuery excludedIds(UUID value) {
this.excludedIds = List.of(value);
return this;
}
public DescriptionElasticQuery excludedIds(UUID... value) {
this.excludedIds = Arrays.asList(value);
return this;
}
public DescriptionElasticQuery statuses(DescriptionStatus value) {
this.statuses = List.of(value);
return this;
}
public DescriptionElasticQuery statuses(DescriptionStatus... value) {
this.statuses = Arrays.asList(value);
return this;
}
public DescriptionElasticQuery statuses(Collection<DescriptionStatus> values) {
this.statuses = values;
return this;
}
public DescriptionElasticQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
private final QueryFactory queryFactory;
private final AppElasticProperties appElasticProperties;
private final ElasticService elasticService;
private final UserScope userScope;
private final AuthorizationService authService;
@Autowired()
public DescriptionElasticQuery(ElasticsearchTemplate elasticsearchTemplate, ElasticProperties elasticProperties, QueryFactory queryFactory, AppElasticProperties appElasticProperties, ElasticService elasticService, UserScope userScope, AuthorizationService authService) {
super(elasticsearchTemplate, elasticProperties);
this.queryFactory = queryFactory;
this.appElasticProperties = appElasticProperties;
this.elasticService = elasticService;
this.userScope = userScope;
this.authService = authService;
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) ||
this.isEmpty(this.excludedIds) ||
this.isEmpty(this.statuses);
}
@Override
protected Class<DescriptionElasticEntity> entityClass() {
return DescriptionElasticEntity.class;
}
@Override
protected Query applyAuthZ() {
if (this.authorize.contains(AuthorizationFlags.None)) return null;
//if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseDescription)) return null;
UUID userId = null;
boolean usePublic = this.authorize.contains(AuthorizationFlags.Public);
if (this.authorize.contains(AuthorizationFlags.DmpAssociated)) userId = this.userScope.getUserIdSafe();
List<Query> predicates = new ArrayList<>();
if (usePublic ) {
predicates.add(this.and(
this.equals(new ElasticField(DescriptionElasticEntity._dmp + "." + DmpElasticEntity._status, this.entityClass()).disableInfer(true), DmpStatus.Finalized.getValue()),
this.equals(new ElasticField(DescriptionElasticEntity._dmp + "." + DmpElasticEntity._accessType, this.entityClass()).disableInfer(true), DmpAccessType.Public.getValue())
));
}
if (userId != null) {
NestedCollaboratorElasticQuery query = this.queryFactory.query(NestedCollaboratorElasticQuery.class).nestedPath(DescriptionElasticEntity._dmp + "." + NestedDmpElasticEntity._collaborators);
query.ids(userId);
predicates.add(this.nestedQuery(query).build()._toQuery());
}
if (!predicates.isEmpty()) {
return this.or(predicates)._toQuery();
} else {
return this.equals(this.elasticFieldOf(DescriptionElasticEntity._id), UUID.randomUUID());
}
}
@Override
protected Query applyFilters() {
List<Query> predicates = new ArrayList<>();
if (like != null && !like.isBlank()) {
if (!like.startsWith("*")) like = "*" + like;
if (!like.endsWith("*")) like = like + "*";
ElasticFields elasticFields = this.elasticFieldsOf();
elasticFields.add("*", null, true);
predicates.add(this.or(
this.like(elasticFields, List.of(like))._toQuery(),
QueryBuilders.nested().path(DescriptionElasticEntity._tags).query(
this.like(elasticFields, List.of(like))._toQuery()
).build()._toQuery(),
QueryBuilders.nested().path(DescriptionElasticEntity._references).query(
this.like(elasticFields, List.of(like))._toQuery()
).build()._toQuery(),
QueryBuilders.nested().path(DescriptionElasticEntity._dmp + "." + NestedDmpElasticEntity._references).query(
this.like(elasticFields, List.of(like))._toQuery()
).build()._toQuery(),
QueryBuilders.nested().path(DescriptionElasticEntity._dmp + "." + NestedDmpElasticEntity._collaborators).query(
this.like(elasticFields, List.of(like))._toQuery()
).build()._toQuery(),
QueryBuilders.nested().path(DescriptionElasticEntity._dmp + "." + NestedDmpElasticEntity._dois).query(
this.like(elasticFields, List.of(like))._toQuery()
).build()._toQuery()
)._toQuery());
}
if (ids != null) {
predicates.add(this.containsUUID(this.elasticFieldOf(DescriptionElasticEntity._id), ids)._toQuery());
}
if (excludedIds != null) {
predicates.add(this.not(this.containsUUID(this.elasticFieldOf(DescriptionElasticEntity._id), excludedIds)._toQuery())._toQuery());
}
if (statuses != null) {
predicates.add(this.contains(this.elasticFieldOf(DescriptionElasticEntity._status), statuses.stream().map(DescriptionStatus::getValue).toList().toArray(new Short[statuses.size()]))._toQuery());
}
if (this.finalizedAfter != null) {
predicates.add(this.dateGreaterThanQuery(this.elasticFieldOf(DescriptionElasticEntity._finalizedAt), this.finalizedAfter)._toQuery());
}
if (this.finalizedBefore != null) {
predicates.add(this.dateLessThanQuery(this.elasticFieldOf(DescriptionElasticEntity._finalizedAt), this.finalizedBefore)._toQuery());
}
if (this.createdAfter != null) {
predicates.add(this.dateGreaterThanQuery(this.elasticFieldOf(DescriptionElasticEntity._createdAt), this.createdAfter)._toQuery());
}
if (this.createdBefore != null) {
predicates.add(this.dateLessThanQuery(this.elasticFieldOf(DescriptionElasticEntity._createdAt), this.createdBefore)._toQuery());
}
if (dmpSubQuery != null) {
predicates.add(dmpSubQuery.innerPath(DescriptionElasticEntity._dmp).applyFilters());
}
if (!predicates.isEmpty()) {
return this.and(predicates);
} else {
return null;
}
}
@Override
public DescriptionElasticEntity convert(Map<String, Object> rawData, Set<String> columns) {
DescriptionElasticEntity mocDoc = new DescriptionElasticEntity();
if (columns.contains(DescriptionElasticEntity._id)) mocDoc.setId(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._id), UUID.class));
if (columns.contains(DescriptionElasticEntity._label)) mocDoc.setLabel(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._label), String.class));
if (columns.contains(DescriptionElasticEntity._description)) mocDoc.setDescription(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._description), String.class));
if (columns.contains(DescriptionElasticEntity._status)) mocDoc.setStatus(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._status), DescriptionStatus.class));
if (columns.contains(DescriptionElasticEntity._finalizedAt)) mocDoc.setFinalizedAt(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._finalizedAt), Date.class));
if (columns.contains(DescriptionElasticEntity._createdAt)) mocDoc.setFinalizedAt(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._createdAt), Date.class));
mocDoc.setTags(this.convertNested(rawData, columns, this.queryFactory.query(NestedTagElasticQuery.class), DescriptionElasticEntity._tags, null));
mocDoc.setReferences(this.convertNested(rawData, columns, this.queryFactory.query(NestedReferenceElasticQuery.class), DescriptionElasticEntity._references, null));
mocDoc.setDescriptionTemplate(this.convertInnerObject(rawData, columns, this.queryFactory.query(InnerObjectDescriptionTemplateElasticQuery.class), DescriptionElasticEntity._descriptionTemplate, null));
mocDoc.setDmp(this.convertInnerObject(rawData, columns, this.queryFactory.query(InnerObjectDmpElasticQuery.class), DescriptionElasticEntity._dmp, null));
return mocDoc;
}
@Override
protected ElasticField fieldNameOf(FieldResolver item) {
if (item.match(DescriptionElasticEntity._id)) return this.elasticFieldOf(DescriptionElasticEntity._id);
else if (item.match(DescriptionElasticEntity._label)) return this.elasticFieldOf(DescriptionElasticEntity._label);
else if (item.match(DescriptionElasticEntity._description)) return this.elasticFieldOf(DescriptionElasticEntity._description);
else if (item.match(DescriptionElasticEntity._status)) return this.elasticFieldOf(DescriptionElasticEntity._status);
else if (item.match(DescriptionElasticEntity._finalizedAt)) return this.elasticFieldOf(DescriptionElasticEntity._finalizedAt);
else if (item.match(DescriptionElasticEntity._createdAt)) return this.elasticFieldOf(DescriptionElasticEntity._createdAt);
else if (item.prefix(DescriptionElasticEntity._references)) return this.queryFactory.query(NestedReferenceElasticQuery.class).nestedPath(DescriptionElasticEntity._references).fieldNameOf(this.extractPrefixed(item, DescriptionElasticEntity._references));
else if (item.prefix(DescriptionElasticEntity._tags)) return this.queryFactory.query(NestedTagElasticQuery.class).nestedPath(DescriptionElasticEntity._tags).fieldNameOf(this.extractPrefixed(item, DescriptionElasticEntity._tags));
else if (item.prefix(DescriptionElasticEntity._descriptionTemplate)) return this.queryFactory.query(InnerObjectDescriptionTemplateElasticQuery.class).innerPath(DescriptionElasticEntity._descriptionTemplate).fieldNameOf(this.extractPrefixed(item, DescriptionElasticEntity._description));
else if (item.prefix(DescriptionElasticEntity._dmp)) return this.queryFactory.query(InnerObjectDmpElasticQuery.class).innerPath(DescriptionElasticEntity._dmp).fieldNameOf(this.extractPrefixed(item, DescriptionElasticEntity._dmp));
else return null;
}
@Override
protected String[] getIndex() {
List<String> indexNames = new ArrayList<>();
indexNames.add(this.appElasticProperties.getDescriptionIndexName());
try {
this.elasticService.ensureDescriptionIndex();
} catch (IOException e) {
throw new RuntimeException(e);
}
return indexNames.toArray(new String[indexNames.size()]);
}
@Override
protected UUID toKey(String key) {
return UUID.fromString(key);
}
@Override
protected ElasticField getKeyField() {
return this.elasticFieldOf(DescriptionElasticEntity._id);
}
@Override
protected ElasticNestedQuery<?, ?, ?> nestedQueryOf(FieldResolver item) {
if (item.prefix(DescriptionElasticEntity._references)) return this.queryFactory.query(NestedReferenceElasticQuery.class).nestedPath(DescriptionElasticEntity._references);
else if (item.prefix(DescriptionElasticEntity._tags)) return this.queryFactory.query(NestedTagElasticQuery.class).nestedPath(DescriptionElasticEntity._tags);
else return null;
}
}