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

io.katharsis.jpa.JpaEntityRepository Maven / Gradle / Ivy

There is a newer version: 3.0.2
Show newest version
package io.katharsis.jpa;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;

import io.katharsis.jpa.internal.JpaRepositoryBase;
import io.katharsis.jpa.internal.JpaRepositoryUtils;
import io.katharsis.jpa.internal.meta.MetaAttribute;
import io.katharsis.jpa.internal.meta.MetaEntity;
import io.katharsis.jpa.internal.paging.DefaultPagedMetaInformation;
import io.katharsis.jpa.internal.paging.PagedMetaInformation;
import io.katharsis.jpa.query.ComputedAttributeRegistry;
import io.katharsis.jpa.query.JpaQuery;
import io.katharsis.jpa.query.JpaQueryExecutor;
import io.katharsis.jpa.query.JpaQueryFactory;
import io.katharsis.jpa.query.Tuple;
import io.katharsis.queryspec.FilterOperator;
import io.katharsis.queryspec.FilterSpec;
import io.katharsis.queryspec.QuerySpec;
import io.katharsis.queryspec.QuerySpecResourceRepository;
import io.katharsis.response.paging.PagedResultList;
import io.katharsis.utils.PropertyUtils;

/**
 * Exposes a JPA entity as ResourceRepository.
 */
public class JpaEntityRepository extends JpaRepositoryBase
		implements QuerySpecResourceRepository {

	private MetaEntity meta;

	private MetaAttribute primaryKeyAttr;

	public JpaEntityRepository(JpaModule module, Class resourceType) {
		super(module, resourceType);
		this.meta = module.getMetaLookup().getMeta(entityClass).asEntity();
		this.primaryKeyAttr = JpaRepositoryUtils.getPrimaryKeyAttr(meta);
	}

	@Override
	public final T findOne(I id, QuerySpec querySpec) {
		checkReadable();
		QuerySpec idQuerySpec = querySpec.duplicate();
		idQuerySpec.addFilter(new FilterSpec(Arrays.asList(primaryKeyAttr.getName()), FilterOperator.EQ, id));
		List results = findAll(idQuerySpec);
		return getUniqueOrNull(results);
	}

	@Override
	public final List findAll(Iterable ids, QuerySpec querySpec) {
		checkReadable();
		QuerySpec idQuerySpec = querySpec.duplicate();
		idQuerySpec.addFilter(new FilterSpec(Arrays.asList(primaryKeyAttr.getName()), FilterOperator.EQ, ids));
		return findAll(idQuerySpec);
	}

	@Override
	public List findAll(QuerySpec querySpec) {
		resetEntityManager();
		checkReadable();
		QuerySpec filteredQuerySpec = filterQuerySpec(querySpec);
		JpaQueryFactory queryFactory = module.getQueryFactory();
		JpaQuery query = queryFactory.query(entityClass);

		ComputedAttributeRegistry computedAttributesRegistry = queryFactory.getComputedAttributes();
		Set computedAttrs = computedAttributesRegistry.getForType(entityClass);

		JpaRepositoryUtils.prepareQuery(query, filteredQuerySpec, computedAttrs);
		query = filterQuery(filteredQuerySpec, query);
		JpaQueryExecutor executor = query.buildExecutor();
		JpaRepositoryUtils.prepareExecutor(executor, filteredQuerySpec, fetchRelations(null));
		executor = filterExecutor(filteredQuerySpec, executor);
		resetEntityManager();
		
		List tuples = executor.getResultTuples();
		tuples = filterTuples(filteredQuerySpec, tuples);
		List resources = map(tuples);
		resources = filterResults(filteredQuerySpec, resources);
		if (filteredQuerySpec.getLimit() != null) {
			long totalRowCount = executor.getTotalRowCount();
			return new PagedResultList<>(resources, totalRowCount);
		}
		else {
			return resources;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public  S save(S resource) {
		Object entity = mapper.unmap(resource);
		
		EntityManager em = module.getEntityManager();
		if(em.contains(entity)){
			checkUpdateable();
		}else{
			checkCreateable();
		}
		
		em.persist(entity);
		em.flush();

		// fetch again since we may have to fetch tuple data and do DTO mapping
		QuerySpec querySpec = new QuerySpec(resourceClass);
		I id = (I) PropertyUtils.getProperty(resource, primaryKeyAttr.getName());
		if (id == null) {
			throw new IllegalStateException("id not available for entity " + id);
		}
		return (S) findOne(id, querySpec);
	}

	@Override
	public void delete(I id) {
		checkDeleteable();
		EntityManager em = module.getEntityManager();

		Object object = em.find(entityClass, id);
		if (object != null) {
			em.remove(object);
		}
	}

	@Override
	public Class getResourceClass() {
		return resourceClass;
	}

	public Class getEntityClass() {
		return entityClass;
	}

	@Override
	protected PagedMetaInformation newPagedMetaInformation() {
		return new DefaultPagedMetaInformation();
	}
}