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