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;
30 import org.onap.policy.apex.context.ContextAlbum;
31 import org.onap.policy.apex.context.ContextException;
32 import org.onap.policy.apex.context.ContextRuntimeException;
33 import org.onap.policy.apex.context.Distributor;
34 import org.onap.policy.apex.context.SchemaHelper;
35 import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
36 import org.onap.policy.apex.context.monitoring.ContextMonitor;
37 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
38 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
39 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
40 import org.onap.policy.common.utils.validation.Assertions;
41 import org.slf4j.ext.XLogger;
42 import org.slf4j.ext.XLoggerFactory;
45 * The Class ContextAlbumImpl implements the methods on the {@link ContextAlbum} interface. It implements the getters
46 * and setters on the {@link Map} and uses the {@link Distributor} to handle distribution and locking.
48 * @author Liam Fallon (liam.fallon@ericsson.com)
50 public final class ContextAlbumImpl implements ContextAlbum, Comparable<ContextAlbumImpl> {
51 // Logger for this class
52 private static final XLogger LOGGER = XLoggerFactory.getXLogger(ContextAlbumImpl.class);
54 // Recurring string constants
55 private static final String NULL_VALUES_ILLEGAL = "null values are illegal on method parameter \"key\"";
56 private static final String ALBUM = "album \"";
58 // The definition of this context album
59 private final AxContextAlbum albumDefinition;
61 /// The map holding the items and their values for this context album
62 private final Map<String, Object> albumMap;
64 // The artifact stack of the artifacts currently using the context album
65 private AxConcept[] userArtifactStack = null;
67 // The context distributor we are using
68 private final Distributor distributor;
70 // The schema helper that handles translations of Java objects for this album
71 private SchemaHelper schemaHelper;
73 // The context monitor for this context album
74 private ContextMonitor monitor = null;
77 * Constructor, instantiate the context album.
79 * @param albumDefinition The model definition of this context album
80 * @param distributor The context distributor passed to us to distribute context across ContextAlbum instances
81 * @param albumMap the album map
82 * @throws ContextException on errors creating context albums
84 public ContextAlbumImpl(final AxContextAlbum albumDefinition, final Distributor distributor,
85 final Map<String, Object> albumMap) throws ContextException {
86 Assertions.argumentNotNull(albumDefinition, "Context album definition may not be null");
87 Assertions.argumentNotNull(distributor, "Distributor may not be null");
88 Assertions.argumentNotNull(albumMap, "Album map may not be null");
90 this.albumDefinition = albumDefinition;
92 // Use the context distributor passed to us
93 this.distributor = distributor;
95 // The map to use to store objects
96 this.albumMap = albumMap;
99 // Get a schema helper to manage the translations between objects on the album map for this album
100 schemaHelper = new SchemaHelperFactory().createSchemaHelper(albumDefinition.getKey(),
101 albumDefinition.getItemSchema());
102 } catch (final ContextRuntimeException e) {
103 final String resultString = "could not initiate schema management for context album " + albumDefinition;
104 LOGGER.warn(resultString, e);
105 throw new ContextException(resultString, e);
108 // Create the context monitor
109 monitor = new ContextMonitor();
117 public AxArtifactKey getKey() {
118 return albumDefinition.getKey();
125 public String getName() {
126 return albumDefinition.getKey().getName();
133 public AxContextAlbum getAlbumDefinition() {
134 return albumDefinition;
141 public SchemaHelper getSchemaHelper() {
149 public void lockForReading(final String keyOnAlbum) throws ContextException {
150 distributor.lockForReading(albumDefinition.getKey(), keyOnAlbum);
151 monitor.monitorReadLock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
159 public void lockForWriting(final String keyOnAlbum) throws ContextException {
160 distributor.lockForWriting(albumDefinition.getKey(), keyOnAlbum);
161 monitor.monitorWriteLock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
169 public void unlockForReading(final String keyOnAlbum) throws ContextException {
170 distributor.unlockForReading(albumDefinition.getKey(), keyOnAlbum);
171 monitor.monitorReadUnlock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
179 public void unlockForWriting(final String keyOnAlbum) throws ContextException {
180 distributor.unlockForWriting(albumDefinition.getKey(), keyOnAlbum);
181 monitor.monitorWriteUnlock(albumDefinition.getKey(), albumDefinition.getItemSchema(), keyOnAlbum,
189 public AxConcept[] getUserArtifactStack() {
190 return userArtifactStack;
197 public void setUserArtifactStack(final AxConcept[] userArtifactStack) {
198 this.userArtifactStack = userArtifactStack;
205 public void flush() throws ContextException {
206 distributor.flushContextAlbum(this);
218 return albumMap.size();
225 public boolean isEmpty() {
226 return albumMap.isEmpty();
233 public boolean containsKey(final Object key) {
235 LOGGER.warn(NULL_VALUES_ILLEGAL);
236 throw new ContextRuntimeException(NULL_VALUES_ILLEGAL);
239 return albumMap.containsKey(key);
246 public boolean containsValue(final Object value) {
248 LOGGER.warn("null values are illegal on method parameter \"value\"");
249 throw new ContextRuntimeException("null values are illegal on method parameter \"value\"");
252 return albumMap.containsValue(value);
259 public Object get(final Object key) {
261 final String returnString =
262 ALBUM + albumDefinition.getId() + "\" null keys are illegal on keys for get()";
263 LOGGER.warn(returnString);
264 throw new ContextRuntimeException(returnString);
267 final Object item = albumMap.get(key);
272 // Get the context value and monitor it
273 monitor.monitorGet(albumDefinition.getKey(), albumDefinition.getItemSchema(), key.toString(), item,
282 public Set<String> keySet() {
283 return albumMap.keySet();
290 public Collection<Object> values() {
291 // Build the key set and return it
292 final ArrayList<Object> valueList = new ArrayList<>();
294 for (final Entry<String, Object> contextAlbumEntry : albumMap.entrySet()) {
295 final Object item = contextAlbumEntry.getValue();
296 monitor.monitorGet(albumDefinition.getKey(), albumDefinition.getItemSchema(), contextAlbumEntry.getKey(),
297 item, userArtifactStack);
298 valueList.add(contextAlbumEntry.getValue());
308 public Set<Entry<String, Object>> entrySet() {
309 // Build the entry set and return it
310 final Set<Entry<String, Object>> entrySet = new HashSet<>();
312 for (final Entry<String, Object> contextAlbumEntry : albumMap.entrySet()) {
313 final Object item = contextAlbumEntry.getValue();
314 monitor.monitorGet(albumDefinition.getKey(), albumDefinition.getItemSchema(), contextAlbumEntry.getKey(),
315 item, userArtifactStack);
316 entrySet.add(new SimpleEntry<>(contextAlbumEntry.getKey(), contextAlbumEntry.getValue()));
326 public Object put(final String key, final Object incomingValue) {
328 final String returnString =
329 ALBUM + albumDefinition.getId() + "\" null keys are illegal on keys for put()";
330 LOGGER.warn(returnString);
331 throw new ContextRuntimeException(returnString);
334 if (incomingValue == null) {
335 final String returnString = ALBUM + albumDefinition.getId() + "\" null values are illegal on key \""
336 + key + "\" for put()";
337 LOGGER.warn(returnString);
338 throw new ContextRuntimeException(returnString);
341 if (!albumDefinition.isWritable()) {
342 final String returnString = ALBUM + albumDefinition.getId()
343 + "\" put() not allowed on read only albums for key=\"" + key + "\", value=\"" + incomingValue;
344 LOGGER.warn(returnString);
345 throw new ContextRuntimeException(returnString);
349 // Translate the object to a schema object
350 final Object valueToPut = schemaHelper.unmarshal(incomingValue);
352 // Check if the key is already in the map
353 if (albumMap.containsKey(key)) {
354 // Update the value in the context item and in the context value map
355 monitor.monitorSet(albumDefinition.getKey(), albumDefinition.getItemSchema(), key, incomingValue,
358 // Update the value in the context item and in the context value map
359 monitor.monitorInit(albumDefinition.getKey(), albumDefinition.getItemSchema(), key, incomingValue,
363 // Put the translated value on the map and return the old map value
364 return albumMap.put(key, valueToPut);
365 } catch (final ContextRuntimeException e) {
366 final String returnString = "Failed to set context value for key \"" + key + "\" in album \""
367 + albumDefinition.getId() + "\": " + e.getMessage();
368 LOGGER.warn(returnString);
369 throw new ContextRuntimeException(returnString, e);
377 public void putAll(final Map<? extends String, ? extends Object> incomingContextAlbum) {
378 if (!albumDefinition.isWritable()) {
379 final String returnString =
380 ALBUM + albumDefinition.getId() + "\" putAll() not allowed on read only albums";
381 LOGGER.warn(returnString);
382 throw new ContextRuntimeException(returnString);
385 // Sanity check on incoming context
386 Assertions.argumentOfClassNotNull(incomingContextAlbum, ContextRuntimeException.class,
387 "cannot update context, context album is null");
389 // Iterate over the incoming context
390 for (final Entry<String, Object> entry : albumMap.entrySet()) {
391 synchronized (albumDefinition) {
392 // Get the key for the incoming name
393 final Object incomingDataItem = incomingContextAlbum.get(entry.getKey());
394 if (incomingDataItem != null) {
395 // Update the value the context album
396 put(entry.getKey(), incomingDataItem);
401 // Put all the objects on the context album
402 for (final Entry<? extends String, ? extends Object> incomingMapEntry : incomingContextAlbum.entrySet()) {
403 // Put the entry on the map
404 this.put(incomingMapEntry.getKey(), incomingMapEntry.getValue());
412 public Object remove(final Object key) {
413 if (!albumDefinition.isWritable()) {
414 final String returnString = ALBUM + albumDefinition.getId()
415 + "\" remove() not allowed on read only albums for key=\"" + key + "\"";
416 LOGGER.warn(returnString);
417 throw new ContextRuntimeException(returnString);
421 LOGGER.warn(NULL_VALUES_ILLEGAL);
422 throw new ContextRuntimeException("null values are illegal on method parameter \"keyID\"");
426 final Object removedValue = albumMap.remove(key);
427 monitor.monitorDelete(albumDefinition.getKey(), albumDefinition.getItemSchema(), key.toString(), removedValue,
430 // Return the value of the deleted item
438 public void clear() {
439 if (!albumDefinition.isWritable()) {
440 final String returnString =
441 ALBUM + albumDefinition.getId() + "\" clear() not allowed on read only albums";
442 LOGGER.warn(returnString);
443 throw new ContextRuntimeException(returnString);
446 // Monitor deletion of each item
447 for (final Entry<String, Object> contextAlbumEntry : albumMap.entrySet()) {
448 final Object item = contextAlbumEntry.getValue();
449 monitor.monitorDelete(albumDefinition.getKey(), albumDefinition.getItemSchema(), contextAlbumEntry.getKey(),
450 item, userArtifactStack);
461 public int compareTo(ContextAlbumImpl otherContextAlbumImpl) {
462 return (equals(otherContextAlbumImpl) ? 0 : 1);
469 public int hashCode() {
470 final int prime = 31;
472 result = prime * result + albumDefinition.hashCode();
473 result = prime * result + albumMap.hashCode();
481 public boolean equals(Object obj) {
488 if (!(obj instanceof ContextAlbumImpl)) {
491 ContextAlbumImpl other = (ContextAlbumImpl) obj;
492 if (!albumDefinition.equals(other.albumDefinition)) {
495 return albumMap.equals(other.albumMap);