Initial commit
Some checks failed
Gradle Build / build (push) Has been cancelled

This commit is contained in:
CaiXiang
2024-11-30 18:36:13 +08:00
commit aa56926258
2134 changed files with 232943 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import java.io.Serializable;
/**
* Thrown when there are insufficient user permissions to perform an operation.
*/
public class CredentialsException
extends
KernelRuntimeException
implements
Serializable {
/**
* Constructs a CredentialsException with no detail message.
*/
public CredentialsException() {
super();
}
/**
* Constructs a CredentialsException with the specified detail message.
*
* @param message The detail message.
*/
public CredentialsException(String message) {
super(message);
}
/**
* Constructs a CredentialsException with the specified detail message and
* cause.
*
* @param message The detail message.
* @param cause The exception's cause.
*/
public CredentialsException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a CredentialsException with the specified cause and a detail
* message of <code>(cause == null ? null : cause.toString())</code> (which
* typically contains the class and detail message of <code>cause</code>).
*
* @param cause The exception's cause.
*/
public CredentialsException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
/**
* Declares the methods an openTCS kernel implements.
*/
public interface Kernel {
/**
* The default name used for the empty model created on startup.
*/
String DEFAULT_MODEL_NAME = "unnamed";
/**
* Returns the current state of the kernel.
*
* @return The current state of the kernel.
* @throws CredentialsException If the calling client is not allowed to
* execute this method.
*/
State getState()
throws CredentialsException;
/**
* Sets the current state of the kernel.
* <p>
* Note: This method should only be used internally by the Kernel application.
* </p>
*
* @param newState The state the kernel is to be set to.
* @throws IllegalArgumentException If setting the new state is not possible,
* e.g. because a transition from the current to the new state is not allowed.
* @throws CredentialsException If the calling client is not allowed to
* execute this method.
*/
void setState(State newState)
throws IllegalArgumentException,
CredentialsException;
/**
* The various states a kernel instance may be running in.
*/
enum State {
/**
* The state in which the model/topology is created and parameters are set.
*/
MODELLING,
/**
* The normal mode of operation in which transport orders may be accepted
* and dispatched to vehicles.
*/
OPERATING,
/**
* A transitional state the kernel is in while shutting down.
*/
SHUTDOWN
}
}

View File

@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import java.io.Serializable;
/**
* An exception thrown by the openTCS kernel.
*/
public class KernelException
extends
Exception
implements
Serializable {
/**
* Constructs a new instance with no detail message.
*/
public KernelException() {
super();
}
/**
* Constructs a new instance with the specified detail message.
*
* @param message The detail message.
*/
public KernelException(String message) {
super(message);
}
/**
* Constructs a new instance with the specified detail message and cause.
*
* @param message The detail message.
* @param cause The exception's cause.
*/
public KernelException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new instance with the specified cause and a detail
* message of <code>(cause == null ? null : cause.toString())</code> (which
* typically contains the class and detail message of <code>cause</code>).
*
* @param cause The exception's cause.
*/
public KernelException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import java.io.Serializable;
/**
* A runtime exception thrown by the openTCS kernel.
*/
public class KernelRuntimeException
extends
RuntimeException
implements
Serializable {
/**
* Constructs a new instance with no detail message.
*/
public KernelRuntimeException() {
super();
}
/**
* Constructs a new instance with the specified detail message.
*
* @param message The detail message.
*/
public KernelRuntimeException(String message) {
super(message);
}
/**
* Constructs a new instance with the specified detail message and cause.
*
* @param message The detail message.
* @param cause The exception's cause.
*/
public KernelRuntimeException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new instance with the specified cause and a detail
* message of <code>(cause == null ? null : cause.toString())</code> (which
* typically contains the class and detail message of <code>cause</code>).
*
* @param cause The exception's cause.
*/
public KernelRuntimeException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,155 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import jakarta.annotation.Nonnull;
import java.util.List;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.components.kernel.services.QueryService;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.components.kernel.services.VehicleService;
/**
* Provides clients access to kernel services.
*/
public interface KernelServicePortal {
/**
* Logs in with/establishes a connection to the remote kernel service portal.
*
* @param hostName The host on which the remote portal is running.
* @param port The port at which we can reach the remote RMI registry.
* @throws KernelRuntimeException If there was a problem logging in with the remote portal.
*/
void login(
@Nonnull
String hostName,
int port
)
throws KernelRuntimeException;
/**
* Logs out from/clears the connection to the remote kernel service portal.
*
* @throws KernelRuntimeException If there was a problem logging out from the remote portal, i.e.
* it is no longer available.
*/
void logout()
throws KernelRuntimeException;
/**
* Returns the current state of the kernel.
*
* @return The current state of the kernel.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
Kernel.State getState()
throws KernelRuntimeException;
/**
* Fetches events buffered for the client.
*
* @param timeout A timeout (in ms) for which to wait for events to arrive.
* @return A list of events (in the order they arrived).
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
List<Object> fetchEvents(long timeout)
throws KernelRuntimeException;
/**
* Publishes an event.
*
* @param event The event to be published.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void publishEvent(Object event)
throws KernelRuntimeException;
/**
* Returns the service a client can use to access methods regarding the plant model.
*
* @return The service a client can use to access methods regarding the plant model.
*/
@Nonnull
PlantModelService getPlantModelService();
/**
* Returns the service a client can use to access methods regarding transport orders and order
* sequences.
*
* @return The service a client can use to access methods regarding transport orders and order
* sequences.
*/
@Nonnull
TransportOrderService getTransportOrderService();
/**
* Returns the service a client can use to access methods regarding vehicles.
*
* @return The service a client can use to access methods regarding vehicles.
*/
@Nonnull
VehicleService getVehicleService();
/**
* Returns the service a client can use to access methods regarding user notifications.
*
* @return The service a client can use to access methods regarding user notifications.
*/
@Nonnull
NotificationService getNotificationService();
/**
* Returns the service a client can use to access methods regarding the dispatcher.
*
* @return The service a client can use to access methods regarding the dispatcher.
*/
@Nonnull
DispatcherService getDispatcherService();
/**
* Returns the service a client can use to access methods regarding the router.
*
* @return The service a client can use to access methods regarding the router.
*/
@Nonnull
RouterService getRouterService();
/**
* Returns the service a client can use to access methods for generic queries.
*
* @return The service a client can use to access methods for generic queries.
*/
@Nonnull
QueryService getQueryService();
/**
* Returns the service a client can use to access methods regarding peripherals.
*
* @return The service a client can use to access methods regarding peripherals.
*/
@Nonnull
PeripheralService getPeripheralService();
/**
* Returns the service a client can use to access methods regarding peripheral jobs.
*
* @return The service a client can use to access methods regarding peripheral jobs.
*/
@Nonnull
PeripheralJobService getPeripheralJobService();
/**
* Returns the service a client can use to access methods regarding the peripheral dispatcher.
*
* @return The service a client can use to access methods regarding the peripheral dispatcher.
*/
@Nonnull
PeripheralDispatcherService getPeripheralDispatcherService();
}

View File

@@ -0,0 +1,82 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import java.io.Serializable;
/**
* Emitted by/for kernel state changes.
*/
public class KernelStateTransitionEvent
implements
Serializable {
/**
* The old state the kernel is leaving.
*/
private final Kernel.State leftState;
/**
* The new state the kernel is in transition to.
*/
private final Kernel.State enteredState;
/**
* Whether the transition to the entered state is finished or not.
*/
private final boolean transitionFinished;
/**
* Creates a new TCSKernelStateEvent.
*
* @param leftState The previous state of the kernel.
* @param enteredState The new state of the kernel.
* @param transitionFinished Whether the transistion is finished, yet.
*/
public KernelStateTransitionEvent(
Kernel.State leftState,
Kernel.State enteredState,
boolean transitionFinished
) {
this.leftState = leftState;
this.enteredState = enteredState;
this.transitionFinished = transitionFinished;
}
/**
* Returns the state the kernel is leaving.
*
* @return The state the kernel is leaving.
*/
public Kernel.State getLeftState() {
return leftState;
}
/**
* Returns the state for which this event was generated.
*
* @return The state for which this event was generated.
*/
public Kernel.State getEnteredState() {
return enteredState;
}
/**
* Returns <code>true</code> if, and only if, the transition to the new kernel
* state is finished.
*
* @return <code>true</code> if, and only if, the transition to the new kernel
* state is finished.
*/
public boolean isTransitionFinished() {
return transitionFinished;
}
@Override
public String toString() {
return getClass().getSimpleName()
+ '{'
+ "leftState=" + leftState
+ ", enteredState=" + enteredState
+ ", transitionFinished=" + transitionFinished
+ '}';
}
}

View File

@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.KernelExtension;
/**
* Declares the methods the openTCS kernel must provide which are not accessible
* to remote peers.
*/
public interface LocalKernel
extends
Kernel,
Lifecycle {
/**
* Adds a <code>KernelExtension</code> to this kernel.
*
* @param newExtension The extension to be added.
*/
void addKernelExtension(KernelExtension newExtension);
/**
* Removes a <code>KernelExtension</code> from this kernel.
*
* @param rmExtension The extension to be removed.
*/
void removeKernelExtension(KernelExtension rmExtension);
}

View File

@@ -0,0 +1,103 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import java.io.Serializable;
/**
* Emitted when the kernel loads a model.
*/
public class ModelTransitionEvent
implements
Serializable {
/**
* The old model the kernel is leaving.
*/
private final String oldModelName;
/**
* The new model the kernel is in transition to.
*/
private final String newModelName;
/**
* Whether the content of the model actually changed with the transition.
*/
private final boolean modelContentChanged;
/**
* Whether the transition to the entered state is finished or not.
*/
private final boolean transitionFinished;
/**
* Creates a new TCSModelTransitionEvent.
*
* @param oldModelName The name of the previously loaded model.
* @param newModelName The name of the new model.
* @param modelContentChanged Whether the content of the model actually
* changed with the transition.
* @param transitionFinished Whether the transition to the new model is
* finished, yet.
*/
public ModelTransitionEvent(
String oldModelName,
String newModelName,
boolean modelContentChanged,
boolean transitionFinished
) {
this.oldModelName = oldModelName;
this.newModelName = newModelName;
this.modelContentChanged = modelContentChanged;
this.transitionFinished = transitionFinished;
}
/**
* Returns the model name the kernel is leaving.
*
* @return The model the kernel is leaving.
*/
public String getOldModelName() {
return oldModelName;
}
/**
* Returns the model for which this event was generated.
*
* @return The model for which this event was generated.
*/
public String getNewModelName() {
return newModelName;
}
/**
* Returns <code>true</code> if, and only if, the content of the model
* actually changed with the transition.
*
* @return <code>true</code> if, and only if, the content of the model
* actually changed with the transition.
*/
public boolean hasModelContentChanged() {
return modelContentChanged;
}
/**
* Returns <code>true</code> if, and only if, the transition to the new kernel
* state is finished.
*
* @return <code>true</code> if, and only if, the transition to the new kernel
* state is finished.
*/
public boolean isTransitionFinished() {
return transitionFinished;
}
@Override
public String toString() {
return getClass().getSimpleName()
+ '{'
+ "oldModelName=" + oldModelName
+ ", newModelName=" + newModelName
+ ", modelContentChanged=" + modelContentChanged
+ ", transitionFinished=" + transitionFinished
+ '}';
}
}

View File

@@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import static java.util.Objects.requireNonNull;
import java.io.Serializable;
import org.opentcs.data.notification.UserNotification;
/**
* Instances of this class represent events emitted by/for notifications being published.
*/
public class NotificationPublicationEvent
implements
Serializable {
/**
* The published message.
*/
private final UserNotification notification;
/**
* Creates a new instance.
*
* @param message The message being published.
*/
public NotificationPublicationEvent(UserNotification message) {
this.notification = requireNonNull(message, "notification");
}
/**
* Returns the message being published.
*
* @return The message being published.
*/
public UserNotification getNotification() {
return notification;
}
@Override
public String toString() {
return getClass().getSimpleName()
+ '{'
+ "notification=" + notification
+ '}';
}
}

View File

@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
/**
* Provides access to a shared {@link KernelServicePortal} instance.
*/
public interface SharedKernelServicePortal
extends
AutoCloseable {
@Override
void close();
/**
* Indicates whether this instance is closed/unregistered from the shared portal pool.
*
* @return {@code true} if, and only if, this instance is closed.
*/
boolean isClosed();
/**
* Returns the {@link KernelServicePortal} instance being shared.
*
* @return The portal instance being shared.
* @throws IllegalStateException If this instance is closed.
*/
KernelServicePortal getPortal()
throws IllegalStateException;
}

View File

@@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
/**
* Pools access to a {@link KernelServicePortal} instance for multiple clients.
*/
public interface SharedKernelServicePortalProvider {
/**
* Creates and registers a new client with this access pool.
* This is a convenience method that supports try-with-ressources and does not require a
* preexisting client.
*
* @return The {@link SharedKernelServicePortal}.
* @throws ServiceUnavailableException in case of connection falure with the portal.
*/
SharedKernelServicePortal register()
throws ServiceUnavailableException;
/**
* Checks whether a kernel reference is currently being shared.
*
* @return {@code true} if, and only if, a portal reference is currently being shared, meaning
* that at least one client is registered and a usable portal reference exists.
*/
boolean portalShared();
/**
* Returns a description for the portal currently being shared.
*
* @return A description for the portal currently being shared, or the empty string, if none is
* currently being shared.
*/
String getPortalDescription();
}

View File

@@ -0,0 +1,122 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.io.File;
import java.io.Serializable;
/**
* A set of parameters to be used for SSL-encrypted socket connections.
*/
public class SslParameterSet
implements
Serializable {
/**
* The default type used for truststore and keystore files.
*/
public static final String DEFAULT_KEYSTORE_TYPE = "PKCS12";
/**
* The type used for keystore and truststore.
*/
private final String keystoreType;
/**
* The file path of the keystore.
*/
private final File keystoreFile;
/**
* The password for the keystore file.
*/
private final String keystorePassword;
/**
* The file path of the truststore.
*/
private final File truststoreFile;
/**
* The password for the truststore file.
*/
private final String truststorePassword;
/**
* Creates a new instance.
*
* @param keystoreType The type used for keystore and truststore
* @param keystoreFile The keystore file
* @param truststoreFile The truststore file
* @param keystorePassword The keystore file password
* @param truststorePassword The truststore file password
*/
public SslParameterSet(
@Nonnull
String keystoreType,
@Nullable
File keystoreFile,
@Nullable
String keystorePassword,
@Nullable
File truststoreFile,
@Nullable
String truststorePassword
) {
this.keystoreType = requireNonNull(keystoreType, "keystoreType");
this.keystoreFile = keystoreFile;
this.keystorePassword = keystorePassword;
this.truststoreFile = truststoreFile;
this.truststorePassword = truststorePassword;
}
/**
* Returns the keystoreType used to decrypt the keystore and truststore.
*
* @return The keystoreType used to decrypt the keystore and truststore
*/
@Nonnull
public String getKeystoreType() {
return keystoreType;
}
/**
* Returns the file path of the keystore file.
*
* @return The file path of the keystore file
*/
@Nullable
public File getKeystoreFile() {
return keystoreFile;
}
/**
* Returns the password for the keystore file.
*
* @return The password for the keystore file
*/
@Nullable
public String getKeystorePassword() {
return keystorePassword;
}
/**
* Returns the file path of the truststore file.
*
* @return The file path of the truststore file
*/
@Nullable
public File getTruststoreFile() {
return truststoreFile;
}
/**
* Returns the password for the truststore file.
*
* @return The password for the truststore file
*/
@Nullable
public String getTruststorePassword() {
return truststorePassword;
}
}

View File

@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Interfaces and classes for accessing the kernel from outside, for instance
* from a remote client or a communication adapter.
*/
package org.opentcs.access;

View File

@@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.UUID;
/**
* Identifies a remote client unambiguously.
*/
public class ClientID
implements
Serializable {
/**
* The client's name.
*/
private final String clientName;
/**
* The client's UUID.
*/
private final UUID uuid;
/**
* Creates a new ClientID.
*
* @param clientName The client's name.
*/
public ClientID(
@Nonnull
String clientName
) {
this.clientName = requireNonNull(clientName, "clientName");
uuid = UUID.randomUUID();
}
/**
* Return the client's name.
*
* @return The client's name.
*/
@Nonnull
public String getClientName() {
return clientName;
}
/**
* Checks if this object equals another one.
*
* @param otherObject The other object to be compared with this object.
* @return <code>true</code> if, and only if, the given object is also a
* <code>ClientID</code> and contains the same name and the same UUID as this
* one.
*/
@Override
public boolean equals(Object otherObject) {
if (otherObject instanceof ClientID) {
ClientID otherID = (ClientID) otherObject;
return clientName.equals(otherID.clientName) && uuid.equals(otherID.uuid);
}
else {
return false;
}
}
@Override
public int hashCode() {
return uuid.hashCode();
}
@Override
public String toString() {
return clientName + ":" + uuid;
}
}

View File

@@ -0,0 +1,132 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.util.function.Predicate;
import org.opentcs.access.CredentialsException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.rmi.factories.NullSocketFactoryProvider;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.access.rmi.services.RemoteKernelServicePortalProxy;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.util.ClassMatcher;
/**
* Builds {@link KernelServicePortal} instances for connections to remote portals.
*/
public class KernelServicePortalBuilder {
/**
* Provides socket factories used for RMI.
*/
private SocketFactoryProvider socketFactoryProvider = new NullSocketFactoryProvider();
/**
* The user name for logging in.
*/
private final String userName;
/**
* The password for logging in.
*/
private final String password;
/**
* The event filter to be applied for the built portal.
*/
private Predicate<Object> eventFilter = new ClassMatcher(Object.class);
/**
* Creates a new instance.
*
* @param userName The user name to use for logging in.
* @param password The password to use for logging in.
*/
public KernelServicePortalBuilder(String userName, String password) {
this.userName = requireNonNull(userName, "userName");
this.password = requireNonNull(password, "password");
}
/**
* Returns the socket factory provider used for RMI.
*
* @return The socket factory provider used for RMI.
*/
public SocketFactoryProvider getSocketFactoryProvider() {
return socketFactoryProvider;
}
/**
* Sets the socket factory provider used for RMI.
*
* @param socketFactoryProvider The socket factory provider.
* @return This instance.
*/
public KernelServicePortalBuilder setSocketFactoryProvider(
@Nonnull
SocketFactoryProvider socketFactoryProvider
) {
this.socketFactoryProvider = requireNonNull(socketFactoryProvider, "socketFactoryProvider");
return this;
}
/**
* Returns the user name used for logging in.
*
* @return The user name used for logging in.
*/
public String getUserName() {
return userName;
}
/**
* Returns the password used for logging in.
*
* @return The password used for logging in.
*/
public String getPassword() {
return password;
}
/**
* Returns the event filter to be applied for the built portal.
*
* @return The event filter to be applied for the built portal.
*/
public Predicate<Object> getEventFilter() {
return eventFilter;
}
/**
* Sets the event filter to be applied for the built portal.
*
* @param eventFilter The event filter.
* @return This instance.
*/
public KernelServicePortalBuilder setEventFilter(
@Nonnull
Predicate<Object> eventFilter
) {
this.eventFilter = requireNonNull(eventFilter, "eventFilter");
return this;
}
/**
* Builds and returns a {@link KernelServicePortal} with the configured parameters.
*
* @return A {@link KernelServicePortal} instance.
* @throws ServiceUnavailableException If the remote portal is not reachable for some reason.
* @throws CredentialsException If the client login with the remote portal failed, e.g. because of
* incorrect login data.
*/
public KernelServicePortal build()
throws ServiceUnavailableException,
CredentialsException {
return new RemoteKernelServicePortalProxy(
userName,
password,
socketFactoryProvider,
eventFilter
);
}
}

View File

@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.factories;
import static java.util.Objects.requireNonNull;
import java.io.IOException;
import java.io.Serializable;
import java.net.Socket;
import java.rmi.server.RMIClientSocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.rmi.ssl.SslRMIClientSocketFactory;
/**
* This implementation is similar to {@link SslRMIClientSocketFactory} but allows the use of a
* custom SSLConext.
*/
class CustomSslRMIClientSocketFactory
implements
RMIClientSocketFactory,
Serializable {
/**
* Provides an instance of {@link SSLContext} used to get the actual socket factory.
*/
private final SecureSslContextFactory secureSslContextFactory;
/**
* Creates a new instance.
*
* @param secureSslContextFactory Provides an instance of {@link SSLContext} used to get the
* actual socket factory.
*/
CustomSslRMIClientSocketFactory(SecureSslContextFactory secureSslContextFactory) {
this.secureSslContextFactory = requireNonNull(
secureSslContextFactory,
"secureSslContextFactory"
);
}
@Override
public Socket createSocket(String host, int port)
throws IOException {
SSLContext context = secureSslContextFactory.createClientContext();
SSLSocketFactory sf = context.getSocketFactory();
SSLSocket socket = (SSLSocket) sf.createSocket(host, port);
SSLParameters param = context.getSupportedSSLParameters();
socket.setEnabledCipherSuites(param.getCipherSuites());
socket.setEnabledProtocols(param.getProtocols());
return socket;
}
}

View File

@@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.factories;
import jakarta.inject.Inject;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
/**
* Provides {@code null} for both client and server socket factories.
* By using this provider, the default client-side/server-side socket factory will be used in
* {@link Registry} stubs.
*/
public class NullSocketFactoryProvider
implements
SocketFactoryProvider {
@Inject
public NullSocketFactoryProvider() {
}
@Override
public RMIClientSocketFactory getClientSocketFactory() {
return null;
}
@Override
public RMIServerSocketFactory getServerSocketFactory() {
return null;
}
}

View File

@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.factories;
import static java.util.Objects.requireNonNull;
import jakarta.inject.Inject;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.rmi.ssl.SslRMIServerSocketFactory;
import org.opentcs.access.SslParameterSet;
/**
* Provides instances of {@link RMIClientSocketFactory} and {@link RMIServerSocketFactory} that are
* implemented over the SSL or TLS protocols.
* Since these factories don't support anonymous cipher suites a keystore on the server-side and a
* truststore on the client-side is necessary.
*/
public class SecureSocketFactoryProvider
implements
SocketFactoryProvider {
/**
* Provides methods for creating client-side and server-side {@link SSLContext} instances.
*/
private final SecureSslContextFactory secureSslContextFactory;
/**
* Creates a new instance.
*
* @param sslParameterSet The SSL parameters to be used for creating socket factories.
*/
@Inject
public SecureSocketFactoryProvider(SslParameterSet sslParameterSet) {
requireNonNull(sslParameterSet, "sslParameterSet");
this.secureSslContextFactory = new SecureSslContextFactory(sslParameterSet);
}
@Override
public RMIClientSocketFactory getClientSocketFactory() {
return new CustomSslRMIClientSocketFactory(secureSslContextFactory);
}
@Override
public RMIServerSocketFactory getServerSocketFactory() {
SSLContext context = secureSslContextFactory.createServerContext();
SSLParameters param = context.getSupportedSSLParameters();
return new SslRMIServerSocketFactory(
context,
param.getCipherSuites(),
param.getProtocols(),
param.getWantClientAuth()
);
}
}

View File

@@ -0,0 +1,111 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.factories;
import static java.util.Objects.requireNonNull;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.opentcs.access.SslParameterSet;
/**
* Provides methods for creating client-side and server-side {@link SSLContext} instances.
*/
class SecureSslContextFactory
implements
Serializable {
/**
* The name of the algorithm to use for the {@link KeyManagerFactory} and
* {@link TrustManagerFactory}.
*/
private static final String KEY_TRUST_MANAGEMENT_ALGORITHM = "SunX509";
/**
* The protocol to use with the ssl context.
*/
private static final String SSL_CONTEXT_PROTOCOL = "TLSv1.2";
/**
* The ssl parameters to be used for creating the ssl context.
*/
private final SslParameterSet sslParameterSet;
/**
* Creates a new instance.
*
* @param sslParameterSet The ssl parameters to be used for creating the ssl context.
*/
SecureSslContextFactory(SslParameterSet sslParameterSet) {
this.sslParameterSet = requireNonNull(sslParameterSet, "sslParameterSet");
}
/**
* Creates an instance of {@link SSLContext} for the client.
*
* @return The ssl context.
* @throws IllegalStateException If the creation of the ssl context fails.
*/
public SSLContext createClientContext()
throws IllegalStateException {
SSLContext context = null;
try {
KeyStore ts = KeyStore.getInstance(sslParameterSet.getKeystoreType());
ts.load(
new FileInputStream(sslParameterSet.getTruststoreFile()),
sslParameterSet.getTruststorePassword().toCharArray()
);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_TRUST_MANAGEMENT_ALGORITHM);
tmf.init(ts);
context = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL);
context.init(null, tmf.getTrustManagers(), null);
}
catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
| KeyManagementException ex) {
throw new IllegalStateException("Error creating the client's ssl context", ex);
}
return context;
}
/**
* Creates an instance of {@link SSLContext} for the server.
*
* @return The ssl context.
* @throws IllegalStateException If the creation of the ssl context fails.
*/
public SSLContext createServerContext()
throws IllegalStateException {
SSLContext context = null;
try {
KeyStore ks = KeyStore.getInstance(sslParameterSet.getKeystoreType());
ks.load(
new FileInputStream(sslParameterSet.getKeystoreFile()),
sslParameterSet.getKeystorePassword().toCharArray()
);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_TRUST_MANAGEMENT_ALGORITHM);
kmf.init(ks, sslParameterSet.getKeystorePassword().toCharArray());
context = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL);
context.init(kmf.getKeyManagers(), null, null);
}
catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
| KeyManagementException | UnrecoverableKeyException ex) {
throw new IllegalStateException("Error creating the server's ssl context", ex);
}
return context;
}
}

View File

@@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.factories;
import jakarta.annotation.Nullable;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
/**
* A provider for instances of {@link RMIClientSocketFactory} and {@link RMIServerSocketFactory}.
* Generally one provider should provide compatible factories for clients and servers.
*/
public interface SocketFactoryProvider {
/**
* Returns a {@link RMIClientSocketFactory}.
*
* @return A {@link RMIClientSocketFactory}.
* May be <code>null</code> to indicate that a default factory implementation is to be used.
*/
@Nullable
RMIClientSocketFactory getClientSocketFactory();
/**
* Returns a {@link RMIServerSocketFactory}.
*
* @return A {@link RMIServerSocketFactory}.
* May be <code>null</code> to indicate that a default factory implementation is to be used.
*/
@Nullable
RMIServerSocketFactory getServerSocketFactory();
}

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Interfaces and classes for configuration of the RMI runtime used by openTCS kernel and clients.
*/
package org.opentcs.access.rmi.factories;

View File

@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Interfaces and classes for transparently providing an openTCS kernel's
* functionality via RMI.
*/
package org.opentcs.access.rmi;

View File

@@ -0,0 +1,141 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
/**
* A base class for remote service proxy implementations.
*
* @param <R> The remote service's type.
*/
abstract class AbstractRemoteServiceProxy<R extends Remote> {
/**
* The message to log when a service is unavailable.
*/
private static final String SERVICE_UNAVAILABLE_MESSAGE = "Remote service unreachable";
/**
* The client using this service.
*/
private ClientID clientId;
/**
* The corresponding remote service.
*/
private R remoteService;
/**
* The listener that is interested in updates of this service.
*/
private ServiceListener serviceListener;
/**
* Returns the client id using this service.
*
* @return The client id using this service.
*/
ClientID getClientId() {
return clientId;
}
/**
* Sets the client id using this service.
*
* @param clientId The client id.
* @return This remote service proxy.
*/
AbstractRemoteServiceProxy<R> setClientId(ClientID clientId) {
this.clientId = clientId;
return this;
}
/**
* Returns the remote service to delegate method invocations to.
*
* @return The remote service to delegate method invocations to.
*/
R getRemoteService() {
return remoteService;
}
/**
* Sets the remote service to delegate method invocations to.
*
* @param remoteService The remote service.
* @return This remote service proxy.
*/
AbstractRemoteServiceProxy<R> setRemoteService(R remoteService) {
this.remoteService = remoteService;
return this;
}
/**
* Returns the listener that is interested in updates of this service.
*
* @return The listener that is interested in updates of this service.
*/
ServiceListener getServiceListener() {
return serviceListener;
}
/**
* Sets the listener that is interested in updates of this service.
*
* @param serviceListener The service listener.
* @return This remote service proxy.
*/
public AbstractRemoteServiceProxy<R> setServiceListener(ServiceListener serviceListener) {
this.serviceListener = serviceListener;
return this;
}
/**
* Checks whether this service is logged in or not.
*
* @return {@code true} if, and only if, this service has both a client id and a remote service
* associated to it.
*/
boolean isLoggedIn() {
return getClientId() != null && getRemoteService() != null;
}
/**
* Ensures that this service is available to be used.
*
* @throws ServiceUnavailableException If the service is not available.
*/
void checkServiceAvailability()
throws ServiceUnavailableException {
if (!isLoggedIn()) {
throw new ServiceUnavailableException(SERVICE_UNAVAILABLE_MESSAGE);
}
}
/**
* Returns a suitable {@link RuntimeException} for the given {@link RemoteException}.
*
* @param ex The exception to find a runtime exception for.
* @return The runtime exception.
*/
RuntimeException findSuitableExceptionFor(RemoteException ex) {
if (ex.getCause() instanceof ObjectUnknownException) {
return (ObjectUnknownException) ex.getCause();
}
if (ex.getCause() instanceof ObjectExistsException) {
return (ObjectExistsException) ex.getCause();
}
if (ex.getCause() instanceof IllegalArgumentException) {
return (IllegalArgumentException) ex.getCause();
}
if (getServiceListener() != null) {
getServiceListener().onServiceUnavailable();
}
return new ServiceUnavailableException(SERVICE_UNAVAILABLE_MESSAGE, ex);
}
}

View File

@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import org.opentcs.access.Kernel;
/**
* A listener for events concerning kernel state changes.
*/
interface KernelStateEventListener {
/**
* Called when the kernel state changes to {@link Kernel.State#SHUTDOWN}.
*/
void onKernelShutdown();
}

View File

@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
/**
* Defines the names used for binding the remote services in the RMI registry.
*/
public interface RegistrationName {
/**
* The name the {@link RemoteKernelServicePortal} registers itself with a RMI registry.
*/
String REMOTE_KERNEL_CLIENT_PORTAL = RemoteKernelServicePortal.class.getCanonicalName();
/**
* The name the {@link RemotePlantModelService} registers itself with a RMI registry.
*/
String REMOTE_PLANT_MODEL_SERVICE = RemotePlantModelService.class.getCanonicalName();
/**
* The name the {@link RemoteTransportOrderService} registers itself with a RMI registry.
*/
String REMOTE_TRANSPORT_ORDER_SERVICE = RemoteTransportOrderService.class.getCanonicalName();
/**
* The name the {@link RemoteVehicleService} registers itself with a RMI registry.
*/
String REMOTE_VEHICLE_SERVICE = RemoteVehicleService.class.getCanonicalName();
/**
* The name the {@link RemoteNotificationService} registers itself with a RMI registry.
*/
String REMOTE_NOTIFICATION_SERVICE = RemoteNotificationService.class.getCanonicalName();
/**
* The name the {@link RemoteRouterService} registers itself with a RMI registry.
*/
String REMOTE_ROUTER_SERVICE = RemoteRouterService.class.getCanonicalName();
/**
* The name the {@link RemoteDispatcherService} registers itself with a RMI registry.
*/
String REMOTE_DISPATCHER_SERVICE = RemoteDispatcherService.class.getCanonicalName();
/**
* The name the {@link RemoteQueryService} registers itself with a RMI registry.
*/
String REMOTE_QUERY_SERVICE = RemoteQueryService.class.getCanonicalName();
/**
* The name the {@link RemotePeripheralService} registers itself with a RMI registry.
*/
String REMOTE_PERIPHERAL_SERVICE = RemotePeripheralService.class.getCanonicalName();
/**
* The name the {@link RemotePeripheralJobService} registers itself with a RMI registry.
*/
String REMOTE_PERIPHERAL_JOB_SERVICE = RemotePeripheralJobService.class.getCanonicalName();
/**
* The name the {@link RemotePeripheralDispatcherService} registers itself with a RMI registry.
*/
String REMOTE_PERIPHERAL_DISPATCHER_SERVICE
= RemotePeripheralDispatcherService.class.getCanonicalName();
}

View File

@@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.ReroutingType;
import org.opentcs.data.order.TransportOrder;
/**
* Declares the methods provided by the {@link DispatcherService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link DispatcherService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link DispatcherService} for these, instead.
* </p>
*/
public interface RemoteDispatcherService
extends
Remote {
// CHECKSTYLE:OFF
void dispatch(ClientID clientId)
throws RemoteException;
void withdrawByVehicle(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
boolean immediateAbort
)
throws RemoteException;
void withdrawByTransportOrder(
ClientID clientId,
TCSObjectReference<TransportOrder> ref,
boolean immediateAbort
)
throws RemoteException;
void reroute(ClientID clientId, TCSObjectReference<Vehicle> ref, ReroutingType reroutingType)
throws RemoteException;
void rerouteAll(ClientID clientId, ReroutingType reroutingType)
throws RemoteException;
void assignNow(ClientID clientId, TCSObjectReference<TransportOrder> ref)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,122 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.ReroutingType;
import org.opentcs.data.order.TransportOrder;
/**
* The default implementation of the dispatcher service.
* Delegates method invocations to the corresponding remote service.
*/
class RemoteDispatcherServiceProxy
extends
AbstractRemoteServiceProxy<RemoteDispatcherService>
implements
DispatcherService {
/**
* Creates a new instance.
*/
RemoteDispatcherServiceProxy() {
}
@Override
public void dispatch()
throws KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().dispatch(getClientId());
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void withdrawByVehicle(
TCSObjectReference<Vehicle> vehicleRef,
boolean immediateAbort
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().withdrawByVehicle(
getClientId(),
vehicleRef,
immediateAbort
);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void withdrawByTransportOrder(
TCSObjectReference<TransportOrder> ref,
boolean immediateAbort
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().withdrawByTransportOrder(
getClientId(),
ref,
immediateAbort
);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void reroute(TCSObjectReference<Vehicle> ref, ReroutingType reroutingType)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().reroute(getClientId(), ref, reroutingType);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void rerouteAll(ReroutingType reroutingType) {
checkServiceAvailability();
try {
getRemoteService().rerouteAll(getClientId(), reroutingType);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void assignNow(TCSObjectReference<TransportOrder> ref)
throws KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().assignNow(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.CredentialsException;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.rmi.ClientID;
/**
* Declares the methods provided by the {@link KernelServicePortal} via RMI.
*/
public interface RemoteKernelServicePortal
extends
Remote {
/**
* Introduce the calling client to the server and authenticate for operations.
*
* @param userName The user's name.
* @param password The user's password.
* @param eventFilter The event filter to be applied to events on the server side.
* @return An identification object that is required for subsequent method calls.
* @throws CredentialsException If authentication with the given username and password failed.
* @throws RemoteException If there was an RMI-related problem.
*/
ClientID login(String userName, String password, Predicate<Object> eventFilter)
throws CredentialsException,
RemoteException;
void logout(ClientID clientId)
throws RemoteException;
Kernel.State getState(ClientID clientId)
throws RemoteException;
List<Object> fetchEvents(ClientID clientId, long timeout)
throws RemoteException;
void publishEvent(ClientID clientId, Object event)
throws RemoteException;
}

View File

@@ -0,0 +1,388 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import static java.util.Objects.requireNonNull;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_DISPATCHER_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_KERNEL_CLIENT_PORTAL;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_NOTIFICATION_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_PERIPHERAL_DISPATCHER_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_PERIPHERAL_JOB_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_PERIPHERAL_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_PLANT_MODEL_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_QUERY_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_ROUTER_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_TRANSPORT_ORDER_SERVICE;
import static org.opentcs.access.rmi.services.RegistrationName.REMOTE_VEHICLE_SERVICE;
import jakarta.annotation.Nonnull;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.CredentialsException;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.components.kernel.services.QueryService;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.components.kernel.services.VehicleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The default implementation for the {@link KernelServicePortal}.
*/
public class RemoteKernelServicePortalProxy
extends
AbstractRemoteServiceProxy<RemoteKernelServicePortal>
implements
KernelServicePortal,
ServiceListener {
/**
* This class' logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(RemoteKernelServicePortalProxy.class);
/**
* The user name used with the remote portal.
*/
private final String userName;
/**
* The password used with the remote portal.
*/
private final String password;
/**
* Provides socket factories used for RMI.
*/
private final SocketFactoryProvider socketFactoryProvider;
/**
* The event filter to be applied to events on the server side (before polling).
*/
private final Predicate<Object> eventFilter;
/**
* The plant model service.
*/
private final RemotePlantModelServiceProxy plantModelService
= new RemotePlantModelServiceProxy();
/**
* The transport order service.
*/
private final RemoteTransportOrderServiceProxy transportOrderService
= new RemoteTransportOrderServiceProxy();
/**
* The vehicle service.
*/
private final RemoteVehicleServiceProxy vehicleService = new RemoteVehicleServiceProxy();
/**
* The notification service.
*/
private final RemoteNotificationServiceProxy notificationService
= new RemoteNotificationServiceProxy();
/**
* The dispatcher service.
*/
private final RemoteDispatcherServiceProxy dispatcherService
= new RemoteDispatcherServiceProxy();
/**
* The router service.
*/
private final RemoteRouterServiceProxy routerService = new RemoteRouterServiceProxy();
/**
* The query service.
*/
private final RemoteQueryServiceProxy queryService = new RemoteQueryServiceProxy();
/**
* The peripheral service.
*/
private final RemotePeripheralServiceProxy peripheralService = new RemotePeripheralServiceProxy();
/**
* The peripheral job service.
*/
private final RemotePeripheralJobServiceProxy peripheralJobService
= new RemotePeripheralJobServiceProxy();
/**
* The peripheral dispatcher service.
*/
private final RemotePeripheralDispatcherServiceProxy peripheralDispatcherService
= new RemotePeripheralDispatcherServiceProxy();
/**
* Creates a new instance.
*
* @param userName The user name used with the remote portal.
* @param password The password used with the remote portal.
* @param socketFactoryProvider Provides socket factories used for RMI.
* @param eventFilter The event filter to be applied to events on the server side.
*/
public RemoteKernelServicePortalProxy(
@Nonnull
String userName,
@Nonnull
String password,
@Nonnull
SocketFactoryProvider socketFactoryProvider,
@Nonnull
Predicate<Object> eventFilter
) {
this.userName = requireNonNull(userName, "userName");
this.password = requireNonNull(password, "password");
this.socketFactoryProvider = requireNonNull(socketFactoryProvider, "socketFactoryProvider");
this.eventFilter = requireNonNull(eventFilter, "eventFilter");
}
@Override
public ServiceListener getServiceListener() {
return this;
}
@Override
public void onServiceUnavailable() {
resetServiceLogins();
}
@Override
public void login(
@Nonnull
String hostName,
int port
)
throws CredentialsException,
ServiceUnavailableException {
requireNonNull(hostName, "hostName");
if (isLoggedIn()) {
LOG.warn("Already logged in, doing nothing.");
return;
}
try {
// Look up the remote portal with the RMI registry.
Registry registry
= LocateRegistry.getRegistry(
hostName,
port,
socketFactoryProvider.getClientSocketFactory()
);
setRemoteService((RemoteKernelServicePortal) registry.lookup(REMOTE_KERNEL_CLIENT_PORTAL));
// Login and save the client ID.
setClientId(getRemoteService().login(userName, password, eventFilter));
// Get notified when a service call on us fails.
setServiceListener(this);
// Look up the remote services with the RMI registry and update the other service logins.
updateServiceLogins(registry);
}
catch (RemoteException | NotBoundException exc) {
resetServiceLogins();
throw new ServiceUnavailableException(
"Exception logging in with remote kernel client portal",
exc
);
}
}
@Override
public void logout() {
if (!isLoggedIn()) {
LOG.warn("Not logged in, doing nothing.");
return;
}
try {
getRemoteService().logout(getClientId());
}
catch (RemoteException ex) {
throw new ServiceUnavailableException("Remote kernel client portal unavailable", ex);
}
resetServiceLogins();
}
@Override
public Kernel.State getState()
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().getState(getClientId());
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public List<Object> fetchEvents(long timeout)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchEvents(getClientId(), timeout);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void publishEvent(Object event)
throws KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().publishEvent(getClientId(), event);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
@Nonnull
public PlantModelService getPlantModelService() {
return plantModelService;
}
@Override
@Nonnull
public TransportOrderService getTransportOrderService() {
return transportOrderService;
}
@Override
@Nonnull
public VehicleService getVehicleService() {
return vehicleService;
}
@Override
@Nonnull
public NotificationService getNotificationService() {
return notificationService;
}
@Override
@Nonnull
public DispatcherService getDispatcherService() {
return dispatcherService;
}
@Override
@Nonnull
public RouterService getRouterService() {
return routerService;
}
@Override
@Nonnull
public QueryService getQueryService() {
return queryService;
}
@Override
@Nonnull
public PeripheralService getPeripheralService() {
return peripheralService;
}
@Override
@Nonnull
public PeripheralJobService getPeripheralJobService() {
return peripheralJobService;
}
@Override
@Nonnull
public PeripheralDispatcherService getPeripheralDispatcherService() {
return peripheralDispatcherService;
}
private void updateServiceLogins(Registry registry)
throws RemoteException,
NotBoundException {
plantModelService
.setClientId(getClientId())
.setRemoteService((RemotePlantModelService) registry.lookup(REMOTE_PLANT_MODEL_SERVICE))
.setServiceListener(this);
transportOrderService
.setClientId(getClientId())
.setRemoteService(
(RemoteTransportOrderService) registry.lookup(REMOTE_TRANSPORT_ORDER_SERVICE)
)
.setServiceListener(this);
vehicleService
.setClientId(getClientId())
.setRemoteService((RemoteVehicleService) registry.lookup(REMOTE_VEHICLE_SERVICE))
.setServiceListener(this);
notificationService
.setClientId(getClientId())
.setRemoteService((RemoteNotificationService) registry.lookup(REMOTE_NOTIFICATION_SERVICE))
.setServiceListener(this);
dispatcherService
.setClientId(getClientId())
.setRemoteService((RemoteDispatcherService) registry.lookup(REMOTE_DISPATCHER_SERVICE))
.setServiceListener(this);
routerService
.setClientId(getClientId())
.setRemoteService((RemoteRouterService) registry.lookup(REMOTE_ROUTER_SERVICE))
.setServiceListener(this);
queryService
.setClientId(getClientId())
.setRemoteService((RemoteQueryService) registry.lookup(REMOTE_QUERY_SERVICE))
.setServiceListener(this);
peripheralService
.setClientId(getClientId())
.setRemoteService((RemotePeripheralService) registry.lookup(REMOTE_PERIPHERAL_SERVICE))
.setServiceListener(this);
peripheralJobService
.setClientId(getClientId())
.setRemoteService(
(RemotePeripheralJobService) registry.lookup(REMOTE_PERIPHERAL_JOB_SERVICE)
)
.setServiceListener(this);
peripheralDispatcherService
.setClientId(getClientId())
.setRemoteService(
(RemotePeripheralDispatcherService) registry.lookup(
REMOTE_PERIPHERAL_DISPATCHER_SERVICE
)
)
.setServiceListener(this);
}
private void resetServiceLogins() {
this.setClientId(null).setRemoteService(null).setServiceListener(null);
plantModelService.setClientId(null).setRemoteService(null).setServiceListener(null);
transportOrderService.setClientId(null).setRemoteService(null).setServiceListener(null);
vehicleService.setClientId(null).setRemoteService(null).setServiceListener(null);
notificationService.setClientId(null).setRemoteService(null).setServiceListener(null);
dispatcherService.setClientId(null).setRemoteService(null).setServiceListener(null);
routerService.setClientId(null).setRemoteService(null).setServiceListener(null);
queryService.setClientId(null).setRemoteService(null).setServiceListener(null);
peripheralService.setClientId(null).setRemoteService(null).setServiceListener(null);
peripheralJobService.setClientId(null).setRemoteService(null).setServiceListener(null);
peripheralDispatcherService.setClientId(null).setRemoteService(null).setServiceListener(null);
}
}

View File

@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.data.notification.UserNotification;
/**
* Declares the methods provided by the {@link NotificationService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link NotificationService}, with an additional {@link ClientID} parameter which serves the
* purpose of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link NotificationService} for these, instead.
* </p>
*/
public interface RemoteNotificationService
extends
Remote {
// CHECKSTYLE:OFF
List<UserNotification> fetchUserNotifications(
ClientID clientId,
Predicate<UserNotification> predicate
)
throws RemoteException;
void publishUserNotification(ClientID clientId, UserNotification notification)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.data.notification.UserNotification;
/**
* The default implementation of the notification service.
* Delegates method invocations to the corresponding remote service.
*/
class RemoteNotificationServiceProxy
extends
AbstractRemoteServiceProxy<RemoteNotificationService>
implements
NotificationService {
/**
* Creates a new instance.
*/
RemoteNotificationServiceProxy() {
}
@Override
public List<UserNotification> fetchUserNotifications(Predicate<UserNotification> predicate)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchUserNotifications(getClientId(), predicate);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void publishUserNotification(UserNotification notification)
throws KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().publishUserNotification(getClientId(), notification);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Declares the methods provided by the {@link PeripheralDispatcherService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link PeripheralDispatcherService}, with an additional {@link ClientID} parameter which serves
* the purpose of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link PeripheralDispatcherService} for these, instead.
* </p>
*/
public interface RemotePeripheralDispatcherService
extends
Remote {
// CHECKSTYLE:OFF
void dispatch(ClientID clientId)
throws RemoteException;
void withdrawByLocation(ClientID clientId, TCSResourceReference<Location> ref)
throws RemoteException;
void withdrawByPeripheralJob(ClientID clientId, TCSObjectReference<PeripheralJob> ref)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,70 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* The default implementation of the peripheral dispatcher service.
* Delegates method invocations to the corresponding remote service.
*/
class RemotePeripheralDispatcherServiceProxy
extends
AbstractRemoteServiceProxy<RemotePeripheralDispatcherService>
implements
PeripheralDispatcherService {
/**
* Creates a new instance.
*/
RemotePeripheralDispatcherServiceProxy() {
}
@Override
public void dispatch()
throws KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().dispatch(getClientId());
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void withdrawByLocation(TCSResourceReference<Location> locationRef)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().withdrawByLocation(getClientId(), locationRef);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void withdrawByPeripheralJob(TCSObjectReference<PeripheralJob> jobRef)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().withdrawByPeripheralJob(getClientId(), jobRef);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Declares the methods provided by the {@link PeripheralJobService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link PeripheralJobService}, with an additional {@link ClientID} parameter which serves the
* purpose of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link PeripheralJobService} for these, instead.
* </p>
*/
public interface RemotePeripheralJobService
extends
RemoteTCSObjectService,
Remote {
// CHECKSTYLE:OFF
PeripheralJob createPeripheralJob(ClientID clientId, PeripheralJobCreationTO to)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* The default implementation of the peripheral job service.
* Delegates method invocations to the corresponding remote service.
*/
class RemotePeripheralJobServiceProxy
extends
RemoteTCSObjectServiceProxy<RemotePeripheralJobService>
implements
PeripheralJobService {
/**
* Creates a new instance.
*/
RemotePeripheralJobServiceProxy() {
}
@Override
public PeripheralJob createPeripheralJob(PeripheralJobCreationTO to)
throws ObjectUnknownException,
ObjectExistsException,
KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().createPeripheralJob(getClientId(), to);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
/**
* Declares the methods provided by the {@link PeripheralService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link PeripheralService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link PeripheralService} for these, instead.
* </p>
*/
public interface RemotePeripheralService
extends
RemoteTCSObjectService,
Remote {
// CHECKSTYLE:OFF
void attachCommAdapter(
ClientID clientId,
TCSResourceReference<Location> ref,
PeripheralCommAdapterDescription description
)
throws RemoteException;
void disableCommAdapter(ClientID clientId, TCSResourceReference<Location> ref)
throws RemoteException;
void enableCommAdapter(ClientID clientId, TCSResourceReference<Location> ref)
throws RemoteException;
PeripheralAttachmentInformation fetchAttachmentInformation(
ClientID clientId,
TCSResourceReference<Location> ref
)
throws RemoteException;
PeripheralProcessModel fetchProcessModel(ClientID clientId, TCSResourceReference<Location> ref)
throws RemoteException;
void sendCommAdapterCommand(
ClientID clientId,
TCSResourceReference<Location> ref,
PeripheralAdapterCommand command
)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,123 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
/**
* The default implementation of the vehicle service.
* Delegates method invocations to the corresponding remote service.
*/
class RemotePeripheralServiceProxy
extends
RemoteTCSObjectServiceProxy<RemotePeripheralService>
implements
PeripheralService {
/**
* Creates a new instance.
*/
RemotePeripheralServiceProxy() {
}
@Override
public void attachCommAdapter(
TCSResourceReference<Location> ref,
PeripheralCommAdapterDescription description
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().attachCommAdapter(getClientId(), ref, description);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void disableCommAdapter(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().disableCommAdapter(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void enableCommAdapter(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().enableCommAdapter(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public PeripheralAttachmentInformation fetchAttachmentInformation(
TCSResourceReference<Location> ref
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchAttachmentInformation(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public PeripheralProcessModel fetchProcessModel(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchProcessModel(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void sendCommAdapterCommand(
TCSResourceReference<Location> ref,
PeripheralAdapterCommand command
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().sendCommAdapterCommand(getClientId(), ref, command);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Map;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.PlantModel;
/**
* Declares the methods provided by the {@link PlantModelService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link PlantModelService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link PlantModelService} for these, instead.
* </p>
*/
public interface RemotePlantModelService
extends
RemoteTCSObjectService,
Remote {
// CHECKSTYLE:OFF
PlantModel getPlantModel(ClientID clientId)
throws RemoteException;
void createPlantModel(ClientID clientId, PlantModelCreationTO to)
throws RemoteException;
String getModelName(ClientID clientId)
throws RemoteException;
Map<String, String> getModelProperties(ClientID clientId)
throws RemoteException;
void updateLocationLock(ClientID clientId, TCSObjectReference<Location> ref, boolean locked)
throws RemoteException;
void updatePathLock(ClientID clientId, TCSObjectReference<Path> ref, boolean locked)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,115 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import java.util.Map;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.PlantModel;
/**
* The default implementation of the plant model service.
* Delegates method invocations to the corresponding remote service.
*/
class RemotePlantModelServiceProxy
extends
RemoteTCSObjectServiceProxy<RemotePlantModelService>
implements
PlantModelService {
/**
* Creates a new instance.
*/
RemotePlantModelServiceProxy() {
}
@Override
public PlantModel getPlantModel()
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().getPlantModel(getClientId());
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void createPlantModel(PlantModelCreationTO to)
throws ObjectUnknownException,
ObjectExistsException,
KernelRuntimeException,
IllegalStateException {
checkServiceAvailability();
try {
getRemoteService().createPlantModel(getClientId(), to);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public String getModelName()
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().getModelName(getClientId());
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public Map<String, String> getModelProperties()
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().getModelProperties(getClientId());
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateLocationLock(TCSObjectReference<Location> ref, boolean locked)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateLocationLock(getClientId(), ref, locked);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updatePathLock(TCSObjectReference<Path> ref, boolean locked)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updatePathLock(getClientId(), ref, locked);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.services.QueryService;
/**
* Declares the methods provided by the {@link QueryService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link QueryService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link QueryService} for these, instead.
* </p>
*/
public interface RemoteQueryService
extends
Remote {
// CHECKSTYLE:OFF
<T> T query(ClientID clientId, Query<T> query)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.services.QueryService;
/**
* The default implementation of the query service.
* Delegates method invocations to the corresponding remote service.
*/
class RemoteQueryServiceProxy
extends
AbstractRemoteServiceProxy<RemoteQueryService>
implements
QueryService {
/**
* Creates a new instance.
*/
RemoteQueryServiceProxy() {
}
@Override
public <T> T query(Query<T> query) {
checkServiceAvailability();
try {
return getRemoteService().query(getClientId(), query);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.Set;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.Route;
/**
* Declares the methods provided by the {@link RouterService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link RouterService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link RouterService} for these, instead.
* </p>
*/
public interface RemoteRouterService
extends
Remote {
// CHECKSTYLE:OFF
public void updateRoutingTopology(ClientID clientId, Set<TCSObjectReference<Path>> refs)
throws RemoteException;
public Map<TCSObjectReference<Point>, Route> computeRoutes(
ClientID clientId,
TCSObjectReference<Vehicle> vehicleRef,
TCSObjectReference<Point> sourcePointRef,
Set<TCSObjectReference<Point>> destinationPointRefs,
Set<TCSResourceReference<?>> resourcesToAvoid
)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,69 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.Set;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.Route;
/**
* The default implementation of the router service.
* Delegates method invocations to the corresponding remote service.
*/
class RemoteRouterServiceProxy
extends
AbstractRemoteServiceProxy<RemoteRouterService>
implements
RouterService {
/**
* Creates a new instance.
*/
RemoteRouterServiceProxy() {
}
@Override
public void updateRoutingTopology(Set<TCSObjectReference<Path>> refs)
throws KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateRoutingTopology(getClientId(), refs);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public Map<TCSObjectReference<Point>, Route> computeRoutes(
TCSObjectReference<Vehicle> vehicleRef,
TCSObjectReference<Point> sourcePointRef,
Set<TCSObjectReference<Point>> destinationPointRefs,
Set<TCSResourceReference<?>> resourcesToAvoid
)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().computeRoutes(
getClientId(),
vehicleRef,
sourcePointRef,
destinationPointRefs,
resourcesToAvoid
);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,69 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Set;
import java.util.function.Predicate;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
/**
* Declares the methods provided by the {@link TCSObjectService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link TCSObjectService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link TCSObjectService} for these, instead.
* </p>
*/
public interface RemoteTCSObjectService
extends
Remote {
// CHECKSTYLE:OFF
<T extends TCSObject<T>> T fetchObject(
ClientID clientId,
Class<T> clazz,
TCSObjectReference<T> ref
)
throws RemoteException;
<T extends TCSObject<T>> T fetchObject(ClientID clientId, Class<T> clazz, String name)
throws RemoteException;
<T extends TCSObject<T>> Set<T> fetchObjects(ClientID clientId, Class<T> clazz)
throws RemoteException;
<T extends TCSObject<T>> Set<T> fetchObjects(
ClientID clientId,
Class<T> clazz,
Predicate<? super T> predicate
)
throws RemoteException;
void updateObjectProperty(
ClientID clientId,
TCSObjectReference<?> ref,
String key,
String value
)
throws RemoteException;
void appendObjectHistoryEntry(
ClientID clientId,
TCSObjectReference<?> ref,
ObjectHistory.Entry entry
)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,110 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import java.util.Set;
import java.util.function.Predicate;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
/**
* The default implementation of the tcs object service.
* Delegates method invocations to the corresponding remote service.
*
* @param <R> The remote service's type.
*/
abstract class RemoteTCSObjectServiceProxy<R extends RemoteTCSObjectService>
extends
AbstractRemoteServiceProxy<R>
implements
TCSObjectService {
@Override
public <T extends TCSObject<T>> T fetchObject(Class<T> clazz, TCSObjectReference<T> ref)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchObject(getClientId(), clazz, ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public <T extends TCSObject<T>> T fetchObject(Class<T> clazz, String name)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchObject(getClientId(), clazz, name);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public <T extends TCSObject<T>> Set<T> fetchObjects(Class<T> clazz)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchObjects(getClientId(), clazz);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public <T extends TCSObject<T>> Set<T> fetchObjects(
Class<T> clazz,
Predicate<? super T> predicate
)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchObjects(getClientId(), clazz, predicate);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateObjectProperty(TCSObjectReference<?> ref, String key, String value)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateObjectProperty(getClientId(), ref, key, value);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void appendObjectHistoryEntry(TCSObjectReference<?> ref, ObjectHistory.Entry entry)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().appendObjectHistoryEntry(getClientId(), ref, entry);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
/**
* Declares the methods provided by the {@link TransportOrderService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link TransportOrderService}, with an additional {@link ClientID} parameter which serves the
* purpose of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link TransportOrderService} for these, instead.
* </p>
*/
public interface RemoteTransportOrderService
extends
RemoteTCSObjectService,
Remote {
// CHECKSTYLE:OFF
OrderSequence createOrderSequence(ClientID clientId, OrderSequenceCreationTO to)
throws RemoteException;
TransportOrder createTransportOrder(ClientID clientId, TransportOrderCreationTO to)
throws RemoteException;
void markOrderSequenceComplete(ClientID clientId, TCSObjectReference<OrderSequence> ref)
throws RemoteException;
void updateTransportOrderIntendedVehicle(
ClientID clientId,
TCSObjectReference<TransportOrder> orderRef,
TCSObjectReference<Vehicle> vehicleRef
)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,91 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
/**
* The default implementation of the transport order service.
* Delegates method invocations to the corresponding remote service.
*/
class RemoteTransportOrderServiceProxy
extends
RemoteTCSObjectServiceProxy<RemoteTransportOrderService>
implements
TransportOrderService {
/**
* Creates a new instance.
*/
RemoteTransportOrderServiceProxy() {
}
@Override
public OrderSequence createOrderSequence(OrderSequenceCreationTO to)
throws KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().createOrderSequence(getClientId(), to);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public TransportOrder createTransportOrder(TransportOrderCreationTO to)
throws ObjectUnknownException,
ObjectExistsException,
KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().createTransportOrder(getClientId(), to);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void markOrderSequenceComplete(TCSObjectReference<OrderSequence> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().markOrderSequenceComplete(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateTransportOrderIntendedVehicle(
TCSObjectReference<TransportOrder> orderRef,
TCSObjectReference<Vehicle> vehicleRef
)
throws ObjectUnknownException,
IllegalArgumentException {
checkServiceAvailability();
try {
getRemoteService().updateTransportOrderIntendedVehicle(getClientId(), orderRef, vehicleRef);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,112 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Set;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.VehicleService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.model.Vehicle.EnergyLevelThresholdSet;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
import org.opentcs.drivers.vehicle.management.VehicleAttachmentInformation;
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
import org.opentcs.util.annotations.ScheduledApiChange;
/**
* Declares the methods provided by the {@link VehicleService} via RMI.
*
* <p>
* The majority of the methods declared here have signatures analogous to their counterparts in
* {@link VehicleService}, with an additional {@link ClientID} parameter which serves the purpose
* of identifying the calling client and determining its permissions.
* </p>
* <p>
* To avoid redundancy, the semantics of methods that only pass through their arguments are not
* explicitly documented here again. See the corresponding API documentation in
* {@link VehicleService} for these, instead.
* </p>
*/
public interface RemoteVehicleService
extends
RemoteTCSObjectService,
Remote {
// CHECKSTYLE:OFF
void attachCommAdapter(
ClientID clientId, TCSObjectReference<Vehicle> ref,
VehicleCommAdapterDescription description
)
throws RemoteException;
void disableCommAdapter(ClientID clientId, TCSObjectReference<Vehicle> ref)
throws RemoteException;
void enableCommAdapter(ClientID clientId, TCSObjectReference<Vehicle> ref)
throws RemoteException;
VehicleAttachmentInformation fetchAttachmentInformation(
ClientID clientId,
TCSObjectReference<Vehicle> ref
)
throws RemoteException;
VehicleProcessModelTO fetchProcessModel(ClientID clientId, TCSObjectReference<Vehicle> ref)
throws RemoteException;
void sendCommAdapterCommand(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
AdapterCommand command
)
throws RemoteException;
void sendCommAdapterMessage(
ClientID clientId,
TCSObjectReference<Vehicle> vehicleRef,
Object message
)
throws RemoteException;
void updateVehicleIntegrationLevel(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
Vehicle.IntegrationLevel integrationLevel
)
throws RemoteException;
void updateVehiclePaused(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
boolean paused
)
throws RemoteException;
@ScheduledApiChange(when = "7.0", details = "Default implementation will be removed.")
default void updateVehicleEnergyLevelThresholdSet(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
EnergyLevelThresholdSet energyLevelThresholdSet
)
throws RemoteException {
throw new UnsupportedOperationException("Not yet implemented.");
}
void updateVehicleAllowedOrderTypes(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
Set<String> allowedOrderTypes
)
throws RemoteException;
void updateVehicleEnvelopeKey(
ClientID clientId,
TCSObjectReference<Vehicle> ref,
String envelopeKey
)
throws RemoteException;
// CHECKSTYLE:ON
}

View File

@@ -0,0 +1,221 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
import java.rmi.RemoteException;
import java.util.Set;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.VehicleService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.model.Vehicle.EnergyLevelThresholdSet;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
import org.opentcs.drivers.vehicle.management.VehicleAttachmentInformation;
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
/**
* The default implementation of the vehicle service.
* Delegates method invocations to the corresponding remote service.
*/
class RemoteVehicleServiceProxy
extends
RemoteTCSObjectServiceProxy<RemoteVehicleService>
implements
VehicleService {
/**
* Creates a new instance.
*/
RemoteVehicleServiceProxy() {
}
@Override
public void attachCommAdapter(
TCSObjectReference<Vehicle> ref,
VehicleCommAdapterDescription description
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().attachCommAdapter(getClientId(), ref, description);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void disableCommAdapter(TCSObjectReference<Vehicle> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().disableCommAdapter(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void enableCommAdapter(TCSObjectReference<Vehicle> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().enableCommAdapter(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public VehicleAttachmentInformation fetchAttachmentInformation(TCSObjectReference<Vehicle> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchAttachmentInformation(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public VehicleProcessModelTO fetchProcessModel(TCSObjectReference<Vehicle> ref)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
return getRemoteService().fetchProcessModel(getClientId(), ref);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void sendCommAdapterCommand(TCSObjectReference<Vehicle> ref, AdapterCommand command)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().sendCommAdapterCommand(getClientId(), ref, command);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void sendCommAdapterMessage(TCSObjectReference<Vehicle> ref, Object message)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().sendCommAdapterMessage(getClientId(), ref, message);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateVehicleIntegrationLevel(
TCSObjectReference<Vehicle> ref,
Vehicle.IntegrationLevel integrationLevel
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateVehicleIntegrationLevel(getClientId(), ref, integrationLevel);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateVehiclePaused(TCSObjectReference<Vehicle> ref, boolean paused)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateVehiclePaused(getClientId(), ref, paused);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateVehicleEnergyLevelThresholdSet(
TCSObjectReference<Vehicle> ref,
EnergyLevelThresholdSet energyLevelThresholdSet
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateVehicleEnergyLevelThresholdSet(
getClientId(),
ref,
energyLevelThresholdSet
);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateVehicleAllowedOrderTypes(
TCSObjectReference<Vehicle> ref,
Set<String> allowedOrderTypes
)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateVehicleAllowedOrderTypes(
getClientId(),
ref,
allowedOrderTypes
);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
@Override
public void updateVehicleEnvelopeKey(TCSObjectReference<Vehicle> ref, String envelopeKey)
throws ObjectUnknownException,
KernelRuntimeException {
checkServiceAvailability();
try {
getRemoteService().updateVehicleEnvelopeKey(getClientId(), ref, envelopeKey);
}
catch (RemoteException ex) {
throw findSuitableExceptionFor(ex);
}
}
}

View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.rmi.services;
/**
* Provides callback methods for instances interested in service updates.
*/
public interface ServiceListener {
/**
* Notifies a listener that the service is unavailable, i.e. is not in a usable state.
*/
void onServiceUnavailable();
}

View File

@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Interfaces and classes for transparently providing an openTCS kernel's service functionality via
* RMI.
*/
package org.opentcs.access.rmi.services;

View File

@@ -0,0 +1,180 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The base class for all creation transfer objects.
*/
public class CreationTO
implements
Serializable {
/**
* The name of this transfer object.
*/
@Nonnull
private final String name;
/**
* The properties of this transfer object.
*/
@Nonnull
private final Map<String, String> properties;
/**
* Creates a new instance.
*
* @param name The name of this transfer object.
*/
public CreationTO(
@Nonnull
String name
) {
this.name = requireNonNull(name, "name");
this.properties = Map.of();
}
protected CreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties
) {
this.name = requireNonNull(name, "name");
this.properties = requireNonNull(properties, "properties");
}
/**
* Returns the name of this transfer object.
*
* @return The name of this transfer object.
*/
@Nonnull
public String getName() {
return name;
}
/**
* Creates a copy of this object with the given name.
*
* @param name the new name
* @return A copy of this object, differing in the given value.
*/
public CreationTO withName(
@Nonnull
String name
) {
return new CreationTO(
name,
properties
);
}
/**
* Returns the properties of this transfer object in an unmodifiable map.
*
* @return The properties of this transfer object in an unmodifiable map.
*/
@Nonnull
public Map<String, String> getProperties() {
return Collections.unmodifiableMap(properties);
}
/**
* Returns the properties of this transfer object.
*
* @return The properties of this transfer object.
*/
protected Map<String, String> getModifiableProperties() {
return properties;
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The properties.
* @return A copy of this object with the given properties.
*/
public CreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new CreationTO(name, properties);
}
/**
* Creates a copy of this object with the given property.
* If value == null is true then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that includes the given property or
* removes the entry, if value == null.
*/
public CreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new CreationTO(
name,
propertiesWith(key, value)
);
}
protected final Map<String, String> propertiesWith(String key, String value) {
return mapWithMapping(properties, key, value);
}
/**
* Returns a new map, with the mappings of the given map and the given mapping added to it.
*
* @param <K> The type of the map's keys.
* @param <V> The type of the map's values.
* @param map The map to be extended.
* @param key The key.
* @param value The value. May be <code>null</code> to remove the mapping from the given map.
* @return a new map, with the mappings of the given map and the given mapping added to it.
*/
protected static final <K, V> Map<K, V> mapWithMapping(Map<K, V> map, K key, V value) {
requireNonNull(map, "map");
requireNonNull(key, "key");
Map<K, V> result = new HashMap<>(map);
if (value == null) {
result.remove(key);
}
else {
result.put(key, value);
}
return result;
}
/**
* Returns a new list, with the elements of the given list and the given element added to it.
*
* @param <T> The element type of the list.
* @param list The list to be extended.
* @param newElement The element to be added to the list.
* @return A new list, consisting of the given list and the given element added to it.
*/
protected static final <T> List<T> listWithAppendix(List<T> list, T newElement) {
List<T> result = new ArrayList<>(list.size() + 1);
result.addAll(list);
result.add(newElement);
return result;
}
}

View File

@@ -0,0 +1,291 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.awt.Color;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.Block;
/**
* A transfer object describing a block in the plant model.
*/
public class BlockCreationTO
extends
CreationTO
implements
Serializable {
/**
* This block's type.
*/
@Nonnull
private final Block.Type type;
/**
* This block's member names.
*/
@Nonnull
private final Set<String> memberNames;
/**
* The information regarding the grahical representation of this block.
*/
private final Layout layout;
/**
* Creates a new instance.
*
* @param name The name of this block.
*/
public BlockCreationTO(String name) {
super(name);
this.type = Block.Type.SINGLE_VEHICLE_ONLY;
this.memberNames = Set.of();
this.layout = new Layout();
}
/**
* Creates a new block.
*
* @param name the name of the new block.
* @param memberNames the names of the block's members.
* @param properties the properties.
*/
private BlockCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
Block.Type type,
@Nonnull
Set<String> memberNames,
@Nonnull
Layout layout
) {
super(name, properties);
this.type = requireNonNull(type, "type");
this.memberNames = requireNonNull(memberNames, "memberNames");
this.layout = requireNonNull(layout, "layout");
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new name.
* @return A copy of this object, differing in the given name.
*/
@Override
public BlockCreationTO withName(
@Nonnull
String name
) {
return new BlockCreationTO(
name,
getModifiableProperties(),
type,
memberNames,
layout
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public BlockCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new BlockCreationTO(
getName(),
properties,
type,
memberNames,
layout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public BlockCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new BlockCreationTO(
getName(),
propertiesWith(key, value),
type,
memberNames,
layout
);
}
/**
* Returns the type of this block.
*
* @return The type of this block.
*/
@Nonnull
public Block.Type getType() {
return type;
}
/**
* Creates a copy of this object with the given type.
*
* @param type The new type.
* @return A copy of this object, differing in the given type.
*/
public BlockCreationTO withType(
@Nonnull
Block.Type type
) {
return new BlockCreationTO(
getName(),
getModifiableProperties(),
type,
memberNames,
layout
);
}
/**
* Returns the names of this block's members.
*
* @return The names of this block's members.
*/
@Nonnull
public Set<String> getMemberNames() {
return Collections.unmodifiableSet(memberNames);
}
/**
* Creates a copy of this object with the given members.
*
* @param memberNames The names of the block's members.
* @return A copy of this object, differing in the given value.
*/
public BlockCreationTO withMemberNames(
@Nonnull
Set<String> memberNames
) {
return new BlockCreationTO(
getName(),
getModifiableProperties(),
type,
memberNames,
layout
);
}
/**
* Returns the information regarding the grahical representation of this block.
*
* @return The information regarding the grahical representation of this block.
*/
public Layout getLayout() {
return layout;
}
/**
* Creates a copy of this object, with the given layout.
*
* @param layout The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public BlockCreationTO withLayout(Layout layout) {
return new BlockCreationTO(
getName(),
getModifiableProperties(),
type,
memberNames,
layout
);
}
@Override
public String toString() {
return "BlockCreationTO{"
+ "name=" + getName()
+ ", type=" + type
+ ", memberNames=" + memberNames
+ ", layout=" + layout
+ ", properties=" + getProperties()
+ '}';
}
/**
* Contains information regarding the grahical representation of a block.
*/
public static class Layout
implements
Serializable {
/**
* The color in which block elements are to be emphasized.
*/
private final Color color;
/**
* Creates a new instance.
*/
public Layout() {
this(Color.RED);
}
/**
* Creates a new instance.
*
* @param color The color in which block elements are to be emphasized.
*/
public Layout(Color color) {
this.color = requireNonNull(color, "color");
}
/**
* Returns the color in which block elements are to be emphasized.
*
* @return The color in which block elements are to be emphasized.
*/
public Color getColor() {
return color;
}
/**
* Creates a copy of this object, with the given color.
*
* @param color The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withColor(Color color) {
return new Layout(color);
}
@Override
public String toString() {
return "Layout{"
+ "color=" + color
+ '}';
}
}
}

View File

@@ -0,0 +1,120 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkInRange;
import java.io.Serializable;
/**
* A transfer object describing a bounding box.
*/
public class BoundingBoxCreationTO
implements
Serializable {
private final long length;
private final long width;
private final long height;
private final CoupleCreationTO referenceOffset;
/**
* Creates a new instance with a (0, 0) reference offset.
*
* @param length The bounding box's length.
* @param width The bounding box's width.
* @param height The bounding box's height.
*/
public BoundingBoxCreationTO(long length, long width, long height) {
this(length, width, height, new CoupleCreationTO(0, 0));
}
private BoundingBoxCreationTO(
long length,
long width,
long height,
CoupleCreationTO referenceOffset
) {
this.length = checkInRange(length, 1, Long.MAX_VALUE, "length");
this.width = checkInRange(width, 1, Long.MAX_VALUE, "width");
this.height = checkInRange(height, 1, Long.MAX_VALUE, "height");
this.referenceOffset = requireNonNull(referenceOffset, "referenceOffset");
}
/**
* Returns the bounding box's length.
*
* @return The bounding box's length.
*/
public long getLength() {
return length;
}
/**
* Creates a copy of this object, with the given length.
*
* @param length The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public BoundingBoxCreationTO withLength(long length) {
return new BoundingBoxCreationTO(length, width, height, referenceOffset);
}
/**
* Returns the bounding box's width.
*
* @return The bounding box's width.
*/
public long getWidth() {
return width;
}
/**
* Creates a copy of this object, with the given width.
*
* @param width The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public BoundingBoxCreationTO withWidth(long width) {
return new BoundingBoxCreationTO(length, width, height, referenceOffset);
}
/**
* Returns the bounding box's height.
*
* @return The bounding box's height.
*/
public long getHeight() {
return height;
}
/**
* Creates a copy of this object, with the given height.
*
* @param height The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public BoundingBoxCreationTO withHeight(long height) {
return new BoundingBoxCreationTO(length, width, height, referenceOffset);
}
/**
* Returns the bounding box's reference offset.
*
* @return The bounding box's reference offset.
*/
public CoupleCreationTO getReferenceOffset() {
return referenceOffset;
}
/**
* Creates a copy of this object, with the given reference offset.
*
* @param referenceOffset The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public BoundingBoxCreationTO withReferenceOffset(CoupleCreationTO referenceOffset) {
return new BoundingBoxCreationTO(length, width, height, referenceOffset);
}
}

View File

@@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import java.io.Serializable;
/**
* A transfer object describing generic 2-tuple of long integer values.
*/
public class CoupleCreationTO
implements
Serializable {
private final long x;
private final long y;
/**
* Creates a new instance.
*
* @param x The X coordinate.
* @param y The Y coordinate.
*/
public CoupleCreationTO(long x, long y) {
this.x = x;
this.y = y;
}
/**
* Returns the x coordinate.
*
* @return The x coordinate.
*/
public long getX() {
return x;
}
/**
* Creates a copy of this object, with the given x coordinate.
*
* @param x The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public CoupleCreationTO withX(long x) {
return new CoupleCreationTO(x, y);
}
/**
* Returns the y coordinate.
*
* @return The y coordinate.
*/
public long getY() {
return y;
}
/**
* Creates a copy of this object, with the given y coordinate.
*
* @param y The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public CoupleCreationTO withY(long y) {
return new CoupleCreationTO(x, y);
}
}

View File

@@ -0,0 +1,515 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.visualization.LocationRepresentation;
/**
* A transfer object describing a location in a plant model.
*/
public class LocationCreationTO
extends
CreationTO
implements
Serializable {
/**
* The name of this location's type.
*/
@Nonnull
private final String typeName;
/**
* This location's position (in mm).
*/
@Nonnull
private final Triple position;
/**
* The links attaching points to this location.
* This is a map of point names to allowed operations.
*/
@Nonnull
private final Map<String, Set<String>> links;
/**
* A flag for marking this location as locked (i.e. to prevent vehicles from using it).
*/
private final boolean locked;
/**
* The information regarding the grahical representation of this location.
*/
private final Layout layout;
/**
* Creates a new instance.
*
* @param name The name of this location.
* @param typeName The name of this location's type.
* @param position The position of this location.
*/
public LocationCreationTO(
@Nonnull
String name,
@Nonnull
String typeName,
@Nonnull
Triple position
) {
super(name);
this.typeName = requireNonNull(typeName, "typeName");
this.position = position;
this.links = Map.of();
this.locked = false;
this.layout = new Layout();
}
private LocationCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
String typeName,
@Nonnull
Triple position,
@Nonnull
Map<String, Set<String>> links,
boolean locked,
@Nonnull
Layout layout
) {
super(name, properties);
this.typeName = requireNonNull(typeName, "typeName");
this.position = requireNonNull(position, "position");
this.links = requireNonNull(links, "links");
this.locked = locked;
this.layout = requireNonNull(layout, "layout");
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new name.
* @return A copy of this object, differing in the given name.
*/
@Override
public LocationCreationTO withName(
@Nonnull
String name
) {
return new LocationCreationTO(
name,
getModifiableProperties(),
typeName,
position,
links,
locked,
layout
);
}
/**
* Returns the name of this location's type.
*
* @return The name of this location's type.
*/
@Nonnull
public String getTypeName() {
return typeName;
}
/**
* Creates a copy of this object with the location's type.
*
* @param typeName The location type.
* @return A copy of this object, differing in the given type.
*/
public LocationCreationTO withTypeName(
@Nonnull
String typeName
) {
return new LocationCreationTO(
getName(),
getModifiableProperties(),
typeName,
position,
links,
locked,
layout
);
}
/**
* Returns the position of this location (in mm).
*
* @return The position of this location (in mm).
*/
@Nonnull
public Triple getPosition() {
return position;
}
/**
* Creates a copy of this object with the given position (in mm).
*
* @param position the new position of this location (in mm).
* @return A copy of this object, differing in the given position.
*/
public LocationCreationTO withPosition(
@Nonnull
Triple position
) {
return new LocationCreationTO(
getName(),
getModifiableProperties(),
typeName,
position,
links,
locked,
layout
);
}
/**
* Returns the links attaching points to this location.
* This is a map of point names to allowed operations.
*
* @return The links attaching points to this location.
*/
@Nonnull
public Map<String, Set<String>> getLinks() {
return Collections.unmodifiableMap(links);
}
/**
* Creates a copy of this object with the given links that attach points to this location.
*
* @param links the new links. This is supposed to be a map of point names to allowed operations.
* @return A copy of this object, differing in the given links.
*/
public LocationCreationTO withLinks(
@Nonnull
Map<String, Set<String>> links
) {
return new LocationCreationTO(
getName(),
getModifiableProperties(),
typeName,
position,
links,
locked,
layout
);
}
/**
* Creates a copy of this object with the given links that attach points to this location.
*
* @param pointName The name of the point linked to.
* @param allowedOperations The operations allowed at the point.
* @return A copy of this object, differing in the given link.
*/
public LocationCreationTO withLink(
@Nonnull
String pointName,
@Nonnull
Set<String> allowedOperations
) {
return new LocationCreationTO(
getName(),
getModifiableProperties(),
typeName,
position,
mapWithMapping(links, pointName, allowedOperations),
locked,
layout
);
}
/**
* Returns the lock status of this location (i.e. whether it my be used by vehicles or not).
*
* @return {@code true} if this location is currently locked (i.e. it may not be used
* by vehicles), else {@code false}.
*/
public boolean isLocked() {
return locked;
}
/**
* Creates a copy of this object with the given locked flag.
*
* @param locked The new locked attribute.
* @return A copy of this object, differing in the locked attribute.
*/
public LocationCreationTO withLocked(boolean locked) {
return new LocationCreationTO(
getName(),
getModifiableProperties(),
typeName,
position,
links,
locked,
layout
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public LocationCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new LocationCreationTO(
getName(),
properties,
typeName,
position,
links,
locked,
layout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public LocationCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new LocationCreationTO(
getName(),
propertiesWith(key, value),
typeName,
position,
links,
locked,
layout
);
}
/**
* Returns the information regarding the grahical representation of this location.
*
* @return The information regarding the grahical representation of this location.
*/
public Layout getLayout() {
return layout;
}
/**
* Creates a copy of this object, with the given layout.
*
* @param layout The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public LocationCreationTO withLayout(Layout layout) {
return new LocationCreationTO(
getName(),
getModifiableProperties(),
typeName,
position,
links,
locked,
layout
);
}
@Override
public String toString() {
return "LocationCreationTO{"
+ "name=" + getName()
+ ", typeName=" + typeName
+ ", position=" + position
+ ", links=" + links
+ ", locked=" + locked
+ ", layout=" + layout
+ ", properties=" + getProperties()
+ '}';
}
/**
* Contains information regarding the grahical representation of a location.
*/
public static class Layout
implements
Serializable {
/**
* The coordinates at which the location is to be drawn (in mm).
*/
private final Couple position;
/**
* The offset of the label's position to the location's position (in lu).
*/
private final Couple labelOffset;
/**
* The location representation to use.
*/
private final LocationRepresentation locationRepresentation;
/**
* The ID of the layer on which the location is to be drawn.
*/
private final int layerId;
/**
* Creates a new instance.
*/
public Layout() {
this(new Couple(0, 0), new Couple(0, 0), LocationRepresentation.DEFAULT, 0);
}
/**
* Creates a new instance.
*
* @param position The coordinates at which the location is to be drawn (in mm).
* @param labelOffset The offset of the label's location to the point's position (in lu).
* @param locationRepresentation The location representation to use.
* @param layerId The ID of the layer on which the location is to be drawn.
*/
public Layout(
Couple position,
Couple labelOffset,
LocationRepresentation locationRepresentation,
int layerId
) {
this.position = requireNonNull(position, "position");
this.labelOffset = requireNonNull(labelOffset, "labelOffset");
this.locationRepresentation = requireNonNull(
locationRepresentation,
"locationRepresentation"
);
this.layerId = layerId;
}
/**
* Returns the coordinates at which the location is to be drawn (in mm).
*
* @return The coordinates at which the location is to be drawn (in mm).
*/
public Couple getPosition() {
return position;
}
/**
* Creates a copy of this object, with the given position.
*
* @param position The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withPosition(Couple position) {
return new Layout(
position,
labelOffset,
locationRepresentation,
layerId
);
}
/**
* Returns the offset of the label's position to the location's position (in lu).
*
* @return The offset of the label's position to the location's position (in lu).
*/
public Couple getLabelOffset() {
return labelOffset;
}
/**
* Creates a copy of this object, with the given X label offset.
*
* @param labelOffset The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLabelOffset(Couple labelOffset) {
return new Layout(
position,
labelOffset,
locationRepresentation,
layerId
);
}
/**
* Returns the location representation to use.
*
* @return The location representation to use.
*/
public LocationRepresentation getLocationRepresentation() {
return locationRepresentation;
}
/**
* Creates a copy of this object, with the given location representation.
*
* @param locationRepresentation The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLocationRepresentation(LocationRepresentation locationRepresentation) {
return new Layout(
position,
labelOffset,
locationRepresentation,
layerId
);
}
/**
* Returns the ID of the layer on which the location is to be drawn.
*
* @return The layer ID.
*/
public int getLayerId() {
return layerId;
}
/**
* Creates a copy of this object, with the given layer ID.
*
* @param layerId The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLayerId(int layerId) {
return new Layout(
position,
labelOffset,
locationRepresentation,
layerId
);
}
@Override
public String toString() {
return "Layout{"
+ "position=" + position
+ ", labelOffset=" + labelOffset
+ ", locationRepresentation=" + locationRepresentation
+ ", layerId=" + layerId
+ '}';
}
}
}

View File

@@ -0,0 +1,291 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.visualization.LocationRepresentation;
/**
* A transfer object describing a location type in the plant model.
*/
public class LocationTypeCreationTO
extends
CreationTO
implements
Serializable {
/**
* The allowed operations for this location type.
*/
private final List<String> allowedOperations;
/**
* The allowed peripheral operations for this location type.
*/
private final List<String> allowedPeripheralOperations;
/**
* The information regarding the grahical representation of this location type.
*/
private final Layout layout;
/**
* Creates a new instance.
*
* @param name The name of this location type.
*/
public LocationTypeCreationTO(
@Nonnull
String name
) {
super(name);
this.allowedOperations = List.of();
this.allowedPeripheralOperations = List.of();
this.layout = new Layout();
}
private LocationTypeCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
List<String> allowedOperations,
@Nonnull
List<String> allowedPeripheralOperations,
@Nonnull
Layout layout
) {
super(name, properties);
this.allowedOperations = requireNonNull(allowedOperations, "allowedOperations");
this.allowedPeripheralOperations = requireNonNull(
allowedPeripheralOperations,
"allowedPeripheralOperations"
);
this.layout = requireNonNull(layout, "layout");
}
/**
* Returns the allowed operations for this location type.
*
* @return The allowed operations for this location type.
*/
@Nonnull
public List<String> getAllowedOperations() {
return Collections.unmodifiableList(allowedOperations);
}
/**
* Creates a copy of this object with the given allowed operations.
*
* @param allowedOperations the new allowed operations.
* @return A copy of this object, differing in the given value.
*/
public LocationTypeCreationTO withAllowedOperations(
@Nonnull
List<String> allowedOperations
) {
return new LocationTypeCreationTO(
getName(),
getModifiableProperties(),
allowedOperations,
allowedPeripheralOperations,
layout
);
}
/**
* Returns the allowed peripheral operations for this location type.
*
* @return The allowed peripheral operations for this location type.
*/
@Nonnull
public List<String> getAllowedPeripheralOperations() {
return Collections.unmodifiableList(allowedPeripheralOperations);
}
/**
* Creates a copy of this object with the given allowed peripheral operations.
*
* @param allowedPeripheralOperations the new allowed peripheral operations.
* @return A copy of this object, differing in the given value.
*/
public LocationTypeCreationTO withAllowedPeripheralOperations(
@Nonnull
List<String> allowedPeripheralOperations
) {
return new LocationTypeCreationTO(
getName(),
getModifiableProperties(),
allowedOperations,
allowedPeripheralOperations,
layout
);
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new name.
* @return A copy of this object, differing in the given name.
*/
@Override
public LocationTypeCreationTO withName(
@Nonnull
String name
) {
return new LocationTypeCreationTO(
name,
getProperties(),
allowedOperations,
allowedPeripheralOperations,
layout
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public LocationTypeCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new LocationTypeCreationTO(
getName(),
properties,
allowedOperations,
allowedPeripheralOperations,
layout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public LocationTypeCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new LocationTypeCreationTO(
getName(),
propertiesWith(key, value),
allowedOperations,
allowedPeripheralOperations,
layout
);
}
/**
* Returns the information regarding the grahical representation of this location type.
*
* @return The information regarding the grahical representation of this location type.
*/
public Layout getLayout() {
return layout;
}
/**
* Creates a copy of this object, with the given layout.
*
* @param layout The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public LocationTypeCreationTO withLayout(Layout layout) {
return new LocationTypeCreationTO(
getName(),
getModifiableProperties(),
allowedOperations,
allowedPeripheralOperations,
layout
);
}
@Override
public String toString() {
return "LocationTypeCreationTO{"
+ "name=" + getName()
+ ", allowedOperations=" + allowedOperations
+ ", allowedPeripheralOperations" + allowedPeripheralOperations
+ ", layout=" + layout
+ ", properties=" + getProperties()
+ '}';
}
/**
* Contains information regarding the grahical representation of a location type.
*/
public static class Layout
implements
Serializable {
/**
* The location representation to use for locations with this location type.
*/
private final LocationRepresentation locationRepresentation;
/**
* Creates a new instance.
*/
public Layout() {
this(LocationRepresentation.NONE);
}
/**
* Creates a new instance.
*
* @param locationRepresentation The location representation to use for locations with this
* location type.
*/
public Layout(LocationRepresentation locationRepresentation) {
this.locationRepresentation = requireNonNull(
locationRepresentation,
"locationRepresentation"
);
}
/**
* Returns the location representation to use for locations with this location type.
*
* @return The location representation to use for locations with this location type.
*/
public LocationRepresentation getLocationRepresentation() {
return locationRepresentation;
}
/**
* Creates a copy of this object, with the given location representation.
*
* @param locationRepresentation The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLocationRepresentation(LocationRepresentation locationRepresentation) {
return new Layout(locationRepresentation);
}
@Override
public String toString() {
return "Layout{"
+ "locationRepresentation=" + locationRepresentation
+ '}';
}
}
}

View File

@@ -0,0 +1,651 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkArgument;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Envelope;
import org.opentcs.data.model.Path.Layout.ConnectionType;
/**
* A transfer object describing a path in the plant model.
*/
public class PathCreationTO
extends
CreationTO
implements
Serializable {
/**
* The point name this path originates in.
*/
@Nonnull
private final String srcPointName;
/**
* The point name this path ends in.
*/
@Nonnull
private final String destPointName;
/**
* This path's length (in mm).
*/
private final long length;
/**
* The absolute maximum allowed forward velocity on this path (in mm/s).
* A value of 0 (default) means forward movement is not allowed on this path.
*/
private final int maxVelocity;
/**
* The absolute maximum allowed reverse velocity on this path (in mm/s).
* A value of 0 (default) means reverse movement is not allowed on this path.
*/
private final int maxReverseVelocity;
/**
* The peripheral operations to be performed when a vehicle travels along this path.
*/
private final List<PeripheralOperationCreationTO> peripheralOperations;
/**
* A flag for marking this path as locked (i.e. to prevent vehicles from using it).
*/
private final boolean locked;
/**
* A map of envelope keys to envelopes that vehicles traversing this path may occupy.
*/
private final Map<String, Envelope> vehicleEnvelopes;
/**
* The information regarding the grahical representation of this path.
*/
private final Layout layout;
/**
* Creates a new instance.
*
* @param name The name of this path.
* @param srcPointName The point name this path originates in.
* @param destPointName The point name this path ends in.
*/
public PathCreationTO(
@Nonnull
String name,
@Nonnull
String srcPointName,
@Nonnull
String destPointName
) {
super(name);
this.srcPointName = requireNonNull(srcPointName, "srcPointName");
this.destPointName = requireNonNull(destPointName, "destPointName");
this.length = 1;
this.maxVelocity = 0;
this.maxReverseVelocity = 0;
this.peripheralOperations = List.of();
this.locked = false;
this.vehicleEnvelopes = Map.of();
this.layout = new Layout();
}
private PathCreationTO(
String name,
@Nonnull
String srcPointName,
@Nonnull
String destPointName,
@Nonnull
Map<String, String> properties,
long length,
int maxVelocity,
int maxReverseVelocity,
List<PeripheralOperationCreationTO> peripheralOperations,
boolean locked,
@Nonnull
Map<String, Envelope> vehicleEnvelopes,
@Nonnull
Layout layout
) {
super(name, properties);
this.srcPointName = requireNonNull(srcPointName, "srcPointName");
this.destPointName = requireNonNull(destPointName, "destPointName");
this.length = length;
this.maxVelocity = maxVelocity;
this.maxReverseVelocity = maxReverseVelocity;
this.peripheralOperations = new ArrayList<>(
requireNonNull(
peripheralOperations,
"peripheralOperations"
)
);
this.locked = locked;
this.vehicleEnvelopes = requireNonNull(vehicleEnvelopes, "vehicleEnvelopes");
this.layout = requireNonNull(layout, "layout");
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new name.
* @return A copy of this object, differing in the given name.
*/
@Override
public PathCreationTO withName(
@Nonnull
String name
) {
return new PathCreationTO(
name,
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the point name this path originates in.
*
* @return The point name this path originates in.
*/
@Nonnull
public String getSrcPointName() {
return srcPointName;
}
/**
* Creates a copy of this object with the given point name this path originates in.
*
* @param srcPointName The new source point name.
* @return A copy of this object, differing in the given source point.
*/
public PathCreationTO withSrcPointName(
@Nonnull
String srcPointName
) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the point name this path ends in.
*
* @return The point name this path ends in.
*/
@Nonnull
public String getDestPointName() {
return destPointName;
}
/**
* Creates a copy of this object with the given destination point.
*
* @param destPointName The new source point.
* @return A copy of this object, differing in the given value.
*/
public PathCreationTO withDestPointName(
@Nonnull
String destPointName
) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the length of this path (in mm).
*
* @return The length of this path (in mm).
*/
public long getLength() {
return length;
}
/**
* Creates a copy of this object with the given path length (in mm).
*
* @param length the new length (in mm). Must be a positive value.
* @return A copy of this object, differing in the given length.
*/
public PathCreationTO withLength(long length) {
checkArgument(length > 0, "length must be a positive value: " + length);
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the maximum allowed forward velocity (in mm/s) for this path.
*
* @return The maximum allowed forward velocity (in mm/s). A value of 0 means forward movement is
* not allowed on this path.
*/
public int getMaxVelocity() {
return maxVelocity;
}
/**
* Creates a copy of this object with the maximum allowed forward velocity (in mm/s) for this
* path.
*
* @param maxVelocity The new maximum allowed velocity (in mm/s). May not be a negative value.
* @return A copy of this object, differing in the given maximum velocity.
*/
public PathCreationTO withMaxVelocity(int maxVelocity) {
checkArgument(
maxVelocity >= 0,
"maxVelocity may not be a negative value: " + maxVelocity
);
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the maximum allowed reverse velocity (in mm/s) for this path.
*
* @return The maximum allowed reverse velocity (in mm/s). A value of 0 means reverse movement is
* not allowed on this path.
*/
public int getMaxReverseVelocity() {
return maxReverseVelocity;
}
/**
* Creates a copy of this object with the allowed maximum reverse velocity (in mm/s).
*
* @param maxReverseVelocity The new maximum allowed reverse velocity (in mm/s). Must not be a
* negative value.
* @return A copy of this object, differing in the given maximum reverse velocity.
*/
public PathCreationTO withMaxReverseVelocity(int maxReverseVelocity) {
checkArgument(
maxReverseVelocity >= 0,
"maxReverseVelocity may not be a negative value: " + maxReverseVelocity
);
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the peripheral operations to be performed when a vehicle travels along this path.
*
* @return The peripheral operations to be performed when a vehicle travels along this path.
*/
public List<PeripheralOperationCreationTO> getPeripheralOperations() {
return Collections.unmodifiableList(peripheralOperations);
}
/**
* Creates a copy of this object with the given peripheral operations.
*
* @param peripheralOperations The peripheral operations.
* @return A copy of this object, differing in the given peripheral operations.
*/
public PathCreationTO withPeripheralOperations(
@Nonnull
List<PeripheralOperationCreationTO> peripheralOperations
) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the lock status of this path (i.e. whether this path my be used by vehicles or not).
*
* @return {@code true} if this path is currently locked (i.e. it may not be used by vehicles),
* else {@code false}.
*/
public boolean isLocked() {
return locked;
}
/**
* Creates a copy of this object that is locked if {@code locked==true} and unlocked otherwise.
*
* @param locked If {@code true}, this path will be locked when the method call returns; if
* {@code false}, this path will be unlocked.
* @return a copy of this object, differing in the locked attribute.
*/
public PathCreationTO withLocked(boolean locked) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public PathCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
properties,
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public PathCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
propertiesWith(key, value),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns a map of envelope keys to envelopes that vehicles traversing this path may occupy.
*
* @return A map of envelope keys to envelopes that vehicles traversing this path may occupy.
*/
public Map<String, Envelope> getVehicleEnvelopes() {
return vehicleEnvelopes;
}
/**
* Creates a copy of this object, with the given vehicle envelopes.
*
* @param vehicleEnvelopes The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PathCreationTO withVehicleEnvelopes(
@Nonnull
Map<String, Envelope> vehicleEnvelopes
) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
/**
* Returns the information regarding the grahical representation of this path.
*
* @return The information regarding the grahical representation of this path.
*/
public Layout getLayout() {
return layout;
}
/**
* Creates a copy of this object, with the given layout.
*
* @param layout The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PathCreationTO withLayout(Layout layout) {
return new PathCreationTO(
getName(),
srcPointName,
destPointName,
getModifiableProperties(),
length,
maxVelocity,
maxReverseVelocity,
peripheralOperations,
locked,
vehicleEnvelopes,
layout
);
}
@Override
public String toString() {
return "PathCreationTO{"
+ "name=" + getName()
+ ", srcPointName=" + srcPointName
+ ", destPointName=" + destPointName
+ ", length=" + length
+ ", maxVelocity=" + maxVelocity
+ ", maxReverseVelocity=" + maxReverseVelocity
+ ", peripheralOperations=" + peripheralOperations
+ ", locked=" + locked
+ ", layout=" + layout
+ ", vehicleEnvelopes=" + vehicleEnvelopes
+ ", properties=" + getProperties()
+ '}';
}
/**
* Contains information regarding the grahical representation of a path.
*/
public static class Layout
implements
Serializable {
/**
* The connection type the path is represented as.
*/
private final ConnectionType connectionType;
/**
* Control points describing the way the path is drawn (if the connection type
* is {@link ConnectionType#BEZIER}, {@link ConnectionType#BEZIER_3}
* or {@link ConnectionType#POLYPATH}).
*/
private final List<Couple> controlPoints;
/**
* The ID of the layer on which the path is to be drawn.
*/
private final int layerId;
/**
* Creates a new instance.
*/
public Layout() {
this(ConnectionType.DIRECT, new ArrayList<>(), 0);
}
/**
* Creates a new instance.
*
* @param connectionType The connection type a path is represented as.
* @param controlPoints Control points describing the way the path is drawn.
* @param layerId The ID of the layer on which the path is to be drawn.
*/
public Layout(ConnectionType connectionType, List<Couple> controlPoints, int layerId) {
this.connectionType = connectionType;
this.controlPoints = requireNonNull(controlPoints, "controlPoints");
this.layerId = layerId;
}
/**
* Returns the connection type the path is represented as.
*
* @return The connection type the path is represented as.
*/
public ConnectionType getConnectionType() {
return connectionType;
}
/**
* Creates a copy of this object, with the given connection type.
*
* @param connectionType The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withConnectionType(ConnectionType connectionType) {
return new Layout(connectionType, controlPoints, layerId);
}
/**
* Returns the control points describing the way the path is drawn.
* Returns an empty list if connection type is not {@link ConnectionType#BEZIER},
* {@link ConnectionType#BEZIER_3} or {@link ConnectionType#POLYPATH}.
*
* @return The control points describing the way the path is drawn.
*/
public List<Couple> getControlPoints() {
return Collections.unmodifiableList(controlPoints);
}
/**
* Creates a copy of this object, with the given control points.
*
* @param controlPoints The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withControlPoints(List<Couple> controlPoints) {
return new Layout(connectionType, controlPoints, layerId);
}
/**
* Returns the ID of the layer on which the path is to be drawn.
*
* @return The layer ID.
*/
public int getLayerId() {
return layerId;
}
/**
* Creates a copy of this object, with the given layer ID.
*
* @param layerId The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLayer(int layerId) {
return new Layout(connectionType, controlPoints, layerId);
}
@Override
public String toString() {
return "Layout{"
+ "connectionType=" + connectionType
+ ", controlPoints=" + controlPoints
+ ", layerId=" + layerId
+ '}';
}
}
}

View File

@@ -0,0 +1,598 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.ModelConstants;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A transfer object describing a plant model.
*/
public class PlantModelCreationTO
extends
CreationTO
implements
Serializable {
/**
* This class's logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(PlantModelCreationTO.class);
/**
* The plant model's points.
*/
private final List<PointCreationTO> points;
/**
* The plant model's paths.
*/
private final List<PathCreationTO> paths;
/**
* The plant model's location types.
*/
private final List<LocationTypeCreationTO> locationTypes;
/**
* The plant model's locations.
*/
private final List<LocationCreationTO> locations;
/**
* The plant model's blocks.
*/
private final List<BlockCreationTO> blocks;
/**
* The plant model's vehicles.
*/
private final List<VehicleCreationTO> vehicles;
/**
* The plant model's visual layout.
*/
private final VisualLayoutCreationTO visualLayout;
/**
* Creates a new instance.
*
* @param name The name of this plant model.
*/
public PlantModelCreationTO(String name) {
super(name);
this.points = List.of();
this.paths = List.of();
this.locationTypes = List.of();
this.locations = List.of();
this.blocks = List.of();
this.vehicles = List.of();
this.visualLayout = defaultVisualLayout();
}
private PlantModelCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
List<PointCreationTO> points,
@Nonnull
List<PathCreationTO> paths,
@Nonnull
List<LocationTypeCreationTO> locationTypes,
@Nonnull
List<LocationCreationTO> locations,
@Nonnull
List<BlockCreationTO> blocks,
@Nonnull
List<VehicleCreationTO> vehicles,
@Nonnull
VisualLayoutCreationTO visualLayout
) {
super(name, properties);
this.points = requireNonNull(points, "points");
this.paths = requireNonNull(paths, "paths");
this.locationTypes = requireNonNull(locationTypes, "locationTypes");
this.locations = requireNonNull(locations, "locations");
this.blocks = requireNonNull(blocks, "blocks");
this.vehicles = requireNonNull(vehicles, "vehicles");
this.visualLayout = requireNonNull(visualLayout, "visualLayout");
}
/**
* Returns this plant model's points.
*
* @return This plant model's points.
*/
public List<PointCreationTO> getPoints() {
return Collections.unmodifiableList(points);
}
/**
* Creates a copy of this object with the given points.
*
* @param points The new points.
* @return A copy of this model, differing in the given points.
*/
public PlantModelCreationTO withPoints(
@Nonnull
List<PointCreationTO> points
) {
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object that includes the given point in the list of points.
*
* @param point the new point.
* @return A copy of this model that also includes the given point.
*/
public PlantModelCreationTO withPoint(
@Nonnull
PointCreationTO point
) {
requireNonNull(point, "point");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
listWithAppendix(points, point),
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Returns this plant model's paths.
*
* @return This plant model's paths.
*/
public List<PathCreationTO> getPaths() {
return Collections.unmodifiableList(paths);
}
/**
* Creates a copy of this object with the given paths.
*
* @param paths The new paths.
* @return A copy of this model, differing in the given paths.
*/
public PlantModelCreationTO withPaths(
@Nonnull
List<PathCreationTO> paths
) {
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object that includes the given path in the list of paths.
*
* @param path the new path.
* @return A copy of this model that also includes the given path.
*/
public PlantModelCreationTO withPath(
@Nonnull
PathCreationTO path
) {
requireNonNull(path, "path");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
listWithAppendix(paths, path),
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Returns this plant model's location types.
*
* @return This plant model's location types.
*/
public List<LocationTypeCreationTO> getLocationTypes() {
return Collections.unmodifiableList(locationTypes);
}
/**
* Creates a copy of this object with the given location type.
*
* @param locationTypes The new location types.
* @return A copy of this model, differing in the given location types.
*/
public PlantModelCreationTO withLocationTypes(
@Nonnull
List<LocationTypeCreationTO> locationTypes
) {
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object that includes the given path in the list of location types.
*
* @param locationType the new location type.
* @return A copy of this model that also includes the given location type.
*/
public PlantModelCreationTO withLocationType(
@Nonnull
LocationTypeCreationTO locationType
) {
requireNonNull(locationType, "locationType");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
listWithAppendix(locationTypes, locationType),
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Returns this plant model's locations.
*
* @return This plant model's locations.
*/
public List<LocationCreationTO> getLocations() {
return Collections.unmodifiableList(locations);
}
/**
* Creates a copy of this object with the given locations.
*
* @param locations The new locations.
* @return A copy of this model, differing in the given locations.
*/
public PlantModelCreationTO withLocations(
@Nonnull
List<LocationCreationTO> locations
) {
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object that includes the given block in the list of locations.
*
* @param location the new location.
* @return A copy of this model that also includes the given location.
*/
public PlantModelCreationTO withLocation(
@Nonnull
LocationCreationTO location
) {
requireNonNull(location, "location");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
listWithAppendix(locations, location),
blocks,
vehicles,
visualLayout
);
}
/**
* Returns this plant model's blocks.
*
* @return This plant model's blocks.
*/
public List<BlockCreationTO> getBlocks() {
return Collections.unmodifiableList(blocks);
}
/**
* Creates a copy of this object with the given blocks.
*
* @param blocks The new blocks.
* @return A copy of this model, differing in the given blocks.
*/
public PlantModelCreationTO withBlocks(
@Nonnull
List<BlockCreationTO> blocks
) {
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object that includes the given block in the list of blocks.
*
* @param block the new block.
* @return A copy of this model that also includes the given block.
*/
public PlantModelCreationTO withBlock(
@Nonnull
BlockCreationTO block
) {
requireNonNull(block, "block");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
CreationTO.listWithAppendix(blocks, block),
vehicles,
visualLayout
);
}
/**
* Returns this plant model's vehicles.
*
* @return This plant model's vehicles.
*/
public List<VehicleCreationTO> getVehicles() {
return Collections.unmodifiableList(vehicles);
}
/**
* Creates a copy of this object with the given vehicles.
*
* @param vehicles The new vehicles.
* @return A copy of this model, differing in the given vehicles.
*/
public PlantModelCreationTO withVehicles(
@Nonnull
List<VehicleCreationTO> vehicles
) {
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object that includes the given vehicle in the list of vehicles.
*
* @param vehicle the new vehicle.
* @return A copy of this model that also includes the given vehicle.
*/
public PlantModelCreationTO withVehicle(
@Nonnull
VehicleCreationTO vehicle
) {
requireNonNull(vehicle, "vehicle");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
listWithAppendix(vehicles, vehicle),
visualLayout
);
}
/**
* Returns this plant model's visual layout.
*
* @return This plant model's visual layout.
*/
public VisualLayoutCreationTO getVisualLayout() {
return visualLayout;
}
/**
* Creates a copy of this object with the given visual layout.
*
* @param visualLayout the new visual layout.
* @return A copy of this model with the given visual layout.
*/
public PlantModelCreationTO withVisualLayout(
@Nonnull
VisualLayoutCreationTO visualLayout
) {
requireNonNull(visualLayout, "visualLayout");
return new PlantModelCreationTO(
getName(),
getModifiableProperties(),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
ensureValidity(visualLayout)
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public PlantModelCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new PlantModelCreationTO(
getName(),
properties,
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public PlantModelCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new PlantModelCreationTO(
getName(),
propertiesWith(key, value),
points,
paths,
locationTypes,
locations,
blocks,
vehicles,
visualLayout
);
}
@Override
public String toString() {
return "PlantModelCreationTO{"
+ "name=" + getName()
+ ", points=" + points
+ ", paths=" + paths
+ ", locationTypes=" + locationTypes
+ ", locations=" + locations
+ ", blocks=" + blocks
+ ", vehicles=" + vehicles
+ ", visualLayout=" + visualLayout
+ ", properties=" + getProperties()
+ '}';
}
private VisualLayoutCreationTO defaultVisualLayout() {
return new VisualLayoutCreationTO(ModelConstants.DEFAULT_VISUAL_LAYOUT_NAME)
.withLayer(
new Layer(
ModelConstants.DEFAULT_LAYER_ID,
ModelConstants.DEFAULT_LAYER_ORDINAL,
true,
ModelConstants.DEFAULT_LAYER_NAME,
ModelConstants.DEFAULT_LAYER_GROUP_ID
)
)
.withLayerGroup(
new LayerGroup(
ModelConstants.DEFAULT_LAYER_GROUP_ID,
ModelConstants.DEFAULT_LAYER_GROUP_NAME,
true
)
);
}
private VisualLayoutCreationTO ensureValidity(
@Nonnull
VisualLayoutCreationTO visualLayout
) {
VisualLayoutCreationTO vLayout = visualLayout;
if (visualLayout.getLayers().isEmpty()) {
LOG.warn("Adding default layer to visual layout with no layers...");
vLayout = visualLayout.withLayer(
new Layer(
ModelConstants.DEFAULT_LAYER_ID,
ModelConstants.DEFAULT_LAYER_ORDINAL,
true,
ModelConstants.DEFAULT_LAYER_NAME,
ModelConstants.DEFAULT_LAYER_GROUP_ID
)
);
}
if (visualLayout.getLayerGroups().isEmpty()) {
LOG.warn("Adding default layer group to visual layout with no layer groups...");
vLayout = vLayout.withLayerGroup(
new LayerGroup(
ModelConstants.DEFAULT_LAYER_GROUP_ID,
ModelConstants.DEFAULT_LAYER_GROUP_NAME,
true
)
);
}
return vLayout;
}
}

View File

@@ -0,0 +1,444 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Envelope;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Pose;
import org.opentcs.data.model.Triple;
/**
* A transfer object describing a point in the plant model.
*/
public class PointCreationTO
extends
CreationTO
implements
Serializable {
/**
* The pose of the vehicle at this point.
*/
private final Pose pose;
/**
* This point's type.
*/
@Nonnull
private final Point.Type type;
/**
* A map of envelope keys to envelopes that vehicles located at this point may occupy.
*/
private final Map<String, Envelope> vehicleEnvelopes;
/**
* The maximum bounding box (in mm) that a vehicle at this point is allowed to have.
*/
private final BoundingBoxCreationTO maxVehicleBoundingBox;
/**
* The information regarding the graphical representation of this point.
*/
private final Layout layout;
/**
* Creates a new instance.
*
* @param name The name of this point.
*/
public PointCreationTO(
@Nonnull
String name
) {
super(name);
this.pose = new Pose(new Triple(0, 0, 0), Double.NaN);
this.type = Point.Type.HALT_POSITION;
this.vehicleEnvelopes = Map.of();
this.maxVehicleBoundingBox
= new BoundingBoxCreationTO(1000, 1000, 1000);
this.layout = new Layout();
}
private PointCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
Pose pose,
@Nonnull
Point.Type type,
@Nonnull
Map<String, Envelope> vehicleEnvelopes,
@Nonnull
BoundingBoxCreationTO maxVehicleBoundingBox,
@Nonnull
Layout layout
) {
super(name, properties);
this.pose = requireNonNull(pose, "pose");
requireNonNull(pose.getPosition(), "A point requires a pose with a position.");
this.type = requireNonNull(type, "type");
this.vehicleEnvelopes = requireNonNull(vehicleEnvelopes, "vehicleEnvelopes");
this.maxVehicleBoundingBox = requireNonNull(maxVehicleBoundingBox, "maxVehicleBoundingBox");
this.layout = requireNonNull(layout, "layout");
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new name.
* @return A copy of this object, differing in the given name.
*/
@Override
public PointCreationTO withName(
@Nonnull
String name
) {
return new PointCreationTO(
name,
getModifiableProperties(),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Returns the pose of the vehicle at this point.
*
* @return The pose of the vehicle at this point.
*/
@Nonnull
public Pose getPose() {
return pose;
}
/**
* Creates a copy of this object with the given pose.
*
* @param pose The new pose.
* @return A copy of this object, differing in the given position.
*/
public PointCreationTO withPose(
@Nonnull
Pose pose
) {
return new PointCreationTO(
getName(),
getModifiableProperties(),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Returns the type of this point.
*
* @return The type of this point.
*/
@Nonnull
public Point.Type getType() {
return type;
}
/**
* Creates a copy of this object with the given type.
*
* @param type The new type.
* @return A copy of this object, differing in the given type.
*/
public PointCreationTO withType(
@Nonnull
Point.Type type
) {
return new PointCreationTO(
getName(),
getProperties(),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public PointCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new PointCreationTO(
getName(),
properties,
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in its current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public PointCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new PointCreationTO(
getName(),
propertiesWith(key, value),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Returns a map of envelope keys to envelopes that vehicles located at this point may occupy.
*
* @return A map of envelope keys to envelopes that vehicles located at this point may occupy.
*/
public Map<String, Envelope> getVehicleEnvelopes() {
return vehicleEnvelopes;
}
/**
* Creates a copy of this object, with the given vehicle envelopes.
*
* @param vehicleEnvelopes The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PointCreationTO withVehicleEnvelopes(
@Nonnull
Map<String, Envelope> vehicleEnvelopes
) {
return new PointCreationTO(
getName(),
getModifiableProperties(),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Returns the maximum bounding box (in mm) that a vehicle at this point is allowed to have.
*
* @return The maximum bounding box (in mm) that a vehicle at this point is allowed to have.
*/
public BoundingBoxCreationTO getMaxVehicleBoundingBox() {
return maxVehicleBoundingBox;
}
/**
* Creates a copy of this object, with the given maximum vehicle bounding box.
*
* @param maxVehicleBoundingBox The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PointCreationTO withMaxVehicleBoundingBox(BoundingBoxCreationTO maxVehicleBoundingBox) {
return new PointCreationTO(
getName(),
getModifiableProperties(),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
/**
* Returns the information regarding the graphical representation of this point.
*
* @return The information regarding the graphical representation of this point.
*/
public Layout getLayout() {
return layout;
}
/**
* Creates a copy of this object, with the given layout.
*
* @param layout The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PointCreationTO withLayout(Layout layout) {
return new PointCreationTO(
getName(),
getModifiableProperties(),
pose,
type,
vehicleEnvelopes,
maxVehicleBoundingBox,
layout
);
}
@Override
public String toString() {
return "PointCreationTO{"
+ "name=" + getName()
+ ", pose=" + pose
+ ", type=" + type
+ ", vehicleEnvelopes=" + vehicleEnvelopes
+ ", layout=" + layout
+ ", maxVehicleBoundingBox=" + maxVehicleBoundingBox
+ ", properties=" + getProperties()
+ '}';
}
/**
* Contains information regarding the graphical representation of a point.
*/
public static class Layout
implements
Serializable {
/**
* The coordinates at which the point is to be drawn (in mm).
*/
private final Couple position;
/**
* The offset of the label's position to the point's position (in lu).
*/
private final Couple labelOffset;
/**
* The ID of the layer on which the point is to be drawn.
*/
private final int layerId;
/**
* Creates a new instance.
*/
public Layout() {
this(new Couple(0, 0), new Couple(0, 0), 0);
}
/**
* Creates a new instance.
*
* @param position The coordinates at which the point is to be drawn (in mm).
* @param labelOffset The offset of the label's position to the point's position (in lu).
* @param layerId The ID of the layer on which the point is to be drawn.
*/
public Layout(
Couple position,
Couple labelOffset,
int layerId
) {
this.position = requireNonNull(position, "position");
this.labelOffset = requireNonNull(labelOffset, "labelOffset");
this.layerId = layerId;
}
/**
* Returns the coordinates at which the point is to be drawn (in mm).
*
* @return The coordinates at which the point is to be drawn (in mm).
*/
public Couple getPosition() {
return position;
}
/**
* Creates a copy of this object, with the given position.
*
* @param position The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withPosition(Couple position) {
return new Layout(
position,
labelOffset,
layerId
);
}
/**
* Returns the offset of the label's position to the point's position (in lu).
*
* @return The offset of the label's position to the point's position (in lu).
*/
public Couple getLabelOffset() {
return labelOffset;
}
/**
* Creates a copy of this object, with the given X label offset.
*
* @param labelOffset The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLabelOffset(Couple labelOffset) {
return new Layout(
position,
labelOffset,
layerId
);
}
/**
* Returns the ID of the layer on which the point is to be drawn.
*
* @return The layer ID.
*/
public int getLayerId() {
return layerId;
}
/**
* Creates a copy of this object, with the given layer ID.
*
* @param layerId The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withLayerId(int layerId) {
return new Layout(
position,
labelOffset,
layerId
);
}
@Override
public String toString() {
return "Layout{"
+ "position=" + position
+ ", labelOffset=" + labelOffset
+ ", layerId=" + layerId
+ '}';
}
}
}

View File

@@ -0,0 +1,729 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkInRange;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.awt.Color;
import java.io.Serializable;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.util.annotations.ScheduledApiChange;
/**
* A transfer object describing a block in the plant model.
*/
public class VehicleCreationTO
extends
CreationTO
implements
Serializable {
/**
* The vehicle's bounding box (in mm).
*/
private final BoundingBoxCreationTO boundingBox;
/**
* Contains information regarding the energy level threshold values of the vehicle.
*/
private final EnergyLevelThresholdSet energyLevelThresholdSet;
/**
* The vehicle's maximum velocity (in mm/s).
*/
private final int maxVelocity;
/**
* The vehicle's maximum reverse velocity (in mm/s).
*/
private final int maxReverseVelocity;
/**
* The key for selecting the envelope to be used for resources the vehicle occupies.
*/
private final String envelopeKey;
/**
* The information regarding the graphical representation of this vehicle.
*/
private final Layout layout;
/**
* Creates a new instance.
*
* @param name The name of this vehicle.
*/
public VehicleCreationTO(
@Nonnull
String name
) {
super(name);
this.boundingBox = new BoundingBoxCreationTO(1000, 1000, 1000);
this.energyLevelThresholdSet = new EnergyLevelThresholdSet(30, 90, 30, 90);
this.maxVelocity = 1000;
this.maxReverseVelocity = 1000;
this.envelopeKey = null;
this.layout = new Layout();
}
private VehicleCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
BoundingBoxCreationTO boundingBox,
@Nonnull
EnergyLevelThresholdSet energyLevelThresholdSet,
int maxVelocity,
int maxReverseVelocity,
@Nullable
String envelopeKey,
@Nonnull
Layout layout
) {
super(name, properties);
this.boundingBox = requireNonNull(boundingBox, "boundingBox");
this.energyLevelThresholdSet
= requireNonNull(energyLevelThresholdSet, "energyLevelThresholdSet");
this.maxVelocity = maxVelocity;
this.maxReverseVelocity = maxReverseVelocity;
this.envelopeKey = envelopeKey;
this.layout = requireNonNull(layout, "layout");
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new instance.
* @return A copy of this object, differing in the given name.
*/
@Override
public VehicleCreationTO withName(
@Nonnull
String name
) {
return new VehicleCreationTO(
name,
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given properties.
*/
@Override
public VehicleCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new VehicleCreationTO(
getName(),
properties,
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in its current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public VehicleCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new VehicleCreationTO(
getName(),
propertiesWith(key, value),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
/**
* Returns the vehicle's current bounding box (in mm).
*
* @return The vehicle's current bounding box (in mm).
*/
public BoundingBoxCreationTO getBoundingBox() {
return boundingBox;
}
/**
* Creates a copy of this object, with the given bounding box (in mm).
*
* @param boundingBox The new bounding box.
* @return A copy of this object, differing in the given vehicle bounding box.
*/
public VehicleCreationTO withBoundingBox(BoundingBoxCreationTO boundingBox) {
return new VehicleCreationTO(
getName(),
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
/**
* Returns the vehicle's length (in mm).
*
* @return The vehicle's length (in mm).
* @deprecated Use {@link #getBoundingBox()} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public int getLength() {
return (int) boundingBox.getLength();
}
/**
* Creates a copy of this object with the vehicle's given length (in mm).
*
* @param length The new length. Must be at least 1.
* @return A copy of this object, differing in the given vehicle length.
* @deprecated Use {@link #withBoundingBox(BoundingBoxCreationTO)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public VehicleCreationTO withLength(int length) {
return withBoundingBox(boundingBox.withLength(length));
}
/**
* Returns this vehicle's critical energy level (in percent of the maximum).
* The critical energy level is the one at/below which the vehicle should be recharged.
*
* @return This vehicle's critical energy level.
* @deprecated Use {@link #getEnergyLevelThresholdSet()} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public int getEnergyLevelCritical() {
return energyLevelThresholdSet.getEnergyLevelCritical();
}
/**
* Creates a copy of this object with the given critical energy level.
* The critical energy level is the one at/below which the vehicle should be recharged.
*
* @param energyLevelCritical The new critical energy level. Must not be smaller than 0 or
* greater than 100.
* @return A copy of this object, differing in the given value.
* @deprecated Use {@link #withEnergyLevelThresholdSet(EnergyLevelThresholdSet)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public VehicleCreationTO withEnergyLevelCritical(int energyLevelCritical) {
return withEnergyLevelThresholdSet(
getEnergyLevelThresholdSet().withEnergyLevelCritical(energyLevelCritical)
);
}
/**
* Returns this vehicle's good energy level (in percent of the maximum).
* The good energy level is the one at/above which the vehicle can be dispatched again when
* charging.
*
* @return This vehicle's good energy level.
* @deprecated Use {@link #getEnergyLevelThresholdSet()} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public int getEnergyLevelGood() {
return energyLevelThresholdSet.getEnergyLevelGood();
}
/**
* Creates a copy of this object with the vehicle's good energy level (in percent of the maximum).
* The good energy level is the one at/above which the vehicle can be dispatched again when
* charging.
*
* @param energyLevelGood The new good energy level. Must not be smaller than 0 or greater than
* 100.
* @return A copy of this object, differing in the given value.
* @deprecated Use {@link #withEnergyLevelThresholdSet(EnergyLevelThresholdSet)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public VehicleCreationTO withEnergyLevelGood(int energyLevelGood) {
return withEnergyLevelThresholdSet(
getEnergyLevelThresholdSet().withEnergyLevelGood(energyLevelGood)
);
}
/**
* Returns this vehicle's fully recharged energy level (in percent of the maximum).
*
* @return This vehicle's fully recharged energy level.
* @deprecated Use {@link #getEnergyLevelThresholdSet()} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public int getEnergyLevelFullyRecharged() {
return energyLevelThresholdSet.getEnergyLevelFullyRecharged();
}
/**
* Creates a copy of this object with the vehicle's fully recharged energy level (in percent of
* the maximum).
*
* @param energyLevelFullyRecharged The new fully recharged energy level.
* Must not be smaller than 0 or greater than 100.
* @return A copy of this object, differing in the given value.
* @deprecated Use {@link #withEnergyLevelThresholdSet(EnergyLevelThresholdSet)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public VehicleCreationTO withEnergyLevelFullyRecharged(int energyLevelFullyRecharged) {
return withEnergyLevelThresholdSet(
getEnergyLevelThresholdSet().withEnergyLevelFullyRecharged(energyLevelFullyRecharged)
);
}
/**
* Returns this vehicle's sufficiently recharged energy level (in percent of the maximum).
*
* @return This vehicle's sufficiently recharged energy level.
* @deprecated Use {@link #getEnergyLevelThresholdSet()} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public int getEnergyLevelSufficientlyRecharged() {
return energyLevelThresholdSet.getEnergyLevelSufficientlyRecharged();
}
/**
* Creates a copy of this object with the vehicle's sufficiently recharged energy level (in
* percent of the maximum).
*
* @param energyLevelSufficientlyRecharged The new sufficiently recharged energy level.
* Must not be smaller than 0 or greater than 100.
* @return A copy of this object, differing in the given value.
* @deprecated Use {@link #withEnergyLevelThresholdSet(EnergyLevelThresholdSet)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
public VehicleCreationTO withEnergyLevelSufficientlyRecharged(
int energyLevelSufficientlyRecharged
) {
return withEnergyLevelThresholdSet(
getEnergyLevelThresholdSet()
.withEnergyLevelSufficientlyRecharged(energyLevelSufficientlyRecharged)
);
}
/**
* Returns this vehicle's energy level threshold set.
*
* @return This vehicle's energy level threshold set.
*/
@Nonnull
public EnergyLevelThresholdSet getEnergyLevelThresholdSet() {
return energyLevelThresholdSet;
}
/**
* Creates a copy of this object, with the given EnergyLevelThresholdSet.
*
* @param energyLevelThresholdSet The new EnergyLevelThresholdSet.
* @return A copy of this object, differing in the given value.
*/
public VehicleCreationTO withEnergyLevelThresholdSet(
@Nonnull
EnergyLevelThresholdSet energyLevelThresholdSet
) {
return new VehicleCreationTO(
getName(),
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
public int getMaxVelocity() {
return maxVelocity;
}
/**
* Creates a copy of this object with the given maximum velocity (in mm/s).
*
* @param maxVelocity the new max velocity.
* @return A copy of this object, differing in the given value.
*/
public VehicleCreationTO withMaxVelocity(int maxVelocity) {
checkInRange(maxVelocity, 0, Integer.MAX_VALUE);
return new VehicleCreationTO(
getName(),
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
public int getMaxReverseVelocity() {
return maxReverseVelocity;
}
/**
* Creates a copy of this object with the given maximum reverse velocity (in mm/s).
*
* @param maxReverseVelocity the new maximum reverse velocity.
* @return A copy of this object, differing in the given value.
*/
public VehicleCreationTO withMaxReverseVelocity(int maxReverseVelocity) {
checkInRange(maxReverseVelocity, 0, Integer.MAX_VALUE);
return new VehicleCreationTO(
getName(),
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
/**
* Returns the key for selecting the envelope to be used for resources the vehicle occupies.
*
* @return The key for selecting the envelope to be used for resources the vehicle occupies.
*/
@ScheduledApiChange(when = "7.0", details = "Envelope key will become non-null.")
@Nullable
public String getEnvelopeKey() {
return envelopeKey;
}
/**
*
* Creates a copy of this object, with the given envelope key.
*
* @param envelopeKey The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
@ScheduledApiChange(when = "7.0", details = "Envelope key will become non-null.")
public VehicleCreationTO withEnvelopeKey(
@Nullable
String envelopeKey
) {
return new VehicleCreationTO(
getName(),
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
/**
* Returns the information regarding the graphical representation of this vehicle.
*
* @return The information regarding the graphical representation of this vehicle.
*/
public Layout getLayout() {
return layout;
}
/**
* Creates a copy of this object, with the given layout.
*
* @param layout The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public VehicleCreationTO withLayout(Layout layout) {
return new VehicleCreationTO(
getName(),
getModifiableProperties(),
boundingBox,
energyLevelThresholdSet,
maxVelocity,
maxReverseVelocity,
envelopeKey,
layout
);
}
@Override
public String toString() {
return "VehicleCreationTO{"
+ "name=" + getName()
+ ", boundingBox=" + boundingBox
+ ", energyLevelThresholdSet=" + energyLevelThresholdSet
+ ", maxVelocity=" + maxVelocity
+ ", maxReverseVelocity=" + maxReverseVelocity
+ ", envelopeKey=" + envelopeKey
+ ", layout=" + layout
+ ", properties=" + getProperties()
+ '}';
}
/**
* Contains information regarding the graphical representation of a vehicle.
*/
public static class Layout
implements
Serializable {
/**
* The color in which vehicle routes are to be emphasized.
*/
private final Color routeColor;
/**
* Creates a new instance.
*/
public Layout() {
this(Color.RED);
}
/**
* Creates a new instance.
*
* @param routeColor The color in which vehicle routes are to be emphasized.
*/
public Layout(Color routeColor) {
this.routeColor = requireNonNull(routeColor, "routeColor");
}
/**
* Returns the color in which vehicle routes are to be emphasized.
*
* @return The color in which vehicle routes are to be emphasized.
*/
public Color getRouteColor() {
return routeColor;
}
/**
* Creates a copy of this object, with the given color.
*
* @param routeColor The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public Layout withRouteColor(Color routeColor) {
return new Layout(routeColor);
}
@Override
public String toString() {
return "Layout{"
+ "routeColor=" + routeColor
+ '}';
}
}
/**
* Contains information regarding the energy level threshold values of a vehicle.
*/
public static class EnergyLevelThresholdSet
implements
Serializable {
private final int energyLevelCritical;
private final int energyLevelGood;
private final int energyLevelSufficientlyRecharged;
private final int energyLevelFullyRecharged;
/**
* Creates a new instance.
*
* @param energyLevelCritical The value at/below which the vehicle's energy level is considered
* "critical".
* @param energyLevelGood The value at/above which the vehicle's energy level is considered
* "good".
* @param energyLevelSufficientlyRecharged The value at/above which the vehicle's energy level
* is considered fully recharged.
* @param energyLevelFullyRecharged The value at/above which the vehicle's energy level is
* considered sufficiently recharged.
*/
public EnergyLevelThresholdSet(
int energyLevelCritical,
int energyLevelGood,
int energyLevelSufficientlyRecharged,
int energyLevelFullyRecharged
) {
this.energyLevelCritical = checkInRange(
energyLevelCritical,
0,
100,
"energyLevelCritical"
);
this.energyLevelGood = checkInRange(
energyLevelGood,
0,
100,
"energyLevelGood"
);
this.energyLevelSufficientlyRecharged = checkInRange(
energyLevelSufficientlyRecharged,
0,
100,
"energyLevelSufficientlyRecharged"
);
this.energyLevelFullyRecharged = checkInRange(
energyLevelFullyRecharged,
0,
100,
"energyLevelFullyRecharged"
);
}
/**
* Returns the vehicle's critical energy level (in percent of the maximum).
* <p>
* The critical energy level is the one at/below which the vehicle should be recharged.
* </p>
*
* @return The vehicle's critical energy level.
*/
public int getEnergyLevelCritical() {
return energyLevelCritical;
}
/**
* Creates a copy of this object, with the given critical energy level.
*
* @param energyLevelCritical The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public EnergyLevelThresholdSet withEnergyLevelCritical(int energyLevelCritical) {
return new EnergyLevelThresholdSet(
energyLevelCritical,
energyLevelGood,
energyLevelSufficientlyRecharged,
energyLevelFullyRecharged
);
}
/**
* Returns the vehicle's good energy level (in percent of the maximum).
* <p>
* The good energy level is the one at/above which the vehicle can be dispatched again when
* charging.
* </p>
*
* @return The vehicle's good energy level.
*/
public int getEnergyLevelGood() {
return energyLevelGood;
}
/**
* Creates a copy of this object, with the given good energy level.
*
* @param energyLevelGood The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public EnergyLevelThresholdSet withEnergyLevelGood(int energyLevelGood) {
return new EnergyLevelThresholdSet(
energyLevelCritical,
energyLevelGood,
energyLevelSufficientlyRecharged,
energyLevelFullyRecharged
);
}
/**
* Returns the vehicle's energy level for being sufficiently recharged (in percent of the
* maximum).
*
* @return This vehicle's sufficiently recharged energy level.
*/
public int getEnergyLevelSufficientlyRecharged() {
return energyLevelSufficientlyRecharged;
}
/**
* Creates a copy of this object, with the given sufficiently recharged energy level.
*
* @param energyLevelSufficientlyRecharged The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public EnergyLevelThresholdSet withEnergyLevelSufficientlyRecharged(
int energyLevelSufficientlyRecharged
) {
return new EnergyLevelThresholdSet(
energyLevelCritical,
energyLevelGood,
energyLevelSufficientlyRecharged,
energyLevelFullyRecharged
);
}
/**
* Returns the vehicle's energy level for being fully recharged (in percent of the maximum).
*
* @return The vehicle's fully recharged threshold.
*/
public int getEnergyLevelFullyRecharged() {
return energyLevelFullyRecharged;
}
/**
* Creates a copy of this object, with the given fully recharged energy level.
*
* @param energyLevelFullyRecharged The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public EnergyLevelThresholdSet withEnergyLevelFullyRecharged(int energyLevelFullyRecharged) {
return new EnergyLevelThresholdSet(
energyLevelCritical,
energyLevelGood,
energyLevelSufficientlyRecharged,
energyLevelFullyRecharged
);
}
@Override
public String toString() {
return "EnergyLevelThresholdSet{"
+ "energyLevelCritical=" + energyLevelCritical
+ ", energyLevelGood=" + energyLevelGood
+ ", energyLevelSufficientlyRecharged=" + energyLevelSufficientlyRecharged
+ ", energyLevelFullyRecharged=" + energyLevelFullyRecharged
+ '}';
}
}
}

View File

@@ -0,0 +1,311 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.model;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
/**
* A transfer object describing a visual layout in the plant model.
*/
public class VisualLayoutCreationTO
extends
CreationTO
implements
Serializable {
/**
* This layout's scale on the X axis (in mm/pixel).
*/
private final double scaleX;
/**
* This layout's scale on the Y axis (in mm/pixel).
*/
private final double scaleY;
/**
* This layout's layers.
*/
private final List<Layer> layers;
/**
* The layout's layer groups.
*/
private final List<LayerGroup> layerGroups;
/**
* Creates a new instance.
*
* @param name The name of this visual layout.
*/
public VisualLayoutCreationTO(
@Nonnull
String name
) {
super(name);
this.scaleX = 50.0;
this.scaleY = 50.0;
this.layers = List.of();
this.layerGroups = List.of();
}
private VisualLayoutCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
double scaleX,
double scaleY,
@Nonnull
List<Layer> layers,
@Nonnull
List<LayerGroup> layerGroups
) {
super(name, properties);
this.scaleX = scaleX;
this.scaleY = scaleY;
this.layers = requireNonNull(layers, "layers");
this.layerGroups = requireNonNull(layerGroups, "layerGroups");
}
/**
* Creates a copy of this object with the given name.
*
* @param name the new name of the instance.
* @return A copy of this object, differing in the given value.
*/
@Override
public VisualLayoutCreationTO withName(
@Nonnull
String name
) {
return new VisualLayoutCreationTO(
name,
getModifiableProperties(),
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given value.
*/
@Override
public VisualLayoutCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new VisualLayoutCreationTO(
getName(),
properties,
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public VisualLayoutCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new VisualLayoutCreationTO(
getName(),
propertiesWith(key, value),
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Returns this layout's scale on the X axis (in mm/pixel).
*
* @return This layout's scale on the X axis.
*/
public double getScaleX() {
return scaleX;
}
/**
* Creates a copy of this object with the layout's scale on the X axis (in mm/pixel).
*
* @param scaleX The new scale.
* @return A copy of this object, differing in the given value.
*/
public VisualLayoutCreationTO withScaleX(double scaleX) {
return new VisualLayoutCreationTO(
getName(),
getModifiableProperties(),
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Returns this layout's scale on the Y axis (in mm/pixel).
*
* @return This layout's scale on the Y axis.
*/
public double getScaleY() {
return scaleY;
}
/**
* Creates a copy of this object with the given layout's scale on the Y axis (in mm/pixel).
*
* @param scaleY The new scale.
* @return A copy of this object, differing in the given value.
*/
public VisualLayoutCreationTO withScaleY(double scaleY) {
return new VisualLayoutCreationTO(
getName(),
getModifiableProperties(),
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Returns the layers of this visual layout.
*
* @return The layers of this visual layout.
*/
@Nonnull
public List<Layer> getLayers() {
return Collections.unmodifiableList(layers);
}
/**
* Creates a copy of this object, with the given layers.
*
* @param layers The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public VisualLayoutCreationTO withLayers(
@Nonnull
List<Layer> layers
) {
return new VisualLayoutCreationTO(
getName(),
getModifiableProperties(),
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Creates a copy of this object, with the given layer.
*
* @param layer The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public VisualLayoutCreationTO withLayer(
@Nonnull
Layer layer
) {
return new VisualLayoutCreationTO(
getName(),
getModifiableProperties(),
scaleX,
scaleY,
listWithAppendix(layers, layer),
layerGroups
);
}
/**
* Returns the layer groups of this visual layout.
*
* @return The layer groups of this visual layout.
*/
@Nonnull
public List<LayerGroup> getLayerGroups() {
return Collections.unmodifiableList(layerGroups);
}
/**
* Creates a copy of this object, with the given layer groups.
*
* @param layerGroups The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public VisualLayoutCreationTO withLayerGroups(
@Nonnull
List<LayerGroup> layerGroups
) {
return new VisualLayoutCreationTO(
getName(),
getModifiableProperties(),
scaleX,
scaleY,
layers,
layerGroups
);
}
/**
* Creates a copy of this object, with the given layer group.
*
* @param layerGroup The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public VisualLayoutCreationTO withLayerGroup(
@Nonnull
LayerGroup layerGroup
) {
return new VisualLayoutCreationTO(
getName(),
getModifiableProperties(),
scaleX,
scaleY,
layers,
listWithAppendix(layerGroups, layerGroup)
);
}
@Override
public String toString() {
return "VisualLayoutCreationTO{"
+ "name=" + getName()
+ ", scaleX=" + scaleX
+ ", scaleY=" + scaleY
+ ", layers=" + layers
+ ", layerGroups=" + layerGroups
+ ", properties=" + getProperties()
+ '}';
}
}

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Transfer object classes for plant model objects.
*/
package org.opentcs.access.to.model;

View File

@@ -0,0 +1,177 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.order;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
/**
* A transfer object describing a destination of a drive order.
*/
public class DestinationCreationTO
extends
CreationTO
implements
Serializable {
/**
* The name of the destination location (or point).
*/
@Nonnull
private final String destLocationName;
/**
* The operation to be performed at the destination.
*/
@Nonnull
private final String destOperation;
/**
* Creates a new instance.
*
* @param destLocationName The name of the destination location (or destination point).
* @param destOperation The operation to be performed at the destination.
*/
public DestinationCreationTO(
@Nonnull
String destLocationName,
@Nonnull
String destOperation
) {
super("");
this.destLocationName = requireNonNull(destLocationName, "destLocationName");
this.destOperation = requireNonNull(destOperation, "destOperation");
}
private DestinationCreationTO(
@Nonnull
String destLocationName,
@Nonnull
String destOperation,
@Nonnull
String name,
@Nonnull
Map<String, String> properties
) {
super(name, properties);
this.destLocationName = requireNonNull(destLocationName, "destLocationName");
this.destOperation = requireNonNull(destOperation, "destOperation");
}
/**
* Creates a copy of this object with the given name.
*
* @param name the new name of the instance.
* @return A copy of this object, differing in the given value.
*/
@Override
public DestinationCreationTO withName(
@Nonnull
String name
) {
return new DestinationCreationTO(
destLocationName,
destOperation,
name,
getModifiableProperties()
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given value.
*/
@Override
public DestinationCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new DestinationCreationTO(destLocationName, destOperation, getName(), properties);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public DestinationCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new DestinationCreationTO(
destLocationName,
destOperation,
getName(),
propertiesWith(key, value)
);
}
/**
* Returns the destination location (or point) name.
*
* @return The destination location (or point) name.
*/
@Nonnull
public String getDestLocationName() {
return destLocationName;
}
/**
* Creates a copy of this object with the given destination location (or point) name.
*
* @param desLocationName The destination location (or point) name.
* @return A copy of this object, differing in the given destination.
*/
public DestinationCreationTO withDestLocationName(
@Nonnull
String desLocationName
) {
return new DestinationCreationTO(
destLocationName,
destOperation,
getName(),
getModifiableProperties()
);
}
/**
* Returns the operation to be performed at the destination.
*
* @return The operation to be performed at the destination.
*/
@Nonnull
public String getDestOperation() {
return destOperation;
}
/**
* Creates a copy of this object with the given operation to be performed at the destination.
*
* @param destOperation The operation.
* @return A copy of this object, differing in the given destination operation.
*/
public DestinationCreationTO withDestOperation(
@Nonnull
String destOperation
) {
return new DestinationCreationTO(
destLocationName,
destOperation,
getName(),
getModifiableProperties()
);
}
}

View File

@@ -0,0 +1,266 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.order;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.io.Serializable;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.order.OrderConstants;
/**
* A transfer object describing a transport order.
*/
public class OrderSequenceCreationTO
extends
CreationTO
implements
Serializable {
/**
* Indicates whether the name is incomplete and requires to be completed when creating the actual
* order sequence.
* (How exactly this is done is decided by the kernel.)
*/
private final boolean incompleteName;
/**
* The type of the order sequence.
*/
private final String type;
/**
* The (optional) name of the vehicle that is supposed to execute the transport order.
*/
@Nullable
private final String intendedVehicleName;
/**
* Whether failure of one transport order in the sequence makes subsequent ones fail, too.
*/
private final boolean failureFatal;
/**
* Creates a new instance.
*
* @param name The name of this transport order.
*/
public OrderSequenceCreationTO(
@Nonnull
String name
) {
super(name);
this.incompleteName = false;
this.type = OrderConstants.TYPE_NONE;
this.intendedVehicleName = null;
this.failureFatal = false;
}
private OrderSequenceCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
boolean incompleteName,
@Nonnull
String type,
@Nullable
String intendedVehicleName,
boolean failureFatal
) {
super(name, properties);
this.incompleteName = incompleteName;
this.type = requireNonNull(type, "type");
this.intendedVehicleName = intendedVehicleName;
this.failureFatal = failureFatal;
}
/**
* Creates a copy of this object with the given name.
*
* @param name the new name of the instance.
* @return A copy of this object, differing in the given name.
*/
@Override
public OrderSequenceCreationTO withName(
@Nonnull
String name
) {
return new OrderSequenceCreationTO(
name,
getModifiableProperties(),
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given value.
*/
@Override
public OrderSequenceCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new OrderSequenceCreationTO(
getName(),
properties,
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public OrderSequenceCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new OrderSequenceCreationTO(
getName(),
propertiesWith(key, value),
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
/**
* Indicates whether the name is incomplete and requires to be completed when creating the actual
* order sequence.
* (How exactly this is done is decided by the kernel.)
*
* @return <code>true</code> if, and only if, the name is incomplete and requires to be completed
* by the kernel.
*/
public boolean hasIncompleteName() {
return incompleteName;
}
/**
* Creates a copy of this object with the given <em>nameIncomplete</em> flag.
*
* @param incompleteName Whether the name is incomplete and requires to be completed when creating
* the actual order sequence.
*
* @return A copy of this object, differing in the given value.
*/
public OrderSequenceCreationTO withIncompleteName(boolean incompleteName) {
return new OrderSequenceCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
/**
* Returns the (optional) type of the order sequence.
*
* @return The (optional) type of the order sequence.
*/
@Nonnull
public String getType() {
return type;
}
/**
* Creates a copy of this object with the given type.
*
* @param type The type.
* @return A copy of this object, differing in the given type.
*/
public OrderSequenceCreationTO withType(
@Nonnull
String type
) {
return new OrderSequenceCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
/**
* Returns the (optional) name of the vehicle that is supposed to execute the transport order.
*
* @return The (optional) name of the vehicle that is supposed to execute the transport order.
*/
@Nullable
public String getIntendedVehicleName() {
return intendedVehicleName;
}
/**
* Creates a copy of this object with the given
* (optional) name of the vehicle that is supposed to execute the transport order.
*
* @param intendedVehicleName The vehicle name.
* @return A copy of this object, differing in the given name of the intended vehicle.
*/
public OrderSequenceCreationTO withIntendedVehicleName(
@Nullable
String intendedVehicleName
) {
return new OrderSequenceCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
/**
* Returns whether failure of one transport order in the sequence makes subsequent ones fail, too.
*
* @return Whether failure of one transport order in the sequence makes subsequent ones fail, too.
*/
public boolean isFailureFatal() {
return failureFatal;
}
/**
* Creates a copy of this object with the given <em>failureFatal</em> flag.
*
* @param failureFatal Whether failure of one transport order in the sequence makes subsequent
* ones fail, too.
*
* @return A copy of this object, differing in the given value.
*/
public OrderSequenceCreationTO withFailureFatal(boolean failureFatal) {
return new OrderSequenceCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
type,
intendedVehicleName,
failureFatal
);
}
}

View File

@@ -0,0 +1,533 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.order;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.io.Serializable;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.order.OrderConstants;
/**
* A transfer object describing a transport order.
*/
public class TransportOrderCreationTO
extends
CreationTO
implements
Serializable {
/**
* Indicates whether the name is incomplete and requires to be completed when creating the actual
* transport order.
* (How exactly this is done is decided by the kernel.)
*/
private final boolean incompleteName;
/**
* The destinations that need to be travelled to.
*/
@Nonnull
private final List<DestinationCreationTO> destinations;
/**
* An optional token for reserving peripheral devices while processing this transport order.
*/
@Nullable
private final String peripheralReservationToken;
/**
* The (optional) name of the order sequence the transport order belongs to.
*/
@Nullable
private final String wrappingSequence;
/**
* The (optional) names of transport orders the transport order depends on.
*/
@Nonnull
private final Set<String> dependencyNames;
/**
* The (optional) name of the vehicle that is supposed to execute the transport order.
*/
@Nullable
private final String intendedVehicleName;
/**
* The type of the transport order.
*/
@Nonnull
private final String type;
/**
* The point of time at which execution of the transport order is supposed to be finished.
*/
@Nonnull
private final Instant deadline;
/**
* Whether the transport order is dispensable or not.
*/
private final boolean dispensable;
/**
* Creates a new instance.
*
* @param name The name of this transport order.
* @param destinations The destinations that need to be travelled to.
*/
public TransportOrderCreationTO(
@Nonnull
String name,
@Nonnull
List<DestinationCreationTO> destinations
) {
super(name);
this.incompleteName = false;
this.destinations = requireNonNull(destinations, "destinations");
this.peripheralReservationToken = null;
this.wrappingSequence = null;
this.dependencyNames = Set.of();
this.intendedVehicleName = null;
this.type = OrderConstants.TYPE_NONE;
this.deadline = Instant.MAX;
this.dispensable = false;
}
private TransportOrderCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
boolean incompleteName,
@Nonnull
List<DestinationCreationTO> destinations,
@Nullable
String peripheralReservationToken,
@Nullable
String wrappingSequence,
@Nonnull
Set<String> dependencyNames,
@Nullable
String intendedVehicleName,
@Nonnull
String type,
@Nonnull
Instant deadline,
boolean dispensable
) {
super(name, properties);
this.incompleteName = incompleteName;
this.destinations = requireNonNull(destinations, "destinations");
this.peripheralReservationToken = peripheralReservationToken;
this.wrappingSequence = wrappingSequence;
this.dependencyNames = requireNonNull(dependencyNames, "dependencyNames");
this.intendedVehicleName = intendedVehicleName;
this.type = requireNonNull(type, "type");
this.deadline = requireNonNull(deadline, "deadline");
this.dispensable = dispensable;
}
/**
* Creates a copy of this object with the given name.
*
* @param name The new name of the instance.
* @return A copy of this object, differing in the given name.
*/
@Override
public TransportOrderCreationTO withName(
@Nonnull
String name
) {
return new TransportOrderCreationTO(
name,
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Creates a copy of this object with the given properties.
*
* @param properties The new properties.
* @return A copy of this object, differing in the given value.
*/
@Override
public TransportOrderCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new TransportOrderCreationTO(
getName(),
properties,
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Creates a copy of this object and adds the given property.
* If value == null, then the key-value pair is removed from the properties.
*
* @param key the key.
* @param value the value
* @return A copy of this object that either
* includes the given entry in it's current properties, if value != null or
* excludes the entry otherwise.
*/
@Override
public TransportOrderCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new TransportOrderCreationTO(
getName(),
propertiesWith(key, value),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Indicates whether the name is incomplete and requires to be completed when creating the actual
* transport order.
* (How exactly this is done is decided by the kernel.)
*
* @return <code>true</code> if, and only if, the name is incomplete and requires to be completed
* by the kernel.
*/
public boolean hasIncompleteName() {
return incompleteName;
}
/**
* Creates a copy of this object with the given <em>nameIncomplete</em> flag.
*
* @param incompleteName Whether the name is incomplete and requires to be completed when creating
* the actual transport order.
*
* @return A copy of this object, differing in the given value.
*/
public TransportOrderCreationTO withIncompleteName(boolean incompleteName) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns the destinations that need to be travelled to.
*
* @return The destinations that need to be travelled to.
*/
@Nonnull
public List<DestinationCreationTO> getDestinations() {
return Collections.unmodifiableList(destinations);
}
/**
* Creates a copy of this object with the given destinations that need to be travelled to.
*
* @param destinations The destinations.
* @return A copy of this object, differing in the given derstinations.
*/
public TransportOrderCreationTO withDestinations(
@Nonnull
List<DestinationCreationTO> destinations
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns an optional token for reserving peripheral devices while processing this transport
* order.
*
* @return An optional token for reserving peripheral devices while processing this transport
* order.
*/
@Nullable
public String getPeripheralReservationToken() {
return peripheralReservationToken;
}
/**
* Creates a copy of this object with the given (optional) peripheral reservation token.
*
* @param peripheralReservationToken The token.
* @return A copy of this object, differing in the given peripheral reservation token.
*/
public TransportOrderCreationTO withPeripheralReservationToken(
@Nullable
String peripheralReservationToken
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns the (optional) name of the order sequence the transport order belongs to.
*
* @return The (optional) name of the order sequence the transport order belongs to.
*/
@Nullable
public String getWrappingSequence() {
return wrappingSequence;
}
/**
* Creates a copy of this object with the given
* (optional) name of the order sequence the transport order belongs to.
*
* @param wrappingSequence The name of the sequence.
* @return A copy of this object, differing in the given name of the sequence.
*/
public TransportOrderCreationTO withWrappingSequence(
@Nullable
String wrappingSequence
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns the (optional) names of transport orders the transport order depends on.
*
* @return The (optional) names of transport orders the transport order depends on.
*/
@Nonnull
public Set<String> getDependencyNames() {
return Collections.unmodifiableSet(dependencyNames);
}
/**
* Creates a copy of this object with the given
* (optional) names of transport orders the transport order depends on.
*
* @param dependencyNames The dependency names.
* @return A copy of this object, differing in the given dependency names.
*/
public TransportOrderCreationTO withDependencyNames(
@Nonnull
Set<String> dependencyNames
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns the (optional) name of the vehicle that is supposed to execute the transport order.
*
* @return The (optional) name of the vehicle that is supposed to execute the transport order.
*/
@Nullable
public String getIntendedVehicleName() {
return intendedVehicleName;
}
/**
* Creates a copy of this object with the given
* (optional) name of the vehicle that is supposed to execute the transport order.
*
* @param intendedVehicleName The vehicle name.
* @return A copy of this object, differing in the given vehicle's name.
*/
public TransportOrderCreationTO withIntendedVehicleName(
@Nullable
String intendedVehicleName
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns the (optional) type of the transport order.
*
* @return The (optional) type of the transport order.
*/
@Nonnull
public String getType() {
return type;
}
/**
* Creates a copy of this object with the given (optional) type of the transport order.
*
* @param type The type.
* @return A copy of this object, differing in the given type.
*/
public TransportOrderCreationTO withType(
@Nonnull
String type
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns the point of time at which execution of the transport order is supposed to be finished.
*
* @return The point of time at which execution of the transport order is supposed to be finished.
*/
@Nonnull
public Instant getDeadline() {
return deadline;
}
/**
* Creates a copy of this object with the given
* point of time at which execution of the transport order is supposed to be finished.
*
* @param deadline The deadline.
* @return A copy of this object, differing in the given deadline.
*/
public TransportOrderCreationTO withDeadline(
@Nonnull
Instant deadline
) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
/**
* Returns whether the transport order is dispensable or not.
*
* @return Whether the transport order is dispensable or not.
*/
public boolean isDispensable() {
return dispensable;
}
/**
* Creates a copy of this object with the
* given indication whether the transport order is dispensable or not.
*
* @param dispensable The dispensable flag.
* @return A copy of this object, differing in the given dispensable flag.
*/
public TransportOrderCreationTO withDispensable(boolean dispensable) {
return new TransportOrderCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
destinations,
peripheralReservationToken,
wrappingSequence,
dependencyNames,
intendedVehicleName,
type,
deadline,
dispensable
);
}
}

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Transfer object classes for transport order objects.
*/
package org.opentcs.access.to.order;

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Transfer object classes for domain objects.
*/
package org.opentcs.access.to;

View File

@@ -0,0 +1,295 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.peripherals;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.io.Serializable;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
/**
* A transfer object describing a peripheral job.
*/
public class PeripheralJobCreationTO
extends
CreationTO
implements
Serializable {
/**
* Indicates whether the name is incomplete and requires to be completed when creating the actual
* peripheral job.
* (How exactly this is done is decided by the kernel.)
*/
private final boolean incompleteName;
/**
* A token that may be used to reserve a peripheral device.
* A peripheral device that is reserved for a specific token can only process jobs which match
* that reservation token.
* This string may not be empty.
*/
@Nonnull
private final String reservationToken;
/**
* The name of the vehicle for which this peripheral job is to be created.
*/
@Nullable
private final String relatedVehicleName;
/**
* The name of the transport order for which this peripheral job is to be created.
*/
@Nullable
private final String relatedTransportOrderName;
/**
* The operation that is to be perfromed by the pripheral device.
*/
@Nonnull
private final PeripheralOperationCreationTO peripheralOperation;
/**
* Creates a new instance.
*
* @param name The name of this peripheral job.
* @param reservationToken The reservation token to be used.
* @param peripheralOperation The peripheral operation to be performed.
*/
public PeripheralJobCreationTO(
@Nonnull
String name,
@Nonnull
String reservationToken,
@Nonnull
PeripheralOperationCreationTO peripheralOperation
) {
super(name);
this.incompleteName = false;
this.reservationToken = requireNonNull(reservationToken, "reservationToken");
this.relatedVehicleName = null;
this.relatedTransportOrderName = null;
this.peripheralOperation = requireNonNull(peripheralOperation, "peripheralOperation");
}
private PeripheralJobCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
boolean incompleteName,
@Nonnull
String reservationToken,
@Nullable
String relatedVehicleName,
@Nullable
String relatedTransportOrderName,
@Nonnull
PeripheralOperationCreationTO peripheralOperation
) {
super(name, properties);
this.incompleteName = incompleteName;
this.reservationToken = requireNonNull(reservationToken, "reservationToken");
this.relatedVehicleName = relatedVehicleName;
this.relatedTransportOrderName = relatedTransportOrderName;
this.peripheralOperation = requireNonNull(peripheralOperation, "peripheralOperation");
}
@Override
public PeripheralJobCreationTO withName(
@Nonnull
String name
) {
return new PeripheralJobCreationTO(
name,
getModifiableProperties(),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
@Override
public PeripheralJobCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new PeripheralJobCreationTO(
getName(),
properties,
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
@Override
public PeripheralJobCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new PeripheralJobCreationTO(
getName(),
propertiesWith(key, value),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
/**
* Indicates whether the name is incomplete and requires to be completed when creating the actual
* transport order.
* (How exactly this is done is decided by the kernel.)
*
* @return {@code true} if, and only if, the name is incomplete and requires to be completed
* by the kernel.
*/
public boolean hasIncompleteName() {
return incompleteName;
}
/**
* Creates a copy of this object, with the given incomplete name flag.
*
* @param incompleteName The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralJobCreationTO withIncompleteName(boolean incompleteName) {
return new PeripheralJobCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
/**
* Returns the token that may be used to reserve a peripheral device.
*
* @return The token that may be used to reserve a peripheral device.
*/
public String getReservationToken() {
return reservationToken;
}
/**
* Creates a copy of this object, with the given reservation token.
*
* @param reservationToken The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralJobCreationTO withReservationToken(String reservationToken) {
return new PeripheralJobCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
/**
* Returns the name of the vehicle for which this peripheral job is to be created.
*
* @return The name of the vehicle for which this peripheral job is to be created.
*/
@Nullable
public String getRelatedVehicleName() {
return relatedVehicleName;
}
/**
* Creates a copy of this object, with the given related vehicle name.
*
* @param relatedVehicleName The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralJobCreationTO withRelatedVehicleName(
@Nullable
String relatedVehicleName
) {
return new PeripheralJobCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
/**
* Returns the name of the transport order for which this peripheral job is to be created.
*
* @return The name of the transport order for which this peripheral job is to be created.
*/
@Nullable
public String getRelatedTransportOrderName() {
return relatedTransportOrderName;
}
/**
* Creates a copy of this object, with the given related transport order name.
*
* @param relatedTransportOrderName The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralJobCreationTO withRelatedTransportOrderName(
@Nullable
String relatedTransportOrderName
) {
return new PeripheralJobCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
/**
* Returns the operation that is to be performed by the pripheral device.
*
* @return The operation that is to be performed by the pripheral device.
*/
public PeripheralOperationCreationTO getPeripheralOperation() {
return peripheralOperation;
}
/**
* Creates a copy of this object, with the given peripheral operation.
*
* @param peripheralOperation The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralJobCreationTO withPeripheralOperation(
PeripheralOperationCreationTO peripheralOperation
) {
return new PeripheralJobCreationTO(
getName(),
getModifiableProperties(),
incompleteName,
reservationToken,
relatedVehicleName,
relatedTransportOrderName,
peripheralOperation
);
}
}

View File

@@ -0,0 +1,252 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.access.to.peripherals;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import java.io.Serializable;
import java.util.Map;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.peripherals.PeripheralOperation;
/**
* A transfer object describing an operation to be performed by a peripheral device.
*/
public class PeripheralOperationCreationTO
extends
CreationTO
implements
Serializable {
/**
* The operation to be performed by the peripheral device.
*/
private final String operation;
/**
* The name of the location the peripheral device is associated with.
*/
@Nonnull
private final String locationName;
/**
* The moment at which this operation is to be performed.
*/
@Nonnull
private final PeripheralOperation.ExecutionTrigger executionTrigger;
/**
* Whether the completion of this operation is required to allow a vehicle to continue driving.
*/
private final boolean completionRequired;
/**
* Creates a new instance with {@code executionTrigger} set to
* {@link PeripheralOperation.ExecutionTrigger#IMMEDIATE} and {@code completionRequired}
* set to {@code false}.
*
* @param operation The operation to be performed by the peripheral device.
* @param locationName The name of the location the peripheral device is associated with.
*/
public PeripheralOperationCreationTO(
@Nonnull
String operation,
@Nonnull
String locationName
) {
super("");
this.operation = requireNonNull(operation, "operation");
this.locationName = requireNonNull(locationName, "locationName");
this.executionTrigger = PeripheralOperation.ExecutionTrigger.IMMEDIATE;
this.completionRequired = false;
}
private PeripheralOperationCreationTO(
@Nonnull
String name,
@Nonnull
Map<String, String> properties,
@Nonnull
String operation,
@Nonnull
String locationName,
@Nonnull
PeripheralOperation.ExecutionTrigger executionTrigger,
boolean completionRequired
) {
super(name, properties);
this.operation = requireNonNull(operation, "operation");
this.locationName = requireNonNull(locationName, "locationName");
this.executionTrigger = requireNonNull(executionTrigger, "executionTrigger");
this.completionRequired = completionRequired;
}
@Override
public PeripheralOperationCreationTO withName(
@Nonnull
String name
) {
return new PeripheralOperationCreationTO(
name,
getModifiableProperties(),
operation,
locationName,
executionTrigger,
completionRequired
);
}
@Override
public PeripheralOperationCreationTO withProperties(
@Nonnull
Map<String, String> properties
) {
return new PeripheralOperationCreationTO(
getName(),
properties,
operation,
locationName,
executionTrigger,
completionRequired
);
}
@Override
public PeripheralOperationCreationTO withProperty(
@Nonnull
String key,
@Nonnull
String value
) {
return new PeripheralOperationCreationTO(
getName(),
propertiesWith(key, value),
operation,
locationName,
executionTrigger,
completionRequired
);
}
/**
* Returns the operation to be performed by the peripheral device.
*
* @return The operation to be performed by the peripheral device.
*/
@Nonnull
public String getOperation() {
return operation;
}
/**
* Creates a copy of this object, with the given operation.
*
* @param operation The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralOperationCreationTO withOperation(
@Nonnull
String operation
) {
return new PeripheralOperationCreationTO(
getName(),
getModifiableProperties(),
operation,
locationName,
executionTrigger,
completionRequired
);
}
/**
* Returns the name of the location the peripheral device is associated with.
*
* @return The name of the location the peripheral device is associated with.
*/
@Nonnull
public String getLocationName() {
return locationName;
}
/**
* Creates a copy of this object, with the given location name.
*
* @param locationName The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralOperationCreationTO withLocationName(
@Nonnull
String locationName
) {
return new PeripheralOperationCreationTO(
getName(),
getModifiableProperties(),
operation,
locationName,
executionTrigger,
completionRequired
);
}
/**
* Returns the moment at which this operation is to be performed.
*
* @return The moment at which this operation is to be performed.
*/
@Nonnull
public PeripheralOperation.ExecutionTrigger getExecutionTrigger() {
return executionTrigger;
}
/**
* Creates a copy of this object, with the given execution trigger.
* <p>
* This method should only be used by the vehicle controller component of the baseline project.
* </p>
*
* @param executionTrigger The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralOperationCreationTO withExecutionTrigger(
@Nonnull
PeripheralOperation.ExecutionTrigger executionTrigger
) {
return new PeripheralOperationCreationTO(
getName(),
getModifiableProperties(),
operation,
locationName,
executionTrigger,
completionRequired
);
}
/**
* Returns whether the completion of this operation is required to allow a vehicle to continue
* driving.
*
* @return Whether the completion of this operation is required to allow a vehicle to continue
* driving.
*/
public boolean isCompletionRequired() {
return completionRequired;
}
/**
* Creates a copy of this object, with the given completion required flag.
* <p>
* This method should only be used by the vehicle controller component of the baseline project.
* </p>
*
* @param completionRequired The value to be set in the copy.
* @return A copy of this object, differing in the given value.
*/
public PeripheralOperationCreationTO withCompletionRequired(boolean completionRequired) {
return new PeripheralOperationCreationTO(
getName(),
getModifiableProperties(),
operation,
locationName,
executionTrigger,
completionRequired
);
}
}

View File

@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components;
/**
* Defines methods for controlling a generic component's lifecycle.
*/
public interface Lifecycle {
/**
* (Re-)Initializes this component before it is being used.
*/
void initialize();
/**
* Checks whether this component is initialized.
*
* @return <code>true</code> if, and only if, this component is initialized.
*/
boolean isInitialized();
/**
* Terminates the instance and frees resources.
*/
void terminate();
}

View File

@@ -0,0 +1,152 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import jakarta.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.dipatching.TransportOrderAssignmentException;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.ReroutingType;
import org.opentcs.data.order.TransportOrder;
/**
* This interface declares the methods a dispatcher module for the openTCS
* kernel must implement.
* <p>
* A dispatcher manages the distribution of transport orders among the vehicles
* in a system. It is basically event-driven, where an event can be a new
* transport order being introduced into the system or a vehicle becoming
* available for processing existing orders.
* </p>
*/
public interface Dispatcher
extends
Lifecycle {
/**
* The key of a parking position property defining its priority.
* <p>
* Whether and in what way this is respected for assigning a parking position to a vehicle is
* implementation-specific.
* </p>
*/
String PROPKEY_PARKING_POSITION_PRIORITY = "tcs:parkingPositionPriority";
/**
* The key of a vehicle property defining the name of the vehicle's assigned parking position.
* <p>
* Whether and in what way this is respected for selecting a parking position is
* implementation-specific.
* </p>
*/
String PROPKEY_ASSIGNED_PARKING_POSITION = "tcs:assignedParkingPosition";
/**
* The key of a vehicle property defining the name of the vehicle's preferred parking position.
* <p>
* Whether and in what way this is respected for selecting a parking position is
* implementation-specific.
* </p>
*/
String PROPKEY_PREFERRED_PARKING_POSITION = "tcs:preferredParkingPosition";
/**
* The key of a vehicle property defining the name of the vehicle's assigned recharge location.
* <p>
* Whether and in what way this is respected for selecting a recharge location is
* implementation-specific.
* </p>
*/
String PROPKEY_ASSIGNED_RECHARGE_LOCATION = "tcs:assignedRechargeLocation";
/**
* The key of a vehicle property defining the name of the vehicle's preferred recharge location.
* <p>
* Whether and in what way this is respected for selecting a recharge location is
* implementation-specific.
* </p>
*/
String PROPKEY_PREFERRED_RECHARGE_LOCATION = "tcs:preferredRechargeLocation";
/**
* Notifies the dispatcher that it should start the dispatching process.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*/
void dispatch();
/**
* Notifies the dispatcher that the given transport order is to be withdrawn/aborted.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param order The transport order to be withdrawn/aborted.
* @param immediateAbort Whether the order should be aborted immediately instead of withdrawn.
*/
void withdrawOrder(
@Nonnull
TransportOrder order,
boolean immediateAbort
);
/**
* Notifies the dispatcher that any order a given vehicle might be processing is to be withdrawn.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param vehicle The vehicle whose order is withdrawn.
* @param immediateAbort Whether the vehicle's order should be aborted immediately instead of
* withdrawn.
*/
void withdrawOrder(
@Nonnull
Vehicle vehicle,
boolean immediateAbort
);
/**
* Notifies the dispatcher of a request to reroute the given vehicle considering the given
* rerouting type.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param vehicle The vehicle to be rerouted.
* @param reroutingType The type of the requested rerouting.
*/
void reroute(
@Nonnull
Vehicle vehicle,
@Nonnull
ReroutingType reroutingType
);
/**
* Notifies the dispatcher to reroute all vehicles considering the given rerouting type.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param reroutingType The type of the requested rerouting.
*/
void rerouteAll(
@Nonnull
ReroutingType reroutingType
);
/**
* Notifies the dispatcher that it should assign the given transport order (to its intended
* vehicle) <em>now</em>.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param transportOrder The transport order to be assigned.
* @throws TransportOrderAssignmentException If the given transport order could not be assigned
* to its intended vehicle.
*/
void assignNow(
@Nonnull
TransportOrder transportOrder
)
throws TransportOrderAssignmentException;
}

View File

@@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import org.opentcs.components.Lifecycle;
/**
* Declares the methods that a generic kernel extension must implement.
*/
public interface KernelExtension
extends
Lifecycle {
}

View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import java.util.function.Function;
import org.opentcs.access.to.CreationTO;
/**
* Provides names for {@link CreationTO}s.
*/
public interface ObjectNameProvider
extends
Function<CreationTO, String> {
}

View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import java.util.function.Predicate;
import org.opentcs.data.order.OrderSequence;
/**
* Implementations of this interface check whether an order sequence may be removed.
*/
public interface OrderSequenceCleanupApproval
extends
Predicate<OrderSequence> {
}

View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import java.util.function.Predicate;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Implementations of this interface check whether a peripheral job may be removed.
*/
public interface PeripheralJobCleanupApproval
extends
Predicate<PeripheralJob> {
}

View File

@@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import jakarta.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Location;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* This interface declares the methods a peripheral job dispatcher module for the openTCS kernel
* must implement.
* <p>
* A peripheral job dispatcher manages the distribution of peripheral jobs among the peripheral
* devices represented by locations in a system. It is basically event-driven, where an event can
* be a new peripheral job being introduced into the system or a peripheral device becoming
* available for processing existing jobs.
* </p>
*/
public interface PeripheralJobDispatcher
extends
Lifecycle {
/**
* Notifies the dispatcher that it should start the dispatching process.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*/
void dispatch();
/**
* Notifies the dispatcher that any job a peripheral device (represented by the given location)
* might be processing is to be withdrawn.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param location The location representing a peripheral device whose job is withdrawn.
* @throws IllegalArgumentException If the given peripheral's current job is already in a final
* state, or if it is related to a transport order and this transport order is not in a final
* state.
*/
void withdrawJob(
@Nonnull
Location location
)
throws IllegalArgumentException;
/**
* Notifies the dispatcher that the given peripheral job is to be withdrawn.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param job The job to be withdrawn.
* @throws IllegalArgumentException If the given peripheral job is already in a final state, or if
* it is related to a transport order and this transport order is not in a final state.
*/
void withdrawJob(
@Nonnull
PeripheralJob job
)
throws IllegalArgumentException;
}

View File

@@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import java.io.Serializable;
/**
* Marks a query (parameter) object.
*
* @param <T> The result type.
*/
public interface Query<T> {
/**
* A convenience class to be used as the result type for queries that do not return any result.
*/
class Void
implements
Serializable {
/**
* Creates a new instance.
*/
public Void() {
}
}
}

View File

@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
/**
* A responder for generic queries.
*/
public interface QueryResponder {
/**
* Executes the specified query.
*
* @param <T> The query/result type.
* @param query The query/parameter object.
* @return The query result.
*/
<T> T query(Query<T> query);
}

View File

@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import org.opentcs.access.KernelException;
/**
* Thrown when allocating resources for a {@link Scheduler.Client Scheduler.Client} is impossible.
*/
public class ResourceAllocationException
extends
KernelException {
/**
* Creates a new ResourceAllocationException with the given detail message.
*
* @param message The detail message.
*/
public ResourceAllocationException(String message) {
super(message);
}
/**
* Creates a new ResourceAllocationException with the given detail message and
* cause.
*
* @param message The detail message.
* @param cause The cause.
*/
public ResourceAllocationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,233 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.util.annotations.ScheduledApiChange;
/**
* This interface declares the methods a router module for the openTCS
* kernel must implement.
* <p>
* A router finds routes from a start point to an end point, rating them
* according to implementation specific criteria/costs parameters.
* </p>
*/
public interface Router
extends
Lifecycle {
/**
* The key of a vehicle property defining the group of vehicles that may share the same routing.
* <p>
* The value is expected to be an integer.
* </p>
*/
String PROPKEY_ROUTING_GROUP = "tcs:routingGroup";
/**
* The key (prefix) of a path property defining the routing cost when its travelled in forward
* direction.
* <p>
* The value is expected to be a (long) integer.
* </p>
*/
String PROPKEY_ROUTING_COST_FORWARD = "tcs:routingCostForward";
/**
* The key (prefix) of a path property defining the routing cost when its travelled in reverse
* direction.
* <p>
* The value is expected to be a (long) integer.
* </p>
*/
String PROPKEY_ROUTING_COST_REVERSE = "tcs:routingCostReverse";
/**
* Notifies the router to update its routing topology with respect to the given paths.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param paths The paths to update in the routing topology. An empty set of paths results in the
* router updating the entire routing topology.
*/
void updateRoutingTopology(
@Nonnull
Set<Path> paths
);
/**
* Checks the routability of a given transport order.
* <p>
* The check for routability is affected by path properties and configured edge evaluators. This
* means that whether a transport order is considered routable <em>can</em> change between
* consecutive calls to this method.
* </p>
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param order The transport order to check for routability.
* @return A set of vehicles for which a route for the given transport order
* would be computable.
*/
@Nonnull
Set<Vehicle> checkRoutability(
@Nonnull
TransportOrder order
);
/**
* Checks the general routability of a given transport order.
* <p>
* The check for general routability is <em>not</em> affected by any path properties or any
* configured edge evaluators. This means that whether a transport order is considered generally
* routable <em>will not</em> change between consecutive calls to this method.
* </p>
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param order The transport order to check for routability.
* @return {@code true}, if the transport order is generally routable, otherwise {@code false}.
*/
@ScheduledApiChange(when = "7.0", details = "Default implementation will be removed.")
default boolean checkGeneralRoutability(
@Nonnull
TransportOrder order
) {
return false;
}
/**
* Returns a complete route for a given vehicle that starts on a specified
* point and allows the vehicle to process a given transport order.
* The route is encapsulated into drive orders which correspond to those drive
* orders that the transport order is composed of. The transport order itself
* is not modified.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param vehicle The vehicle for which the calculated route must be passable.
* @param sourcePoint The position at which the vehicle would start processing
* the transport order (i.e. the vehicle's current position).
* @param transportOrder The transport order to be processed by the vehicle.
* @return A list of drive orders containing the complete calculated route for
* the given transport order, passable the given vehicle and starting on the
* given point, or the empty optional, if no such route exists.
*/
@Nonnull
Optional<List<DriveOrder>> getRoute(
@Nonnull
Vehicle vehicle,
@Nonnull
Point sourcePoint,
@Nonnull
TransportOrder transportOrder
);
/**
* Returns a route from one point to another, passable for a given vehicle.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param vehicle The vehicle for which the route must be passable.
* @param sourcePoint The starting point of the route to calculate.
* @param destinationPoint The end point of the route to calculate.
* @param resourcesToAvoid Resources to avoid when calculating the route.
* @return The calculated route, or the empty optional, if a route between the
* given points does not exist.
*/
@Nonnull
Optional<Route> getRoute(
@Nonnull
Vehicle vehicle,
@Nonnull
Point sourcePoint,
@Nonnull
Point destinationPoint,
@Nonnull
Set<TCSResourceReference<?>> resourcesToAvoid
);
/**
* Returns the costs for travelling a route from one point to another with a
* given vehicle.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param vehicle The vehicle for which the route must be passable.
* @param sourcePoint The starting point of the route.
* @param destinationPoint The end point of the route.
* @param resourcesToAvoid Resources to avoid when calculating the route.
* @return The costs of the route, or <code>Long.MAX_VALUE</code>, if no such
* route exists.
*/
long getCosts(
@Nonnull
Vehicle vehicle,
@Nonnull
Point sourcePoint,
@Nonnull
Point destinationPoint,
@Nonnull
Set<TCSResourceReference<?>> resourcesToAvoid
);
/**
* Notifies the router of a route being selected for a vehicle.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param vehicle The vehicle for which a route is being selected.
* @param driveOrders The drive orders encapsulating the route being selected,
* or <code>null</code>, if no route is being selected for the vehicle (i.e.
* an existing entry for the given vehicle would be removed).
*/
void selectRoute(
@Nonnull
Vehicle vehicle,
@Nullable
List<DriveOrder> driveOrders
);
/**
* Returns an unmodifiable view on the selected routes the router knows about.
* The returned map contains an entry for each vehicle for which a selected
* route is known.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @return An unmodifiable view on the selected routes the router knows about.
*/
@Nonnull
Map<Vehicle, List<DriveOrder>> getSelectedRoutes();
/**
* Returns all points which are currently targeted by any vehicle.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @return A set of all points currently targeted by any vehicle.
*/
@Nonnull
Set<Point> getTargetedPoints();
}

View File

@@ -0,0 +1,402 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.model.Vehicle;
/**
* Manages resources used by clients (vehicles) to help prevent both collisions and deadlocks.
* <p>
* Every client usually interacts with the <code>Scheduler</code> according to the following
* workflow:
* </p>
* <ol>
* <li>
* Initially, the client calls
* {@link #allocateNow(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocateNow()}
* when a vehicle pops up somewhere in the driving course.
* This usually happens either upon kernel startup or when a vehicle communicates its current
* position to the kernel for the first time.
* </li>
* <li>
* Once a transport order is assigned to a vehicle, the client calls
* {@link #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List) claim()} with the
* complete sequence of resource sets the vehicle needs to process the transport order - usually
* each containing a point and the path leading to it.
* </li>
* <li>
* As the vehicle processes the transport order, the client subsequently calls
* {@link #allocate(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocate()} for
* resources needed next (for reaching the next point on the route).
* The <code>Scheduler</code> asynchronously calls back either
* {@link Client#allocationSuccessful(java.util.Set)} or
* {@link Client#allocationFailed(java.util.Set)}, informing the client about the result.
* Upon allocating the resources for the client, it also implicitly removes them from the head of
* the client's claim sequence.
* </li>
* <li>
* As the vehicle passes points (and paths) on the route, the client calls
* {@link #free(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) free()} for resources
* it does not need any more, allowing these resources to be allocated by other clients.
* </li>
* </ol>
* <p>
* At the end of this process, the client's claim sequence is empty, and only the most recently
* allocated resources are still assigned to it, reflecting the vehicle's current position.
* (If the vehicle has disappeared from the driving course after processing the transport order, the
* client would call {@link #freeAll(org.opentcs.components.kernel.Scheduler.Client) freeAll()} to
* inform the <code>Scheduler</code> about this.)
* </p>
*/
public interface Scheduler
extends
Lifecycle {
/**
* The key of a path property defining the direction in which a vehicle is entering a block when
* it's taking the path.
*/
String PROPKEY_BLOCK_ENTRY_DIRECTION = "tcs:blockEntryDirection";
/**
* Sets/Updates the resource claim for a vehicle.
* <p>
* <em>Claimed</em> resources are resources that a vehicle will eventually require for executing
* its movements in the future, but for which it does not request allocation, yet.
* Claiming resources provides information to the scheduler about future allocations <em>and their
* intended order</em>, allowing the scheduler to consider these information for its resource
* planning.
* </p>
* <p>
* Resources can be claimed by multiple vehicles at the same time.
* This is different from allocations:
* Only a single vehicle can allocate a resource at the same time.
* </p>
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client claiming the resources.
* @param resourceSequence The sequence of resources claimed. May be empty to clear the client's
* claim.
*/
void claim(
@Nonnull
Client client,
@Nonnull
List<Set<TCSResource<?>>> resourceSequence
);
/**
* Requests allocation of the given resources.
* The client will be informed via a callback to
* {@link Client#allocationSuccessful(java.util.Set)} or
* {@link Client#allocationFailed(java.util.Set)} whether the allocation was successful or not.
* <ul>
* <li>
* Clients may only allocate resources in the order they have previously
* {@link #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List) claim()}ed them.
* </li>
* <li>
* Upon allocation, the scheduler will implicitly remove the set of allocated resources from (the
* head of) the client's claim sequence.
* </li>
* <li>
* As a result, a client may only allocate the set of resources at the head of its claim sequence.
* </li>
* </ul>
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client requesting the resources.
* @param resources The resources to be allocated.
* @throws IllegalArgumentException If the set of resources to be allocated is not equal to the
* <em>next</em> set in the sequence of currently claimed resources, or if the client has already
* requested resources that have not yet been granted.
* @see #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List)
*/
void allocate(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
)
throws IllegalArgumentException;
/**
* Checks if the resulting system state is safe if the given set of resources
* would be allocated by the given client <em>immediately</em>.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client requesting the resources.
* @param resources The requested resources.
* @return {@code true} if the given resources are safe to be allocated by the given client,
* otherwise {@code false}.
*/
boolean mayAllocateNow(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Informs the scheduler that a set of resources are to be allocated for the given client
* <em>immediately</em>.
* <p>
* Note the following:
* </p>
* <ul>
* <li>
* This method should only be called in urgent/emergency cases, for instance if a vehicle has been
* moved to a different point manually, which has to be reflected by resource allocation in the
* scheduler.
* </li>
* <li>
* Unlike
* {@link #allocate(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocate()},
* this method does not block, i.e. the operation happens synchronously.
* </li>
* <li>
* This method does <em>not</em> implicitly deallocate or unclaim any other resources for the
* client.
* </li>
* </ul>
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client requesting the resources.
* @param resources The resources requested.
* @throws ResourceAllocationException If it's impossible to allocate the given set of resources
* for the given client.
*/
void allocateNow(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
)
throws ResourceAllocationException;
/**
* Releases a set of resources allocated by a client.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client releasing the resources.
* @param resources The resources released. Any resources in the given set not allocated by the
* given client are ignored.
*/
void free(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Releases all resources allocated by the given client.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client.
*/
void freeAll(
@Nonnull
Client client
);
/**
* Releases all pending resource allocations for the given client.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param client The client.
*/
void clearPendingAllocations(
@Nonnull
Client client
);
/**
* Explicitly triggers a rescheduling run during which the scheduler tries to allocate resources
* for all waiting clients.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*/
void reschedule();
/**
* Returns all resource allocations as a map of client IDs to resources.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @return All resource allocations as a map of client IDs to resources.
*/
@Nonnull
Map<String, Set<TCSResource<?>>> getAllocations();
/**
* Informs the scheduler that a set of resources was successfully prepared in order of allocating
* them to a client.
* <p>
* This method is supposed to be called only from the kernel executor thread.
* </p>
*
* @param module The module a preparation was necessary for.
* @param client The client that requested the preparation/allocation.
* @param resources The resources that are now prepared for the client.
*/
void preparationSuccessful(
@Nonnull
Module module,
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Defines callback methods for clients of the resource scheduler.
*/
interface Client {
/**
* Returns an ID string for this client.
* The returned string should be unique among all clients in the system.
*
* @return An unique ID string for this client.
*/
@Nonnull
String getId();
/**
* Returns a reference to the {@link Vehicle} that this client is related to.
*
* @return A reference to the {@link Vehicle} that this client is related to or {@code null}, if
* this client is not related to any {@link Vehicle}.
*/
@Nullable
TCSObjectReference<Vehicle> getRelatedVehicle();
/**
* Called when resources have been reserved for this client.
*
* @param resources The resources reserved.
* @return <code>true</code> if, and only if, this client accepts the resources allocated. A
* return value of <code>false</code> indicates this client does not need the given resources
* (any more), freeing them implicitly, but not restoring any previous claim.
*/
boolean allocationSuccessful(
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Called if it was impossible to allocate a requested set of resources for this client.
*
* @param resources The resources which could not be reserved.
*/
void allocationFailed(
@Nonnull
Set<TCSResource<?>> resources
);
}
/**
* A scheduler module.
*/
interface Module
extends
Lifecycle {
/**
* Informs this module about a client's current allocation state.
*
* @param client The client.
* @param alloc The client's currently allocated resources.
* @param remainingClaim The client's remaining claim.
*/
void setAllocationState(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> alloc,
@Nonnull
List<Set<TCSResource<?>>> remainingClaim
);
/**
* Checks if the resulting system state is safe if the given set of resources
* would be allocated by the given resource user.
*
* @param client The <code>ResourceUser</code> requesting resources set.
* @param resources The requested resources.
* @return <code>true</code> if this module thinks the given resources may be allocated for the
* given client.
*/
boolean mayAllocate(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Lets this module prepare the given resources so they can be allocated to a client.
*
* @param client The client the resources are being prepared for.
* @param resources The resources to be prepared.
*/
void prepareAllocation(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Checks if this module is done preparing the given resources for a client.
*
* @param client The client the resources are being prepared for.
* @param resources The resources to be checked.
* @return <code>true</code> if the resoruces are prepared for a client.
*/
boolean hasPreparedAllocation(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
/**
* Informs this module about resources being fully released by a client.
*
* @param client The client releasing the resources.
* @param resources The resources being released.
*/
void allocationReleased(
@Nonnull
Client client,
@Nonnull
Set<TCSResource<?>> resources
);
}
}

View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel;
import java.util.function.Predicate;
import org.opentcs.data.order.TransportOrder;
/**
* Implementations of this interface check whether a transport order may be removed.
*/
public interface TransportOrderCleanupApproval
extends
Predicate<TransportOrder> {
}

View File

@@ -0,0 +1,89 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.dipatching;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkArgument;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
/**
* Thrown when a {@link TransportOrder} could not be assigned to a {@link Vehicle}.
*/
public class TransportOrderAssignmentException
extends
KernelRuntimeException {
private final TCSObjectReference<TransportOrder> transportOrder;
private final TCSObjectReference<Vehicle> vehicle;
private final TransportOrderAssignmentVeto transportOrderAssignmentVeto;
/**
* Creates a new instance.
*
* @param transportOrder The transport order.
* @param vehicle The vehicle.
* @param transportOrderAssignmentVeto The reason why the transport order could not be assigned
* to the vehicle.
*/
public TransportOrderAssignmentException(
@Nonnull
TCSObjectReference<TransportOrder> transportOrder,
@Nullable
TCSObjectReference<Vehicle> vehicle,
@Nonnull
TransportOrderAssignmentVeto transportOrderAssignmentVeto
) {
super(
"Could not assign transport order '" + transportOrder.getName() + "' to vehicle '"
+ (vehicle != null ? vehicle.getName() : "null") + "': "
+ transportOrderAssignmentVeto.name()
);
// This exception is reasonable only for actual assignment vetos.
checkArgument(
transportOrderAssignmentVeto != TransportOrderAssignmentVeto.NO_VETO,
"Invalid assignment veto for exception: " + transportOrderAssignmentVeto
);
this.transportOrder = requireNonNull(transportOrder, "transportOrder");
this.vehicle = vehicle;
this.transportOrderAssignmentVeto = requireNonNull(
transportOrderAssignmentVeto,
"transportOrderAssignmentVeto"
);
}
/**
* Returns the transport order.
*
* @return The transport order.
*/
@Nonnull
public TCSObjectReference<TransportOrder> getTransportOrder() {
return transportOrder;
}
/**
* Returns the vehicle.
*
* @return The vehicle.
*/
@Nullable
public TCSObjectReference<Vehicle> getVehicle() {
return vehicle;
}
/**
* Returns the reason why a transport order assignment was not possible.
*
* @return The reason why a transport order assignment was not possible.
*/
@Nonnull
public TransportOrderAssignmentVeto getTransportOrderAssignmentVeto() {
return transportOrderAssignmentVeto;
}
}

View File

@@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.dipatching;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
/**
* Defines reasons for a transport order assignment not being possible.
*/
public enum TransportOrderAssignmentVeto {
/**
* There is no reason that prevents the transport order assignment.
*/
NO_VETO,
/**
* The transport order's {@link TransportOrder.State} is invalid (e.g. because it's not in state
* {@link TransportOrder.State#DISPATCHABLE}).
*/
TRANSPORT_ORDER_STATE_INVALID,
/**
* The transport order is part of an {@link OrderSequence}.
*/
TRANSPORT_ORDER_PART_OF_ORDER_SEQUENCE,
/**
* The transport order has its intended vehicle not set.
*/
TRANSPORT_ORDER_INTENDED_VEHICLE_NOT_SET,
/**
* The {@link Vehicle.ProcState} of the vehicle to assign the transport order to is invalid (e.g.
* because it's not {@link Vehicle.ProcState#IDLE}).
*/
VEHICLE_PROCESSING_STATE_INVALID,
/**
* The {@link Vehicle.State} of the vehicle to assign the transport order to is invalid (e.g.
* because it's neither {@link Vehicle.State#IDLE} nor {@link Vehicle.State#CHARGING}).
*/
VEHICLE_STATE_INVALID,
/**
* The {@link Vehicle.IntegrationLevel} of the vehicle to assign the transport order to is invalid
* (e.g. because it's not {@link Vehicle.IntegrationLevel#TO_BE_UTILIZED}).
*/
VEHICLE_INTEGRATION_LEVEL_INVALID,
/**
* The current position of the vehicle to assign the transport order to is unknown.
*/
VEHICLE_CURRENT_POSITION_UNKNOWN,
/**
* The vehicle to assign the transport order to is processing an {@link OrderSequence}.
*/
VEHICLE_PROCESSING_ORDER_SEQUENCE,
/**
* A generic (dispatcher implementation-specific) reason that prevents the transport order
* assignment.
*/
GENERIC_VETO;
}

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
/**
* Interfaces for pluggable strategies and other components for a kernel application.
*/
package org.opentcs.components.kernel;

View File

@@ -0,0 +1,88 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.routing;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import org.opentcs.data.model.Path;
/**
* A wrapper for {@link Path}s that can be used to build routing graphs.
*/
public class Edge {
/**
* The path in the model that is traversed on this edge.
*/
private final Path path;
/**
* Whether the path is travelled in reverse direction.
*/
private final boolean travellingReverse;
/**
* Creates a new instance.
*
* @param modelPath The path in the model that is traversed on this edge.
* @param travellingReverse Whether the path is travelled in reverse direction.
*/
public Edge(
@Nonnull
Path modelPath,
boolean travellingReverse
) {
this.path = requireNonNull(modelPath, "modelPath");
this.travellingReverse = travellingReverse;
}
/**
* Returns the path in the model that is traversed on this edge.
*
* @return The path in the model that is traversed on this edge.
*/
public Path getPath() {
return path;
}
/**
* Indicates whether the path is travelled in reverse direction.
*
* @return Whether the path is travelled in reverse direction.
*/
public boolean isTravellingReverse() {
return travellingReverse;
}
/**
* Returns the source vertex of this edge.
*
* @return The source vertex of this edge.
*/
public String getSourceVertex() {
return isTravellingReverse()
? path.getDestinationPoint().getName()
: path.getSourcePoint().getName();
}
/**
* Returns the target vertex of this edge.
*
* @return The target vertex of this edge.
*/
public String getTargetVertex() {
return isTravellingReverse()
? path.getSourcePoint().getName()
: path.getDestinationPoint().getName();
}
@Override
public String toString() {
return "Edge{"
+ "path=" + path + ", "
+ "travellingReverse=" + travellingReverse + ", "
+ "sourceVertex=" + getSourceVertex() + ", "
+ "targetVertex=" + getTargetVertex()
+ '}';
}
}

View File

@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.routing;
import jakarta.annotation.Nonnull;
import org.opentcs.data.model.Vehicle;
/**
* Computes the weight of edges in the routing graph.
*/
public interface EdgeEvaluator {
/**
* Called when/before computation of a routing graph starts.
*
* @param vehicle The vehicle for which the routing graph is computed.
*/
void onGraphComputationStart(
@Nonnull
Vehicle vehicle
);
/**
* Called when/after a computation of a routing graph is done.
*
* @param vehicle The vehicle for which the routing graph is computed.
*/
void onGraphComputationEnd(
@Nonnull
Vehicle vehicle
);
/**
* Computes the weight of an edge in the routing graph.
*
* @param edge The edge.
* @param vehicle The vehicle for which to compute the edge's weight.
* @return The computed weight of the given edge.
* A value of {@code Double.POSITIVE_INFINITY} indicates that the edge is to be excluded from
* routing.
* Note that negative weights might not be handled well by the respective routing algorithm used.
*/
double computeWeight(
@Nonnull
Edge edge,
@Nonnull
Vehicle vehicle
);
}

View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.routing;
import java.util.function.Function;
import org.opentcs.data.model.Vehicle;
/**
* Determines the routing group for a {@link Vehicle} instance.
*/
public interface GroupMapper
extends
Function<Vehicle, String> {
}

View File

@@ -0,0 +1,123 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import jakarta.annotation.Nonnull;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.components.kernel.dipatching.TransportOrderAssignmentException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.ReroutingType;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.data.order.TransportOrder.State;
/**
* Provides methods concerning the {@link Dispatcher}.
*/
public interface DispatcherService {
/**
* Explicitly trigger the dispatching process.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void dispatch()
throws KernelRuntimeException;
/**
* Withdraw any order that a vehicle might be processing.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param ref A reference to the vehicle to be modified.
* @param immediateAbort If {@code false}, this method once will initiate the withdrawal, leaving
* the transport order assigned to the vehicle until it has finished the movements that it has
* already been ordered to execute. The transport order's state will change to
* {@link State#WITHDRAWN}. If {@code true}, the dispatcher will withdraw the order from the
* vehicle without further waiting.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void withdrawByVehicle(TCSObjectReference<Vehicle> ref, boolean immediateAbort)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Withdraw the referenced order.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param ref A reference to the transport order to be withdrawn.
* @param immediateAbort If {@code false}, this method once will initiate the withdrawal, leaving
* the transport order assigned to the vehicle until it has finished the movements that it has
* already been ordered to execute. The transport order's state will change to
* {@link State#WITHDRAWN}. If {@code true}, the dispatcher will withdraw the order from the
* vehicle without further waiting.
* @throws ObjectUnknownException If the referenced transport order does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void withdrawByTransportOrder(TCSObjectReference<TransportOrder> ref, boolean immediateAbort)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Explicitly trigger a rerouting for the given vehicles.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param ref The vehicle to be rerouted.
* @param reroutingType The type of the requested rerouting.
*/
void reroute(
@Nonnull
TCSObjectReference<Vehicle> ref,
@Nonnull
ReroutingType reroutingType
)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Explicitly trigger a rerouting for all vehicles.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param reroutingType The type of rerouting.
*/
void rerouteAll(
@Nonnull
ReroutingType reroutingType
);
/**
* Assign the referenced transport order (to its intended vehicle) <em>now</em>.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param ref The transport order to be assigned.
* @throws ObjectUnknownException If the referenced transport order does not exist.
* @throws TransportOrderAssignmentException If the given transport order could not be assigned
* to its intended vehicle.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void assignNow(TCSObjectReference<TransportOrder> ref)
throws ObjectUnknownException,
TransportOrderAssignmentException,
KernelRuntimeException;
}

View File

@@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Declares the methods the peripheral job service must provide which are not accessible to remote
* peers.
*/
public interface InternalPeripheralJobService
extends
PeripheralJobService {
/**
* Updates a peripheral job's state.
* Note that peripheral job states are intended to be manipulated by the peripheral job
* dispatcher only.
* Calling this method from any other parts of the kernel may result in undefined behaviour.
*
* @param ref A reference to the peripheral job to be modified.
* @param state The peripheral job's new state.
* @throws ObjectUnknownException If the referenced peripheral job does not exist.
*/
void updatePeripheralJobState(TCSObjectReference<PeripheralJob> ref, PeripheralJob.State state)
throws ObjectUnknownException;
}

View File

@@ -0,0 +1,71 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Declares the methods the peripheral service must provide which are not accessible to remote
* peers.
*/
public interface InternalPeripheralService
extends
PeripheralService {
/**
* Updates a peripheral's processing state.
*
* @param ref A reference to the location to be modified.
* @param state The peripheral's new processing state.
* @throws ObjectUnknownException If the referenced location does not exist.
*/
void updatePeripheralProcState(
TCSResourceReference<Location> ref,
PeripheralInformation.ProcState state
)
throws ObjectUnknownException;
/**
* Updates a peripheral's reservation token.
*
* @param ref A reference to the location to be modified.
* @param reservationToken The peripheral's new reservation token.
* @throws ObjectUnknownException If the referenced location does not exist.
*/
void updatePeripheralReservationToken(
TCSResourceReference<Location> ref,
String reservationToken
)
throws ObjectUnknownException;
/**
* Updates a peripheral's state.
*
* @param ref A reference to the location to be modified.
* @param state The peripheral's new state.
* @throws ObjectUnknownException If the referenced location does not exist.
*/
void updatePeripheralState(
TCSResourceReference<Location> ref,
PeripheralInformation.State state
)
throws ObjectUnknownException;
/**
* Updates a peripheral's current peripheral job.
*
* @param ref A reference to the location to be modified.
* @param peripheralJob A reference to the peripheral job the peripheral device processes.
* @throws ObjectUnknownException If the referenced location does not exist.
*/
void updatePeripheralJob(
TCSResourceReference<Location> ref,
TCSObjectReference<PeripheralJob> peripheralJob
)
throws ObjectUnknownException;
}

View File

@@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import java.util.Set;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.model.TCSResourceReference;
/**
* Declares the methods the plant model service must provide which are not accessible to remote
* peers.
*/
public interface InternalPlantModelService
extends
PlantModelService {
/**
* Expands a set of resources <em>A</em> to a set of resources <em>B</em>.
* <em>B</em> contains the resources in <em>A</em> with blocks expanded to their actual members.
* The given set is not modified.
*
* @param resources The set of resources to be expanded.
* @return The given set with resources expanded.
* @throws ObjectUnknownException If any of the referenced objects does not exist.
*/
Set<TCSResource<?>> expandResources(Set<TCSResourceReference<?>> resources)
throws ObjectUnknownException;
/**
* Loads the saved model into the kernel.
* If there is no saved model, a new empty model will be loaded.
*
* @throws IllegalStateException If the model cannot be loaded.
*/
void loadPlantModel()
throws IllegalStateException;
/**
* Saves the current model under the given name.
* If there is a saved model, it will be overwritten.
*
* @throws IllegalStateException If the model could not be persisted for some reason.
*/
void savePlantModel()
throws IllegalStateException;
}

View File

@@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import jakarta.annotation.Nonnull;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.QueryResponder;
/**
* Declares query-related methods not accessible to remote peers.
*/
public interface InternalQueryService
extends
QueryService {
/**
* Registers the given responder for handling queries of the given type.
*
* @param clazz The query type.
* @param responder The responder to handle the queries.
*/
void registerResponder(
@Nonnull
Class<? extends Query<?>> clazz,
@Nonnull
QueryResponder responder
);
/**
* Unregisters the responder for the given type.
*
* @param clazz The query type.
*/
void unregisterResponder(
@Nonnull
Class<? extends Query<?>> clazz
);
}

View File

@@ -0,0 +1,130 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import java.util.List;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
/**
* Declares the methods the transport order service must provide which are not accessible to remote
* peers.
*/
public interface InternalTransportOrderService
extends
TransportOrderService {
/**
* Sets an order sequence's finished flag.
*
* @param ref A reference to the order sequence to be modified.
* @throws ObjectUnknownException If the referenced transport order is not in this pool.
*/
void markOrderSequenceFinished(TCSObjectReference<OrderSequence> ref)
throws ObjectUnknownException;
/**
* Updates an order sequence's finished index.
*
* @param ref A reference to the order sequence to be modified.
* @param index The sequence's new finished index.
* @throws ObjectUnknownException If the referenced transport order is not in this pool.
*/
void updateOrderSequenceFinishedIndex(TCSObjectReference<OrderSequence> ref, int index)
throws ObjectUnknownException;
/**
* Updates an order sequence's processing vehicle.
*
* @param seqRef A reference to the order sequence to be modified.
* @param vehicleRef A reference to the vehicle processing the order sequence.
* @throws ObjectUnknownException If the referenced transport order is not in this pool.
*/
void updateOrderSequenceProcessingVehicle(
TCSObjectReference<OrderSequence> seqRef,
TCSObjectReference<Vehicle> vehicleRef
)
throws ObjectUnknownException;
/**
* Updates a transport order's list of drive orders.
*
* @param ref A reference to the transport order to be modified.
* @param driveOrders The drive orders containing the data to be copied into this transport
* order's drive orders.
* @throws ObjectUnknownException If the referenced transport order does not exist.
*/
void updateTransportOrderDriveOrders(
TCSObjectReference<TransportOrder> ref,
List<DriveOrder> driveOrders
)
throws ObjectUnknownException;
/**
* Updates a transport order's current drive order.
* Marks the current drive order as finished, adds it to the list of past drive orders and sets
* the current drive order to the next one of the list of future drive orders (or {@code null},
* if that list is empty).
* Also implicitly sets the {@link TransportOrder#getCurrentRouteStepIndex() transport order's
* current route step index} to {@link TransportOrder#ROUTE_STEP_INDEX_DEFAULT}.
* If the current drive order is {@code null} because all drive orders have been finished
* already or none has been started, yet, nothing happens.
*
* @param ref A reference to the transport order to be modified.
* @throws ObjectUnknownException If the referenced transport order is not in this pool.
*/
void updateTransportOrderNextDriveOrder(TCSObjectReference<TransportOrder> ref)
throws ObjectUnknownException;
/**
* Updates a transport order's index of the last route step travelled for the currently processed
* drive order.
*
* @param ref A reference to the transport order to be modified.
* @param index The new index.
* @throws ObjectUnknownException If the referenced transport order does not exist.
*/
void updateTransportOrderCurrentRouteStepIndex(
TCSObjectReference<TransportOrder> ref,
int index
)
throws ObjectUnknownException;
/**
* Updates a transport order's processing vehicle.
*
* @param orderRef A reference to the transport order to be modified.
* @param vehicleRef A reference to the vehicle processing the order.
* @param driveOrders The drive orders containing the data to be copied into this transport
* order's drive orders.
* @throws ObjectUnknownException If the referenced transport order does not exist.
* @throws IllegalArgumentException If the destinations of the given drive orders do not match
* the destinations of the drive orders in this transport order.
*/
void updateTransportOrderProcessingVehicle(
TCSObjectReference<TransportOrder> orderRef,
TCSObjectReference<Vehicle> vehicleRef,
List<DriveOrder> driveOrders
)
throws ObjectUnknownException,
IllegalArgumentException;
/**
* Updates a transport order's state.
* Note that transport order states are intended to be manipulated by the dispatcher only.
* Calling this method from any other parts of the kernel may result in undefined behaviour.
*
* @param ref A reference to the transport order to be modified.
* @param state The transport order's new state.
* @throws ObjectUnknownException If the referenced transport order does not exist.
*/
void updateTransportOrderState(
TCSObjectReference<TransportOrder> ref,
TransportOrder.State state
)
throws ObjectUnknownException;
}

View File

@@ -0,0 +1,232 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import static java.util.Objects.requireNonNull;
import java.util.List;
import java.util.Set;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.BoundingBox;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Pose;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;
import org.opentcs.util.annotations.ScheduledApiChange;
/**
* Declares the methods the vehicle service must provide which are not accessible to remote peers.
*/
public interface InternalVehicleService
extends
VehicleService {
/**
* Updates a vehicle's energy level.
*
* @param ref A reference to the vehicle to be modified.
* @param energyLevel The vehicle's new energy level.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleEnergyLevel(TCSObjectReference<Vehicle> ref, int energyLevel)
throws ObjectUnknownException;
/**
* Updates a vehicle's load handling devices.
*
* @param ref A reference to the vehicle to be modified.
* @param devices The vehicle's new load handling devices.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleLoadHandlingDevices(
TCSObjectReference<Vehicle> ref,
List<LoadHandlingDevice> devices
)
throws ObjectUnknownException;
/**
* Updates the point which a vehicle is expected to occupy next.
*
* @param vehicleRef A reference to the vehicle to be modified.
* @param pointRef A reference to the point which the vehicle is expected to occupy next.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleNextPosition(
TCSObjectReference<Vehicle> vehicleRef,
TCSObjectReference<Point> pointRef
)
throws ObjectUnknownException;
/**
* Updates a vehicle's order sequence.
*
* @param vehicleRef A reference to the vehicle to be modified.
* @param sequenceRef A reference to the order sequence the vehicle processes.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleOrderSequence(
TCSObjectReference<Vehicle> vehicleRef,
TCSObjectReference<OrderSequence> sequenceRef
)
throws ObjectUnknownException;
/**
* Updates the vehicle's current orientation angle (-360..360 degrees, or {@link Double#NaN}, if
* the vehicle doesn't provide an angle).
*
* @param ref A reference to the vehicle to be modified.
* @param angle The vehicle's orientation angle.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
* @deprecated Use {@link #updateVehiclePose(TCSObjectReference,Pose)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
void updateVehicleOrientationAngle(TCSObjectReference<Vehicle> ref, double angle)
throws ObjectUnknownException;
/**
* Places a vehicle on a point.
*
* @param vehicleRef A reference to the vehicle to be modified.
* @param pointRef A reference to the point on which the vehicle is to be placed.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehiclePosition(
TCSObjectReference<Vehicle> vehicleRef,
TCSObjectReference<Point> pointRef
)
throws ObjectUnknownException;
/**
* Updates the vehicle's current precise position in mm.
*
* @param ref A reference to the vehicle to be modified.
* @param position The vehicle's precise position in mm.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
* @deprecated Use {@link #updateVehiclePose(TCSObjectReference,Pose)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
void updateVehiclePrecisePosition(TCSObjectReference<Vehicle> ref, Triple position)
throws ObjectUnknownException;
/**
* Updates the vehicle's pose.
*
* @param ref A reference to the vehicle to be modified.
* @param pose The vehicle's new pose.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
@ScheduledApiChange(when = "7.0", details = "Default implementation will be removed.")
default void updateVehiclePose(TCSObjectReference<Vehicle> ref, Pose pose)
throws ObjectUnknownException {
requireNonNull(ref, "ref");
requireNonNull(pose, "pose");
updateVehiclePrecisePosition(ref, pose.getPosition());
updateVehicleOrientationAngle(ref, pose.getOrientationAngle());
}
/**
* Updates a vehicle's processing state.
*
* @param ref A reference to the vehicle to be modified.
* @param state The vehicle's new processing state.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleProcState(TCSObjectReference<Vehicle> ref, Vehicle.ProcState state)
throws ObjectUnknownException;
/**
* Updates a vehicle's recharge operation.
*
* @param ref A reference to the vehicle to be modified.
* @param rechargeOperation The vehicle's new recharge action.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleRechargeOperation(TCSObjectReference<Vehicle> ref, String rechargeOperation)
throws ObjectUnknownException;
/**
* Updates a vehicle's claimed resources.
*
* @param ref A reference to the vehicle to be modified.
* @param resources The new resources.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleClaimedResources(
TCSObjectReference<Vehicle> ref,
List<Set<TCSResourceReference<?>>> resources
)
throws ObjectUnknownException;
/**
* Updates a vehicle's allocated resources.
*
* @param ref A reference to the vehicle to be modified.
* @param resources The new resources.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleAllocatedResources(
TCSObjectReference<Vehicle> ref,
List<Set<TCSResourceReference<?>>> resources
)
throws ObjectUnknownException;
/**
* Updates a vehicle's state.
*
* @param ref A reference to the vehicle to be modified.
* @param state The vehicle's new state.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleState(TCSObjectReference<Vehicle> ref, Vehicle.State state)
throws ObjectUnknownException;
/**
* Updates a vehicle's length.
*
* @param ref A reference to the vehicle to be modified.
* @param length The vehicle's new length.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
* @deprecated Use {@link #updateVehicleBoundingBox(TCSObjectReference, BoundingBox)} instead.
*/
@Deprecated
@ScheduledApiChange(when = "7.0", details = "Will be removed.")
void updateVehicleLength(TCSObjectReference<Vehicle> ref, int length)
throws ObjectUnknownException;
/**
* Updates the vehicle's bounding box.
*
* @param ref A reference to the vehicle.
* @param boundingBox The vehicle's new bounding box (in mm).
* @throws ObjectUnknownException If the referenced vehicle does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
@ScheduledApiChange(when = "7.0", details = "Default implementation will be removed.")
default void updateVehicleBoundingBox(TCSObjectReference<Vehicle> ref, BoundingBox boundingBox)
throws ObjectUnknownException,
KernelRuntimeException {
throw new UnsupportedOperationException("Not yet implemented.");
}
/**
* Updates a vehicle's transport order.
*
* @param vehicleRef A reference to the vehicle to be modified.
* @param orderRef A reference to the transport order the vehicle processes.
* @throws ObjectUnknownException If the referenced vehicle does not exist.
*/
void updateVehicleTransportOrder(
TCSObjectReference<Vehicle> vehicleRef,
TCSObjectReference<TransportOrder> orderRef
)
throws ObjectUnknownException;
}

View File

@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.notification.UserNotification;
/**
* Provides methods concerning {@link UserNotification}s.
*/
public interface NotificationService {
/**
* Returns a list of user notifications.
*
* @param predicate A filter predicate that accepts the user notifications to be returned. May be
* {@code null} to return all existing user notifications.
* @return A list of user notifications, in the order in which they were published.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
List<UserNotification> fetchUserNotifications(Predicate<UserNotification> predicate)
throws KernelRuntimeException;
/**
* Publishes a user notification.
*
* @param notification The notification to be published.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void publishUserNotification(UserNotification notification)
throws KernelRuntimeException;
}

View File

@@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.PeripheralJobDispatcher;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Provides methods concerning the {@link PeripheralJobDispatcher}.
*/
public interface PeripheralDispatcherService {
/**
* Explicitly trigger the dispatching process for peripheral jobs.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void dispatch()
throws KernelRuntimeException;
/**
* Withdraw any job that a peripheral device (represented by the given location) might be
* processing.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param ref A reference to the location representing the peripheral device.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void withdrawByLocation(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Withdraw the given peripheral job.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @param ref A reference to the peripheral job to be withdrawn.
* @throws ObjectUnknownException If the referenced peripheral job does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void withdrawByPeripheralJob(TCSObjectReference<PeripheralJob> ref)
throws ObjectUnknownException,
KernelRuntimeException;
}

View File

@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.peripherals.PeripheralJob;
/**
* Provides methods concerning {@link PeripheralJob}s.
*/
public interface PeripheralJobService
extends
TCSObjectService {
/**
* Creates a peripheral job.
* A new peripheral job is created with a generated unique ID and all other attributes taken from
* the given transfer object.
* A copy of the newly created transport order is then returned.
*
* @param to Describes the peripheral job to be created.
* @return A copy of the newly created peripheral job.
* @throws ObjectUnknownException If any referenced object does not exist.
* @throws ObjectExistsException If an object with the same name already exists in the model.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
PeripheralJob createPeripheralJob(PeripheralJobCreationTO to)
throws ObjectUnknownException,
ObjectExistsException,
KernelRuntimeException;
}

View File

@@ -0,0 +1,100 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.components.kernel.services;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
/**
* Provides methods concerning peripheral devices represented by {@link Location}s.
*/
public interface PeripheralService
extends
TCSObjectService {
/**
* Attaches the described comm adapter to the referenced location.
*
* @param ref A reference to the location.
* @param description The description for the comm adapter to be attached.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void attachCommAdapter(
TCSResourceReference<Location> ref,
PeripheralCommAdapterDescription description
)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Disables the comm adapter attached to the referenced location.
*
* @param ref A reference to the location the comm adapter is attached to.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void disableCommAdapter(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Enables the comm adapter attached to the referenced location.
*
* @param ref A reference to the location the comm adapter is attached to.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void enableCommAdapter(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Returns attachment information for the referenced location.
*
* @param ref A reference to the location.
* @return The attachment information.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
PeripheralAttachmentInformation fetchAttachmentInformation(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Returns the process model for the referenced location.
*
* @param ref A reference to the location.
* @return The process model.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
PeripheralProcessModel fetchProcessModel(TCSResourceReference<Location> ref)
throws ObjectUnknownException,
KernelRuntimeException;
/**
* Sends a {@link PeripheralAdapterCommand} to the comm adapter attached to the referenced
* location.
* <p>
* If called within the kernel application, this method is supposed to be called only on the
* kernel executor thread.
* </p>
*
* @see PeripheralAdapterCommand#execute(PeripheralCommAdapter)
* @param ref A reference to the location.
* @param command The adapter command to send.
* @throws ObjectUnknownException If the referenced location does not exist.
* @throws KernelRuntimeException In case there is an exception executing this method.
*/
void sendCommAdapterCommand(TCSResourceReference<Location> ref, PeripheralAdapterCommand command)
throws ObjectUnknownException,
KernelRuntimeException;
}

Some files were not shown because too many files have changed in this diff Show More