/*
 *  Copyright (C) 2016 VSCT
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package com.vsct.dt.strowgr.admin.gui.configuration.scheduler;

import com.vsct.dt.strowgr.admin.core.EntryPointKeyDefaultImpl;
import com.vsct.dt.strowgr.admin.core.event.CorrelationId;
import com.vsct.dt.strowgr.admin.core.event.in.TryCommitCurrentConfigurationEvent;
import com.vsct.dt.strowgr.admin.core.event.in.TryCommitPendingConfigurationEvent;
import com.vsct.dt.strowgr.admin.core.repository.EntryPointRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Schedule entrypoint lifecycles.
 * <p>
 * Created by william_montaz on 11/02/2016.
 */
public class PeriodicScheduler<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(PeriodicScheduler.class);

    private final EntryPointRepository entryPointRepository;
    private final Consumer<T> consumer;
    private final Function<String, T> provider;
    private final long periodMilli;
    private volatile boolean stop = false;

    private final Thread automaticScheduler = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!stop) {
                try {
                    Thread.sleep(periodMilli);
                } catch (InterruptedException e) {
                    LOGGER.error("a sleep interruption", e);
                    return;
                }
                try {
                    for (String ep : entryPointRepository.getEntryPointsId()) {
                        consumer.accept(provider.apply(ep));
                    }
                } catch (Throwable t) {
                    LOGGER.error("PeriodicScheduler failed.", t);
                }
            }
        }
    });

    public PeriodicScheduler(EntryPointRepository entryPointRepository, Function<String, T> provider, Consumer<T> consumer, long periodMilli) {
        this.entryPointRepository = entryPointRepository;
        this.consumer = consumer;
        this.provider = provider;
        this.periodMilli = periodMilli;
    }

    public void start() {
        automaticScheduler.setDaemon(true);
        automaticScheduler.start();
    }

    public void stop() {
        stop = true;
    }

    public static PeriodicScheduler<TryCommitPendingConfigurationEvent> newPeriodicCommitPendingScheduler(EntryPointRepository repository, Consumer<TryCommitPendingConfigurationEvent> consumer, long period) {
        return new PeriodicScheduler<>(repository, ep -> new TryCommitPendingConfigurationEvent(CorrelationId.newCorrelationId(), new EntryPointKeyDefaultImpl(ep)), consumer, period);
    }

    public static PeriodicScheduler<TryCommitCurrentConfigurationEvent> newPeriodicCommitCurrentScheduler(EntryPointRepository entryPointRepository, Consumer<TryCommitCurrentConfigurationEvent> consumer, long period) {
        return new PeriodicScheduler<>(entryPointRepository, ep -> new TryCommitCurrentConfigurationEvent(CorrelationId.newCorrelationId(), new EntryPointKeyDefaultImpl(ep)), consumer, period);
    }

}

@@ -1078,16 +1078,147 @@
 ctory;%0A%0A
+import java.util.concurrent.Executors;%0Aimport java.util.concurrent.ScheduledExecutorService;%0Aimport java.util.concurrent.TimeUnit;%0A
 import j
@@ -1500,24 +1500,93 @@
 er.class);%0A%0A
+    private final ScheduledExecutorService scheduledExecutorService;%0A
     private 
@@ -1762,255 +1762,306 @@
 li;%0A
+%0A
     p
-rivate volatile boolean stop = false;%0A%0A    private final Thread automaticScheduler = new Thread(new Runnable() %7B%0A        @Override%0A        public void run() %7B%0A            while (!stop) %7B%0A                try %7B%0A                    Thread.sleep(
+ublic PeriodicScheduler(EntryPointRepository entryPointRepository, Function%3CString, T%3E provider, Consumer%3CT%3E consumer, long periodMilli) %7B%0A        this.entryPointRepository = entryPointRepository;%0A        this.consumer = consumer;%0A        this.provider = provider;%0A        this.periodMilli = 
 peri
@@ -2067,17 +2067,16 @@
 iodMilli
-)
 ;%0A      
@@ -2081,111 +2081,158 @@
     
-   
-     %7D catch (InterruptedException e) %7B
+scheduledExecutorService = Executors.newScheduledThreadPool(1);
 %0A    
+%7D%0A%0A
     
-            LOGGER.error(%22a sleep interruption%22, e);
+public void start() %7B%0A        scheduledExecutorService.scheduleAtFixedRate(
 %0A   
@@ -2248,38 +2248,20 @@
     
-    return;
+() -%3E %7B
 %0A    
-            %7D%0A
     
@@ -2298,16 +2298,20 @@
         
+  
+  
 for (Str
@@ -2386,16 +2386,20 @@
         
+    
 consumer
@@ -2439,34 +2439,42 @@
                 
+  
-%7D%0A
+  %7D%0A    
                 
@@ -2517,16 +2517,20 @@
         
+ 
+   
 LOGGER.e
@@ -2575,34 +2575,42 @@
                 
-%7D%0A
+    %7D%0A    
             %7D%0A  
@@ -2619,327 +2619,51 @@
     
-%7D%0A    %7D);%0A%0A    public PeriodicScheduler(EntryPointRepository entryPointRepository, Function%3CString, T%3E provider, Consumer%3CT%3E consumer, long periodMilli) %7B%0A        this.entryPointRepository = entryPointRepository;%0A        this.consumer = consumer;%0A        this.provider = provider;%0A        this.periodMilli = periodMilli
+        , 0, periodMilli, TimeUnit.SECONDS)
 ;%0A  
@@ -2677,35 +2677,34 @@
   public void st
-art
+op
 () %7B%0A        aut
@@ -2704,131 +2704,43 @@
     
-automaticScheduler.setDaemon(true);%0A        automaticScheduler.start();%0A    %7D%0A%0A    public void stop() %7B%0A        stop = true
+scheduledExecutorService.shutdown()
 ;%0A  

replace Thread.sleep by Executors scheduler thread pool