// Path: micro-core/src/main/java/sample/context/Timestamper.java
// public class Timestamper {
//     public static final String KeyDay = "system.businessDay.day";
// 
//     @Autowired(required = false)
//     private AppSettingHandler setting;
// 
//     private final Clock clock;
// 
//     public Timestamper() {
//         clock = Clock.systemDefaultZone();
//     }
// 
//     public Timestamper(final Clock clock) {
//         this.clock = clock;
//     }
// 
//     /** 営業日を返します。 */
//     public LocalDate day() {
//         return setting == null ? LocalDate.now(clock) : DateUtils.day(setting.setting(KeyDay).str());
//     }
// 
//     /** 日時を返します。 */
//     public LocalDateTime date() {
//         return LocalDateTime.now(clock);
//     }
// 
//     /** 営業日/日時を返します。 */
//     public TimePoint tp() {
//         return TimePoint.of(day(), date());
//     }
// 
//     /**
//      * 営業日を指定日へ進めます。
//      * <p>AppSettingHandlerを設定時のみ有効です。
//      * @param day 更新営業日
//      */
//     public Timestamper proceedDay(LocalDate day) {
//         if (setting != null)
//             setting.update(KeyDay, DateUtils.dayFormat(day));
//         return this;
//     }
// 
// }
// 
// Path: micro-core/src/main/java/sample/context/rest/RestActorSessionBindFilter.java
// public class RestActorSessionBindFilter extends GenericFilterBean {
//     
//     private final ActorSession session;
//     
//     public RestActorSessionBindFilter(ActorSession session) {
//         this.session = session;
//     }
// 
//     @Override
//     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
//             throws IOException, ServletException {
//         try {
//             String actorStr = ((HttpServletRequest)request).getHeader(RestActorSessionInterceptor.AttrActorSession);
//             Optional.ofNullable(actorStr).ifPresent((str) ->
//                 session.bind(RestActorSessionConverter.convert(str)));
//             chain.doFilter(request, response);
//         } finally {
//             session.unbind();
//         }
//     }
//     
// }


import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.health.*;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.*;
import org.springframework.transaction.PlatformTransactionManager;
import sample.context.Timestamper;
import sample.context.actor.ActorSession;
import sample.context.orm.DefaultRepository;
import sample.context.rest.RestActorSessionBindFilter;
import sample.model.*;
import sample.model.BusinessDayHandler.HolidayAccessor;
package sample;



/**
 * アプリケーションドメインのコンポーネント定義を表現します。
 */
@Configuration
@Import({ApplicationConfig.class})
public class MicroAppConfig {

    /** Domain 層のコンテナ管理を表現します。 */
    @Configuration
    static class DomainAutoConfig {
        
        /** データ生成ユーティリティ */
        @Bean
        @ConditionalOnProperty(prefix = DataFixtures.Prefix, name = "enabled", matchIfMissing = false)
        DataFixtures fixtures() {
            return new DataFixtures();
        }
        
        /** 休日情報アクセサ */
        @Bean
        HolidayAccessor holidayAccessor(
                DefaultRepository rep,
                @Qualifier(DefaultRepository.BeanNameTx)
                PlatformTransactionManager txm) {
            return new HolidayAccessor(txm, rep); //low: 定義側にスキーマ指定を委ねるときは外部から設定するアプローチで
        }
        
        /** 営業日ユーティリティ */
        @Bean
// Path: micro-core/src/main/java/sample/context/Timestamper.java
// public class Timestamper {
//     public static final String KeyDay = "system.businessDay.day";
// 
//     @Autowired(required = false)
//     private AppSettingHandler setting;
// 
//     private final Clock clock;
// 
//     public Timestamper() {
//         clock = Clock.systemDefaultZone();
//     }
// 
//     public Timestamper(final Clock clock) {
//         this.clock = clock;
//     }
// 
//     /** 営業日を返します。 */
//     public LocalDate day() {
//         return setting == null ? LocalDate.now(clock) : DateUtils.day(setting.setting(KeyDay).str());
//     }
// 
//     /** 日時を返します。 */
//     public LocalDateTime date() {
//         return LocalDateTime.now(clock);
//     }
// 
//     /** 営業日/日時を返します。 */
//     public TimePoint tp() {
//         return TimePoint.of(day(), date());
//     }
// 
//     /**
//      * 営業日を指定日へ進めます。
//      * <p>AppSettingHandlerを設定時のみ有効です。
//      * @param day 更新営業日
//      */
//     public Timestamper proceedDay(LocalDate day) {
//         if (setting != null)
//             setting.update(KeyDay, DateUtils.dayFormat(day));
//         return this;
//     }
// 
// }
// 
// Path: micro-core/src/main/java/sample/context/rest/RestActorSessionBindFilter.java
// public class RestActorSessionBindFilter extends GenericFilterBean {
//     
//     private final ActorSession session;
//     
//     public RestActorSessionBindFilter(ActorSession session) {
//         this.session = session;
//     }
// 
//     @Override
//     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
//             throws IOException, ServletException {
//         try {
//             String actorStr = ((HttpServletRequest)request).getHeader(RestActorSessionInterceptor.AttrActorSession);
//             Optional.ofNullable(actorStr).ifPresent((str) ->
//                 session.bind(RestActorSessionConverter.convert(str)));
//             chain.doFilter(request, response);
//         } finally {
//             session.unbind();
//         }
//     }
//     
// }


// Path: micro-app/src/main/java/sample/MicroAppConfig.java
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.health.*;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.*;
import org.springframework.transaction.PlatformTransactionManager;
import sample.context.Timestamper;
import sample.context.actor.ActorSession;
import sample.context.orm.DefaultRepository;
import sample.context.rest.RestActorSessionBindFilter;
import sample.model.*;
import sample.model.BusinessDayHandler.HolidayAccessor;

package sample;



/**
 * アプリケーションドメインのコンポーネント定義を表現します。
 */
@Configuration
@Import({ApplicationConfig.class})
public class MicroAppConfig {

    /** Domain 層のコンテナ管理を表現します。 */
    @Configuration
    static class DomainAutoConfig {
        
        /** データ生成ユーティリティ */
        @Bean
        @ConditionalOnProperty(prefix = DataFixtures.Prefix, name = "enabled", matchIfMissing = false)
        DataFixtures fixtures() {
            return new DataFixtures();
        }
        
        /** 休日情報アクセサ */
        @Bean
        HolidayAccessor holidayAccessor(
                DefaultRepository rep,
                @Qualifier(DefaultRepository.BeanNameTx)
                PlatformTransactionManager txm) {
            return new HolidayAccessor(txm, rep); //low: 定義側にスキーマ指定を委ねるときは外部から設定するアプローチで
        }
        
        /** 営業日ユーティリティ */
        @Bean
        BusinessDayHandler businessDayHandler(Timestamper time, HolidayAccessor holiday) {