cleanup and unit tests
This commit is contained in:
@@ -50,14 +50,6 @@ public class QueryService {
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T callNamedQueryList(String namedQuery, Param... objects) {
|
||||
Query query = eManager.createNamedQuery(namedQuery);
|
||||
for (Param param : objects) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return (T) query.getResultList();
|
||||
}
|
||||
|
||||
public int callNamedQueryUpdate(String namedQuery, Param... objects) {
|
||||
Query query = eManager.createNamedQuery(namedQuery);
|
||||
for (Param param : objects) {
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.service;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.ejb.LocalBean;
|
||||
@@ -17,6 +13,7 @@ import jakarta.persistence.criteria.*;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.model.Customer;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.model.Picture;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.query.Param;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.utils.CalendarUtil;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.utils.PdfUtils;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerListValue;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
|
||||
@@ -35,11 +32,13 @@ import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerValue;
|
||||
@LocalBean
|
||||
@PermitAll
|
||||
public class CustomerPictureService extends AbstractService {
|
||||
private static final Log LOG = LogFactory.getLog(CustomerPictureService.class);
|
||||
|
||||
@Inject
|
||||
private PdfUtils pdfUtils;
|
||||
|
||||
@Inject
|
||||
private CalendarUtil calendarUtil;
|
||||
|
||||
public boolean addCustomerPicture(CustomerPictureValue customerPictureValue) {
|
||||
Optional<Customer> customerOpt = queryService.callNamedQuerySingleResult(Customer.FIND_BY_NUMBER, new Param(Customer.PARAM_NUMBER, customerPictureValue.customerNumber()));
|
||||
Customer customer = customerOpt.orElseGet(() -> new Customer.Builder().customerNumber(customerPictureValue.customerNumber()).name(customerPictureValue.pharmacyName())
|
||||
@@ -78,23 +77,10 @@ public class CustomerPictureService extends AbstractService {
|
||||
if (StringUtils.isNotBlank(queryStr)) {
|
||||
|
||||
// check if it contains a date
|
||||
Date date = null;
|
||||
try {
|
||||
date = DateUtils.parseDate(queryStr, Locale.GERMAN, "dd.MM.yyyy", "d.M.yyyy", "dd.MM.yy", "d. MMMM yyyy", "dd MMMM yyyy", "dd-MM-yyyy");
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
Date startOfDay = cal.getTime();
|
||||
|
||||
cal.set(Calendar.HOUR_OF_DAY, 23);
|
||||
cal.set(Calendar.MINUTE, 59);
|
||||
cal.set(Calendar.SECOND, 59);
|
||||
cal.set(Calendar.MILLISECOND, 999);
|
||||
Date endOfDay = cal.getTime();
|
||||
Date date = calendarUtil.parse(queryStr);
|
||||
if (date != null) {
|
||||
Date startOfDay = calendarUtil.getStartOfDay(date);
|
||||
Date endOfDay = calendarUtil.getEndOfDay(date);
|
||||
|
||||
Fetch<Customer, Picture> picturesFetch = customerRoot.fetch("pictures", JoinType.LEFT);
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -103,11 +89,7 @@ public class CustomerPictureService extends AbstractService {
|
||||
var predicateDate = builder.between(pictures.get("pictureDate"), startOfDay, endOfDay);
|
||||
predicates.add(predicateDate);
|
||||
|
||||
} catch (ParseException e) {
|
||||
LOG.trace("Failed to find date in queryStr " + queryStr);
|
||||
}
|
||||
|
||||
if (date == null) {
|
||||
} else {
|
||||
String param = "%" + StringUtils.trimToEmpty(queryStr).toLowerCase() + "%";
|
||||
var predicateName = builder.like(builder.lower(customerRoot.get("name")), param);
|
||||
var predicateNr = builder.like(builder.lower(customerRoot.get("customerNumber")), param);
|
||||
@@ -123,8 +105,6 @@ public class CustomerPictureService extends AbstractService {
|
||||
criteriaQuery = criteriaQuery.where(builder.and(predicates.toArray(new Predicate[0])));
|
||||
}
|
||||
|
||||
//criteriaQuery = criteriaQuery.orderBy(builder.asc(builder.lower(customerRoot.get("name")))); //FIXME: this causes errors
|
||||
|
||||
TypedQuery<Customer> typedQuery = entityManager.createQuery(criteriaQuery);
|
||||
List<Customer> customers = typedQuery.getResultList();
|
||||
customers.forEach(c -> c.getPictures().size());
|
||||
@@ -143,14 +123,14 @@ public class CustomerPictureService extends AbstractService {
|
||||
public byte[] getExport(Long id, Long pictureId) {
|
||||
Customer customer = entityManager.find(Customer.class, id);
|
||||
if (customer == null) {
|
||||
return null;
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
List<Picture> pictures = customer.getPictures().stream().sorted((x, y) -> x.getPictureDate().compareTo(y.getPictureDate())).toList();
|
||||
|
||||
if (pictureId != null) {
|
||||
Optional<Picture> pictureOpt = customer.getPictures().stream().filter(p -> p.getPictureId().equals(pictureId)).findFirst();
|
||||
pictures = pictureOpt.map(p -> Arrays.asList(p)).orElse(pictures);
|
||||
pictures = pictureOpt.map(Arrays::asList).orElse(pictures);
|
||||
}
|
||||
|
||||
return pdfUtils.createPdf(customer, pictures);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.service;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -52,9 +50,8 @@ public class PictureService extends AbstractService {
|
||||
public byte[] getImage(Long id, int size) {
|
||||
try {
|
||||
Picture entity = entityManager.getReference(Picture.class, id);
|
||||
|
||||
String base64 = entity.getImage();
|
||||
return Base64.getDecoder().decode(base64);
|
||||
return imageUtil.getImage(base64, size);
|
||||
} catch (EntityNotFoundException e) {
|
||||
LOG.warn("Failed to get image for id " + id, e);
|
||||
ejbContext.setRollbackOnly();
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.utils;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 3 Feb 2026
|
||||
*/
|
||||
|
||||
public class CalendarUtil {
|
||||
private static final Log LOG = LogFactory.getLog(CalendarUtil.class);
|
||||
private static int HOUR_OF_DAY = 23;
|
||||
private static int MINUTE = 59;
|
||||
private static int SECOND = 59;
|
||||
private static int MILLISECOND = 999;
|
||||
|
||||
public Date parse(String query) {
|
||||
try {
|
||||
return DateUtils.parseDate(query, Locale.GERMAN, "dd.MM.yyyy", "d.M.yyyy", "dd.MM.yy", "d. MMMM yyyy", "dd MMMM yyyy", "dd-MM-yyyy");
|
||||
} catch (ParseException e) {
|
||||
LOG.trace("Failed to find date in queryStr " + query);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Date getStartOfDay(Date date) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public Date getEndOfDay(Date date) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
cal.set(Calendar.HOUR_OF_DAY, HOUR_OF_DAY);
|
||||
|
||||
cal.set(Calendar.MINUTE, MINUTE);
|
||||
cal.set(Calendar.SECOND, SECOND);
|
||||
cal.set(Calendar.MILLISECOND, MILLISECOND);
|
||||
return cal.getTime();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.utils;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 3 Feb 2026
|
||||
*/
|
||||
|
||||
public class EvaluationUtil {
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 1;
|
||||
|
||||
public boolean isValid(Integer value) {
|
||||
return (value == null || value < MIN_VALUE || value > MAX_VALUE);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,18 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jboss.resteasy.annotations.GZIP;
|
||||
import org.wildfly.security.auth.server.SecurityIdentity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ejb.EJB;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.service.CustomerPictureService;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.utils.LoginUtils;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.jackson.JsonSchemaValidate;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
|
||||
|
||||
@@ -37,27 +28,17 @@ import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
|
||||
@RequestScoped
|
||||
@Path("customer-picture")
|
||||
public class CustomerPictureResource {
|
||||
private static final Log LOG = LogFactory.getLog(CustomerPictureResource.class);
|
||||
|
||||
|
||||
@EJB
|
||||
private CustomerPictureService customerPictureService;
|
||||
|
||||
@Inject
|
||||
private LoginUtils loginUtils;
|
||||
|
||||
@GZIP
|
||||
@POST
|
||||
@Path("")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Add Customer Image to database")
|
||||
@ApiResponse(responseCode = "200", description = "Add successfull")
|
||||
public Response doAddCustomerPicture(@Context HttpServletRequest httpServletRequest, @JsonSchemaValidate("schema/customer_picture_add.json") CustomerPictureValue customerPictureValue) {
|
||||
/*Optional<SecurityIdentity> identity = loginUtils.authenticate(httpServletRequest);
|
||||
if (identity.isEmpty()) {
|
||||
LOG.debug("identity empty login invalid");
|
||||
return Response.status(Status.UNAUTHORIZED).build();
|
||||
}
|
||||
*/
|
||||
public Response doAddCustomerPicture(@JsonSchemaValidate("schema/customer_picture_add.json") CustomerPictureValue customerPictureValue) {
|
||||
boolean success = customerPictureService.addCustomerPicture(customerPictureValue);
|
||||
return success ? Response.ok().build() : Response.status(Status.BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class CustomerResource {
|
||||
LOG.debug("Create export for customer " + id + " with optional param " + pictureId);
|
||||
byte[] pdf = customerPictureService.getExport(id, pictureId);
|
||||
|
||||
if (pdf == null) {
|
||||
if (pdf.length == 0) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,14 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ejb.EJB;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.ResponseBuilder;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import jakarta.ws.rs.core.StreamingOutput;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.service.PictureService;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.utils.EvaluationUtil;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.utils.StorageUtils.StorageState;
|
||||
|
||||
/**
|
||||
@@ -34,6 +36,10 @@ public class PictureResource {
|
||||
|
||||
@EJB
|
||||
private PictureService pictureService;
|
||||
|
||||
@Inject
|
||||
private EvaluationUtil evaluationUtil;
|
||||
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@@ -52,7 +58,7 @@ public class PictureResource {
|
||||
@Operation(summary = "Update evaluation for picture data to database")
|
||||
@ApiResponse(responseCode = "200", description = "Task successfully updated")
|
||||
public Response doUpdateEvaluation(@PathParam("id") Long id, @QueryParam("evaluation") Integer value) {
|
||||
if (value == null || value < 1 || value > 3) {
|
||||
if (!evaluationUtil.isValid(value)) {
|
||||
return Response.status(Status.BAD_REQUEST).build();
|
||||
}
|
||||
StorageState state = pictureService.updateEvaluationStatus(id, value);
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 3 Feb 2026
|
||||
*/
|
||||
class CalendarUtilTest {
|
||||
|
||||
private CalendarUtil calendarUtil;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
calendarUtil = new CalendarUtil();
|
||||
}
|
||||
|
||||
// --- parse ---
|
||||
|
||||
@Test
|
||||
void parse_ddMMyyyyDot_returnsDate() {
|
||||
Date result = calendarUtil.parse("15.03.2026");
|
||||
|
||||
assertNotNull(result);
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(15, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH));
|
||||
assertEquals(2026, cal.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_dMyyyyDot_returnsDate() {
|
||||
Date result = calendarUtil.parse("5.3.2026");
|
||||
|
||||
assertNotNull(result);
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(5, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH));
|
||||
assertEquals(2026, cal.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_ddMMyy_returnsDate() {
|
||||
Date result = calendarUtil.parse("15.03.26");
|
||||
|
||||
assertNotNull(result);
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(15, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_ddMMyyyyDash_returnsDate() {
|
||||
Date result = calendarUtil.parse("15-03-2026");
|
||||
|
||||
assertNotNull(result);
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(15, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH));
|
||||
assertEquals(2026, cal.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_germanMonthName_dMMMMyyyy_returnsDate() {
|
||||
Date result = calendarUtil.parse("5. Januar 2026");
|
||||
|
||||
assertNotNull(result);
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(5, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(Calendar.JANUARY, cal.get(Calendar.MONTH));
|
||||
assertEquals(2026, cal.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_germanMonthName_ddMMMMyyyy_returnsDate() {
|
||||
Date result = calendarUtil.parse("15 Dezember 2025");
|
||||
|
||||
assertNotNull(result);
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(15, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(Calendar.DECEMBER, cal.get(Calendar.MONTH));
|
||||
assertEquals(2025, cal.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_invalidString_returnsNull() {
|
||||
assertNull(calendarUtil.parse("not a date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_emptyString_returnsNull() {
|
||||
assertNull(calendarUtil.parse(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_null_throwsException() {
|
||||
assertThrows(IllegalArgumentException.class, () -> calendarUtil.parse(null));
|
||||
}
|
||||
|
||||
// --- getStartOfDay ---
|
||||
|
||||
@Test
|
||||
void getStartOfDay_returnsDateAtMidnight() {
|
||||
Calendar input = Calendar.getInstance();
|
||||
input.set(2026, Calendar.MARCH, 15, 14, 30, 45);
|
||||
input.set(Calendar.MILLISECOND, 500);
|
||||
|
||||
Date result = calendarUtil.getStartOfDay(input.getTime());
|
||||
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(2026, cal.get(Calendar.YEAR));
|
||||
assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH));
|
||||
assertEquals(15, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(0, cal.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(0, cal.get(Calendar.MINUTE));
|
||||
assertEquals(0, cal.get(Calendar.SECOND));
|
||||
assertEquals(0, cal.get(Calendar.MILLISECOND));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStartOfDay_alreadyMidnight_returnsSameTime() {
|
||||
Calendar input = Calendar.getInstance();
|
||||
input.set(2026, Calendar.JANUARY, 1, 0, 0, 0);
|
||||
input.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Date result = calendarUtil.getStartOfDay(input.getTime());
|
||||
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(0, cal.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(0, cal.get(Calendar.MINUTE));
|
||||
assertEquals(0, cal.get(Calendar.SECOND));
|
||||
assertEquals(0, cal.get(Calendar.MILLISECOND));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStartOfDay_endOfDay_returnsStartOfSameDay() {
|
||||
Calendar input = Calendar.getInstance();
|
||||
input.set(2026, Calendar.JUNE, 20, 23, 59, 59);
|
||||
input.set(Calendar.MILLISECOND, 999);
|
||||
|
||||
Date result = calendarUtil.getStartOfDay(input.getTime());
|
||||
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(20, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(0, cal.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(0, cal.get(Calendar.MINUTE));
|
||||
assertEquals(0, cal.get(Calendar.SECOND));
|
||||
assertEquals(0, cal.get(Calendar.MILLISECOND));
|
||||
}
|
||||
|
||||
// --- getEndOfDay ---
|
||||
|
||||
@Test
|
||||
void getEndOfDay_returnsDateAt235959999() {
|
||||
Calendar input = Calendar.getInstance();
|
||||
input.set(2026, Calendar.MARCH, 15, 10, 0, 0);
|
||||
input.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Date result = calendarUtil.getEndOfDay(input.getTime());
|
||||
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(2026, cal.get(Calendar.YEAR));
|
||||
assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH));
|
||||
assertEquals(15, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(23, cal.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(59, cal.get(Calendar.MINUTE));
|
||||
assertEquals(59, cal.get(Calendar.SECOND));
|
||||
assertEquals(999, cal.get(Calendar.MILLISECOND));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getEndOfDay_fromMidnight_returnsEndOfSameDay() {
|
||||
Calendar input = Calendar.getInstance();
|
||||
input.set(2026, Calendar.JANUARY, 1, 0, 0, 0);
|
||||
input.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Date result = calendarUtil.getEndOfDay(input.getTime());
|
||||
|
||||
Calendar cal = toCalendar(result);
|
||||
assertEquals(1, cal.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(23, cal.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(59, cal.get(Calendar.MINUTE));
|
||||
assertEquals(59, cal.get(Calendar.SECOND));
|
||||
assertEquals(999, cal.get(Calendar.MILLISECOND));
|
||||
}
|
||||
|
||||
// --- startOfDay / endOfDay consistency ---
|
||||
|
||||
@Test
|
||||
void startOfDay_isBeforeEndOfDay() {
|
||||
Date now = new Date();
|
||||
|
||||
Date start = calendarUtil.getStartOfDay(now);
|
||||
Date end = calendarUtil.getEndOfDay(now);
|
||||
|
||||
assertTrue(start.before(end));
|
||||
}
|
||||
|
||||
@Test
|
||||
void startAndEnd_preserveSameDay() {
|
||||
Calendar input = Calendar.getInstance();
|
||||
input.set(2026, Calendar.JULY, 4, 12, 0, 0);
|
||||
|
||||
Date start = calendarUtil.getStartOfDay(input.getTime());
|
||||
Date end = calendarUtil.getEndOfDay(input.getTime());
|
||||
|
||||
Calendar startCal = toCalendar(start);
|
||||
Calendar endCal = toCalendar(end);
|
||||
assertEquals(startCal.get(Calendar.YEAR), endCal.get(Calendar.YEAR));
|
||||
assertEquals(startCal.get(Calendar.MONTH), endCal.get(Calendar.MONTH));
|
||||
assertEquals(startCal.get(Calendar.DAY_OF_MONTH), endCal.get(Calendar.DAY_OF_MONTH));
|
||||
}
|
||||
|
||||
private Calendar toCalendar(Date date) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
return cal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 3 Feb 2026
|
||||
*/
|
||||
class EvaluationUtilTest {
|
||||
|
||||
private EvaluationUtil evaluationUtil;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
evaluationUtil = new EvaluationUtil();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_null_returnsTrue() {
|
||||
assertTrue(evaluationUtil.isValid(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_zero_returnsTrue() {
|
||||
assertTrue(evaluationUtil.isValid(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_negativeValue_returnsTrue() {
|
||||
assertTrue(evaluationUtil.isValid(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_one_returnsFalse() {
|
||||
assertFalse(evaluationUtil.isValid(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_two_returnsTrue() {
|
||||
assertTrue(evaluationUtil.isValid(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_three_returnsTrue() {
|
||||
assertTrue(evaluationUtil.isValid(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValid_largeValue_returnsTrue() {
|
||||
assertTrue(evaluationUtil.isValid(100));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 3 Feb 2026
|
||||
*/
|
||||
class ImageUtilTest {
|
||||
|
||||
private ImageUtil imageUtil;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
imageUtil = new ImageUtil();
|
||||
}
|
||||
|
||||
// --- Size 1: original ---
|
||||
|
||||
@Test
|
||||
void getImage_size1_returnsOriginalBytes() {
|
||||
String base64 = createTestImageBase64(800, 600);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 1);
|
||||
|
||||
assertArrayEquals(original, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size1_largeImage_returnsOriginalBytes() {
|
||||
String base64 = createTestImageBase64(2000, 1500);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 1);
|
||||
|
||||
assertArrayEquals(original, result);
|
||||
}
|
||||
|
||||
// --- Size 2: normal (web, max 1200px) ---
|
||||
|
||||
@Test
|
||||
void getImage_size2_largeImage_resizesToMaxWidth1200() throws IOException {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
BufferedImage resized = ImageIO.read(new ByteArrayInputStream(result));
|
||||
assertEquals(1200, resized.getWidth());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size2_largeImage_preservesAspectRatio() throws IOException {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
BufferedImage resized = ImageIO.read(new ByteArrayInputStream(result));
|
||||
assertEquals(1200, resized.getWidth());
|
||||
assertEquals(800, resized.getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size2_largeImage_resultIsSmallerThanOriginal() {
|
||||
String base64 = createNoisyImageBase64(2400, 1600);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
assertTrue(result.length < original.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size2_smallImage_returnsOriginal() {
|
||||
String base64 = createTestImageBase64(800, 600);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
assertArrayEquals(original, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size2_exactMaxWidth_returnsOriginal() {
|
||||
String base64 = createTestImageBase64(1200, 900);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
assertArrayEquals(original, result);
|
||||
}
|
||||
|
||||
// --- Size 3: thumbnail (max 200px) ---
|
||||
|
||||
@Test
|
||||
void getImage_size3_largeImage_resizesToMaxWidth200() throws IOException {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 3);
|
||||
|
||||
BufferedImage resized = ImageIO.read(new ByteArrayInputStream(result));
|
||||
assertEquals(200, resized.getWidth());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size3_largeImage_preservesAspectRatio() throws IOException {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 3);
|
||||
|
||||
BufferedImage resized = ImageIO.read(new ByteArrayInputStream(result));
|
||||
assertEquals(200, resized.getWidth());
|
||||
assertEquals(133, resized.getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size3_largeImage_resultIsSmallerThanNormal() {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] normal = imageUtil.getImage(base64, 2);
|
||||
byte[] thumbnail = imageUtil.getImage(base64, 3);
|
||||
|
||||
assertTrue(thumbnail.length < normal.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size3_smallImage_returnsOriginal() {
|
||||
String base64 = createTestImageBase64(150, 100);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 3);
|
||||
|
||||
assertArrayEquals(original, result);
|
||||
}
|
||||
|
||||
// --- Default size ---
|
||||
|
||||
@Test
|
||||
void getImage_unknownSize_returnsOriginalBytes() {
|
||||
String base64 = createTestImageBase64(800, 600);
|
||||
byte[] original = Base64.getDecoder().decode(base64);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 99);
|
||||
|
||||
assertArrayEquals(original, result);
|
||||
}
|
||||
|
||||
// --- Output format ---
|
||||
|
||||
@Test
|
||||
void getImage_size2_outputIsJpeg() throws IOException {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
// JPEG files start with FF D8 FF
|
||||
assertEquals((byte) 0xFF, result[0]);
|
||||
assertEquals((byte) 0xD8, result[1]);
|
||||
assertEquals((byte) 0xFF, result[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size3_outputIsJpeg() throws IOException {
|
||||
String base64 = createTestImageBase64(2400, 1600);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 3);
|
||||
|
||||
assertEquals((byte) 0xFF, result[0]);
|
||||
assertEquals((byte) 0xD8, result[1]);
|
||||
assertEquals((byte) 0xFF, result[2]);
|
||||
}
|
||||
|
||||
// --- Edge cases ---
|
||||
|
||||
@Test
|
||||
void getImage_size2_squareImage_preservesAspectRatio() throws IOException {
|
||||
String base64 = createTestImageBase64(2000, 2000);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
BufferedImage resized = ImageIO.read(new ByteArrayInputStream(result));
|
||||
assertEquals(1200, resized.getWidth());
|
||||
assertEquals(1200, resized.getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImage_size2_veryWideImage_preservesAspectRatio() throws IOException {
|
||||
String base64 = createTestImageBase64(4000, 500);
|
||||
|
||||
byte[] result = imageUtil.getImage(base64, 2);
|
||||
|
||||
BufferedImage resized = ImageIO.read(new ByteArrayInputStream(result));
|
||||
assertEquals(1200, resized.getWidth());
|
||||
assertEquals(150, resized.getHeight());
|
||||
}
|
||||
|
||||
private String createTestImageBase64(int width, int height) {
|
||||
try {
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "png", baos);
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String createNoisyImageBase64(int width, int height) {
|
||||
try {
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
java.util.Random random = new java.util.Random(42);
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
image.setRGB(x, y, random.nextInt(0xFFFFFF));
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "png", baos);
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,7 @@ class PdfUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void createPdf_nullEvaluation_doesNotThrow() throws IOException {
|
||||
void createPdf_nullEvaluation_doesNotThrow() {
|
||||
Picture picture = new Picture.Builder()
|
||||
.pictureDate(new Date())
|
||||
.comment("Test")
|
||||
|
||||
Reference in New Issue
Block a user