LocationSynchronizerImpl.java
/*
* Copyright 2005-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openwms.wms.location.impl;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.ameba.annotation.Measured;
import org.ameba.annotation.TxService;
import org.ameba.exception.NotFoundException;
import org.ameba.i18n.Translator;
import org.openwms.common.location.api.events.LocationEvent;
import org.openwms.common.location.api.messages.LocationMO;
import org.openwms.wms.location.Location;
import org.openwms.wms.location.LocationPK;
import org.openwms.wms.location.LocationSynchronizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.validation.annotation.Validated;
import static org.openwms.common.location.api.events.LocationEvent.LocationEventType.CREATED;
import static org.openwms.wms.InventoryMessageCodes.LOCATION_NOT_FOUND_BY_FOREIGN_PKEY;
/**
* A LocationSynchronizerImpl is a Spring managed transaction service that is responsible to synchronize the state of {@link Location}s with
* the golden source.
*
* @author Heiko Scherrer
*/
@Validated
@TxService
class LocationSynchronizerImpl implements LocationSynchronizer {
private static final Logger LOGGER = LoggerFactory.getLogger(LocationSynchronizerImpl.class);
private final Translator translator;
private final LocationMapper mapper;
private final LocationRepository repository;
private final ApplicationEventPublisher eventPublisher;
LocationSynchronizerImpl(Translator translator, LocationMapper mapper, LocationRepository repository, ApplicationEventPublisher eventPublisher) {
this.translator = translator;
this.mapper = mapper;
this.repository = repository;
this.eventPublisher = eventPublisher;
}
/**
* {@inheritDoc}
*/
@Measured
@Override
public void create(@NotNull LocationMO location) {
var existing = repository.findByForeignPKey(location.pKey());
if (existing.isPresent()) {
LOGGER.info("Location with pKey [{}] already exists and cannot be created", location.pKey());
return;
}
existing = repository.findByLocationId(LocationPK.fromString(location.id()));
if (existing.isPresent()) {
LOGGER.info("Location with id [{}] already exists and cannot be created", location.id());
return;
}
var newOne = mapper.convertFromMO(location);
newOne = repository.save(newOne);
eventPublisher.publishEvent(LocationEvent.of(newOne, CREATED));
}
/**
* {@inheritDoc}
*/
@Measured
@Override
public void changeState(@NotBlank String foreignPKey, Boolean incomingActive, Boolean outgoingActive, Integer plcState) {
var location = findByForeignPKeyInternal(foreignPKey);
if (incomingActive != null) {
location.setIncomingActive(incomingActive);
}
if (outgoingActive != null) {
location.setOutgoingActive(outgoingActive);
}
if (plcState != null) {
location.setPlcState(plcState);
}
}
/**
* {@inheritDoc}
*/
@Measured
@Override
public void delete(@NotBlank String foreignPKey) {
// Only allow to delete those who where previously marked for deletion
var locationOpt = repository.findByForeignPKeyAndDeleted(foreignPKey, true);
if (locationOpt.isEmpty()) {
LOGGER.warn("Location to delete does not exist, foreignPKey [{}]", foreignPKey);
return;
}
repository.delete(locationOpt.get());
LOGGER.info("Deleted Location with foreignPKey [{}]", foreignPKey);
}
/**
* {@inheritDoc}
*/
@Measured
@Override
public void rollbackDeletionMark(@NotBlank String foreignPKey) {
var locationOpt = repository.findByForeignPKeyAndDeleted(foreignPKey, true);
if (locationOpt.isEmpty()) {
LOGGER.warn("Location with foreignPKey [{}] does either not exist or is not marked for deletion", foreignPKey);
return;
}
locationOpt.get().setMarkForDeletion(false);
repository.save(locationOpt.get());
}
private Location findByForeignPKeyInternal(String foreignPKey) {
return repository.findByForeignPKey(foreignPKey).orElseThrow(() ->
new NotFoundException(translator, LOCATION_NOT_FOUND_BY_FOREIGN_PKEY, new String[]{foreignPKey}, foreignPKey));
}
}