Getting annotation authors on query responses, ui update

This commit is contained in:
Thomas Georgios Giannos 2024-03-13 13:24:21 +02:00
parent dcb112f843
commit 1b7ecf201e
7 changed files with 117 additions and 28 deletions

View File

@ -72,7 +72,7 @@ public class AnnotationController {
this.censorFactory.censor(AnnotationCensor.class).censor(lookup.getProject(), null); this.censorFactory.censor(AnnotationCensor.class).censor(lookup.getProject(), null);
AnnotationQuery query = lookup.enrich(this.queryFactory); AnnotationQuery query = lookup.enrich(this.queryFactory);
List<AnnotationEntity> data = query.collectAs(lookup.getProject()); List<AnnotationEntity> data = query.collect();
List<Annotation> models = this.builderFactory.builder(AnnotationBuilder.class).build(lookup.getProject(), data); List<Annotation> models = this.builderFactory.builder(AnnotationBuilder.class).build(lookup.getProject(), data);
long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size();

View File

@ -51,6 +51,10 @@ public class Annotation {
public static final String _timeStamp = "timeStamp"; public static final String _timeStamp = "timeStamp";
private AnnotationAuthor author;
public static final String _author = "author";
private Instant createdAt; private Instant createdAt;
public static final String _createdAt = "createdAt"; public static final String _createdAt = "createdAt";
@ -111,6 +115,14 @@ public class Annotation {
this.subjectId = subjectId; this.subjectId = subjectId;
} }
public AnnotationAuthor getAuthor() {
return author;
}
public void setAuthor(AnnotationAuthor author) {
this.author = author;
}
public UUID getThreadId() { public UUID getThreadId() {
return threadId; return threadId;
} }

View File

@ -0,0 +1,31 @@
package gr.cite.annotation.model;
import java.util.UUID;
public class AnnotationAuthor {
private UUID id;
public static final String _id = "id";
private String name;
public static final String _name = "name";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -4,7 +4,13 @@ import gr.cite.annotation.authorization.AuthorizationFlags;
import gr.cite.annotation.convention.ConventionService; import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.data.AnnotationEntity; import gr.cite.annotation.data.AnnotationEntity;
import gr.cite.annotation.model.Annotation; 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.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry; import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
@ -14,15 +20,22 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Component @Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity> { public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity> {
private final QueryFactory queryFactory;
private final BuilderFactory builderFactory;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None); private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public AnnotationBuilder(ConventionService conventionService) { public AnnotationBuilder(ConventionService conventionService, QueryFactory queryFactory, BuilderFactory builderFactory) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(AnnotationBuilder.class))); super(conventionService, new LoggerService(LoggerFactory.getLogger(AnnotationBuilder.class)));
this.queryFactory = queryFactory;
this.builderFactory = builderFactory;
} }
public AnnotationBuilder authorize(EnumSet<AuthorizationFlags> values) { public AnnotationBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -39,6 +52,9 @@ public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity>
List<Annotation> models = new ArrayList<>(); List<Annotation> models = new ArrayList<>();
FieldSet authorFields = fields.extractPrefixed(this.asPrefix(Annotation._author));
Map<UUID, AnnotationAuthor> authorsMap = this.collectAuthors(authorFields, data);
if (data == null) if (data == null)
return models; return models;
for (AnnotationEntity d : data) { for (AnnotationEntity d : data) {
@ -55,6 +71,8 @@ public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity>
m.setPayload(d.getPayload()); m.setPayload(d.getPayload());
if (fields.hasField(this.asIndexer(Annotation._subjectId))) if (fields.hasField(this.asIndexer(Annotation._subjectId)))
m.setSubjectId(d.getSubjectId()); m.setSubjectId(d.getSubjectId());
if (authorsMap != null && authorsMap.containsKey(d.getSubjectId()))
m.setAuthor(authorsMap.get(d.getSubjectId()));
if (fields.hasField(this.asIndexer(Annotation._threadId))) if (fields.hasField(this.asIndexer(Annotation._threadId)))
m.setThreadId(d.getThreadId()); m.setThreadId(d.getThreadId());
if (fields.hasField(this.asIndexer(Annotation._parentId))) if (fields.hasField(this.asIndexer(Annotation._parentId)))
@ -75,4 +93,31 @@ public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity>
return models; 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).authorize(this.authorize).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;
}
} }

View File

@ -51,7 +51,7 @@ public class InboxRepositoryImpl implements InboxRepository {
EntityTransaction transaction = null; EntityTransaction transaction = null;
EntityManager entityManager = null; EntityManager entityManager = null;
CandidateInfo candidate = null; CandidateInfo candidate = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) { try (FakeRequestScope ignored = new FakeRequestScope()) {
try { try {
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class); QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
@ -108,9 +108,9 @@ public class InboxRepositoryImpl implements InboxRepository {
public Boolean shouldOmit(CandidateInfo candidate, Function<QueueInbox, Boolean> shouldOmit) { public Boolean shouldOmit(CandidateInfo candidate, Function<QueueInbox, Boolean> shouldOmit) {
EntityTransaction transaction = null; EntityTransaction transaction = null;
EntityManager entityManager = null; EntityManager entityManager = null;
Boolean success = false; boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) { try (FakeRequestScope ignored = new FakeRequestScope()) {
try { try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
@ -123,7 +123,7 @@ public class InboxRepositoryImpl implements InboxRepository {
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first(); QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first();
if (item == null) { if (item == null) {
this.logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidate.getId()); logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidate.getId());
} else { } else {
if (shouldOmit.apply(item)) { if (shouldOmit.apply(item)) {
item.setStatus(QueueInboxStatus.OMITTED); item.setStatus(QueueInboxStatus.OMITTED);
@ -136,7 +136,7 @@ public class InboxRepositoryImpl implements InboxRepository {
transaction.commit(); transaction.commit();
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) if (transaction != null)
transaction.rollback(); transaction.rollback();
success = false; success = false;
@ -145,7 +145,7 @@ public class InboxRepositoryImpl implements InboxRepository {
entityManager.close(); entityManager.close();
} }
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
} }
return success; return success;
} }
@ -154,9 +154,9 @@ public class InboxRepositoryImpl implements InboxRepository {
public boolean shouldWait(CandidateInfo candidate, Function<QueueInbox, Boolean> itIsTimeFunc) { public boolean shouldWait(CandidateInfo candidate, Function<QueueInbox, Boolean> itIsTimeFunc) {
EntityTransaction transaction = null; EntityTransaction transaction = null;
EntityManager entityManager = null; EntityManager entityManager = null;
Boolean success = false; boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) { try (FakeRequestScope ignored = new FakeRequestScope()) {
try { try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
@ -183,7 +183,7 @@ public class InboxRepositoryImpl implements InboxRepository {
} }
transaction.commit(); transaction.commit();
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) if (transaction != null)
transaction.rollback(); transaction.rollback();
success = false; success = false;
@ -192,7 +192,7 @@ public class InboxRepositoryImpl implements InboxRepository {
entityManager.close(); entityManager.close();
} }
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
} }
return success; return success;
} }
@ -201,9 +201,9 @@ public class InboxRepositoryImpl implements InboxRepository {
public QueueInbox create(InboxCreatorParams inboxCreatorParams) { public QueueInbox create(InboxCreatorParams inboxCreatorParams) {
EntityTransaction transaction = null; EntityTransaction transaction = null;
EntityManager entityManager = null; EntityManager entityManager = null;
Boolean success = false; boolean success = false;
QueueInboxEntity queueMessage = null; QueueInboxEntity queueMessage = null;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) { try (FakeRequestScope ignored = new FakeRequestScope()) {
try { try {
queueMessage = this.createQueueInboxEntity(inboxCreatorParams); queueMessage = this.createQueueInboxEntity(inboxCreatorParams);
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
@ -218,7 +218,7 @@ public class InboxRepositoryImpl implements InboxRepository {
transaction.commit(); transaction.commit();
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) if (transaction != null)
transaction.rollback(); transaction.rollback();
success = false; success = false;
@ -227,7 +227,7 @@ public class InboxRepositoryImpl implements InboxRepository {
entityManager.close(); entityManager.close();
} }
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
} }
return queueMessage; return queueMessage;
} }
@ -255,9 +255,9 @@ public class InboxRepositoryImpl implements InboxRepository {
public Boolean emit(CandidateInfo candidateInfo) { public Boolean emit(CandidateInfo candidateInfo) {
EntityTransaction transaction = null; EntityTransaction transaction = null;
EntityManager entityManager = null; EntityManager entityManager = null;
Boolean success = false; boolean success = false;
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) { try (FakeRequestScope ignored = new FakeRequestScope()) {
try { try {
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
@ -270,7 +270,7 @@ public class InboxRepositoryImpl implements InboxRepository {
QueueInboxEntity queueInboxMessage = queryFactory.query(QueueInboxQuery.class).ids(candidateInfo.getId()).first(); QueueInboxEntity queueInboxMessage = queryFactory.query(QueueInboxQuery.class).ids(candidateInfo.getId()).first();
if (queueInboxMessage == null) { if (queueInboxMessage == null) {
this.logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidateInfo.getId()); logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidateInfo.getId());
} else { } else {
EventProcessingStatus status = this.processMessage(queueInboxMessage.getRoute(), queueInboxMessage.getMessageId().toString(), queueInboxMessage.getApplicationId(), queueInboxMessage.getMessage()); EventProcessingStatus status = this.processMessage(queueInboxMessage.getRoute(), queueInboxMessage.getMessageId().toString(), queueInboxMessage.getApplicationId(), queueInboxMessage.getMessage());
@ -302,7 +302,7 @@ public class InboxRepositoryImpl implements InboxRepository {
transaction.commit(); transaction.commit();
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
if (transaction != null) if (transaction != null)
transaction.rollback(); transaction.rollback();
success = false; success = false;
@ -311,7 +311,7 @@ public class InboxRepositoryImpl implements InboxRepository {
entityManager.close(); entityManager.close();
} }
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex); logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
} }
return success; return success;
} }
@ -339,7 +339,7 @@ public class InboxRepositoryImpl implements InboxRepository {
} }
private Boolean RoutingKeyMatched(String routingKey, List<String> topics) { private Boolean RoutingKeyMatched(String routingKey, List<String> topics) {
if (topics == null || topics.size() == 0) if (topics == null || topics.isEmpty())
return false; return false;
return topics.stream().anyMatch(x -> x.equals(routingKey)); return topics.stream().anyMatch(x -> x.equals(routingKey));
} }

View File

@ -46,7 +46,7 @@
<div class="col annotation-time">{{thread.timeStamp | date:'EEEE, MMMM d, y, h:mm a'}}</div> <div class="col annotation-time">{{thread.timeStamp | date:'EEEE, MMMM d, y, h:mm a'}}</div>
<div class="col-auto" *ngIf="thread.protectionType === annotationProtectionTypeEnum.Private" matTooltip="{{'ANNOTATION-DIALOG.PROTECTION.PRIVATE' | translate}}"><i class="material-icons protection-icon icon-{{getAnnotationProtectionType(thread)}}">{{getAnnotationProtectionType(thread)}}</i></div> <div class="col-auto" *ngIf="thread.protectionType === annotationProtectionTypeEnum.Private" matTooltip="{{'ANNOTATION-DIALOG.PROTECTION.PRIVATE' | translate}}"><i class="material-icons protection-icon icon-{{getAnnotationProtectionType(thread)}}">{{getAnnotationProtectionType(thread)}}</i></div>
<div class="col-auto" *ngIf="thread.protectionType === annotationProtectionTypeEnum.EntityAccessors" matTooltip="{{'ANNOTATION-DIALOG.PROTECTION.ENTITY-ACCESSORS' | translate}}"><i class="material-icons protection-icon icon-{{getAnnotationProtectionType(thread)}}">{{getAnnotationProtectionType(thread)}}</i></div> <div class="col-auto" *ngIf="thread.protectionType === annotationProtectionTypeEnum.EntityAccessors" matTooltip="{{'ANNOTATION-DIALOG.PROTECTION.ENTITY-ACCESSORS' | translate}}"><i class="material-icons protection-icon icon-{{getAnnotationProtectionType(thread)}}">{{getAnnotationProtectionType(thread)}}</i></div>
<div class="col-md-12 annotation-full-text">{{thread.text}}</div> <div class="col-md-12 annotation-full-text">{{thread.payload}}</div>
<div class="col-md-12"> <div class="col-md-12">
<em class="user">{{'ANNOTATION-DIALOG.THREADS.FROM-USER' | translate}} {{thread.author.name}}</em> <em class="user">{{'ANNOTATION-DIALOG.THREADS.FROM-USER' | translate}} {{thread.author.name}}</em>
</div> </div>

View File

@ -123,12 +123,11 @@ export class AnnotationDialogComponent extends BaseComponent {
lookup.project = { lookup.project = {
fields: [ fields: [
nameof<Annotation>(x => x.id), nameof<Annotation>(x => x.id),
// nameof<Annotation>(x => x.threadId), nameof<Annotation>(x => x.threadId),
// nameof<Annotation>(x => x.threadId), nameof<Annotation>(x => x.timeStamp),
// nameof<Annotation>(x => x.timeStamp), nameof<Annotation>(x => x.author.name),
// nameof<Annotation>(x => x.author.name),
nameof<Annotation>(x => x.payload), nameof<Annotation>(x => x.payload),
// nameof<Annotation>(x => x.protection), nameof<Annotation>(x => x.protectionType),
] ]
}; };
@ -146,6 +145,8 @@ export class AnnotationDialogComponent extends BaseComponent {
// this.annotationsPerThread[element.id.toString()] = data.items.filter(x => x.threadId === element.id && x.id !== element.id).sort((a1, a2) => new Date(a1.timeStamp).getTime() - new Date(a2.timeStamp).getTime()); // this.annotationsPerThread[element.id.toString()] = data.items.filter(x => x.threadId === element.id && x.id !== element.id).sort((a1, a2) => new Date(a1.timeStamp).getTime() - new Date(a2.timeStamp).getTime());
// }); // });
// // this.annotationsChanged.emit(this.threads); // // this.annotationsChanged.emit(this.threads);
this.threads = data.items;
}, },
error => this.onCallbackError(error), error => this.onCallbackError(error),
); );