Coverage Summary for Class: BaseDAO (org.kitodo.data.database.persistence)

Class Class, % Method, % Line, %
BaseDAO 100% (1/1) 73,1% (19/26) 76,8% (96/125)


 /*
  * (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
  *
  * This file is part of the Kitodo project.
  *
  * It is licensed under GNU General Public License version 3 or later.
  *
  * For the full copyright and license information, please read the
  * GPL3-License.txt file that was distributed with this source code.
  */
 
 package org.kitodo.data.database.persistence;
 
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import javax.persistence.PersistenceException;
 
 import org.hibernate.Hibernate;
 import org.hibernate.Session;
 import org.hibernate.Transaction;
 import org.hibernate.exception.SQLGrammarException;
 import org.hibernate.query.Query;
 import org.kitodo.config.ConfigMain;
 import org.kitodo.data.database.beans.BaseBean;
 import org.kitodo.data.database.beans.BaseIndexedBean;
 import org.kitodo.data.database.enums.IndexAction;
 import org.kitodo.data.database.exceptions.DAOException;
 
 /**
  * Base class for DAOs.
  */
 public abstract class BaseDAO<T extends BaseBean> implements Serializable {
 
     private static final Object lockObject = new Object();
 
     /**
      * Retrieves a BaseBean identified by the given id from the database.
      *
      * @param id
      *            of bean to load
      * @return persisted bean
      * @throws DAOException
      *             if a HibernateException is thrown
      */
     public abstract T getById(Integer id) throws DAOException;
 
     /**
      * Retrieves all BaseBean objects from the database.
      *
      * @return all persisted beans
      */
     public abstract List<T> getAll() throws DAOException;
 
     /**
      * Retrieves all BaseBean objects in given range.
      *
      * @param offset
      *            result
      * @param size
      *            amount of results
      * @return constrained list of persisted beans
      */
     public abstract List<T> getAll(int offset, int size) throws DAOException;
 
     /**
      * Retrieves all not indexed BaseBean objects in given range.
      *
      * @param offset
      *            result
      * @param size
      *            amount of results
      * @return constrained list of persisted beans
      */
     public abstract List<T> getAllNotIndexed(int offset, int size) throws DAOException;
 
     /**
      * Saves a BaseBean object to the database.
      *
      * @param baseBean
      *            object to persist
      * @throws DAOException
      *             if the current session can't be retrieved or an exception is
      *             thrown while performing the rollback
      */
     public void save(T baseBean) throws DAOException {
         storeObject(baseBean);
     }
 
     /**
      * Saves base bean objects as indexed.
      *
      * @param baseBeans
      *            list of base beans
      * @throws DAOException
      *             if the current session can't be retrieved or an exception is
      *             thrown while performing the rollback
      */
     public void saveAsIndexed(List<T> baseBeans) throws DAOException {
         storeAsIndexed(baseBeans);
     }
 
     /**
      * Removes BaseBean object specified by the given id from the database.
      *
      * @param id
      *            of bean to delete
      * @throws DAOException
      *             if the current session can't be retrieved or an exception is
      *             thrown while performing the rollback
      */
     public abstract void remove(Integer id) throws DAOException;
 
     /**
      * Removes given BaseBean object from the database.
      *
      * @param baseBean
      *            bean to delete
      * @throws DAOException
      *             if the current session can't be retrieved or an exception is
      *             thrown while performing the rollback
      */
     public void remove(T baseBean) throws DAOException {
         if (baseBean.getId() != null) {
             try (Session session = HibernateUtil.getSession()) {
                 Transaction transaction = session.beginTransaction();
                 synchronized (lockObject) {
                     Object merged = session.merge(baseBean);
                     session.delete(merged);
                     session.flush();
                     transaction.commit();
                 }
             } catch (PersistenceException e) {
                 throw new DAOException(e);
             }
         }
     }
 
     /**
      * Refresh given bean object.
      *
      * @param baseBean
      *            bean to refresh
      */
     public void refresh(T baseBean) {
         refreshObject(baseBean);
     }
 
     /**
      * Evict given bean object.
      *
      * @param baseBean
      *            bean to evict
      */
     public void evict(T baseBean) {
         evictObject(baseBean);
     }
 
     /**
      * Retrieves BaseBean objects from database by given query.
      *
      * @param query
      *            as String
      * @param parameters
      *            for query
      * @param first
      *            result
      * @param max
      *            amount of results
      * @return list of beans objects
      */
     @SuppressWarnings("unchecked")
     public List<T> getByQuery(String query, Map<String, Object> parameters, int first, int max) {
         try (Session session = HibernateUtil.getSession()) {
             Query<T> q = session.createQuery(query);
             q.setFirstResult(first);
             q.setMaxResults(max);
             addParameters(q, parameters);
             return q.list();
         } catch (SQLGrammarException e) {
             return Collections.emptyList();
         }
     }
 
     /**
      * Retrieves BaseBean objects from database by given query.
      *
      * @param query
      *            as String
      * @param parameters
      *            for query
      * @return list of beans objects
      */
     @SuppressWarnings("unchecked")
     public List<T> getByQuery(String query, Map<String, Object> parameters) {
         try (Session session = HibernateUtil.getSession()) {
             Query<T> q = session.createQuery(query);
             addParameters(q, parameters);
             return q.list();
         }
     }
 
     /**
      * Retrieves BaseBean objects from database by given query.
      *
      * @param query
      *            as String
      * @return list of beans objects
      */
     @SuppressWarnings("unchecked")
     public List<T> getByQuery(String query) {
         try (Session session = HibernateUtil.getSession()) {
             List<T> baseBeanObjects = session.createQuery(query).list();
             if (Objects.isNull(baseBeanObjects)) {
                 baseBeanObjects = new ArrayList<>();
             }
             return baseBeanObjects;
         }
     }
 
     /**
      * Count all rows in database.
      *
      * @param query
      *            for counting objects
      * @param parameters
      *            for query
      * @return amount of rows in database according to given query
      */
     public Long count(String query, Map<String, Object> parameters) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             Query<?> q = session.createQuery(query);
             addParameters(q, parameters);
             return (Long) q.uniqueResult();
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Count all rows in database.
      *
      * @param query
      *            for counting objects
      * @return amount of rows in database according to given query
      */
     public Long count(String query) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             return (Long) session.createQuery(query).uniqueResult();
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Removes the object from the database with with specified class type and
      * {@code id}.
      *
      * @param cls
      *            the class type to remove
      * @param objectId
      *            the id of the class type
      * @throws DAOException
      *             if a HibernateException is thrown
      */
     static void removeObject(Class<?> cls, Integer objectId) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             Transaction transaction = session.beginTransaction();
             synchronized (lockObject) {
                 Object object = session.load(cls, objectId);
                 session.delete(object);
                 session.flush();
                 transaction.commit();
             }
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Initialize child list of objects for given base bean.
      *
      * @param object
      *            for update
      * @param list
      *            child list for initialize
      */
     public void initialize(T object, List<? extends BaseBean> list) {
         try (Session session = HibernateUtil.getSession()) {
             session.update(object);
             Hibernate.initialize(list);
         }
     }
 
     /**
      * Retrieves an object of the class type specified by {@code cls}, and
      * having the given {@code id}.
      *
      * @param cls
      *            the class to load
      * @param id
      *            object id
      * @return Object may be null if object with ID doesn't exist
      */
     T retrieveObject(Class<T> cls, Integer id) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             return session.get(cls, id);
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Retrieve objects by given query for maximum number of objects.
      *
      * @param query
      *            string
      * @param first
      *            result
      * @param max
      *            amount of results
      * @return constrained list of results
      */
     @SuppressWarnings("unchecked")
     List<T> retrieveObjects(String query, int first, int max) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             Query<T> sessionQuery = session.createQuery(query);
             sessionQuery.setFirstResult(first);
             sessionQuery.setMaxResults(max);
             return sessionQuery.list();
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Retrieve all objects fro given class.
      *
      * @param cls
      *            class
      * @return List of all objects
      */
     @SuppressWarnings("unchecked")
     List<T> retrieveAllObjects(Class<T> cls) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             Query<T> query = session.createQuery(String.format("FROM %s ORDER BY id ASC", cls.getSimpleName()));
             return query.list();
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Store given object.
      *
      * @param object
      *            to persist
      */
     void storeObject(T object) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             Transaction transaction = session.beginTransaction();
             session.saveOrUpdate(object);
             session.flush();
             transaction.commit();
         } catch (PersistenceException e) {
             throw new DAOException(e);
         }
     }
 
     void storeAsIndexed(List<T> baseBeans) throws DAOException {
         for (BaseBean baseBean : baseBeans) {
             BaseIndexedBean entity = (BaseIndexedBean) getById(baseBean.getId());
             entity.setIndexAction(IndexAction.DONE);
             storeObject((T) entity);
         }
     }
 
     /**
      * Store given list of objects.
      *
      * @param list
      *            of objects
      */
     void storeList(List<T> list) throws DAOException {
         try (Session session = HibernateUtil.getSession()) {
             Transaction transaction = session.beginTransaction();
             for (Object obj : list) {
                 session.saveOrUpdate(obj);
             }
             session.flush();
             transaction.commit();
         } catch (RuntimeException e) {
             throw new DAOException(e);
         }
     }
 
     /**
      * Evict object associated with the session.
      *
      * @param object
      *            associated with the session
      */
     private void evictObject(T object) {
         try (Session session = HibernateUtil.getSession()) {
             session.evict(object);
         }
     }
 
     /**
      * Refresh object associated with the session.
      *
      * @param object
      *            associated with the session
      */
     private void refreshObject(T object) {
         try (Session session = HibernateUtil.getSession()) {
             session.refresh(object);
         }
     }
 
     /**
      * Update of the object.
      *
      * @param object
      *            to update
      */
     void updateObject(T object) {
         try (Session session = HibernateUtil.getSession()) {
             session.update(object);
         }
     }
 
     private void addParameters(Query<?> query, Map<String, Object> parameters) {
         if (Objects.nonNull(parameters)) {
             for (Map.Entry<String, Object> parameter : parameters.entrySet()) {
                 if (parameter.getValue() instanceof List) {
                     query.setParameterList(parameter.getKey(), (List<?>) parameter.getValue());
                 } else {
                     query.setParameter(parameter.getKey(), parameter.getValue());
                 }
             }
         }
     }
 
     /**
      * Query part of date filter. Filter is configured by "database.subset.dates"
      * parameter in kitodo_config.properties.
      *
      * @param column
      *            The column to filter.
      * @return The query part to filter for dates.
      */
     public static String getDateFilter(String column) {
         List<String> dates = getDatesFromConfig();
         if (!dates.isEmpty()) {
             return " ( "
                     + dates.stream().map(date -> column + " LIKE '" + date + "%' ").collect(Collectors.joining(" OR "))
                     + " )";
         }
         return " 1=1 ";
     }
 
     /*
      * Parameter "database.subset.dates" filters the database to a subset. Atm, only
      * the largest data tables of tasks by processingBegin and process by creation
      * date are considered. The dates can be defined & separated in the format YYYY,
      * YYYY-MM or YYYY-MM-DD e.g. 2017-05-10,2018-06,2022
      */
     private static List<String> getDatesFromConfig() {
         final String[] databaseSubsetDates = ConfigMain.getStringArrayParameter("database.subset.dates");
         // sanitize entries of parameter
         return Arrays.stream(databaseSubsetDates)
                 .filter(Pattern.compile("\\d{4}|\\d{4}-\\d{2}|\\d{4}-\\d{2}-\\d{2}").asMatchPredicate())
                 .collect(Collectors.toList());
     }
 
 }