/*
* Copyright (C) 2014 GG-Net GmbH - Oliver Günther
*
* This program 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.
*
* 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 General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.ggnet.dwoss.util.persistence;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
/**
* An Abstract RemoteAgent is used for general implementation of findAll and findById Methods for a full persistence unit.
* <p/>
* @author oliver.guenther
*/
public abstract class AbstractAgentBean implements RemoteAgent {
/**
* Must return the EntityManager of the persistence unit.
* <p/>
* @return the EntityManger
*/
protected abstract EntityManager getEntityManager();
/**
* Returns the entity identified by Id or null if non found.
* <p/>
* @param <T> type of the entity
* @param entityClass the entityClass
* @param id the id
* @return the entity identified by Id or null if non found.
*/
@Override
public <T> T findById(Class<T> entityClass, Object id) {
validate(entityClass);
if ( id == null ) return null;
return getEntityManager().find(entityClass, id);
}
/**
* Returns the entity identified by Id or null if non found.
* This is the eager implementation. If the Entity implements {@link EagerAble}, the method fetchEager is called in the transaction.
* <p/>
* @param <T> type of the entity
* @param entityClass the entityClass
* @param id the id
* @return the entity identified by Id or null if non found.
*/
@Override
public <T> T findByIdEager(Class<T> entityClass, Object id) {
return optionalFetchEager(findById(entityClass, id));
}
/**
* Returns the entity identified by Id and locks it by lockMode or null if non found.
* <p/>
* @param <T> type of the entity
* @param entityClass the entityClass
* @param id the id
* @param lockModeType the lockMode to use
* @return the entity identified by Id or null if non found.
*/
@Override
public <T> T findById(Class<T> entityClass, Object id, LockModeType lockModeType) {
validate(entityClass);
if ( id == null ) return null;
return getEntityManager().find(entityClass, id, lockModeType);
}
/**
* Returns the entity identified by Id and locks it by lockMode or null if non found.
* This is the eager implementation. If the Entity implements {@link EagerAble}, the method fetchEager is called in the transaction.
* <p/>
* @param <T> type of the entity
* @param entityClass the entityClass
* @param id the id
* @param lockModeType the lockMode to use
* @return the entity identified by Id or null if non found.
*/
@Override
public <T> T findByIdEager(Class<T> entityClass, Object id, LockModeType lockModeType) {
return optionalFetchEager(findById(entityClass, id, lockModeType));
}
/**
* Returns all entities of the entityClass or an empty list.
* <p/>
* @param <T> the type of the entities
* @param entityClass the entityClass
* @return all entities of the entityClass or an empty list.
*/
@Override
public <T> List<T> findAll(Class<T> entityClass) {
validate(entityClass);
javax.persistence.criteria.CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass);
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
/**
* Returns all entities of the entityClass or an empty list.
* This is the eager implementation. If the Entity implements {@link EagerAble}, the method fetchEager is called in the transaction.
* <p/>
* @param <T> the type of the entities
* @param entityClass the entityClass
* @return all entities of the entityClass or an empty list.
*/
@Override
public <T> List<T> findAllEager(Class<T> entityClass) {
return optionalFetchEager(findAll(entityClass));
}
/**
* Returns all entities of the entityClass in the supplied interval or an empty list.
* <p/>
* @param <T> the type of the entities
* @param entityClass the entityClass
* @param start the start of the full result to begin the list with.
* @param amount the amount of elemets to return at max.
* @return all entities of the entityClass or an empty list.
*/
@Override
public <T> List<T> findAll(Class<T> entityClass, int start, int amount) {
validate(entityClass);
javax.persistence.criteria.CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass);
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).setFirstResult(start).setMaxResults(amount).getResultList();
}
/**
* Returns all entities of the entityClass in the supplied interval or an empty list.
* This is the eager implementation. If the Entity implements {@link EagerAble}, the method fetchEager is called in the transaction.
* <p/>
* @param <T> the type of the entities
* @param entityClass the entityClass
* @param start the start of the full result to begin the list with.
* @param amount the amount of elemets to return at max.
* @return all entities of the entityClass or an empty list.
*/
@Override
public <T> List<T> findAllEager(Class<T> entityClass, int start, int amount) {
return optionalFetchEager(findAll(entityClass, start, amount));
}
@Override
public <T> long count(Class<T> entityClass) {
validate(entityClass);
javax.persistence.criteria.CriteriaQuery<Long> cq = getEntityManager().getCriteriaBuilder().createQuery(Long.class);
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.TypedQuery<Long> q = getEntityManager().createQuery(cq);
return q.getSingleResult();
}
private void validate(Class<?> clazz) {
Objects.requireNonNull(clazz, "Supplied entityClass is null");
Objects.requireNonNull(getEntityManager(), "Supplied EntityManager is null");
}
protected final <T> T optionalFetchEager(T entity) {
if ( entity == null ) return null;
if ( entity instanceof EagerAble ) ((EagerAble)entity).fetchEager();
return entity;
}
protected final <T> List<T> optionalFetchEager(List<T> entities) {
if ( entities == null ) return null;
if ( entities.isEmpty() ) return entities;
if ( !(entities.get(0) instanceof EagerAble) ) return entities;
for (T entity : entities) {
((EagerAble)entity).fetchEager();
}
return entities;
}
protected final <T> Set<T> optionalFetchEager(Set<T> entities) {
if ( entities == null ) return null;
if ( entities.isEmpty() ) return entities;
if ( !(entities.iterator().next() instanceof EagerAble) ) return entities;
for (T entity : entities) {
((EagerAble)entity).fetchEager();
}
return entities;
}
}