|
2 | 2 |
|
3 | 3 | import java.util.Collections;
|
4 | 4 | import java.util.List;
|
| 5 | +import java.util.Optional; |
| 6 | +import java.util.concurrent.ConcurrentHashMap; |
5 | 7 | import java.util.stream.Collectors;
|
6 | 8 |
|
7 | 9 | import io.javaoperatorsdk.operator.OperatorException;
|
8 | 10 |
|
| 11 | +/** |
| 12 | + * Contextual information related to {@link DependentResource} either to retrieve the actual |
| 13 | + * implementations to interact with them or to pass information between them and/or the reconciler |
| 14 | + */ |
| 15 | +@SuppressWarnings("rawtypes") |
9 | 16 | public class ManagedDependentResourceContext {
|
10 | 17 |
|
11 |
| - private List<DependentResource> dependentResources; |
| 18 | + private final List<DependentResource> dependentResources; |
| 19 | + private final ConcurrentHashMap attributes = new ConcurrentHashMap(); |
| 20 | + |
| 21 | + /** |
| 22 | + * Retrieve a contextual object, if it exists and is of the specified expected type, associated |
| 23 | + * with the specified key. Contextual objects can be used to pass data between the reconciler and |
| 24 | + * dependent resources and are scoped to the current reconciliation. |
| 25 | + * |
| 26 | + * @param key the key identifying which contextual object to retrieve |
| 27 | + * @param expectedType the class representing the expected type of the contextual object |
| 28 | + * @param <T> the type of the expected contextual object |
| 29 | + * @return an Optional containing the contextual object or {@link Optional#empty()} if no such |
| 30 | + * object exists or doesn't match the expected type |
| 31 | + */ |
| 32 | + public <T> Optional<T> get(Object key, Class<T> expectedType) { |
| 33 | + return Optional.ofNullable(attributes.get(key)) |
| 34 | + .filter(expectedType::isInstance) |
| 35 | + .map(expectedType::cast); |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Associates the specified contextual value to the specified key. If the value is {@code null}, |
| 40 | + * the semantics of this operation is defined as removing the mapping associated with the |
| 41 | + * specified key. |
| 42 | + * |
| 43 | + * @param key the key identifying which contextual object to add or remove from the context |
| 44 | + * @param value the value to add to the context or {@code null} to remove an existing entry |
| 45 | + * associated with the specified key |
| 46 | + * @return an Optional containing the previous value associated with the key or |
| 47 | + * {@link Optional#empty()} if none existed |
| 48 | + */ |
| 49 | + @SuppressWarnings("unchecked") |
| 50 | + public Optional put(Object key, Object value) { |
| 51 | + if (value == null) { |
| 52 | + return Optional.ofNullable(attributes.remove(key)); |
| 53 | + } |
| 54 | + return Optional.ofNullable(attributes.put(key, value)); |
| 55 | + } |
| 56 | + |
| 57 | + /** |
| 58 | + * Retrieves the value associated with the key or fail with an exception if none exists. |
| 59 | + * |
| 60 | + * @param key the key identifying which contextual object to retrieve |
| 61 | + * @param expectedType the expected type of the value to retrieve |
| 62 | + * @param <T> the type of the expected contextual object |
| 63 | + * @return the contextual object value associated with the specified key |
| 64 | + * @see #get(Object, Class) |
| 65 | + */ |
| 66 | + public <T> T getMandatory(Object key, Class<T> expectedType) { |
| 67 | + return get(key, expectedType).orElseThrow(() -> new IllegalStateException( |
| 68 | + "Mandatory attribute (key: " + key + ", type: " + expectedType.getName() |
| 69 | + + ") is missing or not of the expected type")); |
| 70 | + } |
12 | 71 |
|
13 | 72 | public ManagedDependentResourceContext(List<DependentResource> dependentResources) {
|
14 |
| - this.dependentResources = dependentResources; |
| 73 | + this.dependentResources = Collections.unmodifiableList(dependentResources); |
15 | 74 | }
|
16 | 75 |
|
| 76 | + /** |
| 77 | + * Retrieve all the known {@link DependentResource} implementations |
| 78 | + * |
| 79 | + * @return a list of known {@link DependentResource} implementations |
| 80 | + */ |
17 | 81 | public List<DependentResource> getDependentResources() {
|
18 |
| - return Collections.unmodifiableList(dependentResources); |
| 82 | + return dependentResources; |
19 | 83 | }
|
20 | 84 |
|
| 85 | + /** |
| 86 | + * Retrieve the dependent resource implementation associated with the specified resource type. |
| 87 | + * |
| 88 | + * @param resourceClass the dependent resource class for which we want to retrieve the associated |
| 89 | + * dependent resource implementation |
| 90 | + * @param <T> the type of the resources for which we want to retrieve the associated dependent |
| 91 | + * resource implementation |
| 92 | + * @return the associated dependent resource implementation if it exists or an exception if it |
| 93 | + * doesn't or several implementations are associated with the specified resource type |
| 94 | + */ |
| 95 | + @SuppressWarnings("unchecked") |
21 | 96 | public <T extends DependentResource> T getDependentResource(Class<T> resourceClass) {
|
22 | 97 | var resourceList =
|
23 | 98 | dependentResources.stream()
|
|
0 commit comments