package eu.dnetlib.uoamonitorservice.service; import eu.dnetlib.uoaadmintoolslibrary.handlers.ForbiddenException; import eu.dnetlib.uoamonitorservice.dao.*; import eu.dnetlib.uoamonitorservice.dto.SectionFull; import eu.dnetlib.uoamonitorservice.entities.*; import eu.dnetlib.uoamonitorservice.generics.Common; import eu.dnetlib.uoamonitorservice.handlers.EntityNotFoundException; import eu.dnetlib.uoamonitorservice.handlers.PathNotValidException; import eu.dnetlib.uoamonitorservice.primitives.ReorderEvent; import eu.dnetlib.uoamonitorservice.primitives.Visibility; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @Service public class SectionService { private final StakeholderDAO stakeholderDAO; private final TopicDAO topicDAO; private final CategoryDAO categoryDAO; private final SubCategoryDAO subCategoryDAO; private final SectionDAO dao; private final IndicatorService indicatorService; private final CommonService commonService; @Autowired public SectionService(StakeholderDAO stakeholderDAO, TopicDAO topicDAO, CategoryDAO categoryDAO, SubCategoryDAO subCategoryDAO, SectionDAO dao, IndicatorService indicatorService, CommonService commonService) { this.stakeholderDAO = stakeholderDAO; this.topicDAO = topicDAO; this.categoryDAO = categoryDAO; this.subCategoryDAO = subCategoryDAO; this.dao = dao; this.indicatorService = indicatorService; this.commonService = commonService; } public Section find(String id) { return dao.findById(id).orElseThrow(() -> new EntityNotFoundException("Section with id: " + id + " not found")); } public Section findByPath(SubCategory subCategory, String sectionId) { if (!subCategory.getNumbers().contains(sectionId) && !subCategory.getCharts().contains(sectionId)) { throw new PathNotValidException("Section with id: " + sectionId + " not found in SubCategory: " + subCategory.getId()); } return this.dao.findById(sectionId).orElseThrow(() -> new EntityNotFoundException("Section with id: " + sectionId + " not found")); } public SectionFull getFullSection(String type, String alias, Section section) { return new SectionFull(section, section.getIndicators().stream() .map(indicatorId -> this.indicatorService.getIndicator(type, alias, indicatorId)) .collect(Collectors.toList())); } public SectionFull getFullSection(String type, String alias, String id) { Section section = this.find(id); return this.getFullSection(type, alias, section); } public SectionFull buildSection(SectionFull sectionFull) { sectionFull.setIndicators(sectionFull.getIndicators().stream().map(this.indicatorService::save).collect(Collectors.toList())); Section section = this.save(new Section(sectionFull)); return new SectionFull(section, sectionFull.getIndicators()); } public Section save(Section section) { if (section.getId() != null) { section.setIndicators(this.find(section.getId()).getIndicators()); } section.getIndicators().forEach(this.indicatorService::find); return this.dao.save(section); } public void saveBulk(Stakeholder stakeholder, SubCategory subCategory, List sections) { if (this.commonService.hasCreateAuthority(stakeholder.getType())) { sections = sections.stream().map(this::buildSection).collect(Collectors.toList()); sections.forEach(section -> { this.addSection(subCategory, section.getId()); this.createChildren(subCategory, new Section(section), -1); }); } else { throw new ForbiddenException("You are not authorized to create sections in stakeholder with id: " + stakeholder.getId()); } } public SectionFull save(Stakeholder stakeholder, SubCategory subCategory, Section section, int index) { section.setStakeholderAlias(stakeholder.getAlias()); if (section.getId() != null) { if (this.commonService.hasEditAuthority(stakeholder.getType(), stakeholder.getAlias())) { section.setIndicators(this.find(section.getId()).getIndicators()); this.updateChildren(section); section = this.save(section); } else { throw new ForbiddenException("You are not authorized to update stakeholder with id: " + stakeholder.getId()); } } else { if (this.commonService.hasCreateAuthority(stakeholder.getType())) { section = this.save(section); this.createChildren(subCategory, section, index); this.addSection(subCategory, section.getId(), index); } else { throw new ForbiddenException("You are not authorized to create a section in stakeholder with id: " + stakeholder.getId()); } } return this.getFullSection(stakeholder.getType(), stakeholder.getAlias(), section); } public void createChildren(SubCategory defaultSubCategory, Section section, int index) { this.subCategoryDAO.findByDefaultId(defaultSubCategory.getId()).forEach(subCategory -> { this.categoryDAO.findBySubCategoriesContaining(subCategory.getId()).forEach(category -> { this.topicDAO.findByCategoriesContaining(category.getId()).forEach(topic -> { this.stakeholderDAO.findByTopicsContaining(topic.getId()).forEach(stakeholder -> { this.save(stakeholder, subCategory, section.copy(), index); section.getIndicators().forEach(indicator -> { this.indicatorService.createChildren(section, this.indicatorService.find(indicator)); }); }); }); }); }); } public void updateChildren(Section section) { this.dao.findByDefaultId(section.getId()).forEach(child -> { this.save(section.override(child, this.find(section.getId()))); }); } public SectionFull reorderIndicators(Stakeholder stakeholder, Section section, ReorderEvent event) { if (this.commonService.hasEditAuthority(stakeholder.getType(), stakeholder.getAlias())) { event.getIds().forEach(this.indicatorService::find); if (event.getAction().equals("added")) { section.addIndicator(event.getTarget()); } else if (event.getAction().equals("removed")) { section.removeIndicator(event.getTarget()); } if (section.getIndicators().size() == event.getIds().size() && new HashSet<>(section.getIndicators()).containsAll(event.getIds())) { section.setIndicators(event.getIds()); if(event.getAction().equals("moved")) { this.reorderChildren(stakeholder, section, event); } return this.getFullSection(stakeholder.getType(), stakeholder.getAlias(), this.dao.save(section)); } else { throw new EntityNotFoundException("Some indicators dont exist in the section with id " + section.getId()); } } else { throw new ForbiddenException("You are not authorized to reorder indicators in section with id: " + section.getId()); } } public void reorderChildren(Stakeholder defaultStakeholder, Section defaultSection, ReorderEvent event) { this.stakeholderDAO.findByDefaultId(defaultStakeholder.getId()).forEach(stakeholder -> { this.dao.findByDefaultId(defaultSection.getId()).stream().map(section -> this.getFullSection(stakeholder.getType(), stakeholder.getAlias(), section)).forEach(section -> { Indicator target; if(section.isNumber()) { target = this.subCategoryDAO.findByNumbersContaining(section.getId()).stream().flatMap(subCategory -> subCategory.getNumbers().stream()) .map(id -> this.getFullSection(stakeholder.getType(), stakeholder.getAlias(), id)).flatMap(sectionFull -> section.getIndicators().stream()) .filter(indicator -> indicator.getDefaultId().equals(event.getTarget())).findFirst().orElse(null); } else { target = this.subCategoryDAO.findByChartsContaining(section.getId()).stream().flatMap(subCategory -> subCategory.getCharts().stream()) .map(id -> this.getFullSection(stakeholder.getType(), stakeholder.getAlias(), id)).flatMap(sectionFull -> section.getIndicators().stream()) .filter(indicator -> indicator.getDefaultId().equals(event.getTarget())).findFirst().orElse(null); } if (target != null) { List indicators = section.getIndicators().stream().map(indicator -> (Common) indicator).collect(Collectors.toList()); if(event.getAction().equals("removed")) { indicators.removeIf(indicator -> indicator.getId().equals(target.getId())); } else if(event.getAction().equals("added")) { indicators.add(target); } List ids = this.commonService.reorder(event.getIds(), indicators); ReorderEvent childEvent = new ReorderEvent(event.getAction(), target.getId(), ids); this.reorderIndicators(stakeholder, new Section(section), childEvent); } }); }); } public void delete(String type, Section section, boolean remove) { if (this.commonService.hasDeleteAuthority(type)) { this.dao.findByDefaultId(section.getId()).forEach(child -> { this.delete(type, child.getId(), remove); }); section.getIndicators().forEach(indicatorId -> { this.indicatorService.delete(type, indicatorId, false); }); if (remove) { this.removeSection(section.getId()); } this.dao.delete(section); } else { throw new ForbiddenException("Delete section: You are not authorized to delete section with id: " + section.getId()); } } public void delete(String type, String id, boolean remove) { Section section = this.find(id); this.delete(type, section, remove); } public void addSection(SubCategory subCategory, String id) { this.addSection(subCategory, id, -1); } public void addSection(SubCategory subCategory, String id, int index) { if (this.find(id).isNumber()) { subCategory.addNumber(id, index); } else { subCategory.addChart(id, index); } this.subCategoryDAO.save(subCategory); } public void removeSection(String id) { this.subCategoryDAO.findByNumbersContaining(id).forEach(subCategory -> { subCategory.removeNumber(id); this.subCategoryDAO.save(subCategory); }); this.subCategoryDAO.findByChartsContaining(id).forEach(subCategory -> { subCategory.removeChart(id); this.subCategoryDAO.save(subCategory); }); } public SectionFull changeVisibility(String type, String alias, SectionFull section, Visibility visibility) { if (this.commonService.hasEditAuthority(type, alias)) { section.setIndicators(section.getIndicators().stream() .map(indicator -> this.indicatorService.changeVisibility(type, alias, indicator, visibility)) .collect(Collectors.toList())); section.update(this.save(new Section(section))); return section; } else { throw new ForbiddenException("Change section visibility: You are not authorized to update section with id: " + section.getId()); } } }