// Path: src/main/java/org/chorem/ecd/service/JsonService.java
// @ApplicationScoped
// public class JsonService implements ResponseTransformer {
// 
//     private Gson gson;
// 
//     @Override
//     public String render(Object obj) {
//         return getGson().toJson(obj);
//     }
// 
//     public Gson getGson() {
//         if (gson == null) {
//             GsonBuilder gsonBuilder = new GsonBuilder();
//             gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter());
//             gson = gsonBuilder.create();
//         }
//         return gson;
//     }
// 
//     public void saveToJson(Object obj, Path path) throws IOException {
//         String json = getGson().toJson(obj);
//         Files.createDirectories(path.getParent());
//         Files.write(path, json.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
// 
//     }
// 
//     public <T> T loadFromJson(Class<T> type, Path path) throws IOException {
//         if (Files.exists(path)) {
//             String json = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
//             return getGson().fromJson(json, type);
//         } else {
//             return null;
//         }
//     }
// 
//     private static final class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {
//         private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// 
//         @Override
//         public LocalDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
//             return FORMATTER.parse(jsonElement.getAsString(), LocalDateTime::from);
//         }
// 
//         @Override
//         public JsonElement serialize(LocalDateTime localDateTime, Type type, JsonSerializationContext context) {
//             return new JsonPrimitive(FORMATTER.format(localDateTime));
//         }
//     }
// }
// 
// Path: src/main/java/org/chorem/ecd/EcdConfig.java
// @ApplicationScoped
// public class EcdConfig {
// 
//     private static final Logger logger = LoggerFactory.getLogger(EcdConfig.class);
// 
//     private final Properties props;
// 
//     public static final String STREAMS_DIR = "streams";
//     public static final String NEWS_DIR = "news";
//     public static final String WEATHER_DIR = "weather";
// 
//     public EcdConfig() {
//         props = new Properties();
//         try {
//             props.load(getClass().getClassLoader().getResourceAsStream("ecd.properties"));
//         } catch (IOException e) {
//             logger.error(e.getMessage(), e);
//         }
//     }
// 
//     public String getDataSourceUrl() {
//         return props.getProperty("ecd.datasource.url");
//     }
// 
//     public String getDataSourceLogin() {
//         return props.getProperty("ecd.datasource.login");
//     }
// 
//     public String getDataSourcePwd() {
//         return props.getProperty("ecd.datasource.pwd");
//     }
// 
//     public String getApiPathPrefix() {
//         return "/api/ecd";
//     }
// 
//     public String getMediaPathPrefix() {
//         return "/media/ecd";
//     }
// 
//     public String getDataDir() {
//         return props.getProperty("ecd.data.dir");
//     }
// 
//     public String getUploadDir() { return props.getProperty("ecd.upload.dir"); }
// 
//     public String getUnoconvCmd() {
//         return props.getProperty("ecd.cmd.unoconv");
//     }
// 
//     public String getResizeCmd() {
//         return props.getProperty("ecd.cmd.resize");
//     }
// 
//     public String getLocationSearchUrlFormat() {
//         return props.getProperty("ecd.location.searchUrlFormat");
//     }
// 
//     public Integer getDefaultStreamTiming() {
//         return Integer.valueOf(props.getProperty("ecd.default.streamTiming"));
//     }
// 
//     public Path getStreamsPath() {
//         return Paths.get(getDataDir(), STREAMS_DIR);
//     }
// 
//     public Path getAggregatedNewsPath() {
//         return Paths.get(getDataDir(), NEWS_DIR, "aggregated.json");
//     }
// 
//     public Path getWeatherForecastPath() {
//         return Paths.get(getDataDir(), WEATHER_DIR, "forecast.json");
//     }
// 
// }


import org.chorem.ecd.service.JsonService;
import org.chorem.ecd.EcdConfig;
import java.util.concurrent.TimeUnit;
package org.chorem.ecd.task;



/**
 * @author Julien Gaston (gaston@codelutin.com)
 */
public abstract class EcdPeriodicTask implements Runnable {

    protected EcdConfig config;

// Path: src/main/java/org/chorem/ecd/service/JsonService.java
// @ApplicationScoped
// public class JsonService implements ResponseTransformer {
// 
//     private Gson gson;
// 
//     @Override
//     public String render(Object obj) {
//         return getGson().toJson(obj);
//     }
// 
//     public Gson getGson() {
//         if (gson == null) {
//             GsonBuilder gsonBuilder = new GsonBuilder();
//             gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter());
//             gson = gsonBuilder.create();
//         }
//         return gson;
//     }
// 
//     public void saveToJson(Object obj, Path path) throws IOException {
//         String json = getGson().toJson(obj);
//         Files.createDirectories(path.getParent());
//         Files.write(path, json.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
// 
//     }
// 
//     public <T> T loadFromJson(Class<T> type, Path path) throws IOException {
//         if (Files.exists(path)) {
//             String json = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
//             return getGson().fromJson(json, type);
//         } else {
//             return null;
//         }
//     }
// 
//     private static final class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {
//         private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// 
//         @Override
//         public LocalDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
//             return FORMATTER.parse(jsonElement.getAsString(), LocalDateTime::from);
//         }
// 
//         @Override
//         public JsonElement serialize(LocalDateTime localDateTime, Type type, JsonSerializationContext context) {
//             return new JsonPrimitive(FORMATTER.format(localDateTime));
//         }
//     }
// }
// 
// Path: src/main/java/org/chorem/ecd/EcdConfig.java
// @ApplicationScoped
// public class EcdConfig {
// 
//     private static final Logger logger = LoggerFactory.getLogger(EcdConfig.class);
// 
//     private final Properties props;
// 
//     public static final String STREAMS_DIR = "streams";
//     public static final String NEWS_DIR = "news";
//     public static final String WEATHER_DIR = "weather";
// 
//     public EcdConfig() {
//         props = new Properties();
//         try {
//             props.load(getClass().getClassLoader().getResourceAsStream("ecd.properties"));
//         } catch (IOException e) {
//             logger.error(e.getMessage(), e);
//         }
//     }
// 
//     public String getDataSourceUrl() {
//         return props.getProperty("ecd.datasource.url");
//     }
// 
//     public String getDataSourceLogin() {
//         return props.getProperty("ecd.datasource.login");
//     }
// 
//     public String getDataSourcePwd() {
//         return props.getProperty("ecd.datasource.pwd");
//     }
// 
//     public String getApiPathPrefix() {
//         return "/api/ecd";
//     }
// 
//     public String getMediaPathPrefix() {
//         return "/media/ecd";
//     }
// 
//     public String getDataDir() {
//         return props.getProperty("ecd.data.dir");
//     }
// 
//     public String getUploadDir() { return props.getProperty("ecd.upload.dir"); }
// 
//     public String getUnoconvCmd() {
//         return props.getProperty("ecd.cmd.unoconv");
//     }
// 
//     public String getResizeCmd() {
//         return props.getProperty("ecd.cmd.resize");
//     }
// 
//     public String getLocationSearchUrlFormat() {
//         return props.getProperty("ecd.location.searchUrlFormat");
//     }
// 
//     public Integer getDefaultStreamTiming() {
//         return Integer.valueOf(props.getProperty("ecd.default.streamTiming"));
//     }
// 
//     public Path getStreamsPath() {
//         return Paths.get(getDataDir(), STREAMS_DIR);
//     }
// 
//     public Path getAggregatedNewsPath() {
//         return Paths.get(getDataDir(), NEWS_DIR, "aggregated.json");
//     }
// 
//     public Path getWeatherForecastPath() {
//         return Paths.get(getDataDir(), WEATHER_DIR, "forecast.json");
//     }
// 
// }


// Path: src/main/java/org/chorem/ecd/task/EcdPeriodicTask.java
import org.chorem.ecd.service.JsonService;
import org.chorem.ecd.EcdConfig;
import java.util.concurrent.TimeUnit;

package org.chorem.ecd.task;



/**
 * @author Julien Gaston (gaston@codelutin.com)
 */
public abstract class EcdPeriodicTask implements Runnable {

    protected EcdConfig config;

    protected JsonService jsonService;