Merge "Add a new key class which uses @GeneratedValue to base classes"
[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 Nordix Foundation.
4  *  Modifications Copyright (C) 2019-2021 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.dao.impl;
23
24 import java.sql.Timestamp;
25 import java.time.Instant;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Map;
30 import javax.persistence.EntityManager;
31 import javax.persistence.EntityManagerFactory;
32 import javax.persistence.Persistence;
33 import javax.persistence.TypedQuery;
34 import javax.ws.rs.core.Response;
35 import org.onap.policy.models.base.PfConcept;
36 import org.onap.policy.models.base.PfConceptKey;
37 import org.onap.policy.models.base.PfGeneratedIdKey;
38 import org.onap.policy.models.base.PfModelException;
39 import org.onap.policy.models.base.PfModelRuntimeException;
40 import org.onap.policy.models.base.PfReferenceKey;
41 import org.onap.policy.models.base.PfReferenceTimestampKey;
42 import org.onap.policy.models.base.PfTimestampKey;
43 import org.onap.policy.models.base.PfUtils;
44 import org.onap.policy.models.dao.DaoParameters;
45 import org.onap.policy.models.dao.PfDao;
46 import org.onap.policy.models.dao.PfFilter;
47 import org.onap.policy.models.dao.PfFilterFactory;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 /**
52  * The Class DefaultPfDao is an JPA implementation of the {@link PfDao} class for Policy Framework concepts
53  * ({@link PfConcept}). It uses the default JPA implementation in the javax {@link Persistence} class.
54  */
55 public class DefaultPfDao implements PfDao {
56     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPfDao.class);
57
58     // @formatter:off
59     private static final String NAME           = "name";
60     private static final String VERSION        = "version";
61     private static final String TIMESTAMP      = "timeStamp";
62     private static final String GENERATEDID    = "Id";
63     private static final String PARENT_NAME    = "parentname";
64     private static final String PARENT_VERSION = "parentversion";
65     private static final String LOCAL_NAME     = "localname";
66
67     private static final String TABLE_TOKEN = "__TABLE__";
68
69     private static final String DELETE_FROM_TABLE = "DELETE FROM __TABLE__ c";
70
71     private static final String SELECT_FROM_TABLE = "SELECT c FROM __TABLE__ c";
72
73     private static final String WHERE      = " WHERE ";
74     private static final String AND        = " AND ";
75     private static final String ORDER      = " ORDER BY ";
76
77     private static final String NAME_FILTER            = "c.key.name = :name";
78     private static final String VERSION_FILTER         = "c.key.version = :version";
79     private static final String TIMESTAMP_FILTER       = "c.key.timeStamp = :timeStamp";
80     private static final String TIMESTAMP_FILTER_NOKEY = "c.timeStamp = :timeStamp";
81     private static final String GENERATED_ID_FILTER    = "c.key.generatedId = :Id";
82     private static final String PARENT_NAME_FILTER     = "c.key.parentKeyName = :parentname";
83     private static final String PARENT_VERSION_FILTER  = "c.key.parentKeyVersion = :parentversion";
84     private static final String LOCAL_NAME_FILTER      = "c.key.localName = :localname";
85
86     private static final String PARENT_NAME_REF_FILTER     = "c.key.referenceKey.parentKeyName = :parentKeyName";
87
88     private static final String CLONE_ERR_MSG = "Could not clone object of class \"{}\"";
89
90     private static final String DELETE_BY_CONCEPT_KEY =
91             DELETE_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER;
92
93     private static final String DELETE_BY_TIMESTAMP_KEY =
94             DELETE_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER  + AND + TIMESTAMP_FILTER;
95
96     private static final String DELETE_BY_GENERATED_ID_KEY =
97             DELETE_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER  + AND + GENERATED_ID_FILTER;
98
99     private static final String DELETE_BY_REFERENCE_KEY =
100             DELETE_FROM_TABLE + WHERE + PARENT_NAME_FILTER + AND + PARENT_VERSION_FILTER + AND + LOCAL_NAME_FILTER;
101
102     private static final String SELECT_ALL_FOR_PARENT =
103             SELECT_FROM_TABLE + WHERE + PARENT_NAME_FILTER + AND + PARENT_VERSION_FILTER;
104
105     private static final String SELECT_ALL_VERSIONS_FOR_PARENT =
106             SELECT_FROM_TABLE + WHERE + PARENT_NAME_FILTER;
107
108     private static final String SELECT_ALL_VERSIONS = SELECT_FROM_TABLE + WHERE + NAME_FILTER;
109
110     private static final String SELECT_BY_CONCEPT_KEY =
111             SELECT_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER;
112
113     private static final String SELECT_BY_TIMESTAMP_NOKEY =
114             SELECT_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER + AND + TIMESTAMP_FILTER_NOKEY;
115
116     private static final String SELECT_BY_REFERENCE_KEY =
117             SELECT_FROM_TABLE + WHERE + PARENT_NAME_FILTER + AND + PARENT_VERSION_FILTER + AND + LOCAL_NAME_FILTER;
118     // @formatter:on
119
120     // Entity manager for JPA
121     private EntityManagerFactory emf = null;
122
123     @Override
124     public void init(final DaoParameters daoParameters) throws PfModelException {
125         if (daoParameters == null || daoParameters.getPersistenceUnit() == null) {
126             LOGGER.error("Policy Framework persistence unit parameter not set");
127             throw new PfModelException(Response.Status.INTERNAL_SERVER_ERROR,
128                     "Policy Framework persistence unit parameter not set");
129         }
130
131         LOGGER.debug("Creating Policy Framework persistence unit \"{}\" . . .", daoParameters.getPersistenceUnit());
132         try {
133             emf = Persistence.createEntityManagerFactory(daoParameters.getPersistenceUnit(),
134                     daoParameters.getJdbcProperties());
135         } catch (final Exception ex) {
136             String errorMessage = "Creation of Policy Framework persistence unit \""
137                     + daoParameters.getPersistenceUnit() + "\" failed";
138             LOGGER.warn(errorMessage);
139             throw new PfModelException(Response.Status.INTERNAL_SERVER_ERROR, errorMessage, ex);
140         }
141         LOGGER.debug("Created Policy Framework persistence unit \"{}\"", daoParameters.getPersistenceUnit());
142     }
143
144     /**
145      * Gets the entity manager for this DAO.
146      *
147      * @return the entity manager
148      */
149     protected final synchronized EntityManager getEntityManager() {
150         if (emf == null) {
151             LOGGER.warn("Policy Framework DAO has not been initialized");
152             throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
153                     "Policy Framework DAO has not been initialized");
154         }
155
156         return emf.createEntityManager();
157     }
158
159     @Override
160     public final void close() {
161         if (emf != null) {
162             emf.close();
163         }
164     }
165
166     @Override
167     public <T extends PfConcept> void create(final T obj) {
168         if (obj == null) {
169             return;
170         }
171         final EntityManager mg = getEntityManager();
172         try {
173             mg.getTransaction().begin();
174             mg.merge(obj);
175             mg.getTransaction().commit();
176         } finally {
177             mg.close();
178         }
179     }
180
181     @Override
182     public <T extends PfConcept> void delete(final T obj) {
183         if (obj == null) {
184             return;
185         }
186         final EntityManager mg = getEntityManager();
187         try {
188             mg.getTransaction().begin();
189             mg.remove(mg.contains(obj) ? obj : mg.merge(obj));
190             mg.getTransaction().commit();
191         } finally {
192             mg.close();
193         }
194     }
195
196     @Override
197     public <T extends PfConcept> void delete(final Class<T> someClass, final PfConceptKey key) {
198         if (key == null) {
199             return;
200         }
201         final EntityManager mg = getEntityManager();
202         try {
203             // @formatter:off
204             mg.getTransaction().begin();
205             mg.createQuery(setQueryTable(DELETE_BY_CONCEPT_KEY, someClass), someClass)
206                 .setParameter(NAME,    key.getName())
207                 .setParameter(VERSION, key.getVersion())
208                 .executeUpdate();
209             mg.getTransaction().commit();
210             // @formatter:on
211         } finally {
212             mg.close();
213         }
214     }
215
216     @Override
217     public <T extends PfConcept> void delete(final Class<T> someClass, final PfReferenceKey key) {
218         if (key == null) {
219             return;
220         }
221         final EntityManager mg = getEntityManager();
222         try {
223             // @formatter:off
224             mg.getTransaction().begin();
225             mg.createQuery(setQueryTable(DELETE_BY_REFERENCE_KEY, someClass), someClass)
226                 .setParameter(PARENT_NAME,    key.getParentKeyName())
227                 .setParameter(PARENT_VERSION, key.getParentKeyVersion())
228                 .setParameter(LOCAL_NAME,     key.getLocalName())
229                 .executeUpdate();
230             mg.getTransaction().commit();
231             // @formatter:on
232         } finally {
233             mg.close();
234         }
235     }
236
237     @Override
238     public <T extends PfConcept> void delete(final Class<T> someClass, final PfTimestampKey key) {
239         if (key == null) {
240             return;
241         }
242         final EntityManager mg = getEntityManager();
243         try {
244             // @formatter:off
245             mg.getTransaction().begin();
246             mg.createQuery(setQueryTable(DELETE_BY_TIMESTAMP_KEY, someClass), someClass)
247                     .setParameter(NAME,    key.getName())
248                     .setParameter(VERSION, key.getVersion())
249                     .setParameter(TIMESTAMP, key.getTimeStamp())
250                     .executeUpdate();
251             mg.getTransaction().commit();
252             // @formatter:on
253         } finally {
254             mg.close();
255         }
256     }
257
258     @Override
259     public <T extends PfConcept> void delete(final Class<T> someClass, final PfGeneratedIdKey key) {
260         if (key == null) {
261             return;
262         }
263         final EntityManager mg = getEntityManager();
264         try {
265             // @formatter:off
266             mg.getTransaction().begin();
267             mg.createQuery(setQueryTable(DELETE_BY_GENERATED_ID_KEY, someClass), someClass)
268                     .setParameter(NAME,    key.getName())
269                     .setParameter(VERSION, key.getVersion())
270                     .setParameter(GENERATEDID, key.getGeneratedId())
271                     .executeUpdate();
272             mg.getTransaction().commit();
273             // @formatter:on
274         } finally {
275             mg.close();
276         }
277     }
278
279     @Override
280     public <T extends PfConcept> void createCollection(final Collection<T> objs) {
281         if (objs == null || objs.isEmpty()) {
282             return;
283         }
284         final EntityManager mg = getEntityManager();
285         try {
286             mg.getTransaction().begin();
287             for (final T t : objs) {
288                 mg.merge(t);
289             }
290             mg.getTransaction().commit();
291         } finally {
292             mg.close();
293         }
294     }
295
296     @Override
297     public <T extends PfConcept> void deleteCollection(final Collection<T> objs) {
298         if (objs == null || objs.isEmpty()) {
299             return;
300         }
301         final EntityManager mg = getEntityManager();
302         try {
303             mg.getTransaction().begin();
304             for (final T t : objs) {
305                 mg.remove(mg.contains(t) ? t : mg.merge(t));
306             }
307             mg.getTransaction().commit();
308         } finally {
309             mg.close();
310         }
311     }
312
313     @Override
314     public <T extends PfConcept> int deleteByConceptKey(final Class<T> someClass, final Collection<PfConceptKey> keys) {
315         if (keys == null || keys.isEmpty()) {
316             return 0;
317         }
318         int deletedCount = 0;
319         final EntityManager mg = getEntityManager();
320         try {
321             // @formatter:off
322             mg.getTransaction().begin();
323             for (final PfConceptKey key : keys) {
324                 deletedCount += mg.createQuery(setQueryTable(DELETE_BY_CONCEPT_KEY, someClass), someClass)
325                     .setParameter(NAME,    key.getName())
326                     .setParameter(VERSION, key.getVersion())
327                     .executeUpdate();
328             }
329             mg.getTransaction().commit();
330             // @formatter:on
331         } finally {
332             mg.close();
333         }
334         return deletedCount;
335     }
336
337     @Override
338     public <T extends PfConcept> int deleteByReferenceKey(final Class<T> someClass,
339             final Collection<PfReferenceKey> keys) {
340         if (keys == null || keys.isEmpty()) {
341             return 0;
342         }
343         int deletedCount = 0;
344         final EntityManager mg = getEntityManager();
345         try {
346             // @formatter:off
347             mg.getTransaction().begin();
348             for (final PfReferenceKey key : keys) {
349                 deletedCount += mg.createQuery(setQueryTable(DELETE_BY_REFERENCE_KEY, someClass), someClass)
350                     .setParameter(PARENT_NAME,    key.getParentKeyName())
351                     .setParameter(PARENT_VERSION, key.getParentKeyVersion())
352                     .setParameter(LOCAL_NAME,     key.getLocalName())
353                     .executeUpdate();
354             }
355             mg.getTransaction().commit();
356             // @formatter:on
357         } finally {
358             mg.close();
359         }
360         return deletedCount;
361     }
362
363     @Override
364     public <T extends PfConcept> void deleteAll(final Class<T> someClass) {
365         final EntityManager mg = getEntityManager();
366         try {
367             mg.getTransaction().begin();
368             mg.createQuery(setQueryTable(DELETE_FROM_TABLE, someClass), someClass).executeUpdate();
369             mg.getTransaction().commit();
370         } finally {
371             mg.close();
372         }
373     }
374
375     @Override
376     public <T extends PfConcept> List<T> getFiltered(final Class<T> someClass, final String name,
377             final String version) {
378         if (name == null) {
379             return getAll(someClass);
380         }
381
382         if (version == null) {
383             return getAllVersions(someClass, name);
384         }
385
386         T foundConcept = get(someClass, new PfConceptKey(name, version));
387
388         return (foundConcept == null ? Collections.emptyList() : Collections.singletonList(foundConcept));
389     }
390
391     @Override
392     public <T extends PfConcept> List<T> getFiltered(final Class<T> someClass, final String name, final String version,
393             final Instant startTime, final Instant endTime, final Map<String, Object> filterMap, final String sortOrder,
394             final int getRecordNum) {
395         final EntityManager mg = getEntityManager();
396
397         String filterQueryString = SELECT_FROM_TABLE + WHERE;
398
399         try {
400             PfFilter timeStampFilter = new PfFilterFactory().createFilter(someClass);
401             filterQueryString = timeStampFilter.addFilter(filterQueryString,
402                   name, startTime, endTime, filterMap, sortOrder, getRecordNum);
403
404
405             TypedQuery<T> query = mg.createQuery(setQueryTable(filterQueryString, someClass), someClass);
406
407             if (filterMap != null) {
408                 for (Map.Entry<String, Object> entry : filterMap.entrySet()) {
409                     query.setParameter(entry.getKey(), entry.getValue());
410                 }
411             }
412             if (name != null) {
413                 query.setParameter(timeStampFilter.getNameParameter(), name);
414             }
415             if (startTime != null) {
416                 if (endTime != null) {
417                     query.setParameter("startTime", Timestamp.from(startTime));
418                     query.setParameter("endTime", Timestamp.from(endTime));
419                 } else {
420                     query.setParameter("startTime", Timestamp.from(startTime));
421                 }
422             } else {
423                 if (endTime != null) {
424                     query.setParameter("endTime", Timestamp.from(endTime));
425                 }
426             }
427             if (getRecordNum > 0) {
428                 query.setMaxResults(getRecordNum);
429             }
430
431             LOGGER.debug("filterQueryString is  \"{}\"", filterQueryString);
432             return query.getResultList();
433         }  finally {
434             mg.close();
435         }
436     }
437
438     @Override
439     public <T extends PfConcept> T get(final Class<T> someClass, final PfConceptKey key) {
440         return genericGet(someClass, key);
441     }
442
443     @Override
444     public <T extends PfConcept> T get(final Class<T> someClass, final PfReferenceKey key) {
445         return genericGet(someClass, key);
446     }
447
448     @Override
449     public <T extends PfConcept> T get(final Class<T> someClass, final PfGeneratedIdKey key) {
450         return genericGet(someClass, key);
451     }
452
453     @Override
454     public <T extends PfConcept> T get(final Class<T> someClass, final PfTimestampKey key) {
455         return genericGet(someClass, key);
456     }
457
458     @Override
459     public <T extends PfConcept> T get(final Class<T> someClass, final PfReferenceTimestampKey key) {
460         return genericGet(someClass, key);
461     }
462
463     private <T extends PfConcept> T genericGet(final Class<T> someClass, final Object key) {
464         if (someClass == null) {
465             return null;
466         }
467         final EntityManager mg = getEntityManager();
468         try {
469             final T t = mg.find(someClass, key);
470             if (t != null) {
471                 mg.refresh(t);
472             }
473             return checkAndReturn(someClass, t);
474         } finally {
475             mg.close();
476         }
477     }
478
479     @Override
480     public <T extends PfConcept> List<T> getAll(final Class<T> someClass) {
481         if (someClass == null) {
482             return Collections.emptyList();
483         }
484         final EntityManager mg = getEntityManager();
485         try {
486             return mg.createQuery(setQueryTable(SELECT_FROM_TABLE, someClass), someClass).getResultList();
487         } finally {
488             mg.close();
489         }
490     }
491
492     @Override
493     public <T extends PfConcept> List<T> getAll(final Class<T> someClass, final PfConceptKey parentKey) {
494         if (someClass == null) {
495             return Collections.emptyList();
496         }
497         final EntityManager mg = getEntityManager();
498         try {
499             // @formatter:off
500             return mg.createQuery(setQueryTable(SELECT_ALL_FOR_PARENT, someClass), someClass)
501                     .setParameter(PARENT_NAME,    parentKey.getName())
502                     .setParameter(PARENT_VERSION, parentKey.getVersion())
503                     .getResultList();
504             // @formatter:on
505         } finally {
506             mg.close();
507         }
508     }
509
510     @Override
511     public <T extends PfConcept> List<T> getAllVersionsByParent(final Class<T> someClass, final String parentKeyName) {
512         if (someClass == null || parentKeyName == null) {
513             return Collections.emptyList();
514         }
515         final EntityManager mg = getEntityManager();
516         try {
517             // @formatter:off
518             return mg.createQuery(setQueryTable(SELECT_ALL_VERSIONS_FOR_PARENT, someClass), someClass)
519                     .setParameter(PARENT_NAME, parentKeyName)
520                     .getResultList();
521             // @formatter:on
522         } finally {
523             mg.close();
524         }
525     }
526
527     @Override
528     public <T extends PfConcept> List<T> getAllVersions(final Class<T> someClass, final String conceptName) {
529         if (someClass == null || conceptName == null) {
530             return Collections.emptyList();
531         }
532         final EntityManager mg = getEntityManager();
533         try {
534             // @formatter:off
535             return mg.createQuery(setQueryTable(SELECT_ALL_VERSIONS, someClass), someClass)
536                     .setParameter(NAME, conceptName)
537                     .getResultList();
538             // @formatter:on
539         } finally {
540             mg.close();
541         }
542     }
543
544     @Override
545     public <T extends PfConcept> List<T> getByTimestamp(final Class<T> someClass,
546                                                         final PfGeneratedIdKey key,
547                                                         final Instant timeStamp) {
548         if (someClass == null || key == null || timeStamp == null) {
549             return Collections.emptyList();
550         }
551
552         final EntityManager mg = getEntityManager();
553         try {
554             // @formatter:off
555             return mg.createQuery(setQueryTable(SELECT_BY_TIMESTAMP_NOKEY, someClass), someClass)
556                     .setParameter(NAME,    key.getName())
557                     .setParameter(VERSION, key.getVersion())
558                     .setParameter(TIMESTAMP, Timestamp.from(timeStamp))
559                     .getResultList();
560             // @formatter:on
561         } finally {
562             mg.close();
563         }
564     }
565
566     @Override
567     public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfConceptKey key) {
568         if (someClass == null || key == null) {
569             return null;
570         }
571         final EntityManager mg = getEntityManager();
572         List<T> ret;
573         try {
574             // @formatter:off
575             ret = mg.createQuery(setQueryTable(SELECT_BY_CONCEPT_KEY, someClass), someClass)
576                     .setParameter(NAME,    key.getName())
577                     .setParameter(VERSION, key.getVersion())
578                     .getResultList();
579             // @formatter:on
580         } finally {
581             mg.close();
582         }
583
584         return getSingleResult(someClass, key.getId(), ret);
585     }
586
587     @Override
588     public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfReferenceKey key) {
589         if (someClass == null || key == null) {
590             return null;
591         }
592         final EntityManager mg = getEntityManager();
593         List<T> ret;
594         try {
595             // @formatter:off
596             ret = mg.createQuery(setQueryTable(SELECT_BY_REFERENCE_KEY, someClass), someClass)
597                     .setParameter(PARENT_NAME,    key.getParentKeyName())
598                     .setParameter(PARENT_VERSION, key.getParentKeyVersion())
599                     .setParameter(LOCAL_NAME,     key.getLocalName())
600                     .getResultList();
601             // @formatter:on
602         } finally {
603             mg.close();
604         }
605
606         return getSingleResult(someClass, key.getId(), ret);
607     }
608
609     @Override
610     public <T extends PfConcept> T update(final T obj) {
611         final EntityManager mg = getEntityManager();
612         T ret;
613         try {
614             mg.getTransaction().begin();
615             ret = mg.merge(obj);
616             mg.flush();
617             mg.getTransaction().commit();
618         } finally {
619             mg.close();
620         }
621         return ret;
622     }
623
624     @Override
625     public <T extends PfConcept> long size(final Class<T> someClass) {
626         if (someClass == null) {
627             return 0;
628         }
629         final EntityManager mg = getEntityManager();
630         long size = 0;
631         try {
632             size = mg.createQuery("SELECT COUNT(c) FROM " + someClass.getSimpleName() + " c", Long.class)
633                     .getSingleResult();
634         } finally {
635             mg.close();
636         }
637         return size;
638     }
639
640     /**
641      * Add the table to a query string.
642      *
643      * @param queryString the query string
644      * @param tableClass the class name of the table
645      * @return the updated query string
646      */
647     private <T extends PfConcept> String setQueryTable(final String queryString, final Class<T> tableClass) {
648         return queryString.replace(TABLE_TOKEN, tableClass.getSimpleName());
649     }
650
651     /**
652      * Check that a query returned one and only one entry and return that entry.
653      *
654      * @param someClass the class being searched for
655      * @param conceptName the concept name being searched for
656      * @param resultList the result list returned by the query
657      * @return the single unique result
658      */
659     private <T extends PfConcept> T getSingleResult(final Class<T> someClass, final String searchFilter, List<T> ret) {
660         if (ret == null || ret.isEmpty()) {
661             return null;
662         }
663         if (ret.size() > 1) {
664             throw new IllegalArgumentException("More than one result was returned query on " + someClass
665                     + " with filter " + searchFilter + ": " + ret);
666         }
667         return ret.get(0);
668     }
669
670     /**
671      * check the result get from database and return the object.
672      *
673      * @param <T> the type of the object to get, a subclass of {@link PfConcept}
674      * @param someClass the class of the object to get, a subclass of {@link PfConcept}
675      * @param t the object that was retrieved from the database
676      * @return the checked object or null
677      */
678     private <T extends PfConcept> T checkAndReturn(final Class<T> someClass, final T objToCheck) {
679         if (objToCheck != null) {
680             try {
681                 return PfUtils.makeCopy(objToCheck);
682             } catch (final Exception e) {
683                 LOGGER.warn(CLONE_ERR_MSG, someClass.getName(), e);
684             }
685         }
686         return null;
687     }
688 }