Reservation.java
package io.extact.rms.application.domain;
import static java.time.temporal.ChronoUnit.*;
import static jakarta.persistence.AccessType.*;
import java.time.LocalDateTime;
import java.time.chrono.ChronoLocalDateTime;
import java.util.Objects;
import jakarta.persistence.Access;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import org.apache.commons.lang3.Range;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import lombok.Getter;
import lombok.Setter;
import io.extact.rms.application.domain.constraint.BeforeAfterDateTime;
import io.extact.rms.application.domain.constraint.Note;
import io.extact.rms.application.domain.constraint.ReserveEndDateTime;
import io.extact.rms.application.domain.constraint.ReserveStartDateTime;
import io.extact.rms.application.domain.constraint.ReserveStartDateTimeFuture;
import io.extact.rms.application.domain.constraint.RmsId;
import io.extact.rms.application.domain.constraint.BeforeAfterDateTime.BeforeAfterDateTimeValidatable;
import io.extact.rms.application.domain.constraint.ValidationGroups.Add;
import io.extact.rms.application.domain.constraint.ValidationGroups.Update;
@Access(FIELD)
@Entity
@BeforeAfterDateTime(from = "利用開始日時", to = "利用終了日時")
@Getter
@Setter
public class Reservation implements BeforeAfterDateTimeValidatable, Transformable, IdAccessable {
/** id */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@RmsId(groups = Update.class)
private Integer id;
/** 利用開始日時 */
@ReserveStartDateTime
@ReserveStartDateTimeFuture(groups = Add.class)
@Column(columnDefinition = "TIMESTAMP")
private LocalDateTime startDateTime;
/** 利用終了日時 */
@ReserveEndDateTime
@Column(columnDefinition = "TIMESTAMP")
private LocalDateTime endDateTime;
/** メモ */
@Note
private String note;
/** 予約したレンタル品ID */
@RmsId
private int rentalItemId;
/** 予約したユーザのユーザアカウントID */
@RmsId
private int userAccountId;
/** 予約したユーザ */
private transient UserAccount userAccount;
/** 予約したレンタル品 */
private transient RentalItem rentalItem;
// ----------------------------------------------------- factory methods
public static Reservation of(Integer reservationId, LocalDateTime startDateTime, LocalDateTime endDateTime, String note,
int rentalItemId, int userAccountId) {
var entity = new Reservation();
entity.id = reservationId;
entity.startDateTime = startDateTime;
entity.endDateTime = endDateTime;
entity.note = note;
entity.rentalItemId = rentalItemId;
entity.userAccountId = userAccountId;
return entity;
}
public static Reservation ofTransient(LocalDateTime startDateTime, LocalDateTime endDateTime, String note, int rentalItemId, int userAccountId) {
return of(null, startDateTime, endDateTime, note, rentalItemId, userAccountId);
}
// ----------------------------------------------------- original setter methods
public void setStartDateTime(LocalDateTime startDateTime) {
this.startDateTime = Objects.requireNonNull(startDateTime).truncatedTo(MINUTES);
}
public void setEndDateTime(LocalDateTime endDateTime) {
this.endDateTime = Objects.requireNonNull(endDateTime).truncatedTo(MINUTES);
}
// ----------------------------------------------------- service methods
public DateTimePeriod getReservePeriod() {
return new DateTimePeriod(startDateTime, endDateTime);
}
// ----------------------------------------------------- override methods
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
// ----------------------------------------------------- inner classes
public static class DateTimePeriod {
private LocalDateTime startDateTime;
private LocalDateTime endDateTime;
private Range<ChronoLocalDateTime<?>> period;
public DateTimePeriod(LocalDateTime startDateTime, LocalDateTime endDateTime) {
this.startDateTime = startDateTime;
this.endDateTime = endDateTime;
period = Range.between(startDateTime, endDateTime); }
public LocalDateTime getStartDateTime() {
return this.startDateTime;
}
public LocalDateTime getEndDateTime() {
return this.endDateTime;
}
public boolean isOverlappedBy(DateTimePeriod otherPeriod) {
return this.period.isOverlappedBy(otherPeriod.period);
}
}
}