DomainTemplateService.java
package fr.tiogars.domaintemplate.domains.domaintemplate.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import fr.tiogars.domaintemplate.domains.domaintemplate.entities.DomainTemplate;
import fr.tiogars.domaintemplate.domains.domaintemplate.entities.DomainTemplateEntity;
import fr.tiogars.domaintemplate.domains.domaintemplate.models.CreateDomainTemplateRequest;
import fr.tiogars.domaintemplate.domains.domaintemplate.models.UpdateDomainTemplateRequest;
import fr.tiogars.domaintemplate.domains.domaintemplate.repositories.DomainTemplateRepository;
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Coordinates persistence and retrieval of DomainTemplates.
*
* @since 0.1.0
*/
@Service
public class DomainTemplateService {
private final Clock clock;
private final DomainTemplateRepository repository;
/**
* Creates a service using the system UTC clock.
*
* @param repository domain record repository
*/
@Autowired
public DomainTemplateService(DomainTemplateRepository repository) {
this(repository, Clock.systemUTC());
}
/**
* Creates a service using a supplied clock.
*
* @param repository domain record repository
* @param clock clock used to timestamp stored records
*/
DomainTemplateService(DomainTemplateRepository repository, Clock clock) {
this.repository = repository;
this.clock = clock;
}
/**
* Creates a DomainTemplate when its code does not already exist.
*
* @param request business data to create
* @return created template, or an empty optional when the code exists
*/
@Transactional
public Optional<DomainTemplate> create(CreateDomainTemplateRequest request) {
if (repository.findByCode(request.code()).isPresent()) {
return Optional.empty();
}
Instant timestamp = currentTimestamp();
DomainTemplateEntity entity = new DomainTemplateEntity(
request.code(), request.label(), request.description(), timestamp, timestamp);
return Optional.of(toRecord(repository.save(entity)));
}
/**
* Updates the mutable fields of a DomainTemplate.
*
* @param id persistent identifier
* @param request replacement business data
* @return updated template, or an empty optional when it does not exist
*/
@Transactional
public Optional<DomainTemplate> update(Long id, UpdateDomainTemplateRequest request) {
return repository.findById(id)
.map(existing -> {
existing.update(request.label(), request.description(), currentTimestamp());
return toRecord(repository.save(existing));
});
}
/**
* Deletes a DomainTemplate.
*
* @param id persistent identifier
* @return {@code true} when the template existed
*/
@Transactional
public boolean delete(Long id) {
if (!repository.existsById(id)) {
return false;
}
repository.deleteById(id);
return true;
}
/**
* Lists all templates ordered by business code.
*
* @return templates ordered by code
*/
public List<DomainTemplate> findAll() {
return repository.findAllByOrderByCodeAsc().stream()
.map(DomainTemplateService::toRecord)
.toList();
}
/**
* Finds a DomainTemplate by identifier.
*
* @param id persistent identifier
* @return matching template, or an empty optional when none exists
*/
public Optional<DomainTemplate> findById(Long id) {
return repository.findById(id)
.map(DomainTemplateService::toRecord);
}
/**
* Creates or updates templates by immutable business code.
*
* @param requests business data to seed
* @return stored templates in input order
*/
@Transactional
public List<DomainTemplate> seed(List<CreateDomainTemplateRequest> requests) {
List<DomainTemplate> storedTemplates = new ArrayList<>();
for (CreateDomainTemplateRequest request : requests) {
Instant timestamp = currentTimestamp();
DomainTemplateEntity entity = repository.findByCode(request.code())
.map(existing -> {
existing.update(request.label(), request.description(), timestamp);
return existing;
})
.orElseGet(() -> new DomainTemplateEntity(
request.code(), request.label(), request.description(), timestamp, timestamp));
storedTemplates.add(toRecord(repository.save(entity)));
}
return storedTemplates;
}
private Instant currentTimestamp() {
return Instant.now(clock).truncatedTo(ChronoUnit.MICROS);
}
private static DomainTemplate toRecord(DomainTemplateEntity entity) {
return new DomainTemplate(
entity.getId(),
entity.getCode(),
entity.getLabel(),
entity.getDescription(),
entity.getCreatedDate(),
entity.getLastModifiedDate());
}
}