Add DAO module for Models
[policy/models.git] / models-dao / src / main / java / org / onap / policy / models / dao / impl / DefaultPfDao.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.models.dao.impl;
22
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.List;
26
27 import javax.persistence.EntityManager;
28 import javax.persistence.EntityManagerFactory;
29 import javax.persistence.Persistence;
30
31 import org.onap.policy.models.base.PfConcept;
32 import org.onap.policy.models.base.PfConceptKey;
33 import org.onap.policy.models.base.PfModelException;
34 import org.onap.policy.models.base.PfModelRuntimeException;
35 import org.onap.policy.models.base.PfReferenceKey;
36 import org.onap.policy.models.dao.DaoParameters;
37 import org.onap.policy.models.dao.PfDao;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * The Class DefaultPfDao is an JPA implementation of the {@link PfDao} class for Policy Framework
43  * concepts ({@link PfConcept}). It uses the default JPA implementation in the javax
44  * {@link Persistence} class.
45  */
46 public class DefaultPfDao implements PfDao {
47     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPfDao.class);
48
49     private static final String SELECT_C_FROM = "SELECT c FROM ";
50     private static final String AND_C_KEY_LOCAL_NAME = "' AND c.key.localName='";
51     private static final String AND_C_KEY_PARENT_KEY_VERSION = "' AND c.key.parentKeyVersion='";
52     private static final String C_WHERE_C_KEY_PARENT_KEY_NAME = " c WHERE c.key.parentKeyName='";
53     private static final String AND_C_KEY_VERSION = "' AND c.key.version='";
54     private static final String C_WHERE_C_KEY_NAME = " c WHERE c.key.name='";
55     private static final String DELETE_FROM = "DELETE FROM ";
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("Policy Framework persistence unit parameter not set");
65         }
66
67         LOGGER.debug("Creating Policy Framework persistence unit \"{}\" . . .", daoParameters.getPersistenceUnit());
68         try {
69             emf = Persistence.createEntityManagerFactory(daoParameters.getPersistenceUnit(),
70                     daoParameters.getJdbcProperties());
71         } catch (final Exception ex) {
72             String errorMessage = "Creation of Policy Framework persistence unit \""
73                     + daoParameters.getPersistenceUnit() + "\" failed";
74             LOGGER.warn(errorMessage, ex);
75             throw new PfModelException(errorMessage, ex);
76         }
77         LOGGER.debug("Created Policy Framework persistence unit \"{}\"", daoParameters.getPersistenceUnit());
78     }
79
80     /**
81      * Gets the entity manager for this DAO.
82      *
83      * @return the entity manager
84      */
85     protected final synchronized EntityManager getEntityManager() {
86         if (emf == null) {
87             LOGGER.warn("Policy Framework DAO has not been initialized");
88             throw new PfModelRuntimeException("Policy Framework DAO has not been initialized");
89         }
90
91         return emf.createEntityManager();
92     }
93
94     @Override
95     public final void close() {
96         if (emf != null) {
97             emf.close();
98         }
99     }
100
101     @Override
102     public <T extends PfConcept> void create(final T obj) {
103         if (obj == null) {
104             return;
105         }
106         final EntityManager mg = getEntityManager();
107         try {
108             mg.getTransaction().begin();
109             mg.merge(obj);
110             mg.getTransaction().commit();
111         } finally {
112             mg.close();
113         }
114     }
115
116     @Override
117     public <T extends PfConcept> void delete(final T obj) {
118         if (obj == null) {
119             return;
120         }
121         final EntityManager mg = getEntityManager();
122         try {
123             mg.getTransaction().begin();
124             mg.remove(mg.contains(obj) ? obj : mg.merge(obj));
125             mg.getTransaction().commit();
126         } finally {
127             mg.close();
128         }
129     }
130
131     @Override
132     public <T extends PfConcept> void delete(final Class<T> someClass, final PfConceptKey key) {
133         if (key == null) {
134             return;
135         }
136         final EntityManager mg = getEntityManager();
137         try {
138             mg.getTransaction().begin();
139             mg.createQuery(DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_NAME + key.getName()
140                     + AND_C_KEY_VERSION + key.getVersion() + "'", someClass).executeUpdate();
141             mg.getTransaction().commit();
142         } finally {
143             mg.close();
144         }
145     }
146
147     @Override
148     public <T extends PfConcept> void delete(final Class<T> someClass, final PfReferenceKey key) {
149         if (key == null) {
150             return;
151         }
152         final EntityManager mg = getEntityManager();
153         try {
154             mg.getTransaction().begin();
155             mg.createQuery(DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
156                     + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION + key.getParentKeyVersion()
157                     + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'", someClass).executeUpdate();
158             mg.getTransaction().commit();
159         } finally {
160             mg.close();
161         }
162     }
163
164     @Override
165     public <T extends PfConcept> void createCollection(final Collection<T> objs) {
166         if (objs == null || objs.isEmpty()) {
167             return;
168         }
169         final EntityManager mg = getEntityManager();
170         try {
171             mg.getTransaction().begin();
172             for (final T t : objs) {
173                 mg.merge(t);
174             }
175             mg.getTransaction().commit();
176         } finally {
177             mg.close();
178         }
179     }
180
181     @Override
182     public <T extends PfConcept> void deleteCollection(final Collection<T> objs) {
183         if (objs == null || objs.isEmpty()) {
184             return;
185         }
186         final EntityManager mg = getEntityManager();
187         try {
188             mg.getTransaction().begin();
189             for (final T t : objs) {
190                 mg.remove(mg.contains(t) ? t : mg.merge(t));
191             }
192             mg.getTransaction().commit();
193         } finally {
194             mg.close();
195         }
196     }
197
198     @Override
199     public <T extends PfConcept> int deleteByConceptKey(final Class<T> someClass,
200             final Collection<PfConceptKey> keys) {
201         if (keys == null || keys.isEmpty()) {
202             return 0;
203         }
204         int deletedCount = 0;
205         final EntityManager mg = getEntityManager();
206         try {
207             mg.getTransaction().begin();
208             for (final PfConceptKey key : keys) {
209                 deletedCount += mg.createQuery(DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_NAME
210                         + key.getName() + AND_C_KEY_VERSION + key.getVersion() + "'", someClass).executeUpdate();
211             }
212             mg.getTransaction().commit();
213         } finally {
214             mg.close();
215         }
216         return deletedCount;
217     }
218
219     @Override
220     public <T extends PfConcept> int deleteByReferenceKey(final Class<T> someClass,
221             final Collection<PfReferenceKey> keys) {
222         if (keys == null || keys.isEmpty()) {
223             return 0;
224         }
225         int deletedCount = 0;
226         final EntityManager mg = getEntityManager();
227         try {
228             mg.getTransaction().begin();
229             for (final PfReferenceKey key : keys) {
230                 deletedCount +=
231                         mg.createQuery(
232                                 DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
233                                         + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION
234                                         + key.getParentKeyVersion() + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'",
235                                 someClass).executeUpdate();
236             }
237             mg.getTransaction().commit();
238         } finally {
239             mg.close();
240         }
241         return deletedCount;
242     }
243
244     @Override
245     public <T extends PfConcept> void deleteAll(final Class<T> someClass) {
246         final EntityManager mg = getEntityManager();
247         try {
248             mg.getTransaction().begin();
249             mg.createQuery(DELETE_FROM + someClass.getSimpleName() + " c ", someClass).executeUpdate();
250             mg.getTransaction().commit();
251         } finally {
252             mg.close();
253         }
254     }
255
256     @Override
257     public <T extends PfConcept> T get(final Class<T> someClass, final PfConceptKey key) {
258         if (someClass == null) {
259             return null;
260         }
261         final EntityManager mg = getEntityManager();
262         try {
263             final T t = mg.find(someClass, key);
264             if (t != null) {
265                 // This clone is created to force the JPA DAO to recurse down through the object
266                 try {
267                     final T clonedT = someClass.newInstance();
268                     t.copyTo(clonedT);
269                     return clonedT;
270                 } catch (final Exception e) {
271                     LOGGER.warn("Could not clone object of class \"" + someClass.getCanonicalName() + "\"", e);
272                     return null;
273                 }
274             } else {
275                 return null;
276             }
277         } finally {
278             mg.close();
279         }
280     }
281
282     @Override
283     public <T extends PfConcept> T get(final Class<T> someClass, final PfReferenceKey key) {
284         if (someClass == null) {
285             return null;
286         }
287         final EntityManager mg = getEntityManager();
288         try {
289             final T t = mg.find(someClass, key);
290             if (t != null) {
291                 try {
292                     final T clonedT = someClass.newInstance();
293                     t.copyTo(clonedT);
294                     return clonedT;
295                 } catch (final Exception e) {
296                     LOGGER.warn("Could not clone object of class \"" + someClass.getCanonicalName() + "\"", e);
297                     return null;
298                 }
299             } else {
300                 return null;
301             }
302         } finally {
303             mg.close();
304         }
305     }
306
307     @Override
308     public <T extends PfConcept> List<T> getAll(final Class<T> someClass) {
309         if (someClass == null) {
310             return Collections.emptyList();
311         }
312         final EntityManager mg = getEntityManager();
313         try {
314             return mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + " c", someClass).getResultList();
315         } finally {
316             mg.close();
317         }
318     }
319
320     @Override
321     public <T extends PfConcept> List<T> getAll(final Class<T> someClass, final PfConceptKey parentKey) {
322         if (someClass == null) {
323             return Collections.emptyList();
324         }
325         final EntityManager mg = getEntityManager();
326         try {
327             return mg
328                     .createQuery(
329                             SELECT_C_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
330                                     + parentKey.getName() + AND_C_KEY_PARENT_KEY_VERSION + parentKey.getVersion() + "'",
331                             someClass)
332                     .getResultList();
333         } finally {
334             mg.close();
335         }
336     }
337
338     @Override
339     public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfConceptKey key) {
340         if (someClass == null || key == null) {
341             return null;
342         }
343         final EntityManager mg = getEntityManager();
344         List<T> ret;
345         try {
346             ret = mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_NAME + key.getName()
347                     + AND_C_KEY_VERSION + key.getVersion() + "'", someClass).getResultList();
348         } finally {
349             mg.close();
350         }
351         if (ret == null || ret.isEmpty()) {
352             return null;
353         }
354         if (ret.size() > 1) {
355             throw new IllegalArgumentException("More than one result was returned for search for " + someClass
356                     + " with key " + key.getId() + ": " + ret);
357         }
358         return ret.get(0);
359     }
360
361     @Override
362     public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfReferenceKey key) {
363         if (someClass == null || key == null) {
364             return null;
365         }
366         final EntityManager mg = getEntityManager();
367         List<T> ret;
368         try {
369             ret = mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
370                     + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION + key.getParentKeyVersion()
371                     + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'", someClass).getResultList();
372         } finally {
373             mg.close();
374         }
375         if (ret == null || ret.isEmpty()) {
376             return null;
377         }
378         if (ret.size() > 1) {
379             throw new IllegalArgumentException("More than one result was returned for search for " + someClass
380                     + " with key " + key.getId() + ": " + ret);
381         }
382         return ret.get(0);
383     }
384
385     @Override
386     public <T extends PfConcept> T update(final T obj) {
387         final EntityManager mg = getEntityManager();
388         T ret;
389         try {
390             mg.getTransaction().begin();
391             ret = mg.merge(obj);
392             mg.flush();
393             mg.getTransaction().commit();
394         } finally {
395             mg.close();
396         }
397         return ret;
398     }
399
400     @Override
401     public <T extends PfConcept> long size(final Class<T> someClass) {
402         if (someClass == null) {
403             return 0;
404         }
405         final EntityManager mg = getEntityManager();
406         long size = 0;
407         try {
408             size = mg.createQuery("SELECT COUNT(c) FROM " + someClass.getSimpleName() + " c", Long.class)
409                     .getSingleResult();
410         } finally {
411             mg.close();
412         }
413         return size;
414     }
415 }