[BP-843] feat: add cyclic reports controller
* added cyclic reports controller
* added report generation config dto
* added dozer mapping entry to map between ReportGenerationConfig
and ReportGenerationConfigDto
* added testcases for ReportGenerationConfigDto
Signed-off-by: Tobias Stummer <stummer@develop-group.de>
diff --git a/oKBereitschaftsplanungBackend/src/main/java/org/eclipse/openk/sp/controller/CyclicReportsController.java b/oKBereitschaftsplanungBackend/src/main/java/org/eclipse/openk/sp/controller/CyclicReportsController.java
new file mode 100644
index 0000000..a2550df
--- /dev/null
+++ b/oKBereitschaftsplanungBackend/src/main/java/org/eclipse/openk/sp/controller/CyclicReportsController.java
@@ -0,0 +1,286 @@
+/* *******************************************************************************
+ * Copyright (c) 2020 Basys GmbH
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * *******************************************************************************/
+package org.eclipse.openk.sp.controller;
+
+import java.io.File;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+
+import javax.annotation.PostConstruct;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import javax.ws.rs.core.Response;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.sp.controller.reports.ReportController;
+import org.eclipse.openk.sp.db.converter.EntityConverter;
+import org.eclipse.openk.sp.db.dao.CyclicReportGenerationConfigRepository;
+import org.eclipse.openk.sp.db.model.ReportGenerationConfig;
+import org.eclipse.openk.sp.dto.ReportGenerationConfigDto;
+import org.eclipse.openk.sp.dto.report.ReportDto;
+import org.eclipse.openk.sp.exceptions.SpErrorEntry;
+import org.eclipse.openk.sp.exceptions.SpException;
+import org.eclipse.openk.sp.exceptions.SpExceptionEnum;
+import org.eclipse.openk.sp.util.ArchiveHelper;
+import org.eclipse.openk.sp.util.MailHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@EnableScheduling
+@Transactional(rollbackFor = Exception.class)
+/** Class to handle automatic report generation and configuration. */
+public class CyclicReportsController extends AbstractController {
+
+ protected static final Logger LOGGER = Logger.getLogger(CyclicReportsController.class);
+
+ @Autowired
+ private CyclicReportGenerationConfigRepository automaticReportGenerationConfigRepository;
+
+ @Autowired
+ private MailHelper mailHelper;
+
+ @Autowired
+ private ArchiveHelper archiveHelper;
+
+ @Autowired
+ private EntityConverter entityConverter;
+
+ @Autowired
+ private ReportController reportController;
+
+ @Value("${report.cyclic.datePattern:yyyy-MM-dd}")
+ private String datePattern;
+
+ @Value("${report.cyclic.timePattern:HH-mm}")
+ private String timePattern;
+
+ @Value("${report.cyclic.weekPattern:'KW'ww}")
+ private String weekPattern;
+
+ @Value("${report.cyclic.archivePath:/opt/openk/reports/}")
+ private String archivePath;
+
+ @Value("${report.cyclic.slotDeltaMin:5}")
+ private int slotDeltaMin;
+
+ @Value("${report.cyclic.zoneName:Europe/Berlin}")
+ private String zoneName;
+
+ @Value("${report.cyclic.locale:de}")
+ private String locale;
+
+ @Value("${report.cyclic.sendReportMail:true}")
+ private boolean sendReportMail;
+
+ @Value("${report.cyclic.archiveReport:true}")
+ private boolean archiveReport;
+
+ private DateTimeFormatter datePatternFormatter;
+
+ private DateTimeFormatter timePatternFormatter;
+
+ private DateTimeFormatter weekPatternFormatter;
+
+ private ZoneId zoneId;
+
+ private ZoneId zoneIdUTC;
+
+
+ @PostConstruct
+ private void init() {
+ Locale l = new Locale(locale);
+ datePatternFormatter = DateTimeFormatter.ofPattern(datePattern).withLocale(l);
+ timePatternFormatter = DateTimeFormatter.ofPattern(timePattern).withLocale(l);
+ weekPatternFormatter = DateTimeFormatter.ofPattern(weekPattern).withLocale(l);
+ zoneId = ZoneId.of(zoneName);
+ zoneIdUTC = ZoneId.of("UTC");
+
+ }
+
+ public List<ReportGenerationConfigDto> getAllReportGenerationConfig() throws SpException {
+ List<ReportGenerationConfigDto> configs = new ArrayList<>();
+ for (ReportGenerationConfig cfg : automaticReportGenerationConfigRepository.findAll()) {
+ configs.add((ReportGenerationConfigDto) entityConverter.convertEntityToDto(cfg,
+ new ReportGenerationConfigDto()));
+ }
+ return configs;
+ }
+
+ public Response deleteReportGenerationConfig(Long configId) throws SpException {
+ Optional<ReportGenerationConfig> oConfig = automaticReportGenerationConfigRepository.findById(configId);
+ if (oConfig.isPresent()) {
+ automaticReportGenerationConfigRepository.delete(configId);
+ return Response.noContent().build();
+ }
+ SpErrorEntry ee = SpExceptionEnum.HTTP_NOT_FOUND_EXCEPTION.getEntry();
+ String msgParam = "Not Found. Report generation config with id: " + configId;
+ SpException spE = new SpException(ee.getCode(), null, ee.getMessage(), msgParam);
+ LOGGER.error(spE, spE);
+ throw spE;
+ }
+
+ public ReportGenerationConfigDto editReportGenerationConfig(Long configId,
+ ReportGenerationConfigDto reportGenerationConfig) throws SpException {
+ Optional<ReportGenerationConfig> oConfig = automaticReportGenerationConfigRepository.findById(configId);
+ if (oConfig.isPresent()) {
+ ReportGenerationConfig cfg = (ReportGenerationConfig) entityConverter
+ .convertDtoToEntity(reportGenerationConfig, new ReportGenerationConfig());
+ cfg.setId(configId);
+ automaticReportGenerationConfigRepository.save(cfg);
+ reportGenerationConfig.setId(configId);
+ return reportGenerationConfig;
+ }
+ SpErrorEntry ee = SpExceptionEnum.HTTP_NOT_FOUND_EXCEPTION.getEntry();
+ String msgParam = "Not Found. Report generation config with id: " + configId;
+ SpException spE = new SpException(ee.getCode(), null, ee.getMessage(), msgParam);
+ LOGGER.error(spE, spE);
+ throw spE;
+ }
+
+ public ReportGenerationConfigDto addReportGenerationConfig(ReportGenerationConfigDto reportGenerationConfig)
+ throws SpException {
+ ReportGenerationConfig newCfg = (ReportGenerationConfig) entityConverter
+ .convertDtoToEntity(reportGenerationConfig, new ReportGenerationConfig());
+ newCfg.setId(null);
+ ReportGenerationConfig savedCfg = automaticReportGenerationConfigRepository.save(newCfg);
+ return (ReportGenerationConfigDto) entityConverter.convertEntityToDto(savedCfg,
+ new ReportGenerationConfigDto());
+ }
+
+ protected File generateReport(ReportGenerationConfig reportCfg, LocalDateTime triggerDate) throws SpException {
+ ReportDto reportDto = new ReportDto();
+ reportDto.setReportName(reportCfg.getReportName());
+ reportDto.setPrintFormat(reportCfg.getPrintFormat().toLowerCase());
+ reportDto.setStatusId(reportCfg.getStatusId());
+
+ // calculate from and to date
+ LocalDateTime fromLocalDateTime = triggerDate.plusDays(reportCfg.getValidFromDayOffset())
+ .withHour(reportCfg.getValidFromHour()).withMinute(reportCfg.getValidFromMinute());
+ LocalDateTime toLocalDateTime = triggerDate.plusDays(reportCfg.getValidToDayOffset())
+ .withHour(reportCfg.getValidToHour()).withMinute(reportCfg.getValidToMinute());
+ Date fromDate = Date.from(fromLocalDateTime.atZone(zoneIdUTC).toInstant());
+ Date toDate = Date.from(toLocalDateTime.atZone(zoneIdUTC).toInstant());
+
+ reportDto.setValidFromDate(fromDate);
+ reportDto.setValidToDate(toDate);
+ reportDto.setStandByListId(reportCfg.getStandByListId());
+ return reportController.generateReport(reportDto);
+ }
+
+
+ protected void generateAndDistributeReports(LocalDateTime triggerTimeGreaterEqual,
+ LocalDateTime triggerTimeLowerEqual) {
+ List<ReportGenerationConfig> currentConfigs = getReportGenerationConfigs(triggerTimeGreaterEqual,
+ triggerTimeLowerEqual);
+ for (ReportGenerationConfig cfg : currentConfigs) {
+ LOGGER.info("Matching report generationg config: " + cfg.getName());
+ try {
+ LocalDateTime triggerDateTime = triggerTimeGreaterEqual.withHour(cfg.getTriggerHour())
+ .withMinute(cfg.getTriggerMinute());
+ File reportFile = generateReport(cfg, triggerDateTime);
+ String fileName = fileNameOfCfg(triggerDateTime, cfg);
+ storeReport(reportFile, fileName);
+ sendReport(reportFile, fileName, cfg, triggerDateTime);
+ } catch (Exception e) {
+ LOGGER.warn("Could not autogenerate and send report configuration with name: " + cfg.getName(), e);
+ }
+ }
+ }
+
+ protected void sendReport(File reportFile, String fileName, ReportGenerationConfig cfg, LocalDateTime triggerDateTime) {
+ if (!sendReportMail || cfg.getTo() == null || cfg.getTo().isEmpty()) {
+ return;
+ }
+ try {
+ MimeMessage mail = mailHelper.newMultipartMail();
+ String subject = placeholderReplacement(triggerDateTime, cfg.getSubject());
+ MailHelper.setSubject(mail, subject);
+ MailHelper.setToRecipients(mail, cfg.getTo());
+ String text = placeholderReplacement(triggerDateTime, cfg.getEmailText());
+ MailHelper.addText(mail, text);
+ MailHelper.addAttachment(mail, reportFile, fileName);
+ mailHelper.send(mail);
+ } catch (IOException | MessagingException e) {
+ LOGGER.warn("Could not send report mail with name: " + cfg.getName() + " - " + e.getMessage(), e);
+ }
+ }
+
+ private void storeReport(File reportFile, String fileName) {
+ if (!archiveReport) {
+ return;
+ }
+ String absPath = archivePath + File.separator + fileName;
+ try {
+ archiveHelper.copyFile(reportFile.getAbsolutePath(), absPath);
+ } catch (IOException e) {
+ LOGGER.warn("Could not store report file with name: " + fileName + " - " + e.getMessage(), e);
+ }
+ }
+
+ protected String fileNameOfCfg(LocalDateTime triggerDateTime, ReportGenerationConfig cfg) {
+ String fileName = cfg.getFileNamePattern() + "." + cfg.getPrintFormat().toLowerCase();
+ fileName = placeholderReplacement(triggerDateTime, fileName);
+ return fileName;
+ }
+
+ private String placeholderReplacement(LocalDateTime triggerDateTime, String orig) {
+ String triggerDateString = datePatternFormatter.format(triggerDateTime);
+ String triggerTimeString = timePatternFormatter.format(triggerDateTime);
+ String triggerWeekString = weekPatternFormatter.format(triggerDateTime);
+ String newString = orig.replace("{Date}", triggerDateString);
+ newString = newString.replace("{Time}", triggerTimeString);
+ newString = newString.replace("{Week}", triggerWeekString);
+ return newString;
+ }
+
+
+ protected List<ReportGenerationConfig> getReportGenerationConfigs(LocalDateTime triggerTimeGreaterEqual,
+ LocalDateTime triggerTimeLower) {
+ int weekDay = triggerTimeGreaterEqual.getDayOfWeek().getValue();
+ int hour = triggerTimeGreaterEqual.getHour();
+ int minuteGE = triggerTimeGreaterEqual.getMinute();
+ int minuteLE = triggerTimeLower.getMinute();
+ LOGGER.info("Search for report generation configs: " + weekDay + ", " + hour + ", " + minuteGE + ", " + minuteLE);
+ return automaticReportGenerationConfigRepository.findConfigs(weekDay, hour, minuteGE, minuteLE);
+ }
+
+ /**
+ * Checks cyclic report generation configuration for matching trigger time.
+ */
+ @Scheduled(cron = "${report.cyclic.checkCron:0 0/5 * * * ?}")
+ public void checkCyclicGenerationSlot() {
+ LOGGER.info("Check for automatic report generation");
+ LocalDateTime now = LocalDateTime.now(zoneId);
+ int slotNumber = now.getMinute() / slotDeltaMin;
+ LocalDateTime triggerTimeGreaterEqual = now.withMinute(slotNumber * slotDeltaMin);
+ LocalDateTime triggerTimeLowerEqual = triggerTimeGreaterEqual.plusMinutes(slotDeltaMin - 1L);
+ LOGGER.info("Check for automatic report generation - " + triggerTimeGreaterEqual);
+ generateAndDistributeReports(triggerTimeGreaterEqual, triggerTimeLowerEqual);
+
+
+
+ }
+
+}
diff --git a/oKBereitschaftsplanungBackend/src/main/java/org/eclipse/openk/sp/dto/ReportGenerationConfigDto.java b/oKBereitschaftsplanungBackend/src/main/java/org/eclipse/openk/sp/dto/ReportGenerationConfigDto.java
new file mode 100644
index 0000000..77aedca
--- /dev/null
+++ b/oKBereitschaftsplanungBackend/src/main/java/org/eclipse/openk/sp/dto/ReportGenerationConfigDto.java
@@ -0,0 +1,268 @@
+/* *******************************************************************************
+ * Copyright (c) 2020 Basys GmbH
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * *******************************************************************************/
+package org.eclipse.openk.sp.dto;
+
+import java.util.Set;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.eclipse.openk.sp.abstracts.AbstractDto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+/**
+ * The "ReportGenerationConfig" Data Transfer Object (DTO)
+ */
+@XmlRootElement(name = "ReportGenerationConfigDto")
+@JsonInclude(Include.NON_NULL)
+public class ReportGenerationConfigDto extends AbstractDto {
+
+ /**
+ * default serial id.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+
+ @NotNull(message = "Name is not set")
+ @Size(max = 256, message = "Name with max. 256 characters")
+ private String name;
+
+ @NotNull(message = "FileNamePattern is not set")
+ @Size(max = 128, message = "FileNamePattern with max. 128 characters")
+ private String fileNamePattern;
+
+ @NotNull(message = "Subject is not set")
+ @Size(max = 128, message = "Subject with max. 128 characters")
+ private String subject;
+
+ @NotNull(message = "To is not set")
+ private Set<String> to;
+
+ @NotNull(message = "PrintFormat is not set")
+ private String printFormat;
+
+ @NotNull(message = "ReportName is not set")
+ @Size(max = 256, message = "ReportName with max. 256 characters")
+ private String reportName;
+
+ @NotNull(message = "StandByListId is not set")
+ private Long standByListId;
+
+ @NotNull(message = "StatusId is not set")
+ @Min(0)
+ private Long statusId;
+
+ @Min(1)
+ @Max(7)
+ @NotNull(message = "TriggerWeekDay is not set")
+ private Integer triggerWeekDay;
+
+ @Min(0)
+ @Max(23)
+ @NotNull(message = "TriggerHour is not set")
+ private Integer triggerHour;
+
+ @Min(0)
+ @Max(59)
+ @NotNull(message = "TriggerMinute is not set")
+ private Integer triggerMinute;
+
+ @NotNull(message = "ValidFromDayOffset is not set")
+ private Integer validFromDayOffset;
+
+ @Min(0)
+ @Max(23)
+ @NotNull(message = "ValidFromHour is not set")
+ private Integer validFromHour;
+
+ @Min(0)
+ @Max(59)
+ @NotNull(message = "ValidFromMinute is not set")
+ private Integer validFromMinute;
+
+ @NotNull(message = "ValidToDayOffset is not set")
+ private Integer validToDayOffset;
+
+ @Min(0)
+ @Max(23)
+ @NotNull(message = "ValidToHour not set")
+ private Integer validToHour;
+
+ @Min(0)
+ @Max(59)
+ @NotNull(message = "ValidToMinute is not set")
+ private Integer validToMinute;
+
+
+ @NotNull(message = "EmailText is not set")
+ private String emailText;
+
+ public void setId(final Long id) {
+ this.id = id;
+ }
+
+ public Long getId() {
+ return this.id;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getFileNamePattern() {
+ return fileNamePattern;
+ }
+
+ public void setFileNamePattern(String fileNamePattern) {
+ this.fileNamePattern = fileNamePattern;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ public Set<String> getTo() {
+ return to;
+ }
+
+ public void setTo(Set<String> to) {
+ this.to = to;
+ }
+
+ public String getPrintFormat() {
+ return printFormat;
+ }
+
+ public void setPrintFormat(String printFormat) {
+ this.printFormat = printFormat;
+ }
+
+ public String getReportName() {
+ return reportName;
+ }
+
+ public void setReportName(String reportName) {
+ this.reportName = reportName;
+ }
+
+ public Long getStandByListId() {
+ return standByListId;
+ }
+
+ public void setStandByListId(Long standByListId) {
+ this.standByListId = standByListId;
+ }
+
+ public Long getStatusId() {
+ return statusId;
+ }
+
+ public void setStatusId(Long statusId) {
+ this.statusId = statusId;
+ }
+
+ public Integer getTriggerWeekDay() {
+ return triggerWeekDay;
+ }
+
+ public void setTriggerWeekDay(Integer triggerWeekDay) {
+ this.triggerWeekDay = triggerWeekDay;
+ }
+
+ public Integer getTriggerHour() {
+ return triggerHour;
+ }
+
+ public void setTriggerHour(Integer triggerHour) {
+ this.triggerHour = triggerHour;
+ }
+
+ public Integer getTriggerMinute() {
+ return triggerMinute;
+ }
+
+ public void setTriggerMinute(Integer triggerMinute) {
+ this.triggerMinute = triggerMinute;
+ }
+
+ public Integer getValidFromDayOffset() {
+ return validFromDayOffset;
+ }
+
+ public void setValidFromDayOffset(Integer validFromDayOffset) {
+ this.validFromDayOffset = validFromDayOffset;
+ }
+
+ public Integer getValidFromHour() {
+ return validFromHour;
+ }
+
+ public void setValidFromHour(Integer validFromHour) {
+ this.validFromHour = validFromHour;
+ }
+
+ public Integer getValidFromMinute() {
+ return validFromMinute;
+ }
+
+ public void setValidFromMinute(Integer validFromMinute) {
+ this.validFromMinute = validFromMinute;
+ }
+
+ public Integer getValidToDayOffset() {
+ return validToDayOffset;
+ }
+
+ public void setValidToDayOffset(Integer validToDayOffset) {
+ this.validToDayOffset = validToDayOffset;
+ }
+
+ public Integer getValidToHour() {
+ return validToHour;
+ }
+
+ public void setValidToHour(Integer validToHour) {
+ this.validToHour = validToHour;
+ }
+
+ public Integer getValidToMinute() {
+ return validToMinute;
+ }
+
+ public void setValidToMinute(Integer validToMinute) {
+ this.validToMinute = validToMinute;
+ }
+
+ public String getEmailText() {
+ return emailText;
+ }
+
+ public void setEmailText(String emailText) {
+ this.emailText = emailText;
+ }
+
+}
diff --git a/oKBereitschaftsplanungBackend/src/main/resources/dozer-mapping.xml b/oKBereitschaftsplanungBackend/src/main/resources/dozer-mapping.xml
index 8b924d3..0829b15 100644
--- a/oKBereitschaftsplanungBackend/src/main/resources/dozer-mapping.xml
+++ b/oKBereitschaftsplanungBackend/src/main/resources/dozer-mapping.xml
@@ -412,5 +412,10 @@
<b>locationId</b>
</field>
</mapping>
+
+ <mapping>
+ <class-a>org.eclipse.openk.sp.db.model.ReportGenerationConfig</class-a>
+ <class-b>org.eclipse.openk.sp.dto.ReportGenerationConfigDto</class-b>
+ </mapping>
</mappings>
\ No newline at end of file
diff --git a/oKBereitschaftsplanungBackend/src/test/java/org/eclipse/openk/sp/dto/ReportGenerationConfigDtoTest.java b/oKBereitschaftsplanungBackend/src/test/java/org/eclipse/openk/sp/dto/ReportGenerationConfigDtoTest.java
new file mode 100644
index 0000000..ebfdd8b
--- /dev/null
+++ b/oKBereitschaftsplanungBackend/src/test/java/org/eclipse/openk/sp/dto/ReportGenerationConfigDtoTest.java
@@ -0,0 +1,88 @@
+package org.eclipse.openk.sp.dto;
+
+import static org.junit.Assert.*;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+public class ReportGenerationConfigDtoTest {
+
+ @Test
+ public void testGetterAndSetter() {
+
+ ReportGenerationConfigDto config = new ReportGenerationConfigDto();
+
+ Integer triggerHour = 1;
+ Integer triggerMinute = 1;
+ Integer triggerWeekDay = 1;
+ Integer validFromDayOffset = -1;
+ Integer validFromHour = 2;
+ Integer validFromMinute = 30;
+ Integer validToDayOffset = 1;
+ Integer validToHour = 3;
+ Integer validToMinute = 35;
+ Long standByListId = 23L;
+ Long statusId = 4L;
+ String fileNamePattern = "pattern";
+ String name = "name";
+ String printFormat = "pdf";
+ String reportName = "REPORT_NAME";
+ String subject = "subject";
+ Set<String> to = new HashSet<>();
+
+
+ config.setFileNamePattern(fileNamePattern);
+ assertEquals(fileNamePattern, config.getFileNamePattern());
+
+ config.setName(name);
+ assertEquals(name, config.getName());
+
+ config.setPrintFormat(printFormat);
+ assertEquals(printFormat, config.getPrintFormat());
+
+ config.setReportName(reportName);
+ assertEquals(reportName, config.getReportName());
+
+ config.setStandByListId(standByListId);
+ assertEquals(standByListId, config.getStandByListId());
+
+ config.setStatusId(statusId);
+ assertEquals(statusId, config.getStatusId());
+
+ config.setSubject(subject);
+ assertEquals(subject, config.getSubject());
+
+ config.setTo(to);
+ assertEquals(to, config.getTo());
+
+ config.setTriggerHour(triggerHour);
+ assertEquals(triggerHour, config.getTriggerHour());
+
+ config.setTriggerMinute(triggerMinute);
+ assertEquals(triggerMinute, config.getTriggerMinute());
+
+ config.setTriggerWeekDay(triggerWeekDay);
+ assertEquals(triggerWeekDay, config.getTriggerWeekDay());
+
+ config.setValidFromDayOffset(validFromDayOffset);
+ assertEquals(validFromDayOffset, config.getValidFromDayOffset());
+
+ config.setValidFromHour(validFromHour);
+ assertEquals(validFromHour, config.getValidFromHour());
+
+ config.setValidFromMinute(validFromMinute);
+ assertEquals(validFromMinute, config.getValidFromMinute());
+
+ config.setValidToDayOffset(validToDayOffset);
+ assertEquals(validToDayOffset, config.getValidToDayOffset());
+
+ config.setValidToHour(validToHour);
+ assertEquals(validToHour, config.getValidToHour());
+
+ config.setValidToMinute(validToMinute);
+ assertEquals(validToMinute, config.getValidToMinute());
+ }
+
+}