5bb96b9dc0077d01efd29259b2ecf83534202825
[policy/pap.git] / main / src / main / java / org / onap / policy / pap / main / rest / depundep / SessionData.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP PAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.pap.main.rest.depundep;
22
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.stream.Collectors;
28 import org.onap.policy.common.utils.validation.Version;
29 import org.onap.policy.models.base.PfModelException;
30 import org.onap.policy.models.pdp.concepts.PdpGroup;
31 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
32 import org.onap.policy.models.pdp.concepts.PdpUpdate;
33 import org.onap.policy.models.pdp.enums.PdpState;
34 import org.onap.policy.models.provider.PolicyModelsProvider;
35 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
36 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter;
37 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
39 import org.onap.policy.pap.main.PolicyPapRuntimeException;
40
41 /**
42  * Data used during a single REST call when updating PDP policies.
43  */
44 public class SessionData {
45     private final PolicyModelsProvider dao;
46
47     /**
48      * Maps a group name to its group data. This accumulates the set of groups to be
49      * created and updated when the REST call completes.
50      */
51     private final Map<String, GroupData> groupCache = new HashMap<>();
52
53     /**
54      * Maps a policy type to the list of matching groups. Every group appearing within
55      * this map has a corresponding entry in {@link #groupCache}.
56      */
57     private final Map<ToscaPolicyTypeIdentifier, List<GroupData>> type2groups = new HashMap<>();
58
59     /**
60      * Maps a PDP name to its most recently generated update request.
61      */
62     private final Map<String, PdpUpdate> pdpUpdates = new HashMap<>();
63
64     /**
65      * Maps a policy's identifier to the policy.
66      */
67     private final Map<ToscaPolicyIdentifier, ToscaPolicy> policyCache = new HashMap<>();
68
69     /**
70      * Maps a policy name to its latest policy. Every policy appearing within this map has
71      * a corresponding entry in {@link #policyCache}.
72      */
73     private final Map<String, ToscaPolicy> latestPolicy = new HashMap<>();
74
75
76     /**
77      * Constructs the object.
78      *
79      * @param dao DAO provider
80      */
81     public SessionData(PolicyModelsProvider dao) {
82         this.dao = dao;
83     }
84
85     /**
86      * Gets the policy, referenced by an identifier. Loads it from the cache, if possible.
87      * Otherwise, gets it from the DB.
88      *
89      * @param ident policy identifier
90      * @return the specified policy
91      * @throws PolicyPapRuntimeException if an error occurs
92      */
93     public ToscaPolicy getPolicy(ToscaPolicyIdentifier ident) {
94
95         return policyCache.computeIfAbsent(ident, key -> {
96
97             try {
98                 List<ToscaPolicy> lst = dao.getPolicyList(ident.getName(), ident.getVersion());
99
100                 if (lst.isEmpty()) {
101                     throw new PolicyPapRuntimeException(
102                                     "cannot find policy: " + ident.getName() + " " + ident.getVersion());
103                 }
104
105                 if (lst.size() > 1) {
106                     throw new PolicyPapRuntimeException(
107                                     "too many policies match: " + ident.getName() + " " + ident.getVersion());
108                 }
109
110                 return lst.get(0);
111
112             } catch (PfModelException e) {
113                 throw new PolicyPapRuntimeException("cannot get policy: " + ident.getName() + " " + ident.getVersion(),
114                                 e);
115             }
116         });
117     }
118
119     /**
120      * Adds an update to the set of updates, replacing any previous entry for the given
121      * PDP.
122      *
123      * @param update the update to be added
124      */
125     public void addUpdate(PdpUpdate update) {
126         pdpUpdates.put(update.getName(), update);
127     }
128
129     /**
130      * Gets the accumulated UPDATE requests.
131      *
132      * @return the UPDATE requests
133      */
134     public Collection<PdpUpdate> getPdpUpdates() {
135         return pdpUpdates.values();
136     }
137
138     /**
139      * Determines if a group has been newly created as part of this REST call.
140      *
141      * @param group name to the group of interest
142      * @return {@code true} if the group has been newly created, {@code false} otherwise
143      */
144     public boolean isNewlyCreated(String group) {
145         GroupData data = groupCache.get(group);
146         return (data != null && data.isNew());
147     }
148
149     /**
150      * Gets the policy having the given name and the maximum version.
151      *
152      * @param name name of the desired policy
153      * @return the desired policy, or {@code null} if there is no policy with given name
154      * @throws PfModelException if an error occurs
155      */
156     public ToscaPolicy getPolicyMaxVersion(String name) throws PfModelException {
157         ToscaPolicy policy = latestPolicy.get(name);
158         if (policy != null) {
159             return policy;
160         }
161
162         ToscaPolicyFilter filter =
163                         ToscaPolicyFilter.builder().name(name).version(ToscaPolicyFilter.LATEST_VERSION).build();
164         List<ToscaPolicy> policies = dao.getFilteredPolicyList(filter);
165         if (policies.isEmpty()) {
166             throw new PolicyPapRuntimeException("cannot find policy: " + name);
167         }
168
169         policy = policies.get(0);
170         policyCache.putIfAbsent(policy.getIdentifier(), policy);
171         latestPolicy.put(name, policy);
172
173         return policy;
174     }
175
176     /**
177      * Adds a new version of a group to the cache.
178      *
179      * @param newGroup the new group to be added
180      * @throws IllegalStateException if the old group has not been loaded into the cache
181      *         yet
182      * @throws PfModelException if an error occurs
183      */
184     public void setNewGroup(PdpGroup newGroup) throws PfModelException {
185         String name = newGroup.getName();
186         GroupData data = groupCache.get(name);
187         if (data == null) {
188             throw new IllegalStateException("group not cached: " + name);
189         }
190
191         if (data.getLatestVersion() != null) {
192             // already have the latest version
193             data.setNewGroup(newGroup);
194             return;
195         }
196
197         // must determine the latest version of this group, regardless of its state
198         PdpGroupFilter filter = PdpGroupFilter.builder().name(name).version(PdpGroupFilter.LATEST_VERSION).build();
199         List<PdpGroup> groups = dao.getFilteredPdpGroups(filter);
200         if (groups.isEmpty()) {
201             throw new PolicyPapRuntimeException("cannot find group: " + name);
202         }
203
204         PdpGroup group = groups.get(0);
205         Version vers = Version.makeVersion("PdpGroup", group.getName(), group.getVersion());
206         if (vers == null) {
207             // none of the versions are numeric - start with zero and increment from there
208             vers = new Version(0, 0, 0);
209         }
210
211         data.setLatestVersion(vers);
212         data.setNewGroup(newGroup);
213     }
214
215     /**
216      * Gets the active groups supporting the given policy.
217      *
218      * @param type desired policy type
219      * @return the active groups supporting the given policy
220      * @throws PfModelException if an error occurs
221      */
222     public List<PdpGroup> getActivePdpGroupsByPolicyType(ToscaPolicyTypeIdentifier type) throws PfModelException {
223         List<GroupData> data = type2groups.get(type);
224         if (data != null) {
225             return data.stream().map(GroupData::getCurrentGroup).collect(Collectors.toList());
226         }
227
228         PdpGroupFilter filter = PdpGroupFilter.builder().policyType(type).groupState(PdpState.ACTIVE).build();
229
230         List<PdpGroup> groups = dao.getFilteredPdpGroups(filter);
231
232         data = groups.stream().map(this::addGroup).collect(Collectors.toList());
233         type2groups.put(type, data);
234
235         return groups;
236     }
237
238     /**
239      * Adds a group to the group cache, if it isn't already in the cache.
240      *
241      * @param group the group to be added
242      * @return the cache entry
243      */
244     private GroupData addGroup(PdpGroup group) {
245         GroupData data = groupCache.get(group.getName());
246         if (data != null) {
247             return data;
248         }
249
250         data = new GroupData(group);
251         groupCache.put(group.getName(), data);
252
253         return data;
254     }
255
256     /**
257      * Update the DB with the changes.
258      *
259      * @throws PfModelException if an error occurs
260      */
261     public void updateDb() throws PfModelException {
262         List<GroupData> updatedGroups =
263                         groupCache.values().stream().filter(GroupData::isNew).collect(Collectors.toList());
264         if (updatedGroups.isEmpty()) {
265             return;
266         }
267
268         // create new groups BEFORE we deactivate the old groups
269         dao.createPdpGroups(updatedGroups.stream().map(GroupData::getCurrentGroup).collect(Collectors.toList()));
270         dao.updatePdpGroups(updatedGroups.stream().map(GroupData::getOldGroup).collect(Collectors.toList()));
271     }
272 }