package sample.context.audit; import java.time.*; import javax.persistence.*; import javax.validation.constraints.NotNull; import org.apache.commons.lang3.StringUtils; import org.hibernate.criterion.MatchMode; import lombok.*; import sample.ActionStatusType; import sample.context.Dto; import sample.context.orm.*; import sample.context.orm.Sort.SortOrder; import sample.model.constraints.*; import sample.util.DateUtils; /** * システムイベントの監査ログを表現します。 */ @Entity @Data @EqualsAndHashCode(callSuper = false) public class AuditEvent extends OrmActiveRecord<AuditEvent> { private static final long serialVersionUID = 1l; @Id @GeneratedValue private Long id; /** カテゴリ */ private String category; /** メッセージ */ private String message; /** 処理ステータス */ @Enumerated(EnumType.STRING) private ActionStatusType statusType; /** エラー事由 */ private String errorReason; /** 処理時間(msec) */ private Long time; /** 開始日時 */ @NotNull private LocalDateTime startDate; /** 終了日時(未完了時はnull) */ private LocalDateTime endDate; /** イベント監査ログを完了状態にします。 */ public AuditEvent finish(final SystemRepository rep) { LocalDateTime now = rep.dh().time().date(); setStatusType(ActionStatusType.Processed); setEndDate(now); setTime(DateUtils.between(startDate, endDate).get().toMillis()); return update(rep); } /** イベント監査ログを取消状態にします。 */ public AuditEvent cancel(final SystemRepository rep, String errorReason) { LocalDateTime now = rep.dh().time().date(); setStatusType(ActionStatusType.Cancelled); setErrorReason(StringUtils.abbreviate(errorReason, 250)); setEndDate(now); setTime(DateUtils.between(startDate, endDate).get().toMillis()); return update(rep); } /** イベント監査ログを例外状態にします。 */ public AuditEvent error(final SystemRepository rep, String errorReason) { LocalDateTime now = rep.dh().time().date(); setStatusType(ActionStatusType.Error); setErrorReason(StringUtils.abbreviate(errorReason, 250)); setEndDate(now); setTime(DateUtils.between(startDate, endDate).get().toMillis()); return update(rep); } /** イベント監査ログを登録します。 */ public static AuditEvent register(final SystemRepository rep, final RegAuditEvent p) { return p.create(rep.dh().time().date()).save(rep); } /** イベント監査ログを検索します。 */ public static PagingList<AuditEvent> find(final SystemRepository rep, final FindAuditEvent p) { return rep.tmpl().find(AuditEvent.class, (criteria) -> { return criteria .equal("category", p.category) .equal("statusType", p.statusType) .like(new String[] { "message", "errorReason" }, p.keyword, MatchMode.ANYWHERE) .between("startDate", p.fromDay.atStartOfDay(), DateUtils.dateTo(p.toDay)); }, p.page.sortIfEmpty(SortOrder.desc("startDate"))); } /** 検索パラメタ */ @Data @NoArgsConstructor @AllArgsConstructor public static class FindAuditEvent implements Dto { private static final long serialVersionUID = 1l; @NameEmpty private String category; @DescriptionEmpty private String keyword; private ActionStatusType statusType; @ISODate private LocalDate fromDay; @ISODate private LocalDate toDay; @NotNull private Pagination page = new Pagination(); } /** 登録パラメタ */ @Data @NoArgsConstructor @AllArgsConstructor public static class RegAuditEvent implements Dto { private static final long serialVersionUID = 1l; @NameEmpty private String category; private String message; public AuditEvent create(LocalDateTime now) { AuditEvent event = new AuditEvent(); event.setCategory(category); event.setMessage(message); event.setStatusType(ActionStatusType.Processing); event.setStartDate(now); return event; } public static RegAuditEvent of(String message) { return of("default", message); } public static RegAuditEvent of(String category, String message) { return new RegAuditEvent(category, message); } } }