ReservationsController.java
@RequestMapping(method = RequestMethod.POST) String reserve(@Validated ReservationForm form, BindingResult bindingResult, @DateTimeFormat(iso=DateTimeFormat.ISO.DATE) @PathVariable("date") LocalDate date, @PathVariable("roomId") Integer roomId, Model model) { if(bindingResult.hasErrors()) { return reserveForm(date, roomId, model); } ReservableRoom reservableRoom = new ReservableRoom( new ReservableRoomId(roomId, date)); Reservation reservation = new Reservation(); reservation.setStarttime(form.getStartTime()); reservation.setEndTime(form.getEndTime()); reservation.setReservableRoom(reservableRoom); reservation.setUser(dummyUser()); try { reservationService.reserve(reservation); } catch (UnavailableReservationException | AlreadyReservedException e) { model.addAttribute("error", e.getMessage()); return reserveForm(date, roomId, model); } return "redirect:/reservations/{date}/{roomId}"; } @RequestMapping(method = RequestMethod.POST, params = "cancel") String cancel(@RequestParam("reservationId") Integer reservationId, @PathVariable("roomId") Integer roomId, @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) @PathVariable("date") LocalDate date, Model model) { User user = dummyUser(); try { reservationService.cancel(reservationId, user); } catch (IllegalStateException e) { model.addAttribute("error", e.getMessage()); return reserveForm(date, roomId, model); } return "redirect:/reservations/{date}/{roomId}"; }
ThirtyMinutesUnit.java
package mrs.app.reservation; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.*; import javax.validation.*; @Documented @Constraint(validatedBy = {ThirtyMinutesUnitValidator.class}) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RINTIME) public @interface ThirtyMinutesUnit { String message() default "{mrs.app.reservation.ThirtyMinutesUnit.message}"; Class<?>[]groups() default {}; Class<? extends Playload>[]playload() default {}; @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented public @interface List { ThirtyMinutesUnit[]value(); } }
ThirtyMinutesUnitValidator.java
package mrs.app.reservation; import java.time.LocalTime; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class ThirtyMinutesUnitValidator implements ConstraintValidator<ThirtyMinutesUnit, LocalTime>{ @Override public void initialize(ThirtyMinutesUnit constraintAnnotation) { } @Override public boolean isValid(LocalTime value, ConstraintValidatorContext context) { if(value == null) { return true; } return value.getMinute() % 30 == 0; } }
EndTimeMuustBeAfterStartTime.java
package mrs.app.reservation; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.*; import javax.validation.*; @Documented @Constraint(validatedBy = {EndTimeMustBeAfterStartTimeValidator.class}) @Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) public @interface EntTimeMustBeAfterStartTime{ String message() default "{mrs.app.reservation.EndTimeMustBeAfterStartTime.message}"; Class<?>[]groups() default{}; Class<? extends Playload>[]payload() default {}; @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented public @interface List { EndTimeMustBeAfterStartTime[]value(); } }
EndTimeMustBeAfterStartTimeValidator.java
package mrs.app.reservation; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class EndTimeMustBeAfterStartTimeValidator implements ConstraintValidator<EndTimeMustBeAfterStartTime, ReservationForm>{ private String message; @Override public void initialize(EndTimeMustBeAfterStartTime constraintAnnotation) { message = constraintAnnotation.message(); } @Override public boolean isValid(ReservationForm value, ConstraintValidatorContext context) { if(value.getStarttime() == null || value.getEndTime() == null) { return true; } boolean isEndTimeMustBeAfterStartTime = value.getEndTime().isAfter(value.getStartTime()); if(!isEndTimeMustBeAfterStartTime) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(message).addPropertyNode("endTime").addConstraintViolation(); } return isEndTimeMustBeAfterStartTime; } }
うーむ、ちょっと混乱してきたな。