From 212216815da8ec4e0f00e202f3035d2cd04f295e Mon Sep 17 00:00:00 2001 From: Bogdan Kostov Date: Mon, 29 Apr 2024 12:10:26 +0200 Subject: [PATCH] [Fix #83] Implement service layer for fetching ManagedEntity and FaultTreeSummary properties. - add ComplexManagedEntityRepositoryService encapsulating common functionality for complex artifacts such as fault trees and systems. - fix bug not being able to update fault tree name --- .../service/BaseRepositoryService.java | 5 ++ ...ComplexManagedEntityRepositoryService.java | 68 +++++++++++++++++++ .../service/FaultEventRepositoryService.java | 21 +++++- .../service/FaultTreeRepositoryService.java | 33 ++++++--- .../service/SystemRepositoryService.java | 14 ++-- .../service/security/SecurityUtils.java | 7 +- 6 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java diff --git a/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java index 8ce7c89b..458f0c6d 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/BaseRepositoryService.java @@ -125,6 +125,7 @@ public void persist(@NonNull T instance) { Objects.requireNonNull(instance); prePersist(instance); getPrimaryDao().persist(instance); + postPersist(instance); } /** @@ -139,6 +140,10 @@ protected void prePersist(@NonNull T instance) { validate(instance); } + protected void postPersist(@NonNull T instance) { + } + + /** * Merges the specified updated instance into the repository. * diff --git a/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java new file mode 100644 index 00000000..a5690903 --- /dev/null +++ b/src/main/java/cz/cvut/kbss/analysis/service/ComplexManagedEntityRepositoryService.java @@ -0,0 +1,68 @@ +package cz.cvut.kbss.analysis.service; + + +import cz.cvut.kbss.analysis.dao.ManagedEntityDao; +import cz.cvut.kbss.analysis.dao.UserDao; +import cz.cvut.kbss.analysis.model.ManagedEntity; +import cz.cvut.kbss.analysis.model.UserReference; +import cz.cvut.kbss.analysis.service.security.SecurityUtils; +import lombok.NonNull; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.Validator; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * A common repository service for entities stored in their own context, e.g. System, FaultTree, along with their parts, + * e.g. for System its components and their behaviors, for FaultTrees its FaultEvents. + * @param + */ +public abstract class ComplexManagedEntityRepositoryService extends BaseRepositoryService { + protected final UserDao userDao; + + public ComplexManagedEntityRepositoryService(Validator validator, UserDao userDao) { + super(validator); + this.userDao = userDao; + } + + @Override + protected void preUpdate(@NonNull T instance) { + super.preUpdate(instance); + UserReference user = SecurityUtils.currentUserReference(); + instance.setLastEditor(user); + instance.setModified(new Date()); + } + + @Override + protected void prePersist(@NonNull T instance) { + super.prePersist(instance); + UserReference user = SecurityUtils.currentUserReference(); + instance.setCreator(user); + instance.setCreated(new Date()); + } + + + @Transactional(readOnly = true) + public List findAllSummaries(){ + return ((ManagedEntityDao)getPrimaryDao()).findAllSummaries().stream().map(this::postLoad).toList(); + } + + + @Override + protected T postLoad(@NonNull T instance) { + super.postLoad(instance); + for(UserReference user :Arrays.asList(instance.getLastEditor(), instance.getCreator())){ + if(user == null) continue; + setUserName(user); + } + return instance; + } + + protected void setUserName(UserReference user){ + String username = userDao.findUsername(user.getUri()); + user.setUsername(username); + } + +} diff --git a/src/main/java/cz/cvut/kbss/analysis/service/FaultEventRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/FaultEventRepositoryService.java index 9a961d8b..6226f357 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/FaultEventRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/FaultEventRepositoryService.java @@ -9,6 +9,7 @@ import cz.cvut.kbss.analysis.model.fta.FtaEventType; import cz.cvut.kbss.analysis.service.strategy.DirectFtaEvaluation; import cz.cvut.kbss.analysis.util.Vocabulary; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -17,6 +18,7 @@ import org.springframework.validation.Validator; import java.net.URI; +import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -75,7 +77,7 @@ protected void setExternalReference(URI eventUri, FaultEvent inputEvent){ List supertypes = inputEvent.getSupertypes().stream() .filter(e -> e.getTypes() == null || !e.getTypes().contains(ATOMIC_TYPE)) - .collect(Collectors.toList()); + .toList(); if(supertypes.isEmpty()) return; @@ -172,4 +174,21 @@ public boolean isRootEventReused(FaultEvent rootEvent) { return faultEventDao.isChild(rootEvent.getUri()); } + @Override + protected void postUpdate(@NonNull FaultEvent instance) { + super.postUpdate(instance); + setChange(instance); + } + + @Override + protected void postRemove(@NonNull FaultEvent instance) { + super.postRemove(instance); + setChange(instance); + } + + protected void setChange(FaultEvent instance){ + URI context = faultEventDao.getContext(instance); + faultTreeDao.setChangedByContext(context, new Date()); + } + } diff --git a/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java index 14e2f481..42307e84 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/FaultTreeRepositoryService.java @@ -3,6 +3,8 @@ import cz.cvut.kbss.analysis.dao.FaultEventScenarioDao; import cz.cvut.kbss.analysis.dao.FaultTreeDao; import cz.cvut.kbss.analysis.dao.GenericDao; +import cz.cvut.kbss.analysis.dao.UserDao; +import cz.cvut.kbss.analysis.exception.EntityNotFoundException; import cz.cvut.kbss.analysis.model.*; import cz.cvut.kbss.analysis.model.diagram.Rectangle; import cz.cvut.kbss.analysis.model.fta.CutSetExtractor; @@ -12,6 +14,7 @@ import cz.cvut.kbss.analysis.service.util.FaultTreeTraversalUtils; import cz.cvut.kbss.analysis.service.util.Pair; import cz.cvut.kbss.analysis.util.Vocabulary; +import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -26,7 +29,7 @@ @Service @Slf4j -public class FaultTreeRepositoryService extends BaseRepositoryService { +public class FaultTreeRepositoryService extends ComplexManagedEntityRepositoryService { private final FaultTreeDao faultTreeDao; private final FaultEventScenarioDao faultEventScenarioDao; @@ -34,6 +37,7 @@ public class FaultTreeRepositoryService extends BaseRepositoryService private final FunctionRepositoryService functionRepositoryService; private final IdentifierService identifierService; + private final ThreadLocal> visitedBehaviors = new ThreadLocal<>(); @Autowired @@ -42,9 +46,10 @@ public FaultTreeRepositoryService(@Qualifier("defaultValidator") Validator valid FaultEventScenarioDao faultEventScenarioDao, FaultEventRepositoryService faultEventRepositoryService, FunctionRepositoryService functionRepositoryService, - IdentifierService identifierService + IdentifierService identifierService, + UserDao userDao ) { - super(validator); + super(validator, userDao); this.faultTreeDao = faultTreeDao; this.faultEventScenarioDao = faultEventScenarioDao; this.faultEventRepositoryService = faultEventRepositoryService; @@ -78,7 +83,7 @@ public FaultTree findRequired(URI id) { .map(Behavior::getItem) .filter(c -> c != null).collect(Collectors.toSet()); for(Item i : items){ - items.forEach(c -> c.setComponents(null)); + i.setComponents(null); } setReferences(ft); @@ -115,8 +120,19 @@ public FaultTree findWithPropagation(URI faultTreeUri) { return faultTree; } + public FaultTree update(FaultTree instance) { + if(instance.getManifestingEvent() == null && instance.getUri() != null){ + FaultTree managedInstance = getPrimaryDao().find(instance.getUri()).orElse(null); + if(managedInstance == null) + throw EntityNotFoundException.create("Could find instance to update", instance.getUri()); + managedInstance.setName(instance.getName()); + instance = managedInstance; + } + return super.update(instance); + } + @Override - protected void prePersist(FaultTree instance) { + protected void prePersist(@NotNull FaultTree instance) { super.prePersist(instance); URI faultEventUri = instance.getManifestingEvent().getUri(); @@ -258,7 +274,7 @@ private void processBehavior(Behavior behavior, FaultEvent parentFaultEvent) thr } } - setFaultEventTypes(faultEvents.size() == 0, parentFaultEvent); + setFaultEventTypes(faultEvents.isEmpty(), parentFaultEvent); removeVisited(behavior); parentFaultEvent.addChildren(faultEvents); } @@ -439,11 +455,6 @@ private void setFaultEventTypes(boolean isBasic, FaultEvent fEvent){ } } - @Transactional(readOnly = true) - public List findAllSummaries(){ - return ((FaultTreeDao)getPrimaryDao()).findAllSummaries(); - } - @Transactional public FaultTree performCutSetAnalysis(URI faultTreeUri){ FaultTree faultTree = findRequired(faultTreeUri); diff --git a/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java b/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java index 0a0cbb27..feb81289 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/SystemRepositoryService.java @@ -1,9 +1,9 @@ package cz.cvut.kbss.analysis.service; -import com.fasterxml.jackson.databind.ObjectMapper; import cz.cvut.kbss.analysis.dao.ComponentDao; import cz.cvut.kbss.analysis.dao.GenericDao; import cz.cvut.kbss.analysis.dao.SystemDao; +import cz.cvut.kbss.analysis.dao.UserDao; import cz.cvut.kbss.analysis.model.Component; import cz.cvut.kbss.analysis.model.FailureMode; import cz.cvut.kbss.analysis.model.Item; @@ -22,15 +22,21 @@ @Service @Slf4j -public class SystemRepositoryService extends BaseRepositoryService { +public class SystemRepositoryService extends ComplexManagedEntityRepositoryService { private final SystemDao systemDao; private final ComponentRepositoryService componentRepositoryService; private final ComponentDao componentDao; @Autowired - public SystemRepositoryService(@Qualifier("defaultValidator") Validator validator, SystemDao systemDao, ComponentRepositoryService componentRepositoryService, ComponentDao componentDao) { - super(validator); + public SystemRepositoryService(@Qualifier("defaultValidator") Validator validator, + SystemDao systemDao, + ComponentRepositoryService componentRepositoryService, + ComponentDao componentDao, + UserDao userDao + + ) { + super(validator, userDao); this.systemDao = systemDao; this.componentRepositoryService = componentRepositoryService; this.componentDao = componentDao; diff --git a/src/main/java/cz/cvut/kbss/analysis/service/security/SecurityUtils.java b/src/main/java/cz/cvut/kbss/analysis/service/security/SecurityUtils.java index 4ee4ddc5..f76bb819 100755 --- a/src/main/java/cz/cvut/kbss/analysis/service/security/SecurityUtils.java +++ b/src/main/java/cz/cvut/kbss/analysis/service/security/SecurityUtils.java @@ -1,12 +1,11 @@ package cz.cvut.kbss.analysis.service.security; import cz.cvut.kbss.analysis.model.User; -import org.springframework.beans.factory.annotation.Autowired; +import cz.cvut.kbss.analysis.model.UserReference; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; /** @@ -32,6 +31,10 @@ public static User currentUser() { return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } + public static UserReference currentUserReference(){ + return new UserReference(currentUser()); + } + /** * Sets authentication to the current thread's security context. *