package com.exadel.controller; import com.exadel.dto.EntryDTO; import com.exadel.dto.EventDTO; import com.exadel.dto.TrainingDTO; import com.exadel.model.entity.events.Event; import com.exadel.model.entity.events.TrainingEvent; import com.exadel.model.entity.training.Entry; import com.exadel.model.entity.training.Training; import com.exadel.model.entity.training.TrainingStatus; import com.exadel.model.entity.user.UserRole; import com.exadel.search.TrainingSearch; import com.exadel.service.EntryService; import com.exadel.service.TrainingService; import com.exadel.service.UserService; import com.exadel.service.events.TrainingEventService; import com.exadel.service.events.TrainingFeedbackEventService; import com.exadel.service.events.UserFeedbackEventService; import com.exadel.service.impl.EmailMessages; import com.exadel.service.impl.SmtpMailSender; import com.exadel.util.UserUtil; import com.google.common.collect.Lists; import org.apache.lucene.search.Query; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextQuery; import org.hibernate.search.query.dsl.QueryBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.*; import static com.exadel.Utils.addWeekToDate; import static com.exadel.Utils.getDayNumberToAdd; @RestController @PreAuthorize("hasAnyRole('0','1','2')") @RequestMapping(value = "/trainings", headers = "Accept=application/json") public class TrainingsController { @Autowired private TrainingService trainingService; @Autowired private TrainingEventService trainingEventService; @Autowired private EntryService entryService; @Autowired private UserService userService; @Autowired private SmtpMailSender smtpMailSender; @Autowired private EmailMessages emailMessages; @Autowired TrainingSearch trainingSearch; public static int size; @PersistenceContext private EntityManager entityManager; @Autowired private TrainingFeedbackEventService trainingFeedbackEventService; @Autowired private UserFeedbackEventService userFeedbackEventService; @PreAuthorize("hasAnyRole('0','1','2')") @RequestMapping(method = RequestMethod.GET) public List<TrainingDTO> getTrainings() { List<Training> trainings = (List<Training>) trainingService.getAllTrainings(); List<TrainingDTO> trainingDTOs = new ArrayList<>(); for (Training training : trainings) { trainingDTOs.add(new TrainingDTO(training)); } return trainingDTOs; } @PreAuthorize("hasAnyRole('0','1','2')") @RequestMapping(value = "/newTraining", method = RequestMethod.POST) //called only by ADMIN public Training createTraining(@RequestBody TrainingDTO trainingDTO) { Training training = new Training(trainingDTO); if (UserUtil.hasRole(0)) { training.setStatus(TrainingStatus.APPROVED); training = trainingService.addTraining(training); } else { training.setStatus(TrainingStatus.DRAFTED); training = trainingService.addTraining(training); trainingDTO.setId(training.getId()); trainingDTO.setEventDescription(training.getTrainer().getName()+" wants to create a new training \""+training.getName()+"\""); smtpMailSender.sendToUsers(userService.getUsersByRole(UserRole.ADMIN), "Changes in Trainings", emailMessages.newTrainingToAdmin(training)); trainingEventService.addEvent(new TrainingEvent(trainingDTO)); List<EventDTO> eventDTOs = new ArrayList<>(); List<Event> events = new ArrayList<>(); events.addAll(trainingEventService.getUnwatchedEvents()); events.addAll(trainingFeedbackEventService.getUnwatchedEvents()); events.addAll(userFeedbackEventService.getUnwatchedEvents()); for (Event event: events){ eventDTOs.add(event.toEventDTO()); } for (Map.Entry<DeferredResult<List<EventDTO>>, Integer> entry : EventController.eventRequests.entrySet()) { entry.getKey().setResult(eventDTOs); } } if (trainingDTO.isRepeated()) { generateEntries(trainingDTO.getBegin(), trainingDTO.getEnd(), training, trainingDTO.getEntries()); } else { List<EntryDTO> entryDTOs = trainingDTO.getEntries(); Collections.sort(entryDTOs); for (EntryDTO entryDTO : entryDTOs) { Entry entry = new Entry(entryDTO); entry.setTraining(training); entryService.addEntry(entry); } } return training; } void generateEntries(Date beginDay, Date endDay, Training training, List<EntryDTO> entryDTOs) { if (beginDay == null || endDay == null) return; Calendar begin = new GregorianCalendar(); begin.setTime(beginDay); int beginDayOfWeek = begin.get(Calendar.DAY_OF_WEEK); Calendar generator = new GregorianCalendar(); for (EntryDTO entryDTO : entryDTOs) { generateTime(generator, entryDTO.getBeginTime(), begin); generator.add(Calendar.DATE, getDayNumberToAdd(beginDayOfWeek, entryDTO.getDayOfWeek())); entryDTO.setBeginTime(generator.getTime()); generateTime(generator, entryDTO.getEndTime(), begin); generator.add(Calendar.DATE, getDayNumberToAdd(beginDayOfWeek, entryDTO.getDayOfWeek())); entryDTO.setEndTime(generator.getTime()); } Collections.sort(entryDTOs); Queue<EntryDTO> duplicates = new LinkedList<>(entryDTOs); EntryDTO entryDTO = duplicates.remove(); while (entryDTO.getBeginTime().before(endDay)) { Entry entry = new Entry(entryDTO); entry.setTraining(training); entryService.addEntry(entry); entryDTO.setEndTime(addWeekToDate(entryDTO.getEndTime())); entryDTO.setBeginTime(addWeekToDate(entryDTO.getBeginTime())); duplicates.add(entryDTO); entryDTO = duplicates.remove(); } } private void generateTime(Calendar calendar, Date time, Calendar beginDay) { calendar.clear(); calendar.setTime(time); calendar.set(beginDay.get(Calendar.YEAR), beginDay.get(Calendar.MONTH), beginDay.get(Calendar.DAY_OF_MONTH)); } @RequestMapping(value = "/pages/count/{pageNumber}", method = RequestMethod.GET) public Integer getCount(@PathVariable Integer pageNumber, @RequestParam Integer size,String sortParam, @RequestParam (required = false) boolean isReversed) { return this.size; } @PreAuthorize("hasAnyRole('0','1','2')") @RequestMapping(value ="/pages/{pageNumber}",method = RequestMethod.GET) public List<TrainingDTO> getTrainingsPaging(@PathVariable Integer pageNumber, @RequestParam Integer size, @RequestParam (required = false)String name, @RequestParam (required = false)String trainer, @RequestParam (required = false)String targetAudience, @RequestParam (required = false) boolean isReversed, @RequestParam (required = false) String sortParam) { this.size=0; FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(entityManager); QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory() .buildQueryBuilder().forEntity(Training.class).get(); List<Training> results = new ArrayList<>(); if(sortParam!=null && sortParam.equals("trainer")) { sortParam = "trainer.name"; } Query query = null; Query trainerNameQuery ; Query targetAudienceQuery; Query nameQuery; if(trainer!= null) { trainerNameQuery = trainingSearch.searchByTrainerName(trainer); query = queryBuilder.bool().must(trainerNameQuery).createQuery(); } if(targetAudience!=null) { targetAudienceQuery = trainingSearch.searchByTargetAudience(targetAudience); if (query != null) { query = queryBuilder.bool().must(query).must(targetAudienceQuery).createQuery(); } else query = queryBuilder.bool().must(targetAudienceQuery).createQuery(); } if(name != null) { nameQuery = trainingSearch.searchByName(name); if (query != null) { query = queryBuilder.bool().must(query).must(nameQuery).createQuery(); } else query = queryBuilder.bool().must(nameQuery).createQuery(); } if(query!=null) { FullTextQuery jpaQuery = fullTextEntityManager.createFullTextQuery(query, Training.class); jpaQuery.setFirstResult(pageNumber); jpaQuery.setMaxResults(size); if(sortParam!=null) { Sort sort = new Sort( new SortField(sortParam, SortField.Type.STRING)); jpaQuery.setSort(sort); } this.size=jpaQuery.getResultList().size(); if(this.size<size) { this.size=1; } else this.size = this.size/ size; size = jpaQuery.getResultSize(); results=jpaQuery.getResultList(); if(isReversed) { results = Lists.reverse(results); } } if(name == null && trainer ==null && targetAudience==null) { Page<Training> page = trainingService.getTrainings(pageNumber, size,sortParam,isReversed); results = page.getContent(); this.size = page.getTotalPages(); } List<TrainingDTO> trainingDTOs = new ArrayList<>(); for (Training training : results) { trainingDTOs.add(new TrainingDTO(training)); } return trainingDTOs; } }