2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.context.impl;
24 import java.util.AbstractMap.SimpleEntry;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashSet;
31 import org.onap.policy.apex.context.ContextAlbum;
32 import org.onap.policy.apex.context.ContextException;
33 import org.onap.policy.apex.context.ContextRuntimeException;
34 import org.onap.policy.apex.context.Distributor;
35 import org.onap.policy.apex.context.SchemaHelper;
36 import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
37 import org.onap.policy.apex.context.monitoring.ContextMonitor;
38 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
39 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
40 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
41 import org.onap.policy.common.utils.validation.Assertions;
42 import org.slf4j.ext.XLogger;
43 import org.slf4j.ext.XLoggerFactory;
46 * The Class ContextAlbumImpl implements the methods on the {@link ContextAlbum} interface. It implements the getters
47 * and setters on the {@link Map} and uses the {@link Distributor} to handle distribution and locking.
49 * @author Liam Fallon (liam.fallon@ericsson.com)
51 public final class ContextAlbumImpl implements ContextAlbum, Comparable<ContextAlbumImpl> {
52 // Logger for this class
53 private static final XLogger LOGGER = XLoggerFactory.getXLogger(ContextAlbumImpl.class);
55 // Recurring string constants
56 private static final String NULL_VALUES_ILLEGAL = "null values are illegal on method parameter \"key\"";
57 private static final String ALBUM = "album \"";
59 // The definition of this context album
60 private final AxContextAlbum albumDefinition;
62 /// The map holding the items and their values for this context album
63 private final Map<String, Object> albumMap;
65 // The artifact stack of the artifacts currently using the context album
66 private AxConcept[] userArtifactStack = null;
68 // The context distributor we are using
69 private final Distributor distributor;
71 // The schema helper that handles translations of Java objects for this album
72 private SchemaHelper schemaHelper;
74 // The context monitor for this context album
75 private ContextMonitor monitor = null;
78 * Constructor, instantiate the context album.
80 * @param albumDefinition The model definition of this context album
81 * @param distributor The context distributor passed to us to distribute context across ContextAlbum instances
82 * @param albumMap the album map
83 * @throws ContextException on errors creating context albums
85 public ContextAlbumImpl(final AxContextAlbum albumDefinition, final Distributor distributor,
86 final Map<String, Object> albumMap) throws ContextException {
87 Assertions.argumentNotNull(albumDefinition, "Context album definition may not be null");
88 Assertions.argumentNotNull(distributor, "Distributor may not be null");
89 Assertions.argumentNotNull(albumMap, "Album map may not be null");
91 this.albumDefinition = albumDefinition;
93 // Use the context distributor passed to us
94 this.distributor = distributor;
96 // The map to use to store objects
97 this.albumMap = albumMap;
100 // Get a schema helper to manage the translations between objects on the album map for this album
101 schemaHelper = new SchemaHelperFactory().createSchemaHelper(albumDefinition.getKey(),
102 albumDefinition.getItemSchema());
103 } catch (final ContextRuntimeException e) {
104 final String resultString = "could not initiate schema management for context album " + albumDefinition;
105 LOGGER.warn(resultString, e);
106 throw new ContextException(resultString, e);
109 // Create the context monitor
110 monitor = new ContextMonitor();
118 public AxArtifactKey getKey() {
119 return albumDefinition.getKey();
126 public String getName() {
127 return albumDefinition.getKey().getName();
134 public AxContextAlbum getAlbumDefinition() {
135 return albumDefinition;
142 public SchemaHelper getSchemaHelper() {
150 public void lockForReading(final String keyOnAlbum) throws ContextException {
151 distributor.lockForReading(albumDefinition.getKey(), keyOnAlbum);
152 monitor.monitorReadLock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
160 public void lockForWriting(final String keyOnAlbum) throws ContextException {
161 distributor.lockForWriting(albumDefinition.getKey(), keyOnAlbum);
162 monitor.monitorWriteLock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
170 public void unlockForReading(final String keyOnAlbum) throws ContextException {
171 distributor.unlockForReading(albumDefinition.getKey(), keyOnAlbum);
172 monitor.monitorReadUnlock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
180 public void unlockForWriting(final String keyOnAlbum) throws ContextException {
181 distributor.unlockForWriting(albumDefinition.getKey(), keyOnAlbum);
182 monitor.monitorWriteUnlock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
190 public AxConcept[] getUserArtifactStack() {
191 return userArtifactStack;
198 public void setUserArtifactStack(final AxConcept[] userArtifactStack) {
199 this.userArtifactStack = userArtifactStack;
206 public void flush() throws ContextException {
207 distributor.flushContextAlbum(this);
219 return albumMap.size();
226 public boolean isEmpty() {
227 return albumMap.isEmpty();
234 public boolean containsKey(final Object key) {
236 LOGGER.warn(NULL_VALUES_ILLEGAL);
237 throw new ContextRuntimeException(NULL_VALUES_ILLEGAL);
240 return albumMap.containsKey(key);
247 public boolean containsValue(final Object value) {
249 LOGGER.warn("null values are illegal on method parameter \"value\"");
250 throw new ContextRuntimeException("null values are illegal on method parameter \"value\"");
253 return albumMap.containsValue(value);
260 public Object get(final Object key) {
262 final String returnString =
263 ALBUM + albumDefinition.getId() + "\" null keys are illegal on keys for get()";
264 LOGGER.warn(returnString);
265 throw new ContextRuntimeException(returnString);
268 final Object item = albumMap.get(key);
273 // Get the context value and monitor it
274 monitor.monitorGet(albumDefinition.getKey(), albumDefinition.getItemSchema(), key.toString(), item,
283 public Set<String> keySet() {
284 return albumMap.keySet();
291 public Collection<Object> values() {
292 // Build the key set and return it
293 final ArrayList<Object> valueList = new ArrayList<>();
295 for (final Entry<String, Object> contextAlbumEntry : albumMap.entrySet()) {
296 final Object item = contextAlbumEntry.getValue();
297 monitor.monitorGet(albumDefinition.getKey(), albumDefinition.getItemSchema(), contextAlbumEntry.getKey(),
298 item, userArtifactStack);
299 valueList.add(contextAlbumEntry.getValue());
309 public Set<Entry<String, Object>> entrySet() {
310 // Build the entry set and return it
311 final Set<Entry<String, Object>> entrySet = new HashSet<>();
313 for (final Entry<String, Object> contextAlbumEntry : albumMap.entrySet()) {
314 final Object item = contextAlbumEntry.getValue();
315 monitor.monitorGet(albumDefinition.getKey(), albumDefinition.getItemSchema(), contextAlbumEntry.getKey(),
316 item, userArtifactStack);
317 entrySet.add(new SimpleEntry<>(contextAlbumEntry.getKey(), contextAlbumEntry.getValue()));
327 public Object put(final String key, final Object incomingValue) {
329 final String returnString =
330 ALBUM + albumDefinition.getId() + "\" null keys are illegal on keys for put()";
331 LOGGER.warn(returnString);
332 throw new ContextRuntimeException(returnString);
335 if (incomingValue == null) {
336 final String returnString = ALBUM + albumDefinition.getId() + "\" null values are illegal on key \""
337 + key + "\" for put()";
338 LOGGER.warn(returnString);
339 throw new ContextRuntimeException(returnString);
342 if (!albumDefinition.isWritable()) {
343 final String returnString = ALBUM + albumDefinition.getId()
344 + "\" put() not allowed on read only albums for key=\"" + key + "\", value=\"" + incomingValue;
345 LOGGER.warn(returnString);
346 throw new ContextRuntimeException(returnString);
350 // Translate the object to a schema object
351 final Object valueToPut = schemaHelper.unmarshal(incomingValue);
353 // Check if the key is already in the map
354 if (albumMap.containsKey(key)) {
355 // Update the value in the context item and in the context value map
356 monitor.monitorSet(albumDefinition.getKey(), albumDefinition.getItemSchema(), key, incomingValue,
359 // Update the value in the context item and in the context value map
360 monitor.monitorInit(albumDefinition.getKey(), albumDefinition.getItemSchema(), key, incomingValue,
364 // Put the translated value on the map and return the old map value
365 return albumMap.put(key, valueToPut);
366 } catch (final ContextRuntimeException e) {
367 final String returnString = "Failed to set context value for key \"" + key + "\" in album \""
368 + albumDefinition.getId() + "\": " + e.getMessage();
369 LOGGER.warn(returnString);
370 throw new ContextRuntimeException(returnString, e);
378 public void putAll(final Map<? extends String, ? extends Object> incomingContextAlbum) {
379 if (!albumDefinition.isWritable()) {
380 final String returnString =
381 ALBUM + albumDefinition.getId() + "\" putAll() not allowed on read only albums";
382 LOGGER.warn(returnString);
383 throw new ContextRuntimeException(returnString);
386 // Sanity check on incoming context
387 Assertions.argumentOfClassNotNull(incomingContextAlbum, ContextRuntimeException.class,
388 "cannot update context, context album is null");
390 // Iterate over the incoming context
391 for (final Entry<String, Object> entry : albumMap.entrySet()) {
392 synchronized (albumDefinition) {
393 // Get the key for the incoming name
394 final Object incomingDataItem = incomingContextAlbum.get(entry.getKey());
395 if (incomingDataItem != null) {
396 // Update the value the context album
397 put(entry.getKey(), incomingDataItem);
402 // Put all the objects on the context album
403 for (final Entry<? extends String, ? extends Object> incomingMapEntry : incomingContextAlbum.entrySet()) {
404 // Put the entry on the map
405 this.put(incomingMapEntry.getKey(), incomingMapEntry.getValue());
413 public Object remove(final Object key) {
414 if (!albumDefinition.isWritable()) {
415 final String returnString = ALBUM + albumDefinition.getId()
416 + "\" remove() not allowed on read only albums for key=\"" + key + "\"";
417 LOGGER.warn(returnString);
418 throw new ContextRuntimeException(returnString);
422 LOGGER.warn(NULL_VALUES_ILLEGAL);
423 throw new ContextRuntimeException("null values are illegal on method parameter \"keyID\"");
427 final Object removedValue = albumMap.remove(key);
428 monitor.monitorDelete(albumDefinition.getKey(), albumDefinition.getItemSchema(), key.toString(), removedValue,
431 // Return the value of the deleted item
439 public void clear() {
440 if (!albumDefinition.isWritable()) {
441 final String returnString =
442 ALBUM + albumDefinition.getId() + "\" clear() not allowed on read only albums";
443 LOGGER.warn(returnString);
444 throw new ContextRuntimeException(returnString);
447 // Monitor deletion of each item
448 for (final Entry<String, Object> contextAlbumEntry : albumMap.entrySet()) {
449 final Object item = contextAlbumEntry.getValue();
450 monitor.monitorDelete(albumDefinition.getKey(), albumDefinition.getItemSchema(), contextAlbumEntry.getKey(),
451 item, userArtifactStack);
462 public int compareTo(ContextAlbumImpl otherContextAlbumImpl) {
463 return (equals(otherContextAlbumImpl) ? 0 : 1);
470 public int hashCode() {
471 final int prime = 31;
473 result = prime * result + albumDefinition.hashCode();
474 result = prime * result + albumMap.hashCode();
482 public boolean equals(Object obj) {
489 if (!(obj instanceof ContextAlbumImpl)) {
492 ContextAlbumImpl other = (ContextAlbumImpl) obj;
493 if (!albumDefinition.equals(other.albumDefinition)) {
496 return albumMap.equals(other.albumMap);