2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.pap.main.comm;
23 import java.util.ArrayList;
24 import java.util.HashMap;
26 import org.onap.policy.models.pdp.concepts.PdpStateChange;
27 import org.onap.policy.models.pdp.concepts.PdpUpdate;
28 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
29 import org.onap.policy.pap.main.comm.msgdata.StateChangeData;
30 import org.onap.policy.pap.main.comm.msgdata.UpdateData;
31 import org.onap.policy.pap.main.parameters.PdpModifyRequestMapParams;
34 * Maps a PDP name to requests that modify PDPs.
36 public class PdpModifyRequestMap {
39 * Maps a PDP name to its request data. An entry is removed once all of the requests
40 * within the data have been completed.
42 private final Map<String, ModifyReqData> name2data = new HashMap<>();
45 * PDP modification lock.
47 private final Object modifyLock;
50 * The configuration parameters.
52 private final PdpModifyRequestMapParams params;
55 * Constructs the data.
57 * @param params configuration parameters
59 * @throws IllegalArgumentException if a required parameter is not set
61 public PdpModifyRequestMap(PdpModifyRequestMapParams params) {
65 this.modifyLock = params.getModifyLock();
69 * Adds an UPDATE request to the map.
71 * @param update the UPDATE request or {@code null}
73 public void addRequest(PdpUpdate update) {
74 addRequest(update, null);
78 * Adds STATE-CHANGE request to the map.
80 * @param stateChange the STATE-CHANGE request or {@code null}
82 public void addRequest(PdpStateChange stateChange) {
83 addRequest(null, stateChange);
87 * Adds a pair of requests to the map.
89 * @param update the UPDATE request or {@code null}
90 * @param stateChange the STATE-CHANGE request or {@code null}
92 public void addRequest(PdpUpdate update, PdpStateChange stateChange) {
93 if (update == null && stateChange == null) {
97 synchronized (modifyLock) {
98 String pdpName = getPdpName(update, stateChange);
100 ModifyReqData data = name2data.get(pdpName);
102 // update the existing request
104 data.add(stateChange);
107 data = makeRequestData(update, stateChange);
108 name2data.put(pdpName, data);
109 data.startPublishing();
115 * Gets the PDP name from two requests.
117 * @param update the update request, or {@code null}
118 * @param stateChange the state-change request, or {@code null}
119 * @return the PDP name, or {@code null} if both requests are {@code null}
121 private static String getPdpName(PdpUpdate update, PdpStateChange stateChange) {
124 if (update != null) {
125 if ((pdpName = update.getName()) == null) {
126 throw new IllegalArgumentException("missing name in " + update);
129 if (stateChange != null && !pdpName.equals(stateChange.getName())) {
130 throw new IllegalArgumentException(
131 "name " + stateChange.getName() + " does not match " + pdpName + " " + stateChange);
135 if ((pdpName = stateChange.getName()) == null) {
136 throw new IllegalArgumentException("missing name in " + stateChange);
144 * Determines if two requests are the "same", which is does not necessarily mean
147 * @param first first request to check
148 * @param second second request to check
149 * @return {@code true} if the requests are the "same", {@code false} otherwise
151 protected static boolean isSame(PdpUpdate first, PdpUpdate second) {
152 if (first.getPolicies().size() != second.getPolicies().size()) {
156 if (!first.getPdpGroup().equals(second.getPdpGroup())) {
160 if (!first.getPdpSubgroup().equals(second.getPdpSubgroup())) {
164 // see if the other has any policies that this does not have
165 ArrayList<ToscaPolicy> lst = new ArrayList<>(second.getPolicies());
166 lst.removeAll(first.getPolicies());
168 return lst.isEmpty();
172 * Determines if two requests are the "same", which is does not necessarily mean
175 * @param first first request to check
176 * @param second second request to check
177 * @return {@code true} if this update subsumes the other, {@code false} otherwise
179 protected static boolean isSame(PdpStateChange first, PdpStateChange second) {
180 return (first.getState() == second.getState());
184 * Request data, which contains an UPDATE or a STATE-CHANGE request, or both. The
185 * UPDATE is always published before the STATE-CHANGE. In addition, both requests may
186 * be changed at any point, possibly triggering a restart of the publishing.
188 public class ModifyReqData extends RequestData {
191 * The UPDATE message to be published, or {@code null}.
193 private PdpUpdate update;
196 * The STATE-CHANGE message to be published, or {@code null}.
198 private PdpStateChange stateChange;
202 * Constructs the object.
204 * @param newUpdate the UPDATE message to be sent, or {@code null}
205 * @param newState the STATE-CHANGE message to be sent, or {@code null}
207 public ModifyReqData(PdpUpdate newUpdate, PdpStateChange newState) {
210 if (newUpdate != null) {
211 this.stateChange = newState;
212 setName(newUpdate.getName());
214 configure(new ModUpdateData(newUpdate));
218 setName(newState.getName());
219 stateChange = newState;
220 configure(new ModStateChangeData(newState));
225 * Determines if this request is still in the map.
228 protected boolean isActive() {
229 return (name2data.get(getName()) == this);
233 * Removes this request from the map.
236 protected void allCompleted() {
237 name2data.remove(getName(), this);
241 * Adds an UPDATE to the request data, replacing any existing UPDATE, if
242 * appropriate. If the UPDATE is replaced, then publishing is restarted.
244 * @param newRequest the new UPDATE request
246 private void add(PdpUpdate newRequest) {
247 if (newRequest == null) {
251 synchronized (modifyLock) {
252 if (update != null && isSame(update, newRequest)) {
253 // already have this update - discard it
257 // must restart from scratch
261 configure(new ModUpdateData(newRequest));
268 * Adds a STATE-CHANGE to the request data, replacing any existing UPDATE, if
269 * appropriate. If the STATE-CHANGE is replaced, and we're currently publishing
270 * the STATE-CHANGE, then publishing is restarted.
272 * @param newRequest the new STATE-CHANGE request
274 private void add(PdpStateChange newRequest) {
275 if (newRequest == null) {
279 synchronized (modifyLock) {
280 if (stateChange != null && isSame(stateChange, newRequest)) {
281 // already have this update - discard it
285 if (getWrapper() instanceof StateChangeData) {
286 // we were publishing STATE-CHANGE, thus must restart it
289 stateChange = newRequest;
290 configure(new ModStateChangeData(newRequest));
295 // haven't started publishing STATE-CHANGE yet, just replace it
296 stateChange = newRequest;
302 * Indicates that the retry count was exhausted.
304 protected void retryCountExhausted() {
305 // remove this request data from the PDP request map
312 * Indicates that a response did not match the data.
314 * @param reason the reason for the mismatch
316 protected void mismatch(String reason) {
317 // remove this request data from the PDP request map
326 private class ModUpdateData extends UpdateData {
328 public ModUpdateData(PdpUpdate message) {
329 super(message, params);
333 public void mismatch(String reason) {
334 ModifyReqData.this.mismatch(reason);
338 public void completed() {
339 if (stateChange == null) {
340 // no STATE-CHANGE request - we're done
344 // now process the STATE-CHANGE request
345 configure(new ModStateChangeData(stateChange));
352 * Wraps a STATE-CHANGE.
354 private class ModStateChangeData extends StateChangeData {
356 public ModStateChangeData(PdpStateChange message) {
357 super(message, params);
361 public void mismatch(String reason) {
362 ModifyReqData.this.mismatch(reason);
366 public void completed() {
372 // these may be overridden by junit tests
374 protected ModifyReqData makeRequestData(PdpUpdate update, PdpStateChange stateChange) {
375 return new ModifyReqData(update, stateChange);