org.opentcs.kernel.workingset.TCSObjectRepository Maven / Gradle / Ivy
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.kernel.workingset;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkArgument;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
/**
* A container for TCSObject
s belonging together.
*
* Provides access to a set of data objects and ensures they have unique names.
*
*/
public class TCSObjectRepository {
/**
* The objects contained in this pool, mapped by their names, grouped by their classes.
*/
private final Map, Map>> objects = new HashMap<>();
/**
* Creates a new instance.
*/
public TCSObjectRepository() {
}
/**
* Adds a new object to the pool.
*
* @param newObject The object to be added to the pool.
* @throws ObjectExistsException If an object with the same ID or the same
* name as the new one already exists in this pool.
*/
public void addObject(
@Nonnull
TCSObject> newObject
)
throws ObjectExistsException {
requireNonNull(newObject, "newObject");
if (containsName(newObject.getName())) {
throw new ObjectExistsException("Object name already exists: " + newObject.getName());
}
Map> objectsByName = objects.get(newObject.getClass());
if (objectsByName == null) {
objectsByName = new HashMap<>();
objects.put(newObject.getClass(), objectsByName);
}
objectsByName.put(newObject.getName(), newObject);
}
/**
* Uses the given object to replace an object in the pool with same name.
*
* @param object The replacing object.
* @throws IllegalArgumentException If an object with the same name as the given object does not
* exist in this repository, yet, or if an object with the same name does exist but is an instance
* of a different class.
*/
@Nonnull
public void replaceObject(
@Nonnull
TCSObject> object
)
throws IllegalArgumentException {
requireNonNull(object, "object");
TCSObject> oldObject = getObjectOrNull(object.getName());
checkArgument(
oldObject != null,
"Object named '%s' does not exist",
object.getName()
);
checkArgument(
object.getClass() == oldObject.getClass(),
"Object named '%s' not an instance of the same class: '%s' != '%s'",
object.getName(),
object.getClass().getName(),
oldObject.getClass().getName()
);
objects.get(object.getClass()).put(object.getName(), object);
}
/**
* Returns an object from the pool.
*
* @param ref A reference to the object to return.
* @return The referenced object, or null
, if no such object exists in this pool.
*/
@Nullable
public TCSObject> getObjectOrNull(
@Nonnull
TCSObjectReference> ref
) {
requireNonNull(ref);
return objects.getOrDefault(ref.getReferentClass(), Map.of()).get(ref.getName());
}
/**
* Returns an object from the pool.
*
* @param ref A reference to the object to return.
* @return The referenced object.
* @throws ObjectUnknownException If the referenced object does not exist.
*/
@Nonnull
public TCSObject> getObject(
@Nonnull
TCSObjectReference> ref
)
throws ObjectUnknownException {
TCSObject> result = getObjectOrNull(ref);
if (result == null) {
throw new ObjectUnknownException(ref);
}
return result;
}
/**
* Returns an object from the pool.
*
* @param The object's type.
* @param clazz The class of the object to be returned.
* @param ref A reference to the object to be returned.
* @return The referenced object, or null
, if no such object
* exists in this pool or if an object exists but is not an instance of the
* given class.
*/
@Nullable
public > T getObjectOrNull(
@Nonnull
Class clazz,
@Nonnull
TCSObjectReference ref
) {
requireNonNull(clazz, "clazz");
requireNonNull(ref, "ref");
TCSObject> result = objects.getOrDefault(clazz, Map.of()).get(ref.getName());
if (clazz.isInstance(result)) {
return clazz.cast(result);
}
else {
return null;
}
}
/**
* Returns an object from the pool.
*
* @param The object's type.
* @param clazz The class of the object to be returned.
* @param ref A reference to the object to be returned.
* @return The referenced object.
* @throws ObjectUnknownException If the referenced object does not exist, or if an object exists
* but is not an instance of the given class.
*/
@Nonnull
public > T getObject(
@Nonnull
Class clazz,
@Nonnull
TCSObjectReference ref
)
throws ObjectUnknownException {
T result = getObjectOrNull(clazz, ref);
if (result == null) {
throw new ObjectUnknownException(ref);
}
return result;
}
/**
* Returns an object from the pool.
*
* @param name The name of the object to return.
* @return The object with the given name, or null
, if no such
* object exists in this pool.
*/
@Nullable
public TCSObject> getObjectOrNull(
@Nonnull
String name
) {
requireNonNull(name, "name");
return objects.values().stream()
.map(objectsByName -> objectsByName.get(name))
.filter(object -> object != null)
.findAny()
.orElse(null);
}
/**
* Returns an object from the pool.
*
* @param name The name of the object to return.
* @return The object with the given name.
* @throws ObjectUnknownException If the referenced object does not exist.
*/
@Nonnull
public TCSObject> getObject(
@Nonnull
String name
)
throws ObjectUnknownException {
TCSObject> result = getObjectOrNull(name);
if (result == null) {
throw new ObjectUnknownException(name);
}
return result;
}
/**
* Returns an object from the pool.
*
* @param The object's type.
* @param clazz The class of the object to be returned.
* @param name The name of the object to be returned.
* @return The named object, or null
, if no such object
* exists in this pool or if an object exists but is not an instance of the
* given class.
*/
@Nullable
public > T getObjectOrNull(
@Nonnull
Class clazz,
@Nonnull
String name
) {
requireNonNull(clazz, "clazz");
requireNonNull(name, "name");
TCSObject> result = objects.getOrDefault(clazz, Map.of()).get(name);
if (clazz.isInstance(result)) {
return clazz.cast(result);
}
else {
return null;
}
}
/**
* Returns an object from the pool.
*
* @param The object's type.
* @param clazz The class of the object to be returned.
* @param name The name of the object to be returned.
* @return The named object.
* @throws ObjectUnknownException If no object with the given name exists in this pool or if an
* object exists but is not an instance of the given class.
*/
@Nonnull
public > T getObject(
@Nonnull
Class clazz,
@Nonnull
String name
)
throws ObjectUnknownException {
T result = getObjectOrNull(clazz, name);
if (result == null) {
throw new ObjectUnknownException(name);
}
return result;
}
/**
* Returns a set of objects belonging to the given class.
*
* @param The objects' type.
* @param clazz The class of the objects to be returned.
* @return A set of objects belonging to the given class.
*/
@Nonnull
public > Set getObjects(
@Nonnull
Class clazz
) {
return objects.getOrDefault(clazz, Map.of()).values().stream()
.map(object -> clazz.cast(object))
.collect(Collectors.toSet());
}
/**
* Returns a set of objects of the given class for which the given predicate is true.
*
* @param The objects' type.
* @param clazz The class of the objects to be returned.
* @param predicate The predicate that must be true for returned objects.
* @return A set of objects of the given class for which the given predicate is true. If no such
* objects exist, the returned set is empty.
*/
@Nonnull
public > Set getObjects(
@Nonnull
Class clazz,
@Nonnull
Predicate super T> predicate
) {
requireNonNull(clazz, "clazz");
requireNonNull(predicate, "predicate");
return objects.getOrDefault(clazz, Map.of()).values().stream()
.map(object -> clazz.cast(object))
.filter(predicate)
.collect(Collectors.toSet());
}
/**
* Removes a referenced object from this pool.
*
* @param ref A reference to the object to be removed.
* @return The object that was removed from the pool.
* @throws ObjectUnknownException If the referenced object does not exist.
*/
@Nonnull
public TCSObject> removeObject(
@Nonnull
TCSObjectReference> ref
)
throws ObjectUnknownException {
requireNonNull(ref, "ref");
Map> map = objects.get(ref.getReferentClass());
TCSObject> obj = (map == null) ? null : map.remove(ref.getName());
if (obj == null) {
throw new ObjectUnknownException(ref);
}
return obj;
}
private boolean containsName(String name) {
return objects.values().stream().anyMatch(objectsByName -> objectsByName.containsKey(name));
}
}