All Downloads are FREE. Search and download functionalities are using the official Maven repository.

br.gov.frameworkdemoiselle.template.JPACrud Maven / Gradle / Ivy

/*
 * Demoiselle Framework
 * Copyright (C) 2010 SERPRO
 * ----------------------------------------------------------------------------
 * This file is part of Demoiselle Framework.
 * 
 * Demoiselle Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.
 * 
 * This program 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 Lesser General Public License version 3
 * along with this program; if not,  see 
 * or write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA  02110-1301, USA.
 * ----------------------------------------------------------------------------
 * Este arquivo é parte do Framework Demoiselle.
 * 
 * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou
 * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação
 * do Software Livre (FSF).
 * 
 * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA
 * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou
 * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português
 * para maiores detalhes.
 * 
 * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título
 * "LICENCA.txt", junto com esse programa. Se não, acesse 
 * ou escreva para a Fundação do Software Livre (FSF) Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
 */
package br.gov.frameworkdemoiselle.template;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.Enumerated;
import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import br.gov.frameworkdemoiselle.DemoiselleException;
import br.gov.frameworkdemoiselle.annotation.Name;
import br.gov.frameworkdemoiselle.configuration.Configuration;
import br.gov.frameworkdemoiselle.pagination.Pagination;
import br.gov.frameworkdemoiselle.pagination.PaginationContext;
import br.gov.frameworkdemoiselle.transaction.Transactional;
import br.gov.frameworkdemoiselle.util.Beans;
import br.gov.frameworkdemoiselle.util.Reflections;
import br.gov.frameworkdemoiselle.util.ResourceBundle;

/**
 * JPA specific implementation for Crud interface.
 * 
 * @param 
 *            bean object type
 * @param 
 *            bean id type
 * @author SERPRO
 * @see Crud
 */
public class JPACrud implements Crud {

	private static final long serialVersionUID = 1L;

	private EntityManager entityManager;

	private Pagination pagination;

	@Inject
	@Name("demoiselle-jpa-bundle")
	private Instance bundle;

	private Class beanClass;

	protected Class getBeanClass() {
		if (this.beanClass == null) {
			this.beanClass = Reflections.getGenericTypeArgument(this.getClass(), 0);
		}

		return this.beanClass;
	}

	protected CriteriaBuilder getCriteriaBuilder() {
		return getEntityManager().getCriteriaBuilder();
	}

	protected EntityManager getEntityManager() {
		if (this.entityManager == null) {
			this.entityManager = Beans.getReference(EntityManager.class);
		}

		return this.entityManager;
	}

	protected Pagination getPagination() {
		if (pagination == null) {
			try {
				PaginationContext context = Beans.getReference(PaginationContext.class);
				pagination = context.getPagination(getBeanClass());

			} catch (ContextNotActiveException cause) {
				pagination = null;
			}
		}

		return pagination;
	}

	protected CriteriaQuery createCriteriaQuery() {
		return getCriteriaBuilder().createQuery(getBeanClass());
	}

	protected Query createQuery(final String ql) {
		return getEntityManager().createQuery(ql);
	}

	protected void handleException(Throwable cause) throws Throwable {
		if (cause instanceof TransactionRequiredException) {
			String message = bundle.get().getString("no-transaction-active", "frameworkdemoiselle.transaction.class",
					Configuration.DEFAULT_RESOURCE);

			throw new DemoiselleException(message, cause);

		} else {
			throw cause;
		}
	}

	/**
	 * Insert a new instance of the entity in the database. After insertion the entity becomes "managed"
	 * as stated by the JPA specification.
	 * 
	 * @param entity A non-detached instance of an entity. If this instance is not managed, it will be after this method returns.
	 * @return The same instance passed as argument.
	 * @throws EntityExistsException if entity is an unmanaged instance
	 * and the persistence provider already has a persisted instance that matches the entity's primary key.
	 * @throws IllegalArgumentException if the instance is not an entity
	 * @see EntityManager#persist(Object entity)
	 */
	@Override
	@Transactional
	public T insert(final T entity) {
		getEntityManager().persist(entity);
		return entity;
	}

	/**
	 * Finds an instance of this entity by it's primary ID and asks to the
	 * persistence provider to remove this entity instance from the persistence
	 * context.
	 * 
     * @see EntityManager#remove(Object entity)
	 */
	@Override
	@Transactional
	public void delete(final I id) {
		T entity = getEntityManager().getReference(getBeanClass(), id);
		getEntityManager().remove(entity);
	}
	
	/**
	 * Merge all changes made to the passed entity to a managed entity. The passed instance is not
	 * modified nor becomes managed, instead the managed entity is returned by this method. 
	 */
	@Override
	@Transactional
	public T update(T entity) {
		return getEntityManager().merge(entity);
	}
	
	@Override
	public T load(final I id) {
		return getEntityManager().find(getBeanClass(), id);
	}

	@Override
	public List findAll() {
		Entity entityAnnotation = getBeanClass().getAnnotation(Entity.class);
		String entityName = null;
		if (entityAnnotation!=null 
				&& entityAnnotation.name()!=null
				&& !entityAnnotation.name().trim().equals("")) {
			entityName = entityAnnotation.name();
		}
		else {
			entityName = getBeanClass().getSimpleName();
		}
		return findByJPQL("select this from " + entityName + " this");
	}

	/**
	 * Search JPQL integrated into the context of paging
	 * 
	 * @param jpql
	 *            - query in syntax JPQL
	 * @return a list of entities
	 */
	protected List findByJPQL(String jpql) {
		TypedQuery listQuery = getEntityManager().createQuery(jpql, getBeanClass());
		
		if (getPagination() != null) {
			String countQuery = createCountQuery(jpql);
			Query query = getEntityManager().createQuery(countQuery);
			Number cResults = (Number) query.getSingleResult();
			getPagination().setTotalResults(cResults.intValue());
			listQuery.setFirstResult(getPagination().getFirstResult());
			listQuery.setMaxResults(getPagination().getPageSize());
		}

		return listQuery.getResultList();
	}

	/**
	 * Search CriteriaQuery integrated into the context of paging
	 * 
	 * @param criteriaQuery
	 *            - structure CriteriaQuery
	 * @return a list of entities
	 */
	protected List findByCriteriaQuery(CriteriaQuery criteriaQuery) {
		TypedQuery listQuery = getEntityManager().createQuery(criteriaQuery);

		if (getPagination() != null) {
			CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
			CriteriaQuery countQuery = builder.createQuery(Long.class);
			countQuery.select(builder.count(countQuery.from(getBeanClass())));
			countQuery.where(criteriaQuery.getRestriction());
			getEntityManager().createQuery(countQuery);
			getPagination().setTotalResults((int) (getEntityManager().createQuery(countQuery).getSingleResult() + 0));
			listQuery.setFirstResult(getPagination().getFirstResult());
			listQuery.setMaxResults(getPagination().getPageSize());
		}

		return listQuery.getResultList();
	}

	/**
	 * Converts a query into a count query
	 * 
	 * @param query
	 * @return
	 */
	private String createCountQuery(String query) {
		String result = query;
		Matcher matcher = Pattern.compile("[Ss][Ee][Ll][Ee][Cc][Tt](.+)[Ff][Rr][Oo][Mm]").matcher(result);

		if (matcher.find()) {
			String group = matcher.group(1).trim();
			result = result.replaceFirst(group, "COUNT(" + group + ")");
			matcher = Pattern.compile("[Oo][Rr][Dd][Ee][Rr](.+)").matcher(result);

			if (matcher.find()) {
				group = matcher.group(0);
				result = result.replaceFirst(group, "");
			}

		} else {
			throw new DemoiselleException(bundle.get().getString("malformed-jpql"));
		}

		return result;
	}

	/**
	 * Retrieves a list of entities based on a single example instance of it.
	 * 

* See below a sample of its usage: * *

	 * Employee example = new Employee();
	 * example.setId(12345);
	 * return (List<Employee>) findByExample(example);
	 * 
* * @param example * an entity example * @return a list of entities */ protected List findByExample(final T example) { final CriteriaQuery criteria = createCriteriaByExample(example); return getEntityManager().createQuery(criteria).getResultList(); } /** * Support method which will be used for construction of criteria-based queries. * * @param example * an example of the given entity * @return an instance of {@code CriteriaQuery} */ private CriteriaQuery createCriteriaByExample(final T example) { final CriteriaBuilder builder = getCriteriaBuilder(); final CriteriaQuery query = builder.createQuery(getBeanClass()); final Root entity = query.from(getBeanClass()); final List predicates = new ArrayList(); final Field[] fields = example.getClass().getDeclaredFields(); for (Field field : fields) { if (!field.isAnnotationPresent(Column.class) && !field.isAnnotationPresent(Basic.class) && !field.isAnnotationPresent(Enumerated.class)) { continue; } Object value = null; try { field.setAccessible(true); value = field.get(example); } catch (IllegalArgumentException e) { continue; } catch (IllegalAccessException e) { continue; } if (value == null) { continue; } final Predicate pred = builder.equal(entity.get(field.getName()), value); predicates.add(pred); } return query.where(predicates.toArray(new Predicate[0])).select(entity); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy