-1

Let's say that we have a TrainingDate class like below:

@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
class TrainingDate {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private LocalDateTime startDate;

  private LocalDateTime endDate;

  @OneToOne(mappedBy = "trainingDate")
  private Training training;

}

I want to create a method that will check if the proposed date of training will not collide with the time table of the trainer. The method looks like:

private boolean isTrainingDateNotCollidingWithTrainerSchedule(List<Training> trainerTrainings,
      TrainingDate potentialTrainingDate) {

    List<TrainingDate> trainingList = trainerTrainings
        .stream()
        .map(Training::getTrainingDate)
        .filter(
            trainingDate -> trainingDate.startDate.isAfter(potentialTrainingDate.endDate) &&
                trainingDate.endDate.isBefore(potentialTrainingDate.startDate))
        .collect(Collectors.toList());

    if (trainingList.size() > 1) {
      throw exception here 
    } else {
      return true;
    }
  }

Seemingly it's working fine but for me, it's not so gentle way to reach a goal. Here comes the question, is it possible to refactor the above solution and make it a little more clear. I know that I can split this filter declaration but this post click suggests that this is not a good choice if we will take a final performance into consideration. I will be grateful for the suggestion on how to check if start date and end date will not collide with the trainer timetable by improving clearness of the current solution.

Martin
  • 1,139
  • 4
  • 23
  • 49
  • 1
    That condition looks wrong, how can one period both start after another period has ended and end before the other period has started? Off topic but TrainingDate is a strange name for something that has a start and an end date, maybe it would be better to use something like period, interval or schedule. – Joakim Danielson Nov 26 '19 at 14:33
  • What does this method return `getTrainingDate` and is this property inside of `TrainingDate` or `Training` ? – Ryuzaki L Nov 26 '19 at 14:42
  • a simple refactoring would be to move the comparison inside a method called `overlap(LocalDateTime otherstart, LocalDateTime otherend)` inside `TrainingDate` class. And then as Joakim mentioned, you have to fix the condition to: `(startDate.isBefore(otherStart) && endDate.isAfter(otherStart)) || (startDate.isBefore(otherEnd) && endDate.isAfter(otherEnd));` – sudipn Nov 26 '19 at 15:17

1 Answers1

0

You can return directly a result from stream

private boolean isTrainingDateNotCollidingWithTrainerSchedule(List<Training> trainerTrainings,TrainingDate potentialTrainingDate) {

     return trainerTrainings.stream().noneMatch(trainingDate -> trainingDate.startDate.isAfter(potentialTrainingDate.endDate) &&
            trainingDate.endDate.isBefore(potentialTrainingDate.startDate));
}
b.GHILAS
  • 2,273
  • 1
  • 8
  • 16