WarehouseResourceImpl.java
package com.fulfilment.application.monolith.warehouses.adapters.restapi;
import com.fulfilment.application.monolith.exception.HttpStatus;
import com.fulfilment.application.monolith.warehouses.domain.ports.ArchiveWarehouseOperation;
import com.fulfilment.application.monolith.warehouses.domain.ports.CreateWarehouseOperation;
import com.fulfilment.application.monolith.warehouses.domain.ports.ReplaceWarehouseOperation;
import com.fulfilment.application.monolith.warehouses.domain.ports.WarehouseStore;
import com.warehouse.api.WarehouseResource;
import com.warehouse.api.beans.Warehouse;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.WebApplicationException;
import java.util.List;
import org.jboss.logging.Logger;
@RequestScoped
public class WarehouseResourceImpl implements WarehouseResource {
// Alias: domain model uses fully qualified name throughout to avoid conflict with API bean
private static final Logger LOGGER = Logger.getLogger(WarehouseResourceImpl.class.getName());
@Inject WarehouseStore warehouseStore;
@Inject CreateWarehouseOperation createWarehouseOperation;
@Inject ArchiveWarehouseOperation archiveWarehouseOperation;
@Inject ReplaceWarehouseOperation replaceWarehouseOperation;
@Override
public List<Warehouse> listAllWarehousesUnits() {
LOGGER.debug("Listing all active warehouses");
return warehouseStore.getAll().stream().map(this::toApiWarehouse).toList();
}
@Override
@Transactional
public Warehouse createANewWarehouseUnit(@NotNull Warehouse data) {
validateForCreate(data);
LOGGER.debugf("Request to create warehouse: %s", data.getBusinessUnitCode());
com.fulfilment.application.monolith.warehouses.domain.models.Warehouse domain =
toDomainWarehouse(data);
createWarehouseOperation.create(domain);
LOGGER.infof("Warehouse '%s' created", domain.businessUnitCode);
return toApiWarehouse(domain);
}
@Override
public Warehouse getAWarehouseUnitByID(String id) {
LOGGER.debugf("Fetching warehouse by id: %s", id);
com.fulfilment.application.monolith.warehouses.domain.models.Warehouse warehouse =
warehouseStore.findActiveById(parseId(id));
if (warehouse == null) {
LOGGER.warnf("Warehouse with id '%s' not found", id);
throw new NotFoundException("Warehouse with id '" + id + "' not found.");
}
return toApiWarehouse(warehouse);
}
@Override
@Transactional
public void archiveAWarehouseUnitByID(String id) {
LOGGER.debugf("Request to archive warehouse with id: %s", id);
com.fulfilment.application.monolith.warehouses.domain.models.Warehouse warehouse =
warehouseStore.findActiveById(parseId(id));
if (warehouse == null) {
LOGGER.warnf("Warehouse with id '%s' not found for archiving", id);
throw new NotFoundException("Warehouse with id '" + id + "' not found.");
}
archiveWarehouseOperation.archive(warehouse);
LOGGER.infof("Warehouse with id '%s' archived", id);
}
@Override
@Transactional
public Warehouse replaceTheCurrentActiveWarehouse(
String businessUnitCode, @NotNull Warehouse data) {
validateForReplace(data);
LOGGER.debugf("Request to replace warehouse: %s", businessUnitCode);
// Set the businessUnitCode from the path — new warehouse inherits the same code
com.fulfilment.application.monolith.warehouses.domain.models.Warehouse newWarehouse =
toDomainWarehouse(data);
newWarehouse.businessUnitCode = businessUnitCode;
replaceWarehouseOperation.replace(newWarehouse);
LOGGER.infof("Warehouse '%s' replaced successfully", businessUnitCode);
return toApiWarehouse(newWarehouse);
}
// ─────────────────────────────────────────────────────────────
// ID parsing helper
// ─────────────────────────────────────────────────────────────
/** Parses a String path parameter as a Long ID. Returns -1L if non-numeric (yields 404). */
private Long parseId(String id) {
try {
return Long.parseLong(id);
} catch (NumberFormatException e) {
return -1L;
}
}
// ─────────────────────────────────────────────────────────────
// Validation helpers
// ─────────────────────────────────────────────────────────────
/**
* Validates a create request — businessUnitCode must be present and well-formed in the body.
*/
private void validateForCreate(Warehouse data) {
if (data.getBusinessUnitCode() == null || data.getBusinessUnitCode().isBlank()) {
throw new WebApplicationException(
"Warehouse business unit code is required.", HttpStatus.UNPROCESSABLE_ENTITY);
}
if (!data.getBusinessUnitCode().matches("^[A-Z0-9][A-Z0-9.\\-_]{2,19}$")) {
throw new WebApplicationException(
"Warehouse business unit code has an invalid format (e.g. MWH.001).",
HttpStatus.UNPROCESSABLE_ENTITY);
}
validateForReplace(data);
}
/**
* Validates a replace request body — businessUnitCode is intentionally excluded
* because it is supplied via the path parameter, not the body.
*/
private void validateForReplace(Warehouse data) {
if (data.getLocation() == null || data.getLocation().isBlank()) {
throw new WebApplicationException(
"Warehouse location is required.", HttpStatus.UNPROCESSABLE_ENTITY);
}
if (data.getCapacity() == null || data.getCapacity() < 0) {
throw new WebApplicationException(
"Warehouse capacity must be a non-negative number.", HttpStatus.UNPROCESSABLE_ENTITY);
}
if (data.getStock() == null || data.getStock() < 0) {
throw new WebApplicationException(
"Warehouse stock must be a non-negative number.", HttpStatus.UNPROCESSABLE_ENTITY);
}
}
// ─────────────────────────────────────────────────────────────
// Mapping helpers
// ─────────────────────────────────────────────────────────────
/** Maps domain Warehouse → API response Warehouse. */
private Warehouse toApiWarehouse(
com.fulfilment.application.monolith.warehouses.domain.models.Warehouse warehouse) {
var response = new Warehouse();
if (warehouse.id != null) {
response.setId(String.valueOf(warehouse.id));
}
response.setBusinessUnitCode(warehouse.businessUnitCode);
response.setLocation(warehouse.location);
response.setCapacity(warehouse.capacity);
response.setStock(warehouse.stock);
return response;
}
/** Maps API request Warehouse → domain Warehouse. */
private com.fulfilment.application.monolith.warehouses.domain.models.Warehouse toDomainWarehouse(
Warehouse apiWarehouse) {
var warehouse =
new com.fulfilment.application.monolith.warehouses.domain.models.Warehouse();
warehouse.businessUnitCode = apiWarehouse.getBusinessUnitCode();
warehouse.location = apiWarehouse.getLocation();
warehouse.capacity = apiWarehouse.getCapacity();
warehouse.stock = apiWarehouse.getStock();
return warehouse;
}
}