All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.opentcs.kernel.services.StandardPlantModelService Maven / Gradle / Ivy
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.kernel.services;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Objects.requireNonNull;
import jakarta.inject.Inject;
import java.util.Map;
import java.util.Set;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.LocalKernel;
import org.opentcs.access.ModelTransitionEvent;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Block;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.PlantModel;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.model.visualization.VisualLayout;
import org.opentcs.data.notification.UserNotification;
import org.opentcs.kernel.persistence.ModelPersister;
import org.opentcs.kernel.workingset.PlantModelManager;
import org.opentcs.util.event.EventHandler;
/**
* This class is the standard implementation of the {@link PlantModelService} interface.
*/
public class StandardPlantModelService
extends
AbstractTCSObjectService
implements
InternalPlantModelService {
/**
* The kernel.
*/
private final Kernel kernel;
/**
* A global object to be used for synchronization within the kernel.
*/
private final Object globalSyncObject;
/**
* The plant model manager.
*/
private final PlantModelManager plantModelManager;
/**
* The persister loading and storing model data.
*/
private final ModelPersister modelPersister;
/**
* Where we send events to.
*/
private final EventHandler eventHandler;
/**
* The notification service.
*/
private final NotificationService notificationService;
/**
* Creates a new instance.
*
* @param kernel The kernel.
* @param objectService The tcs object service.
* @param globalSyncObject The kernel threads' global synchronization object.
* @param plantModelManager The plant model manager to be used.
* @param modelPersister The model persister to be used.
* @param eventHandler Where this instance sends events to.
* @param notificationService The notification service.
*/
@Inject
public StandardPlantModelService(
LocalKernel kernel,
TCSObjectService objectService,
@GlobalSyncObject
Object globalSyncObject,
PlantModelManager plantModelManager,
ModelPersister modelPersister,
@ApplicationEventBus
EventHandler eventHandler,
NotificationService notificationService
) {
super(objectService);
this.kernel = requireNonNull(kernel, "kernel");
this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
this.plantModelManager = requireNonNull(plantModelManager, "plantModelManager");
this.modelPersister = requireNonNull(modelPersister, "modelPersister");
this.eventHandler = requireNonNull(eventHandler, "eventHandler");
this.notificationService = requireNonNull(notificationService, "notificationService");
}
@Override
public Set> expandResources(Set> resources)
throws ObjectUnknownException {
requireNonNull(resources, "resources");
synchronized (globalSyncObject) {
return plantModelManager.expandResources(resources);
}
}
@Override
public void loadPlantModel()
throws IllegalStateException {
synchronized (globalSyncObject) {
if (!modelPersister.hasSavedModel()) {
createPlantModel(new PlantModelCreationTO(Kernel.DEFAULT_MODEL_NAME));
return;
}
final String oldModelName = getModelName();
// Load the new model
PlantModelCreationTO modelCreationTO = modelPersister.readModel();
final String newModelName = isNullOrEmpty(modelCreationTO.getName())
? ""
: modelCreationTO.getName();
// Let listeners know we're in transition.
emitModelEvent(oldModelName, newModelName, true, false);
plantModelManager.createPlantModelObjects(modelCreationTO);
// Let listeners know we're done with the transition.
emitModelEvent(oldModelName, newModelName, true, true);
notificationService.publishUserNotification(
new UserNotification(
"Kernel loaded model " + newModelName,
UserNotification.Level.INFORMATIONAL
)
);
}
}
@Override
public void savePlantModel()
throws IllegalStateException {
synchronized (globalSyncObject) {
modelPersister.saveModel(plantModelManager.createPlantModelCreationTO());
}
}
@Override
public PlantModel getPlantModel() {
synchronized (globalSyncObject) {
return new PlantModel(plantModelManager.getName())
.withProperties(getModelProperties())
.withPoints(fetchObjects(Point.class))
.withPaths(fetchObjects(Path.class))
.withLocationTypes(fetchObjects(LocationType.class))
.withLocations(fetchObjects(Location.class))
.withBlocks(fetchObjects(Block.class))
.withVehicles(fetchObjects(Vehicle.class))
.withVisualLayout(fetchObjects(VisualLayout.class).stream().findFirst().get());
}
}
@Override
public void createPlantModel(PlantModelCreationTO to)
throws ObjectUnknownException,
ObjectExistsException,
IllegalStateException {
requireNonNull(to, "to");
boolean kernelInOperating = kernel.getState() == Kernel.State.OPERATING;
// If we are in state operating, change the kernel state before creating the plant model
if (kernelInOperating) {
kernel.setState(Kernel.State.MODELLING);
}
String oldModelName = getModelName();
emitModelEvent(oldModelName, to.getName(), true, false);
// Create the plant model
synchronized (globalSyncObject) {
plantModelManager.createPlantModelObjects(to);
}
savePlantModel();
// If we were in state operating before, change the kernel state back to operating
if (kernelInOperating) {
kernel.setState(Kernel.State.OPERATING);
}
emitModelEvent(oldModelName, to.getName(), true, true);
notificationService.publishUserNotification(
new UserNotification(
"Kernel created model " + to.getName(),
UserNotification.Level.INFORMATIONAL
)
);
}
@Override
public String getModelName() {
synchronized (globalSyncObject) {
return plantModelManager.getName();
}
}
@Override
public Map getModelProperties()
throws KernelRuntimeException {
synchronized (globalSyncObject) {
return plantModelManager.getProperties();
}
}
@Override
public void updateLocationLock(TCSObjectReference ref, boolean locked)
throws ObjectUnknownException {
requireNonNull(ref, "ref");
synchronized (globalSyncObject) {
plantModelManager.setLocationLocked(ref, locked);
}
}
@Override
public void updatePathLock(TCSObjectReference ref, boolean locked)
throws ObjectUnknownException,
KernelRuntimeException {
synchronized (globalSyncObject) {
plantModelManager.setPathLocked(ref, locked);
}
}
/**
* Generates an event for a Model change.
*
* @param oldModelName The old model name.
* @param newModelName The new model name.
* @param modelContentChanged Whether the model's content actually changed.
* @param transitionFinished Whether the transition is finished or not.
*/
private void emitModelEvent(
String oldModelName,
String newModelName,
boolean modelContentChanged,
boolean transitionFinished
) {
requireNonNull(newModelName, "newModelName");
eventHandler.onEvent(
new ModelTransitionEvent(
oldModelName,
newModelName,
modelContentChanged,
transitionFinished
)
);
}
}