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

io.crnk.jpa.JpaRepositoryConfig Maven / Gradle / Ivy

There is a newer version: 2.6.20180522184741
Show newest version
package io.crnk.jpa;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import io.crnk.core.engine.internal.utils.ClassUtils;
import io.crnk.core.queryspec.QuerySpec;
import io.crnk.core.repository.ResourceRepositoryV2;
import io.crnk.core.repository.decorate.RelationshipRepositoryDecorator;
import io.crnk.core.repository.decorate.ResourceRepositoryDecorator;
import io.crnk.core.resource.links.DefaultPagedLinksInformation;
import io.crnk.core.resource.links.LinksInformation;
import io.crnk.core.resource.list.DefaultResourceList;
import io.crnk.core.resource.list.ResourceListBase;
import io.crnk.core.resource.meta.DefaultPagedMetaInformation;
import io.crnk.core.resource.meta.MetaInformation;
import io.crnk.jpa.mapping.IdentityMapper;
import io.crnk.jpa.mapping.JpaMapper;
import net.jodah.typetools.TypeResolver;

/**
 * @param  document type (entity or mapped dto)
 */
public class JpaRepositoryConfig {

	private Class entityClass;

	private Class resourceClass;

	private JpaMapper mapper;

	private Class> listClass;

	private Class listMetaClass;

	private Class listLinksClass;

	private ResourceRepositoryDecorator resourceRepositoryDecorator;

	private Map, RelationshipRepositoryDecorator> relationshipRepositoriesDecorators;

	private JpaRepositoryConfig() {
	}

	/**
	 * Shortcut for builder(entityClass).build().
	 *
	 * @param entityClass to directly expose
	 * @return config
	 */
	public static  JpaRepositoryConfig create(Class entityClass) {
		return builder(entityClass).build();
	}

	/**
	 * Prepares a builder to configure a jpa document for the given entity.
	 *
	 * @param          entity type
	 * @param entityClass to directly expose
	 * @return builder
	 */
	public static  JpaRepositoryConfig.Builder builder(Class entityClass) {
		JpaRepositoryConfig.Builder builder = new JpaRepositoryConfig.Builder<>();
		builder.entityClass = entityClass;
		builder.resourceClass = entityClass;
		return builder;
	}

	/**
	 * Prepares a builder to configure a jpa document for the given entity class which is
	 * mapped to a DTO with the provided mapper.
	 *
	 * @param          entity type
	 * @param          dto type
	 * @param entityClass to use
	 * @param dtoClass    to expose
	 * @param mapper      to convert entity to dto and back
	 * @return builder
	 */
	public static  JpaRepositoryConfig.Builder builder(Class entityClass, Class dtoClass, JpaMapper mapper) {
		JpaRepositoryConfig.Builder builder = new JpaRepositoryConfig.Builder<>();
		builder.entityClass = entityClass;
		builder.resourceClass = dtoClass;
		builder.mapper = mapper;
		return builder;
	}

	public Class getEntityClass() {
		return entityClass;
	}

	public Class getResourceClass() {
		return resourceClass;
	}

	public Class getListMetaClass() {
		return listMetaClass;
	}

	public Class getListLinksClass() {
		return listLinksClass;
	}

	@SuppressWarnings("unchecked")
	public  JpaMapper getMapper() {
		return (JpaMapper) mapper;
	}

	@SuppressWarnings("unchecked")
	public  Class> getListClass() {
		return (Class>) listClass;
	}

	public DefaultResourceList newResultList() {
		DefaultResourceList list = ClassUtils.newInstance(listClass);
		list.setMeta(newMetaInformation());
		list.setLinks(newLinksInformation());
		return list;
	}

	private MetaInformation newMetaInformation() {
		if (listMetaClass != null) {
			return ClassUtils.newInstance(listMetaClass);
		} else {
			return null;
		}
	}

	private LinksInformation newLinksInformation() {
		if (listLinksClass != null) {
			return ClassUtils.newInstance(listLinksClass);
		} else {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public  ResourceRepositoryDecorator getRepositoryDecorator() {
		return (ResourceRepositoryDecorator) resourceRepositoryDecorator;
	}

	@SuppressWarnings("unchecked")
	public  RelationshipRepositoryDecorator getRepositoryDecorator(
			Class targetResourceType) {
		return (RelationshipRepositoryDecorator) relationshipRepositoriesDecorators.get(targetResourceType);
	}

	protected void setListMetaClass(Class listMetaClass) {
		this.listMetaClass = listMetaClass;
	}

	public static class Builder {

		private Class entityClass;

		private Class resourceClass;

		private JpaMapper mapper = IdentityMapper.newInstance();

		@SuppressWarnings({"rawtypes", "unchecked"})
		private Class> listClass = (Class) DefaultResourceList.class;

		private Class listMetaClass = DefaultPagedMetaInformation.class;

		private Class listLinksClass = DefaultPagedLinksInformation.class;

		private ResourceRepositoryDecorator resourceRepositoryDecorator;

		private Map, RelationshipRepositoryDecorator> relationshipRepositoryDecorators = new HashMap<>();

		public JpaRepositoryConfig build() {
			JpaRepositoryConfig config = new JpaRepositoryConfig<>();
			config.entityClass = entityClass;
			config.resourceClass = resourceClass;
			config.mapper = mapper;
			config.listClass = listClass;
			config.listMetaClass = listMetaClass;
			config.listLinksClass = listLinksClass;
			config.resourceRepositoryDecorator = resourceRepositoryDecorator;
			config.relationshipRepositoriesDecorators = relationshipRepositoryDecorators;
			return config;
		}

		/**
		 * Extracts information about listClass, listMetaClass, listLinkClass from the provided document
		 * interface.
		 *
		 * @param interfaceClass of the document
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public Builder setInterfaceClass(Class> interfaceClass) {

			try {
				Method findMethod = interfaceClass.getDeclaredMethod("findAll", QuerySpec.class);
				Class returnType = findMethod.getReturnType();
				if (!ResourceListBase.class.isAssignableFrom(returnType)) {
					throw new IllegalStateException("findAll return type must extend " + ResourceListBase.class.getName());
				}
				setListClass((Class>) returnType);

				Class[] typeArgs = TypeResolver.resolveRawArguments(ResourceListBase.class, returnType);
				setListMetaClass((Class) typeArgs[1]);
				setListLinksClass((Class) typeArgs[2]);
				return this;
			} catch (NoSuchMethodException e) {
				throw new IllegalStateException("findAll method not overriden by " + interfaceClass.getName(), e);
			}
		}

		/**
		 * @param listClass to be used to return list of resources
		 * @return this builder
		 */
		public Builder setListClass(Class> listClass) {
			this.listClass = listClass;
			return this;
		}

		/**
		 * @param listMetaClass holding the meta information
		 * @return this builder
		 */
		public Builder setListMetaClass(Class listMetaClass) {
			this.listMetaClass = listMetaClass;
			return this;
		}

		/**
		 * @param listLinksClass holding the links information
		 * @return this builder
		 */
		public Builder setListLinksClass(Class listLinksClass) {
			this.listLinksClass = listLinksClass;
			return this;
		}

		/**
		 * Sets a decorator that allows to intercept all requests to the actual document.
		 *
		 * @param decoratorResourceRepository that decorates the jpa document.
		 * @return this builder
		 */
		public Builder setRepositoryDecorator(ResourceRepositoryDecorator decoratorResourceRepository) {
			this.resourceRepositoryDecorator = decoratorResourceRepository;
			return this;
		}

		/**
		 * Sets a decorator that allows to intercept all requests to the actual document.
		 *
		 * @param targetClass
		 * @param decoratorRelationshipRepository
		 * @return this builder
		 */
		public  Builder putRepositoryDecorator(Class targetClass,
													 RelationshipRepositoryDecorator decoratorRelationshipRepository) {
			this.relationshipRepositoryDecorators.put(targetClass, decoratorRelationshipRepository);
			return this;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy