argos/annotation-service/annotation/src/main/java/gr/cite/annotation/model/builder/AnnotationBuilder.java

121 lines
6.7 KiB
Java

package gr.cite.annotation.model.builder;
import gr.cite.annotation.authorization.AffiliatedResource;
import gr.cite.annotation.authorization.AuthorizationFlags;
import gr.cite.annotation.authorization.authorizationcontentresolver.AuthorizationContentResolver;
import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.data.AnnotationEntity;
import gr.cite.annotation.model.Annotation;
import gr.cite.annotation.model.AnnotationAuthor;
import gr.cite.annotation.model.User;
import gr.cite.annotation.query.UserQuery;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity> {
private final QueryFactory queryFactory;
private final BuilderFactory builderFactory;
private final AuthorizationContentResolver authorizationContentResolver;
private final AuthorizationService authorizationService;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public AnnotationBuilder(ConventionService conventionService, QueryFactory queryFactory, BuilderFactory builderFactory, AuthorizationContentResolver authorizationContentResolver, AuthorizationService authorizationService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(AnnotationBuilder.class)));
this.queryFactory = queryFactory;
this.builderFactory = builderFactory;
this.authorizationContentResolver = authorizationContentResolver;
this.authorizationService = authorizationService;
}
public AnnotationBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<Annotation> build(FieldSet fields, List<AnnotationEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || fields.isEmpty())
return new ArrayList<>();
List<Annotation> models = new ArrayList<>();
if (data == null) return models;
FieldSet authorFields = fields.extractPrefixed(this.asPrefix(Annotation._author));
Map<UUID, AnnotationAuthor> authorsMap = this.collectAuthors(authorFields, data);
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Annotation._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.annotationsAffiliation(data.stream().map(AnnotationEntity::getId).toList());
for (AnnotationEntity d : data) {
Annotation m = new Annotation();
if (fields.hasField(this.asIndexer(Annotation._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(Annotation._entityId))) m.setEntityId(d.getEntityId());
if (fields.hasField(this.asIndexer(Annotation._entityType))) m.setEntityType(d.getEntityType());
if (fields.hasField(this.asIndexer(Annotation._anchor))) m.setAnchor(d.getAnchor());
if (fields.hasField(this.asIndexer(Annotation._payload))) m.setPayload(d.getPayload());
if (fields.hasField(this.asIndexer(Annotation._subjectId))) m.setSubjectId(d.getSubjectId());
if (fields.hasField(this.asIndexer(Annotation._threadId))) m.setThreadId(d.getThreadId());
if (fields.hasField(this.asIndexer(Annotation._parentId))) m.setParentId(d.getParentId());
if (fields.hasField(this.asIndexer(Annotation._protectionType))) m.setProtectionType(d.getProtectionType());
if (fields.hasField(this.asIndexer(Annotation._timeStamp))) m.setTimeStamp(d.getTimeStamp());
if (fields.hasField(this.asIndexer(Annotation._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(Annotation._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(Annotation._isActive))) m.setIsActive(d.getIsActive());
if (fields.hasField(this.asIndexer(Annotation._hash))) m.setHash(this.hashValue(d.getUpdatedAt()));
if (!authorFields.isEmpty() && authorsMap != null && authorsMap.containsKey(d.getSubjectId())) m.setAuthor(authorsMap.get(d.getSubjectId()));
if (affiliatedResourceMap != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
private Map<UUID, AnnotationAuthor> collectAuthors(FieldSet fields, List<AnnotationEntity> data) {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", User.class.getSimpleName());
Map<UUID, AnnotationAuthor> itemMap = new HashMap<>();
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(User._id), this.asIndexer(User._name));
List<UUID> userIds = data.stream()
.map(AnnotationEntity::getSubjectId)
.distinct()
.collect(Collectors.toList());
UserQuery query = this.queryFactory.query(UserQuery.class).ids(userIds);
Map<UUID, List<User>> users = this.builderFactory.builder(UserBuilder.class).authorize(this.authorize).asMasterKey(query, clone, User::getId);
users.forEach((key, val) -> {
itemMap.put(key, this.authorFromUser(val.getFirst()));
});
return itemMap;
}
private AnnotationAuthor authorFromUser(User user) {
AnnotationAuthor author = new AnnotationAuthor();
author.setId(user.getId());
author.setName(user.getName());
return author;
}
}