Fix config files to remove outdated configuration for hibernate
[policy/models.git] / models-dao / src / main / java / org / onap / policy / models / dao / impl / DefaultPfDao.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019-2021, 2023-2024 Nordix Foundation.
4  *  Modifications Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
5  *  Modifications Copyright (C) 2022 Bell Canada. 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  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.models.dao.impl;
24
25 import jakarta.persistence.EntityManager;
26 import jakarta.persistence.EntityManagerFactory;
27 import jakarta.persistence.Persistence;
28 import jakarta.persistence.TypedQuery;
29 import jakarta.ws.rs.core.Response;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.List;
33 import org.apache.commons.lang3.StringUtils;
34 import org.onap.policy.models.base.PfConcept;
35 import org.onap.policy.models.base.PfConceptKey;
36 import org.onap.policy.models.base.PfModelException;
37 import org.onap.policy.models.base.PfModelRuntimeException;
38 import org.onap.policy.models.base.PfReferenceKey;
39 import org.onap.policy.models.base.PfReferenceTimestampKey;
40 import org.onap.policy.models.base.PfTimestampKey;
41 import org.onap.policy.models.base.PfUtils;
42 import org.onap.policy.models.dao.DaoParameters;
43 import org.onap.policy.models.dao.PfDao;
44 import org.onap.policy.models.dao.PfFilter;
45 import org.onap.policy.models.dao.PfFilterFactory;
46 import org.onap.policy.models.dao.PfFilterParametersIntfc;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 /**
51  * The Class DefaultPfDao is an JPA implementation of the {@link PfDao} class for Policy Framework concepts
52  * ({@link PfConcept}). It uses the default JPA implementation in the jakarta {@link Persistence} class.
53  */
54 public class DefaultPfDao implements PfDao {
55     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPfDao.class);
56
57     // Entity manager for JPA
58     private EntityManagerFactory emf = null;
59
60     @Override
61     public void init(final DaoParameters daoParameters) throws PfModelException {
62         if (daoParameters == null || daoParameters.getPersistenceUnit() == null) {
63             LOGGER.error("Policy Framework persistence unit parameter not set");
64             throw new PfModelException(Response.Status.INTERNAL_SERVER_ERROR,
65                 "Policy Framework persistence unit parameter not set");
66         }
67
68         LOGGER.debug("Creating Policy Framework persistence unit \"{}\" . . .", daoParameters.getPersistenceUnit());
69         try {
70             emf = Persistence.createEntityManagerFactory(daoParameters.getPersistenceUnit(),
71                 daoParameters.getJdbcProperties());
72         } catch (final Exception ex) {
73             String errorMessage = "Creation of Policy Framework persistence unit \""
74                 + daoParameters.getPersistenceUnit() + "\" failed";
75             LOGGER.warn(errorMessage);
76             throw new PfModelException(Response.Status.INTERNAL_SERVER_ERROR, errorMessage, ex);
77         }
78         LOGGER.debug("Created Policy Framework persistence unit \"{}\"", daoParameters.getPersistenceUnit());
79     }
80
81     /**
82      * Gets the entity manager for this DAO.
83      *
84      * @return the entity manager
85      */
86     protected final synchronized EntityManager getEntityManager() {
87         if (emf == null) {
88             LOGGER.warn("Policy Framework DAO has not been initialized");
89             throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
90                 "Policy Framework DAO has not been initialized");
91         }
92
93         return emf.createEntityManager();
94     }
95
96     @Override
97     public final void close() {
98         if (emf != null) {
99             emf.close();
100         }
101     }
102
103     @Override
104     public <T extends PfConcept> void create(final T obj) {
105         if (obj == null) {
106             return;
107         }
108         try (var mg = getEntityManager()) {
109             mg.getTransaction().begin();
110             mg.merge(obj);
111             mg.getTransaction().commit();
112         }
113     }
114
115     @Override
116     public <T extends PfConcept> void delete(final T obj) {
117         if (obj == null) {
118             return;
119         }
120         try (var mg = getEntityManager()) {
121             mg.getTransaction().begin();
122             mg.remove(mg.contains(obj) ? obj : mg.merge(obj));
123             mg.getTransaction().commit();
124         }
125     }
126
127     @Override
128     public <T extends PfConcept> void delete(final Class<T> someClass, final PfConceptKey key) {
129         if (key == null) {
130             return;
131         }
132         try (var mg = getEntityManager()) {
133             // @formatter:off
134             mg.getTransaction().begin();
135             mg.createQuery(setQueryTable(DELETE_BY_CONCEPT_KEY, someClass))
136                 .setParameter(NAME,    key.getName())
137                 .setParameter(VERSION, key.getVersion())
138                 .executeUpdate();
139             mg.getTransaction().commit();
140             // @formatter:on
141         }
142     }
143
144     @Override
145     public <T extends PfConcept> void delete(final Class<T> someClass, final PfReferenceKey key) {
146         if (key == null) {
147             return;
148         }
149         try (var mg = getEntityManager()) {
150             // @formatter:off
151             mg.getTransaction().begin();
152             mg.createQuery(setQueryTable(DELETE_BY_REFERENCE_KEY, someClass))
153                 .setParameter(PARENT_NAME,    key.getParentKeyName())
154                 .setParameter(PARENT_VERSION, key.getParentKeyVersion())
155                 .setParameter(LOCAL_NAME,     key.getLocalName())
156                 .executeUpdate();
157             mg.getTransaction().commit();
158             // @formatter:on
159         }
160     }
161
162     @Override
163     public <T extends PfConcept> void delete(final Class<T> someClass, final PfTimestampKey key) {
164         if (key == null) {
165             return;
166         }
167         try (var mg = getEntityManager()) {
168             // @formatter:off
169             mg.getTransaction().begin();
170             mg.createQuery(setQueryTable(DELETE_BY_TIMESTAMP_KEY, someClass))
171                     .setParameter(NAME,    key.getName())
172                     .setParameter(VERSION, key.getVersion())
173                     .setParameter(TIMESTAMP, key.getTimeStamp())
174                     .executeUpdate();
175             mg.getTransaction().commit();
176             // @formatter:on
177         }
178     }
179
180     @Override
181     public <T extends PfConcept> void createCollection(final Collection<T> objs) {
182         if (objs == null || objs.isEmpty()) {
183             return;
184         }
185         try (var mg = getEntityManager()) {
186             mg.getTransaction().begin();
187             for (final T t : objs) {
188                 mg.merge(t);
189             }
190             mg.getTransaction().commit();
191         }
192     }
193
194     @Override
195     public <T extends PfConcept> void deleteCollection(final Collection<T> objs) {
196         if (objs == null || objs.isEmpty()) {
197             return;
198         }
199         try (var mg = getEntityManager()) {
200             mg.getTransaction().begin();
201             for (final T t : objs) {
202                 mg.remove(mg.contains(t) ? t : mg.merge(t));
203             }
204             mg.getTransaction().commit();
205         }
206     }
207
208     @Override
209     public <T extends PfConcept> int deleteByConceptKey(final Class<T> someClass, final Collection<PfConceptKey> keys) {
210         if (keys == null || keys.isEmpty()) {
211             return 0;
212         }
213         var deletedCount = 0;
214         try (var mg = getEntityManager()) {
215             // @formatter:off
216             mg.getTransaction().begin();
217             for (final PfConceptKey key : keys) {
218                 deletedCount += mg.createQuery(setQueryTable(DELETE_BY_CONCEPT_KEY, someClass))
219                     .setParameter(NAME,    key.getName())
220                     .setParameter(VERSION, key.getVersion())
221                     .executeUpdate();
222             }
223             mg.getTransaction().commit();
224             // @formatter:on
225         }
226         return deletedCount;
227     }
228
229     @Override
230     public <T extends PfConcept> int deleteByReferenceKey(final Class<T> someClass,
231                                                           final Collection<PfReferenceKey> keys) {
232         if (keys == null || keys.isEmpty()) {
233             return 0;
234         }
235         var deletedCount = 0;
236         try (var mg = getEntityManager()) {
237             // @formatter:off
238             mg.getTransaction().begin();
239             for (final PfReferenceKey key : keys) {
240                 deletedCount += mg.createQuery(setQueryTable(DELETE_BY_REFERENCE_KEY, someClass))
241                     .setParameter(PARENT_NAME,    key.getParentKeyName())
242                     .setParameter(PARENT_VERSION, key.getParentKeyVersion())
243                     .setParameter(LOCAL_NAME,     key.getLocalName())
244                     .executeUpdate();
245             }
246             mg.getTransaction().commit();
247             // @formatter:on
248         }
249         return deletedCount;
250     }
251
252     @Override
253     public <T extends PfConcept> void deleteAll(final Class<T> someClass) {
254         try (var mg = getEntityManager()) {
255             mg.getTransaction().begin();
256             mg.createQuery(setQueryTable(DELETE_FROM_TABLE, someClass)).executeUpdate();
257             mg.getTransaction().commit();
258         }
259     }
260
261     @Override
262     public <T extends PfConcept> List<T> getFiltered(final Class<T> someClass, final String name,
263                                                      final String version) {
264         if (name == null) {
265             return getAll(someClass);
266         }
267
268         if (version == null) {
269             return getAllVersions(someClass, name);
270         }
271
272         var foundConcept = get(someClass, new PfConceptKey(name, version));
273
274         return (foundConcept == null ? Collections.emptyList() : Collections.singletonList(foundConcept));
275     }
276
277     @Override
278     public <T extends PfConcept> List<T> getFiltered(final Class<T> someClass, PfFilterParametersIntfc filterParams) {
279
280         try (var mg = getEntityManager()) {
281             PfFilter filter = new PfFilterFactory().createFilter(someClass);
282             var filterQueryString = SELECT_FROM_TABLE
283                 + filter.genWhereClause(filterParams)
284                 + filter.genOrderClause(filterParams);
285
286             TypedQuery<T> query = mg.createQuery(setQueryTable(filterQueryString, someClass), someClass);
287             filter.setParams(query, filterParams);
288
289             LOGGER.debug("filterQueryString is  \"{}\"", filterQueryString);
290             return query.getResultList();
291         }
292     }
293
294     @Override
295     public <T extends PfConcept> T get(final Class<T> someClass, final PfConceptKey key) {
296         return genericGet(someClass, key);
297     }
298
299     @Override
300     public <T extends PfConcept> T get(final Class<T> someClass, final PfReferenceKey key) {
301         return genericGet(someClass, key);
302     }
303
304     @Override
305     public <T extends PfConcept> T get(final Class<T> someClass, final PfTimestampKey key) {
306         return genericGet(someClass, key);
307     }
308
309     @Override
310     public <T extends PfConcept> T get(final Class<T> someClass, final PfReferenceTimestampKey key) {
311         return genericGet(someClass, key);
312     }
313
314     private <T extends PfConcept> T genericGet(final Class<T> someClass, final Object key) {
315         if (someClass == null) {
316             return null;
317         }
318         try (var mg = getEntityManager()) {
319             final var t = mg.find(someClass, key);
320             if (t != null) {
321                 mg.refresh(t);
322             }
323             return checkAndReturn(someClass, t);
324         }
325     }
326
327     @Override
328     public <T extends PfConcept> List<T> getAll(final Class<T> someClass) {
329         if (someClass == null) {
330             return Collections.emptyList();
331         }
332         try (var mg = getEntityManager()) {
333             return mg.createQuery(setQueryTable(SELECT_FROM_TABLE, someClass), someClass).getResultList();
334         }
335     }
336
337     @Override
338     public <T extends PfConcept> List<T> getAll(final Class<T> someClass, final PfConceptKey parentKey) {
339         if (someClass == null) {
340             return Collections.emptyList();
341         }
342         try (var mg = getEntityManager()) {
343             // @formatter:off
344             return mg.createQuery(setQueryTable(SELECT_ALL_FOR_PARENT, someClass), someClass)
345                     .setParameter(PARENT_NAME,    parentKey.getName())
346                     .setParameter(PARENT_VERSION, parentKey.getVersion())
347                     .getResultList();
348             // @formatter:on
349         }
350     }
351
352     @Override
353     public <T extends PfConcept> List<T> getAll(Class<T> someClass, String orderBy, Integer numRecords) {
354
355         if (someClass == null) {
356             return Collections.emptyList();
357         }
358         try (var mg = getEntityManager()) {
359             String query = setQueryTable(SELECT_FROM_TABLE, someClass);
360
361             if (StringUtils.isNotBlank(orderBy)) {
362                 query = query.concat(ORDER_BY).concat(orderBy);
363             }
364
365             return mg.createQuery(query, someClass).setMaxResults(numRecords)
366                 .getResultList();
367         }
368     }
369
370     @Override
371     public <T extends PfConcept> List<T> getAllVersionsByParent(final Class<T> someClass, final String parentKeyName) {
372         if (someClass == null || parentKeyName == null) {
373             return Collections.emptyList();
374         }
375         try (var mg = getEntityManager()) {
376             // @formatter:off
377             return mg.createQuery(setQueryTable(SELECT_ALL_VERSIONS_FOR_PARENT, someClass), someClass)
378                     .setParameter(PARENT_NAME, parentKeyName)
379                     .getResultList();
380             // @formatter:on
381         }
382     }
383
384     @Override
385     public <T extends PfConcept> List<T> getAllVersions(final Class<T> someClass, final String conceptName) {
386         if (someClass == null || conceptName == null) {
387             return Collections.emptyList();
388         }
389         try (var mg = getEntityManager()) {
390             // @formatter:off
391             return mg.createQuery(setQueryTable(SELECT_ALL_VERSIONS, someClass), someClass)
392                     .setParameter(NAME, conceptName)
393                     .getResultList();
394             // @formatter:on
395         }
396     }
397
398     @Override
399     public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfConceptKey key) {
400         if (someClass == null || key == null) {
401             return null;
402         }
403         List<T> ret;
404         try (var mg = getEntityManager()) {
405             // @formatter:off
406             ret = mg.createQuery(setQueryTable(SELECT_BY_CONCEPT_KEY, someClass), someClass)
407                     .setParameter(NAME,    key.getName())
408                     .setParameter(VERSION, key.getVersion())
409                     .getResultList();
410             // @formatter:on
411         }
412
413         return getSingleResult(someClass, key.getId(), ret);
414     }
415
416     @Override
417     public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfReferenceKey key) {
418         if (someClass == null || key == null) {
419             return null;
420         }
421         List<T> ret;
422         try (var mg = getEntityManager()) {
423             // @formatter:off
424             ret = mg.createQuery(setQueryTable(SELECT_BY_REFERENCE_KEY, someClass), someClass)
425                     .setParameter(PARENT_NAME,    key.getParentKeyName())
426                     .setParameter(PARENT_VERSION, key.getParentKeyVersion())
427                     .setParameter(LOCAL_NAME,     key.getLocalName())
428                     .getResultList();
429             // @formatter:on
430         }
431
432         return getSingleResult(someClass, key.getId(), ret);
433     }
434
435     @Override
436     public <T extends PfConcept> T update(final T obj) {
437         T ret;
438         try (var mg = getEntityManager()) {
439             mg.getTransaction().begin();
440             ret = mg.merge(obj);
441             mg.flush();
442             mg.getTransaction().commit();
443         }
444         return ret;
445     }
446
447     @Override
448     public <T extends PfConcept> long size(final Class<T> someClass) {
449         if (someClass == null) {
450             return 0;
451         }
452         long size;
453         try (var mg = getEntityManager()) {
454             /*
455              * The invoking code only passes well-known classes into this method, thus
456              * disabling the sonar about SQL injection.
457              */
458             size = mg.createQuery("SELECT COUNT(c) FROM " + someClass.getSimpleName() + " c", Long.class) // NOSONAR
459                 .getSingleResult();
460         }
461         return size;
462     }
463
464     /**
465      * Add the table to a query string.
466      *
467      * @param queryString the query string
468      * @param tableClass  the class name of the table
469      * @return the updated query string
470      */
471     private <T extends PfConcept> String setQueryTable(final String queryString, final Class<T> tableClass) {
472         return queryString.replace(TABLE_TOKEN, tableClass.getSimpleName());
473     }
474
475     /**
476      * Check that a query returned one and only one entry and return that entry.
477      *
478      * @param someClass    the class being searched for
479      * @param searchFilter the search filter
480      * @param resultList   the result list returned by the query
481      * @return the single unique result
482      */
483     private <T extends PfConcept> T getSingleResult(final Class<T> someClass, final String searchFilter,
484                                                     List<T> resultList) {
485         if (resultList == null || resultList.isEmpty()) {
486             return null;
487         }
488         if (resultList.size() > 1) {
489             throw new IllegalArgumentException("More than one result was returned query on " + someClass
490                 + " with filter " + searchFilter + ": " + resultList);
491         }
492         return resultList.get(0);
493     }
494
495     /**
496      * check the result get from database and return the object.
497      *
498      * @param <T>        the type of the object to get, a subclass of {@link PfConcept}
499      * @param someClass  the class of the object to get, a subclass of {@link PfConcept}
500      * @param objToCheck the object that was retrieved from the database
501      * @return the checked object or null
502      */
503     private <T extends PfConcept> T checkAndReturn(final Class<T> someClass, final T objToCheck) {
504         if (objToCheck != null) {
505             try {
506                 return PfUtils.makeCopy(objToCheck);
507             } catch (final Exception e) {
508                 LOGGER.warn(CLONE_ERR_MSG, someClass.getName(), e);
509             }
510         }
511         return null;
512     }
513 }