Java tutorial
/** * This file is part of alf.io. * * alf.io is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * alf.io is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with alf.io. If not, see <http://www.gnu.org/licenses/>. */ package alfio.manager; import alfio.manager.i18n.I18nManager; import alfio.model.ContentLanguage; import alfio.model.Event; import alfio.model.SpecialPrice; import alfio.model.TicketCategory; import alfio.model.modification.SendCodeModification; import alfio.model.user.Organization; import alfio.repository.SpecialPriceRepository; import alfio.util.TemplateManager; import alfio.util.TemplateResource; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.stereotype.Component; import java.time.ZonedDateTime; import java.util.*; import java.util.function.Predicate; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; @Component public class SpecialPriceManager { private static final Predicate<SendCodeModification> IS_CODE_PRESENT = v -> Optional.ofNullable(v.getCode()) .isPresent(); private final EventManager eventManager; private final NotificationManager notificationManager; private final SpecialPriceRepository specialPriceRepository; private final TemplateManager templateManager; private final MessageSource messageSource; private final I18nManager i18nManager; @Autowired public SpecialPriceManager(EventManager eventManager, NotificationManager notificationManager, SpecialPriceRepository specialPriceRepository, TemplateManager templateManager, MessageSource messageSource, I18nManager i18nManager) { this.eventManager = eventManager; this.notificationManager = notificationManager; this.specialPriceRepository = specialPriceRepository; this.templateManager = templateManager; this.messageSource = messageSource; this.i18nManager = i18nManager; } private List<String> checkCodeAssignment(Set<SendCodeModification> input, int categoryId, Event event, String username) { final TicketCategory category = checkOwnership(categoryId, event, username); List<String> availableCodes = new ArrayList<>( specialPriceRepository.findActiveByCategoryId(category.getId()).stream() .filter(SpecialPrice::notSent).map(SpecialPrice::getCode).collect(toList())); Validate.isTrue(input.size() <= availableCodes.size(), "Requested codes: " + input.size() + ", available: " + availableCodes.size() + "."); List<String> requestedCodes = input.stream().filter(IS_CODE_PRESENT).map(SendCodeModification::getCode) .collect(toList()); Validate.isTrue(requestedCodes.stream().distinct().count() == requestedCodes.size(), "Cannot assign the same code twice. Please fix the input file."); Validate.isTrue(requestedCodes.stream().allMatch(availableCodes::contains), "some requested codes don't exist."); return availableCodes; } private TicketCategory checkOwnership(int categoryId, Event event, String username) { eventManager.checkOwnership(event, username, event.getOrganizationId()); final List<TicketCategory> categories = eventManager.loadTicketCategories(event); final TicketCategory category = categories.stream().filter(tc -> tc.getId() == categoryId).findFirst() .orElseThrow(IllegalArgumentException::new); Validate.isTrue(category.isAccessRestricted(), "Access to the selected category is not restricted."); return category; } public List<SendCodeModification> linkAssigneeToCode(List<SendCodeModification> input, String eventName, int categoryId, String username) { final Event event = eventManager.getSingleEvent(eventName, username); Set<SendCodeModification> set = new LinkedHashSet<>(input); List<String> availableCodes = checkCodeAssignment(set, categoryId, event, username); final Iterator<String> codes = availableCodes.iterator(); return Stream.concat(set.stream().filter(IS_CODE_PRESENT), input.stream().filter(IS_CODE_PRESENT.negate()) .map(p -> new SendCodeModification(codes.next(), p.getAssignee(), p.getEmail(), p.getLanguage()))) .collect(toList()); } public List<SpecialPrice> loadSentCodes(String eventName, int categoryId, String username) { final Event event = eventManager.getSingleEvent(eventName, username); checkOwnership(categoryId, event, username); Predicate<SpecialPrice> p = SpecialPrice::notSent; return specialPriceRepository.findAllByCategoryId(categoryId).stream().filter(p.negate()).collect(toList()); } public boolean clearRecipientData(String eventName, int categoryId, int codeId, String username) { final Event event = eventManager.getSingleEvent(eventName, username); checkOwnership(categoryId, event, username); int result = specialPriceRepository.clearRecipientData(codeId, categoryId); Validate.isTrue(result <= 1, "too many records affected"); return result == 1; } public boolean sendCodeToAssignee(List<SendCodeModification> input, String eventName, int categoryId, String username) { final Event event = eventManager.getSingleEvent(eventName, username); final Organization organization = eventManager.loadOrganizer(event, username); Set<SendCodeModification> set = new LinkedHashSet<>(input); checkCodeAssignment(set, categoryId, event, username); Validate.isTrue(set.stream().allMatch(IS_CODE_PRESENT), "There are missing codes. Please check input file."); List<ContentLanguage> eventLanguages = i18nManager.getEventLanguages(event.getLocales()); Validate.isTrue(!eventLanguages.isEmpty(), "No locales have been defined for the event. Please check the configuration"); ContentLanguage defaultLocale = eventLanguages.contains(ContentLanguage.ENGLISH) ? ContentLanguage.ENGLISH : eventLanguages.get(0); set.forEach(m -> { Locale locale = Locale.forLanguageTag(StringUtils.defaultString(StringUtils.trimToNull(m.getLanguage()), defaultLocale.getLanguage())); Map<String, Object> model = TemplateResource.prepareModelForSendReservedCode(organization, event, m, eventManager.getEventUrl(event)); notificationManager.sendSimpleEmail(event, m.getEmail(), messageSource.getMessage("email-code.subject", new Object[] { event.getDisplayName() }, locale), () -> templateManager.renderTemplate(event, TemplateResource.SEND_RESERVED_CODE, model, locale)); int marked = specialPriceRepository.markAsSent(ZonedDateTime.now(event.getZoneId()), m.getAssignee().trim(), m.getEmail().trim(), m.getCode().trim()); Validate.isTrue(marked == 1, "Expected exactly one row updated, got " + marked); }); return true; } }