Add safe entity delete, fix multiple entity get
[policy/models.git] / models-provider / src / main / java / org / onap / policy / models / provider / impl / DatabasePolicyModelsProviderImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019-2020 Nordix Foundation.
4  *  Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.models.provider.impl;
23
24 import java.util.Base64;
25 import java.util.Date;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29
30 import javax.ws.rs.core.Response;
31
32 import lombok.NonNull;
33
34 import org.eclipse.persistence.config.PersistenceUnitProperties;
35 import org.onap.policy.models.base.PfModelException;
36 import org.onap.policy.models.base.PfModelRuntimeException;
37 import org.onap.policy.models.dao.DaoParameters;
38 import org.onap.policy.models.dao.PfDao;
39 import org.onap.policy.models.dao.PfDaoFactory;
40 import org.onap.policy.models.dao.impl.DefaultPfDao;
41 import org.onap.policy.models.pdp.concepts.Pdp;
42 import org.onap.policy.models.pdp.concepts.PdpGroup;
43 import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
44 import org.onap.policy.models.pdp.concepts.PdpStatistics;
45 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
46 import org.onap.policy.models.pdp.persistence.provider.PdpProvider;
47 import org.onap.policy.models.pdp.persistence.provider.PdpStatisticsProvider;
48 import org.onap.policy.models.provider.PolicyModelsProvider;
49 import org.onap.policy.models.provider.PolicyModelsProviderParameters;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
54 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeFilter;
55 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
56 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
57 import org.onap.policy.models.tosca.authorative.provider.AuthorativeToscaProvider;
58 import org.onap.policy.models.tosca.legacy.concepts.LegacyGuardPolicyInput;
59 import org.onap.policy.models.tosca.legacy.concepts.LegacyGuardPolicyOutput;
60 import org.onap.policy.models.tosca.legacy.concepts.LegacyOperationalPolicy;
61 import org.onap.policy.models.tosca.legacy.provider.LegacyProvider;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 /**
66  * This class provides an implementation of the Policy Models Provider for the ONAP Policy Framework that works towards
67  * a relational database.
68  *
69  * @author Liam Fallon (liam.fallon@est.tech)
70  */
71 public class DatabasePolicyModelsProviderImpl implements PolicyModelsProvider {
72
73     private static final Logger LOGGER = LoggerFactory.getLogger(DatabasePolicyModelsProviderImpl.class);
74
75     private final PolicyModelsProviderParameters parameters;
76
77     // Database connection and the DAO for reading and writing Policy Framework concepts
78     private PfDao pfDao;
79
80     /**
81      * Constructor that takes the parameters.
82      *
83      * @param parameters the parameters for the provider
84      */
85     public DatabasePolicyModelsProviderImpl(@NonNull final PolicyModelsProviderParameters parameters) {
86         this.parameters = parameters;
87     }
88
89     @Override
90     public void init() throws PfModelException {
91         LOGGER.debug("opening the database connection to {} using persistence unit {}", parameters.getDatabaseUrl(),
92                 parameters.getPersistenceUnit());
93
94         if (pfDao != null) {
95             String errorMessage = "provider is already initialized";
96             LOGGER.warn(errorMessage);
97             throw new PfModelException(Response.Status.NOT_ACCEPTABLE, errorMessage);
98         }
99
100         // Parameters for the DAO
101         final DaoParameters daoParameters = new DaoParameters();
102         daoParameters.setPluginClass(DefaultPfDao.class.getName());
103         daoParameters.setPersistenceUnit(parameters.getPersistenceUnit());
104
105         // Decode the password using Base64
106         String decodedPassword = new String(Base64.getDecoder().decode(parameters.getDatabasePassword()));
107
108         // @formatter:off
109         Properties jdbcProperties = new Properties();
110         jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_DRIVER,   parameters.getDatabaseDriver());
111         jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_URL,      parameters.getDatabaseUrl());
112         jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_USER,     parameters.getDatabaseUser());
113         jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_PASSWORD, decodedPassword);
114         // @formatter:on
115
116         daoParameters.setJdbcProperties(jdbcProperties);
117
118         try {
119             pfDao = new PfDaoFactory().createPfDao(daoParameters);
120             pfDao.init(daoParameters);
121         } catch (Exception exc) {
122             String errorMessage = "could not create Data Access Object (DAO) using url \"" + parameters.getDatabaseUrl()
123                     + "\" and persistence unit \"" + parameters.getPersistenceUnit() + "\"";
124
125             this.close();
126             throw new PfModelException(Response.Status.NOT_ACCEPTABLE, errorMessage, exc);
127         }
128     }
129
130     @Override
131     public void close() throws PfModelException {
132         LOGGER.debug("closing the database connection to {} using persistence unit {}", parameters.getDatabaseUrl(),
133                 parameters.getPersistenceUnit());
134
135         if (pfDao != null) {
136             pfDao.close();
137             pfDao = null;
138         }
139
140         LOGGER.debug("closed the database connection to {} using persistence unit {}", parameters.getDatabaseUrl(),
141                 parameters.getPersistenceUnit());
142     }
143
144     @Override
145     public ToscaServiceTemplate getPolicyTypes(final String name, final String version) throws PfModelException {
146         assertInitialized();
147         return new AuthorativeToscaProvider().getPolicyTypes(pfDao, name, version);
148     }
149
150     @Override
151     public List<ToscaPolicyType> getPolicyTypeList(final String name, final String version) throws PfModelException {
152         assertInitialized();
153         return new AuthorativeToscaProvider().getPolicyTypeList(pfDao, name, version);
154     }
155
156     @Override
157     public ToscaServiceTemplate getFilteredPolicyTypes(@NonNull ToscaPolicyTypeFilter filter) throws PfModelException {
158         assertInitialized();
159         return new AuthorativeToscaProvider().getFilteredPolicyTypes(pfDao, filter);
160     }
161
162     @Override
163     public List<ToscaPolicyType> getFilteredPolicyTypeList(@NonNull ToscaPolicyTypeFilter filter)
164             throws PfModelException {
165         assertInitialized();
166         return new AuthorativeToscaProvider().getFilteredPolicyTypeList(pfDao, filter);
167     }
168
169     @Override
170     public ToscaServiceTemplate createPolicyTypes(@NonNull final ToscaServiceTemplate serviceTemplate)
171             throws PfModelException {
172         assertInitialized();
173         return new AuthorativeToscaProvider().createPolicyTypes(pfDao, serviceTemplate);
174     }
175
176     @Override
177     public ToscaServiceTemplate updatePolicyTypes(@NonNull final ToscaServiceTemplate serviceTemplate)
178             throws PfModelException {
179         assertInitialized();
180         return new AuthorativeToscaProvider().updatePolicyTypes(pfDao, serviceTemplate);
181     }
182
183     @Override
184     public ToscaServiceTemplate deletePolicyType(@NonNull final String name, @NonNull final String version)
185             throws PfModelException {
186         assertInitialized();
187
188         ToscaPolicyTypeIdentifier policyTypeIdentifier = new ToscaPolicyTypeIdentifier(name, version);
189         assertPolicyTypeNotSupportedInPdpGroup(policyTypeIdentifier);
190
191         return new AuthorativeToscaProvider().deletePolicyType(pfDao, name, version);
192     }
193
194     @Override
195     public ToscaServiceTemplate getPolicies(final String name, final String version) throws PfModelException {
196         assertInitialized();
197         return new AuthorativeToscaProvider().getPolicies(pfDao, name, version);
198     }
199
200     @Override
201     public List<ToscaPolicy> getPolicyList(final String name, final String version) throws PfModelException {
202         assertInitialized();
203         return new AuthorativeToscaProvider().getPolicyList(pfDao, name, version);
204     }
205
206     @Override
207     public ToscaServiceTemplate getFilteredPolicies(@NonNull ToscaPolicyFilter filter) throws PfModelException {
208         assertInitialized();
209         return new AuthorativeToscaProvider().getFilteredPolicies(pfDao, filter);
210     }
211
212     @Override
213     public List<ToscaPolicy> getFilteredPolicyList(@NonNull ToscaPolicyFilter filter) throws PfModelException {
214         assertInitialized();
215         return new AuthorativeToscaProvider().getFilteredPolicyList(pfDao, filter);
216     }
217
218     @Override
219     public ToscaServiceTemplate createPolicies(@NonNull final ToscaServiceTemplate serviceTemplate)
220             throws PfModelException {
221         assertInitialized();
222         return new AuthorativeToscaProvider().createPolicies(pfDao, serviceTemplate);
223     }
224
225     @Override
226     public ToscaServiceTemplate updatePolicies(@NonNull final ToscaServiceTemplate serviceTemplate)
227             throws PfModelException {
228         assertInitialized();
229         return new AuthorativeToscaProvider().updatePolicies(pfDao, serviceTemplate);
230     }
231
232     @Override
233     public ToscaServiceTemplate deletePolicy(@NonNull final String name, @NonNull final String version)
234             throws PfModelException {
235         assertInitialized();
236
237         ToscaPolicyIdentifier policyIdentifier = new ToscaPolicyIdentifier(name, version);
238         assertPolicyNotDeployedInPdpGroup(policyIdentifier);
239
240         return new AuthorativeToscaProvider().deletePolicy(pfDao, name, version);
241     }
242
243     @Override
244     public LegacyOperationalPolicy getOperationalPolicy(@NonNull final String policyId, final String policyVersion)
245             throws PfModelException {
246         assertInitialized();
247         return new LegacyProvider().getOperationalPolicy(pfDao, policyId, policyVersion);
248     }
249
250     @Override
251     public LegacyOperationalPolicy createOperationalPolicy(
252             @NonNull final LegacyOperationalPolicy legacyOperationalPolicy) throws PfModelException {
253         assertInitialized();
254         return new LegacyProvider().createOperationalPolicy(pfDao, legacyOperationalPolicy);
255     }
256
257     @Override
258     public LegacyOperationalPolicy updateOperationalPolicy(
259             @NonNull final LegacyOperationalPolicy legacyOperationalPolicy) throws PfModelException {
260         assertInitialized();
261         return new LegacyProvider().updateOperationalPolicy(pfDao, legacyOperationalPolicy);
262     }
263
264     @Override
265     public LegacyOperationalPolicy deleteOperationalPolicy(@NonNull final String policyId,
266             @NonNull final String policyVersion) throws PfModelException {
267         assertInitialized();
268
269         assertPolicyNotDeployedInPdpGroup(
270                 new ToscaPolicyIdentifier(policyId, policyVersion + LegacyProvider.LEGACY_MINOR_PATCH_SUFFIX));
271
272         return new LegacyProvider().deleteOperationalPolicy(pfDao, policyId, policyVersion);
273     }
274
275     @Override
276     public Map<String, LegacyGuardPolicyOutput> getGuardPolicy(@NonNull final String policyId,
277             final String policyVersion) throws PfModelException {
278         assertInitialized();
279         return new LegacyProvider().getGuardPolicy(pfDao, policyId, policyVersion);
280     }
281
282     @Override
283     public Map<String, LegacyGuardPolicyOutput>
284             createGuardPolicy(@NonNull final LegacyGuardPolicyInput legacyGuardPolicy) throws PfModelException {
285         assertInitialized();
286         return new LegacyProvider().createGuardPolicy(pfDao, legacyGuardPolicy);
287     }
288
289     @Override
290     public Map<String, LegacyGuardPolicyOutput>
291             updateGuardPolicy(@NonNull final LegacyGuardPolicyInput legacyGuardPolicy) throws PfModelException {
292         assertInitialized();
293         return new LegacyProvider().updateGuardPolicy(pfDao, legacyGuardPolicy);
294     }
295
296     @Override
297     public Map<String, LegacyGuardPolicyOutput> deleteGuardPolicy(@NonNull final String policyId,
298             @NonNull final String policyVersion) throws PfModelException {
299         assertInitialized();
300
301         assertPolicyNotDeployedInPdpGroup(
302                 new ToscaPolicyIdentifier(policyId, policyVersion + LegacyProvider.LEGACY_MINOR_PATCH_SUFFIX));
303
304         return new LegacyProvider().deleteGuardPolicy(pfDao, policyId, policyVersion);
305     }
306
307     @Override
308     public List<PdpGroup> getPdpGroups(final String name) throws PfModelException {
309         assertInitialized();
310         return new PdpProvider().getPdpGroups(pfDao, name);
311     }
312
313     @Override
314     public List<PdpGroup> getFilteredPdpGroups(@NonNull PdpGroupFilter filter) throws PfModelException {
315         assertInitialized();
316         return new PdpProvider().getFilteredPdpGroups(pfDao, filter);
317     }
318
319     @Override
320     public List<PdpGroup> createPdpGroups(@NonNull final List<PdpGroup> pdpGroups) throws PfModelException {
321         assertInitialized();
322         return new PdpProvider().createPdpGroups(pfDao, pdpGroups);
323     }
324
325     @Override
326     public List<PdpGroup> updatePdpGroups(@NonNull final List<PdpGroup> pdpGroups) throws PfModelException {
327         assertInitialized();
328         return new PdpProvider().updatePdpGroups(pfDao, pdpGroups);
329     }
330
331     @Override
332     public void updatePdpSubGroup(@NonNull final String pdpGroupName, @NonNull final PdpSubGroup pdpSubGroup)
333             throws PfModelException {
334         assertInitialized();
335         new PdpProvider().updatePdpSubGroup(pfDao, pdpGroupName, pdpSubGroup);
336     }
337
338     @Override
339     public void updatePdp(@NonNull String pdpGroupName, @NonNull String pdpSubGroup, @NonNull Pdp pdp)
340             throws PfModelException {
341         new PdpProvider().updatePdp(pfDao, pdpGroupName, pdpSubGroup, pdp);
342     }
343
344     @Override
345     public PdpGroup deletePdpGroup(@NonNull final String name) throws PfModelException {
346         assertInitialized();
347         return new PdpProvider().deletePdpGroup(pfDao, name);
348     }
349
350     @Override
351     public List<PdpStatistics> getPdpStatistics(final String name, final Date timestamp) throws PfModelException {
352         assertInitialized();
353         return new PdpStatisticsProvider().getPdpStatistics(pfDao, name, timestamp);
354     }
355
356     @Override
357     public List<PdpStatistics> getFilteredPdpStatistics(final String name, @NonNull final String pdpGroupName,
358             final String pdpSubGroup, final Date startTimeStamp, final Date endTimeStamp, final String sortOrder,
359             final int getRecordNum) throws PfModelException {
360         assertInitialized();
361         return new PdpStatisticsProvider().getFilteredPdpStatistics(pfDao, name, pdpGroupName, pdpSubGroup,
362                 startTimeStamp, endTimeStamp, sortOrder, getRecordNum);
363     }
364
365     @Override
366     public List<PdpStatistics> createPdpStatistics(@NonNull final List<PdpStatistics> pdpStatisticsList)
367             throws PfModelException {
368         assertInitialized();
369         return new PdpStatisticsProvider().createPdpStatistics(pfDao, pdpStatisticsList);
370     }
371
372     @Override
373     public List<PdpStatistics> updatePdpStatistics(@NonNull final List<PdpStatistics> pdpStatisticsList)
374             throws PfModelException {
375         assertInitialized();
376         return new PdpStatisticsProvider().updatePdpStatistics(pfDao, pdpStatisticsList);
377     }
378
379     @Override
380     public List<PdpStatistics> deletePdpStatistics(@NonNull final String name, final Date timestamp)
381             throws PfModelException {
382         assertInitialized();
383         return new PdpStatisticsProvider().deletePdpStatistics(pfDao, name, timestamp);
384     }
385
386     /**
387      * Check if the model provider is initialized.
388      */
389     private void assertInitialized() {
390         if (pfDao == null) {
391             String errorMessage = "policy models provider is not initilaized";
392             LOGGER.warn(errorMessage);
393             throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage);
394         }
395     }
396
397     /**
398      * Assert that the policy type is not supported in any PDP group.
399      *
400      * @param policyTypeIdentifier the policy type identifier
401      * @throws PfModelException if the policy type is supported in a PDP group
402      */
403     private void assertPolicyTypeNotSupportedInPdpGroup(ToscaPolicyTypeIdentifier policyTypeIdentifier)
404             throws PfModelException {
405         for (PdpGroup pdpGroup : getPdpGroups(null)) {
406             for (PdpSubGroup pdpSubGroup : pdpGroup.getPdpSubgroups()) {
407                 if (pdpSubGroup.getSupportedPolicyTypes().contains(policyTypeIdentifier)) {
408                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE,
409                             "policy type is in use, it is referenced in PDP group " + pdpGroup.getName() + " subgroup "
410                                     + pdpSubGroup.getPdpType());
411                 }
412             }
413         }
414     }
415
416     /**
417      * Assert that the policy is not deployed in a PDP group.
418      *
419      * @param policyIdentifier the identifier of the policy
420      * @throws PfModelException thrown if the policy is deployed in a PDP group
421      */
422     private void assertPolicyNotDeployedInPdpGroup(final ToscaPolicyIdentifier policyIdentifier)
423             throws PfModelException {
424         for (PdpGroup pdpGroup : getPdpGroups(null)) {
425             for (PdpSubGroup pdpSubGroup : pdpGroup.getPdpSubgroups()) {
426                 if (pdpSubGroup.getPolicies().contains(policyIdentifier)) {
427                     throw new PfModelRuntimeException(Response.Status.NOT_ACCEPTABLE,
428                             "policy is in use, it is deployed in PDP group " + pdpGroup.getName() + " subgroup "
429                                     + pdpSubGroup.getPdpType());
430                 }
431             }
432         }
433     }
434 }