d0d1f5f0d11085196df2c228b97f96fed464129d
[policy/pap.git] / main / src / main / java / org / onap / policy / pap / main / comm / msgdata / UpdateReq.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP PAP
4  * ================================================================================
5  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2021 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pap.main.comm.msgdata;
23
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.stream.Collectors;
33 import lombok.Getter;
34 import org.apache.commons.lang3.StringUtils;
35 import org.onap.policy.models.pdp.concepts.PdpMessage;
36 import org.onap.policy.models.pdp.concepts.PdpStatus;
37 import org.onap.policy.models.pdp.concepts.PdpUpdate;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
39 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
40 import org.onap.policy.pap.main.parameters.RequestParams;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44
45 /**
46  * Wraps an UPDATE.
47  */
48 public class UpdateReq extends RequestImpl {
49
50     private static final Logger logger = LoggerFactory.getLogger(RequestImpl.class);
51
52     /**
53      * Policies to be undeployed if the request fails.
54      */
55     @Getter
56     private Collection<ToscaConceptIdentifier> undeployPolicies = Collections.emptyList();
57
58     /**
59      * Constructs the object, and validates the parameters.
60      *
61      * @param params configuration parameters
62      * @param name the request name, used for logging purposes
63      * @param message the initial message
64      *
65      * @throws IllegalArgumentException if a required parameter is not set
66      */
67     public UpdateReq(RequestParams params, String name, PdpUpdate message) {
68         super(params, name, message);
69     }
70
71     @Override
72     public PdpUpdate getMessage() {
73         return (PdpUpdate) super.getMessage();
74     }
75
76     @Override
77     public String checkResponse(PdpStatus response) {
78         // reset the list
79         undeployPolicies = Collections.emptyList();
80
81         String reason = super.checkResponse(response);
82         if (reason != null) {
83             // response isn't for this PDP - don't generate notifications
84             return reason;
85         }
86
87         PdpUpdate message = getMessage();
88
89         if (!StringUtils.equals(message.getPdpGroup(), response.getPdpGroup())) {
90             return "group does not match";
91         }
92
93         if (!StringUtils.equals(message.getPdpSubgroup(), response.getPdpSubgroup())) {
94             return "subgroup does not match";
95         }
96
97         if (message.getPdpSubgroup() == null) {
98             return null;
99         }
100
101         Set<ToscaConceptIdentifier> actualSet = new HashSet<>(alwaysList(response.getPolicies()));
102         Set<ToscaConceptIdentifier> expectedSet = new HashSet<>(alwaysList(message.getPoliciesToBeDeployed()).stream()
103                         .map(ToscaPolicy::getIdentifier).collect(Collectors.toSet()));
104
105         getNotifier().processResponse(response.getName(), message.getPdpGroup(), expectedSet, actualSet);
106
107         Set<ToscaConceptIdentifier> expectedUndeploySet =
108                 new HashSet<>(alwaysList(message.getPoliciesToBeUndeployed()));
109
110         if (actualSet.stream().anyMatch(expectedUndeploySet::contains)) {
111             logger.info("some policies have failed to undeploy");
112         }
113
114         if (!actualSet.containsAll(expectedSet)) {
115             // need to undeploy the policies that are expected, but missing from the
116             // response
117             undeployPolicies = expectedSet;
118             undeployPolicies.removeAll(actualSet);
119
120             return "policies do not match";
121         }
122
123         return null;
124     }
125
126     @Override
127     public boolean reconfigure(PdpMessage newMessage) {
128         if (!(newMessage instanceof PdpUpdate)) {
129             // not an update - no change to this request
130             return false;
131         }
132
133         PdpUpdate update = (PdpUpdate) newMessage;
134
135         if (isSameContent(update)) {
136             // content hasn't changed - nothing more to do
137             return true;
138         }
139
140         Map<ToscaConceptIdentifier, ToscaPolicy> newDeployMap = update.getPoliciesToBeDeployed().stream()
141                 .collect(Collectors.toMap(ToscaPolicy::getIdentifier, policy -> policy));
142
143         // Merge undpeloy lists
144         Set<ToscaConceptIdentifier> policiesToBeUndeployedSet = new HashSet<>(getMessage().getPoliciesToBeUndeployed());
145         policiesToBeUndeployedSet.removeAll(newDeployMap.keySet());
146         policiesToBeUndeployedSet.addAll(update.getPoliciesToBeUndeployed());
147         final List<ToscaConceptIdentifier> policiestoBeUndeployed = new LinkedList<>(policiesToBeUndeployedSet);
148
149         // Merge deploy lists
150         Map<ToscaConceptIdentifier, ToscaPolicy> policiesToBeDeployedMap = getMessage().getPoliciesToBeDeployed()
151                 .stream().collect(Collectors.toMap(ToscaPolicy::getIdentifier, policy -> policy));
152         policiesToBeDeployedMap.keySet().removeAll(update.getPoliciesToBeUndeployed());
153         policiesToBeDeployedMap.putAll(newDeployMap);
154         final List<ToscaPolicy> policiesToBeDeployed = new LinkedList<>(policiesToBeDeployedMap.values());
155
156         // Set lists in update
157         update.setPoliciesToBeDeployed(policiesToBeDeployed);
158         update.setPoliciesToBeUndeployed(policiestoBeUndeployed);
159
160         reconfigure2(update);
161         return true;
162     }
163
164     protected final boolean isSameContent(PdpUpdate second) {
165         PdpUpdate first = getMessage();
166
167         if (!StringUtils.equals(first.getPdpGroup(), second.getPdpGroup())) {
168             return false;
169         }
170
171         if (!StringUtils.equals(first.getPdpSubgroup(), second.getPdpSubgroup())) {
172             return false;
173         }
174
175         // see if the policies are the same
176         Set<ToscaPolicy> set1 = new HashSet<>(alwaysList(first.getPoliciesToBeDeployed()));
177         Set<ToscaPolicy> set2 = new HashSet<>(alwaysList(second.getPoliciesToBeDeployed()));
178
179         if (!(set1.equals(set2))) {
180             return false;
181         }
182
183         Set<ToscaConceptIdentifier> undep1 = new HashSet<>(alwaysList(first.getPoliciesToBeUndeployed()));
184         Set<ToscaConceptIdentifier> undep2 = new HashSet<>(alwaysList(second.getPoliciesToBeUndeployed()));
185
186         return undep1.equals(undep2);
187     }
188
189     /**
190      * Always get a list, even if the original is {@code null}.
191      *
192      * @param list the original list, or {@code null}
193      * @return the list, or an empty list if the original was {@code null}
194      */
195     private <T> List<T> alwaysList(List<T> list) {
196         return (list != null ? list : Collections.emptyList());
197     }
198 }