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 { private final QueryFactory queryFactory; private final BuilderFactory builderFactory; private final AuthorizationContentResolver authorizationContentResolver; private final AuthorizationService authorizationService; private EnumSet 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 values) { this.authorize = values; return this; } @Override public List build(FieldSet fields, List 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 models = new ArrayList<>(); if (data == null) return models; FieldSet authorFields = fields.extractPrefixed(this.asPrefix(Annotation._author)); Map authorsMap = this.collectAuthors(authorFields, data); Set authorizationFlags = this.extractAuthorizationFlags(fields, Annotation._authorizationFlags, this.authorizationContentResolver.getPermissionNames()); Map 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 collectAuthors(FieldSet fields, List data) { if (fields.isEmpty() || data.isEmpty()) return null; this.logger.debug("checking related - {}", User.class.getSimpleName()); Map itemMap = new HashMap<>(); FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(User._id), this.asIndexer(User._name)); List userIds = data.stream() .map(AnnotationEntity::getSubjectId) .distinct() .collect(Collectors.toList()); UserQuery query = this.queryFactory.query(UserQuery.class).ids(userIds); Map> 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; } }