Package org.pau.assetmanager.business

Source Code of org.pau.assetmanager.business.DaoFunction

/**
* This file is part of Pau's Asset Manager Project.
*
* Pau's Asset Manager Project is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pau's Asset Manager Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Pau's Asset Manager Project.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.pau.assetmanager.business;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.pau.assetmanager.entities.EntityInterface;
import org.pau.assetmanager.utils.AssetManagerRuntimeException;
import org.pau.assetmanager.utils.PropertiesEntityManagerFactory;

import com.google.common.base.Function;
import com.google.common.base.Optional;

/**
* This class adds DAO capabilities in a functional way by using Guava
* easing the transaction management and the resource finalization
*
* @author Pau Carré Cardona
*
*/
public abstract class DaoFunction<F, T> implements Function<F, T> {
 
  private static final Logger logger = LogManager.getLogger(DaoFunction.class);
 
  /*
   * This method is the apply method of the Function interface implemented for this class
   * The method guarantees not only that the code in 'doInTransaction' is actually transactional
   * but also that the resources are properly closed once the code in 'doInTransaction' finishes
   *
   * It is important to note that if the entity manager is managed inside of the 'doInTransaction' method
   * the rules above are no longer guaranteed (i.e. do *not* begin nor commit transactions in 'doInTransaction')
   */
  @Override
  public T apply(F argument) {
    EntityManager entityManager = null;
    try {
      entityManager = PropertiesEntityManagerFactory.getEntityManager();
      entityManager.getTransaction().begin();
      T result = doInTransaction(entityManager, argument);
      entityManager.getTransaction().commit();
      return result;
    } finally {
      if (entityManager != null && entityManager.isOpen()) {
        if (entityManager.getTransaction().isActive()) {
          try {
            entityManager.getTransaction().rollback();
          } finally {
            entityManager.close();
          }
        } else {
          entityManager.close();
        }
      }
    }
  }

  /**
   * This method is executed in the one that is actually executed and should contain the
   * database login assuming that it is already in a transaction and without changing the
   * general state of the entity manager (i.e. close or open) not its transaction (i.e. commit or roll back)
   *
   * @param argument argument of the function
   * @param entityManager entity manager already in transaction
   *
   * @return the result of the function
   */
  protected abstract T doInTransaction(EntityManager entityManager, F argument);

  /**
   * This method is used to delete a JPA pojo from the database
   *
   * @return the void function to remove the pojo
   */
  public static <F extends EntityInterface> DaoFunction<F, Void> deleteDetachedFunction() {
    return new DaoFunction<F, Void>() {
      @Override
      protected Void doInTransaction(
          EntityManager entityManager, F argument) {
        EntityInterface result = entityManager.find(
            argument.getClass(), argument.getId());
        entityManager.remove(result);
        return null;
      }
    };
  }

  /**
   * This method is used to persist a pojo in the database
   *
   * @return the void function to persist the pojo
   *
   */
  public static DaoFunction<Object, Void> persistFunction() {
    return new DaoFunction<Object, Void>() {
      @Override
      protected Void doInTransaction(EntityManager entityManager, Object argument) {
        entityManager.persist(argument);
        return null;
      }
    };
  }
 

  /**
   * This method is used to execute a native (SQL) update given an update query
   *
   * @return the void function to make a native update
   */
  public static DaoFunction<String, Void> nativeUpdateFunction() {
    return new DaoFunction<String, Void>() {
      @Override
      protected Void doInTransaction(EntityManager entityManager, String nativeQuery
          ) {
        Query query = entityManager.createNativeQuery(nativeQuery);
        query.executeUpdate();
        return null;
      }
    };
  }

  /**
   * This method is used to merge a pojo in the database
   *
   * @return the function 'Pojo to persist' -> 'Persisted Pojo' to merge a pojo in database
   */
  public static <T> DaoFunction<T, T> mergeFunction() {
    return new DaoFunction<T, T>() {
      @Override
      protected T doInTransaction(EntityManager entityManager,T argument
           ) {
        argument = entityManager.merge(argument);
        return argument;
      }
    };
  }

  /**
   * This function is used to execute a JPA query that returns a list of Pojos
   *
   * @param argument 'Object[]{parameter_label_1, parameter_value_1, ... ,parameter_label_N, parameter_value_N}'
   *
   * @return A function of the form:
   *  query to be executed to retrieve the list -> 'List of pojos'
   */
  public static <T> DaoFunction<String, List<T>> querySimpleListFunction(final Object... argument) {
    return new DaoFunction<String, List<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected List<T> doInTransaction(EntityManager entityManager, String queryString
           ) {
        Query query = entityManager.createQuery(queryString);
        if (argument.length % 2 != 0) {
          String message = "The arguments for the query should be a list of <String, Object> pairs";
          logger.error(message);
          throw new AssetManagerRuntimeException(message);
        }
        for (int index = 0; index < argument.length; index = index + 2) {
          String label = (String) argument[index];
          Object value = argument[index + 1];
          query.setParameter(label, value);
        }
        return query.getResultList();
      }

    };
  }

  /**
   * This function is used to execute a JPA query that returns a list of Pojos
   *
   * @param queryString query to be executed to retrieve the list
   *
   * @return A function of the form:
   * 'Map< parameter_label, parameter_value >' -> 'List of pojos'
   */
  public static <T> DaoFunction<Map<String, Serializable>, List<T>> queryListFunction(
      final String queryString) {
    return new DaoFunction<Map<String, Serializable>, List<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected List<T> doInTransaction(EntityManager entityManager,
          Map<String, Serializable> argument
           ) {
        Query query = entityManager.createQuery(queryString);
        for (Entry<String, Serializable> entry : argument.entrySet()) {
          query.setParameter(entry.getKey(), entry.getValue());
        }
        return query.getResultList();
      }

    };
  }

  /**
   * This function is used to execute a JPA query that returns a single Pojo
   *
   * @param argument 'Object[]{parameter_label_1, parameter_value_1, ... ,parameter_label_N, parameter_value_N}'
   *
   * @return A function of the form:
   *  query to be executed to retrieve the pojo  -> 'Optional pojo'
   */
  public static <T> DaoFunction<String, Optional<T>> querySimpleUniqueFunction(
      final Object... argument) {
    return new DaoFunction<String, Optional<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected Optional<T> doInTransaction(EntityManager entityManager, String queryString
           ) {
        Query query = entityManager.createQuery(queryString);
        if (argument.length % 2 != 0) {
          String message = "The arguments for the query should be a list of <String, Object> pairs";
          throw new AssetManagerRuntimeException(message);
        }
        for (int index = 0; index < argument.length; index = index + 2) {
          String label = (String) argument[index];
          Object value = argument[index + 1];
          query.setParameter(label, value);
        }
        try {
          T result = (T) query.getSingleResult();
          return Optional.of(result);
        } catch (NoResultException e) {
          logger.info("No result found searching a unique element", e);
          return Optional.absent();
        } catch(NonUniqueResultException nonUniqueResultException){
          logger.error("Non unique result found searching a unique element", nonUniqueResultException);
          throw new AssetManagerRuntimeException("Returned more that one element in the query", nonUniqueResultException);
        }
      }

    };
  }

  /**
   * This function is used to execute a JPA query that returns a single Pojo
   *
   * @param queryString query to be executed to retrieve the pojo
   *
   * @return A function of the form:
   * 'Map< parameter_label, parameter_value >' -> 'Optional pojo'
   */
  public static <T> DaoFunction<Map<String, Serializable>, Optional<T>> queryUniqueFunction(
      final String queryString) {
    return new DaoFunction<Map<String, Serializable>, Optional<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected Optional<T> doInTransaction(
          EntityManager entityManager, Map<String, Serializable> argument
           ) {
        Query query = entityManager.createQuery(queryString);
        for (Entry<String, Serializable> entry : argument.entrySet()) {
          query.setParameter(entry.getKey(), entry.getValue());
        }
        try {
          T result = (T) query.getSingleResult();
          return Optional.of(result);
        } catch (NoResultException e) {
          logger.info("No result from unique query", e);
          return Optional.absent();
        }
      }

    };
  }


  /**
   * This function is used to make native queries (SQL) that return a list of objects.
   *
   * @param queryString  query to be executed
   *
   * @return the function of the form:
   *  ' Map<'parameter_label','parameter_value'> ->  'List of pojos'
   */
  public static <T> DaoFunction<Map<String, Serializable>, List<T>> nativeQueryListFunction(
      final String queryString) {
    return new DaoFunction<Map<String, Serializable>, List<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected List<T> doInTransaction(
          EntityManager entityManager,Map<String, Serializable> argument
           ) {
        Query query = entityManager.createNativeQuery(queryString);
        for (Entry<String, Serializable> entry : argument.entrySet()) {
          query.setParameter(entry.getKey(), entry.getValue());
        }
        return query.getResultList();
      }

    };
  }

 
  /**
   * This function is used to make native queries (SQL) that return a list of objects.
   *
   * @param arguments 'Object[]{parameter_label_1, parameter_value_1, ... ,parameter_label_N, parameter_value_N}'
   *
   * @return the function of the form:
   *   'query to be executed' ->  'List of pojos'
   */
  public static <T> DaoFunction<String, List<T>> nativeQuerySimpleListFunction(
      final Object... arguments) {
    return new DaoFunction<String, List<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected List<T> doInTransaction(
          EntityManager entityManager,String queryString
           ) {
        Query query = entityManager.createNativeQuery(queryString);
        if (arguments.length % 2 != 0) {
          String message = "The arguments for the query should be a list of <String, Object> pairs";
          throw new AssetManagerRuntimeException(message);
        }
        for (int index = 0; index < arguments.length; index = index + 2) {
          String label = (String) arguments[index];
          Object value = arguments[index + 1];
          query.setParameter(label, value);
        }
        return query.getResultList();
      }

    };
  }
 
 
  /**
   * This function is used to make native queries (SQL) that return an optional object.
   *
   * @param arguments 'Object[]{parameter_label_1, parameter_value_1, ... ,parameter_label_N, parameter_value_N}'
   *
   * @return the function of the form:
   *   'query to be executed' ->  'Optional pojo'
   */
  public static <T> DaoFunction<String, Optional<T>> nativeQuerySimpleUniqueFunction(
      final Object... arguments) {
    return new DaoFunction<String, Optional<T>>() {
      @SuppressWarnings("unchecked")
      @Override
      protected Optional<T> doInTransaction(
          EntityManager entityManager,String queryString
           ) {
        Query query = entityManager.createNativeQuery(queryString);
        if (arguments.length % 2 != 0) {
          String message = "The arguments for the query should be a list of <String, Object> pairs";
          throw new AssetManagerRuntimeException(message);
        }
        for (int index = 0; index < arguments.length; index = index + 2) {
          String label = (String) arguments[index];
          Object value = arguments[index + 1];
          query.setParameter(label, value);
        }
        try {
          T result = (T) query.getSingleResult();
          return Optional.of(result);
        } catch (NoResultException e) {
          logger.info("No result from unique query", e);
          return Optional.absent();
        }
      }

    };
  }
}
TOP

Related Classes of org.pau.assetmanager.business.DaoFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.