package eu.dnetlib.uoamonitorservice.service; import eu.dnetlib.uoaadmintoolslibrary.handlers.ForbiddenException; import eu.dnetlib.uoamonitorservice.dao.StakeholderDAO; import eu.dnetlib.uoamonitorservice.dao.TopicDAO; import eu.dnetlib.uoamonitorservice.dto.TopicFull; import eu.dnetlib.uoamonitorservice.entities.Stakeholder; import eu.dnetlib.uoamonitorservice.entities.Topic; import eu.dnetlib.uoamonitorservice.generics.Common; import eu.dnetlib.uoamonitorservice.handlers.EntityNotFoundException; import eu.dnetlib.uoamonitorservice.handlers.PathNotValidException; import eu.dnetlib.uoamonitorservice.primitives.Visibility; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @Service public class TopicService { private final StakeholderDAO stakeholderDAO; private final TopicDAO dao; private final CategoryService categoryService; private final CommonService commonService; @Autowired public TopicService(StakeholderDAO stakeholderDAO, TopicDAO dao, CategoryService categoryService, CommonService commonService) { this.stakeholderDAO = stakeholderDAO; this.dao = dao; this.categoryService = categoryService; this.commonService = commonService; } public Topic find(String id) { return dao.findById(id).orElseThrow(() -> new EntityNotFoundException("Topic with id: " + id + " not found")); } public Topic findByPath(Stakeholder stakeholder, String topicId) { if (!stakeholder.getTopics().contains(topicId)) { throw new PathNotValidException("Topic with id: " + topicId + " not found in Stakeholder: " + stakeholder.getId()); } return this.dao.findById(topicId).orElseThrow(() -> new EntityNotFoundException("Topic with id: " + topicId + " not found")); } public TopicFull getFullTopic(String type, String alias, Topic topic) { if (commonService.hasVisibilityAuthority(type, alias, topic)) { return new TopicFull(topic, topic.getCategories().stream() .map(categoryId -> this.categoryService.getFullCategory(type, alias, categoryId)) .collect(Collectors.toList())); } else { return null; } } public TopicFull getFullTopic(String type, String alias, String id) { Topic topic = this.find(id); return this.getFullTopic(type, alias, topic); } public TopicFull buildTopic(TopicFull topicFull) { topicFull.setCategories(topicFull.getCategories().stream().map(this.categoryService::buildCategory).collect(Collectors.toList())); topicFull.update(this.save(new Topic(topicFull))); return topicFull; } public Topic save(Topic topic) { if(topic.getId() != null) { topic.setCategories(this.find(topic.getId()).getCategories()); } else { topic.setCreationDate(new Date()); } topic.setUpdateDate(new Date()); topic.getCategories().forEach(this.categoryService::find); return this.dao.save(topic); } public TopicFull save(Stakeholder stakeholder, Topic topic) { if(topic.getId() != null) { if(this.commonService.hasEditAuthority(stakeholder.getType(), stakeholder.getAlias())) { topic.setCategories(this.find(topic.getId()).getCategories()); this.updateChildren(topic); topic = this.save(topic); } else { throw new ForbiddenException("You are not authorized to update stakeholder with id: " + stakeholder.getId()); } } else { if(this.commonService.hasCreateAuthority(stakeholder.getType())) { topic = this.save(topic); this.createChildren(stakeholder, topic); this.addTopic(stakeholder, topic.getId()); } else { throw new ForbiddenException("You are not authorized to create a topic in stakeholder with id: " + stakeholder.getId()); } } return this.getFullTopic(stakeholder.getType(), stakeholder.getAlias(), topic); } public void createChildren(Stakeholder defaultStakeholder, Topic topic) { this.stakeholderDAO.findByDefaultId(defaultStakeholder.getId()).forEach(stakeholder -> { this.save(stakeholder, topic.copy()); }); } public void updateChildren(Topic topic) { this.dao.findByDefaultId(topic.getId()).forEach(child -> { this.save(topic.override(child, this.find(topic.getId()))); }); } public TopicFull reorderCategories(Stakeholder stakeholder, Topic topic, List categories) { if(this.commonService.hasEditAuthority(stakeholder.getType(), stakeholder.getAlias())) { categories.forEach(this.categoryService::find); if (topic.getCategories().size() == categories.size() && new HashSet<>(topic.getCategories()).containsAll(categories)) { topic.setCategories(categories); this.reorderChildren(stakeholder, topic, categories); topic.setUpdateDate(new Date()); return this.getFullTopic(stakeholder.getType(), stakeholder.getAlias(), this.dao.save(topic)); } else { throw new EntityNotFoundException("Some categories dont exist in the topic with id " + topic.getId()); } } else { throw new ForbiddenException("You are not authorized to reorder categories in topic with id: " + topic.getId()); } } public void reorderChildren(Stakeholder defaultStakeholder, Topic defaultTopic, List defaultCategories) { this.stakeholderDAO.findByDefaultId(defaultStakeholder.getId()).forEach(stakeholder -> { this.dao.findByDefaultId(defaultTopic.getId()).stream().map(topic -> this.getFullTopic(stakeholder.getType(), stakeholder.getAlias(), topic)).forEach(topic -> { this.reorderCategories(stakeholder, new Topic(topic), this.commonService.reorder(defaultCategories, topic.getCategories().stream().map(category -> (Common) category).collect(Collectors.toList()))); }); }); } public void delete(String type, Topic topic, boolean remove) { if (this.commonService.hasDeleteAuthority(type)) { this.dao.findByDefaultId(topic.getId()).forEach(child -> { this.delete(type, child.getId(), remove); }); topic.getCategories().forEach(categoryId -> { this.categoryService.delete(type, categoryId, false); }); if (remove) { this.removeTopic(topic.getId()); } this.dao.delete(topic); } else { throw new ForbiddenException("Delete topic: You are not authorized to delete topic with id: " + topic.getId()); } } public void delete(String type, String id, boolean remove) { Topic topic = this.find(id); this.delete(type, topic, remove); } public void addTopic(Stakeholder stakeholder, String id) { stakeholder.addTopic(id); stakeholder.setUpdateDate(new Date()); this.stakeholderDAO.save(stakeholder); } public void removeTopic(String id) { this.stakeholderDAO.findByTopicsContaining(id).forEach(stakeholder -> { stakeholder.removeTopic(id); stakeholder.setUpdateDate(new Date()); this.stakeholderDAO.save(stakeholder); }); } public TopicFull changeVisibility(String type, String alias, TopicFull topic, Visibility visibility, Boolean propagate) { if (this.commonService.hasEditAuthority(type, alias)) { topic.setVisibility(visibility); if (propagate) { topic.setCategories(topic.getCategories().stream() .map(category -> this.categoryService.changeVisibility(type, alias, category, visibility, true)) .collect(Collectors.toList())); } topic.update(this.save(new Topic(topic))); return topic; } else { throw new ForbiddenException("Change topic visibility: You are not authorized to update topic with id: " + topic.getId()); } } public TopicFull changeVisibility(String type, String alias, Topic topic, Visibility visibility, Boolean propagate) { TopicFull topicFull = this.getFullTopic(type, alias, topic); return this.changeVisibility(type, alias, topicFull, visibility, propagate); } }