Package $

Source Code of $.BaseService

#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.services.base;

import java.beans.Introspector;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import ${package}.customrepository.GenericRepository;
import ${package}.domain.base.BaseEntity;
import ${package}.domain.base.IEntity;
import ${package}.jsf.datatable.PaginationConfiguration;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;

import com.mysema.query.types.Predicate;
import com.mysema.query.types.expr.BooleanExpression;
import com.mysema.query.types.path.BooleanPath;
import com.mysema.query.types.path.DatePath;
import com.mysema.query.types.path.EnumPath;
import com.mysema.query.types.path.ListPath;
import com.mysema.query.types.path.NumberPath;
import com.mysema.query.types.path.PathBuilder;
import com.mysema.query.types.path.StringPath;

/**
* Base service that other persistence services can extend. It provides all
* common crud operations. Also provide default search capabilities which work
* nicely with composite jsf search components.
*
* @author Ignas
*
* @param <T>
*            Type of entity.
*
*/
@Transactional(readOnly = true)
public abstract class BaseService<T extends IEntity> implements IService<T>, Serializable {

    /**
     * Class version id for serialization. After a change to serialized field
     * this number should be changed so it would be clear its different class
     * version.
     */
    private static final long serialVersionUID = 1L;

    // CHECKSTYLE:OFF
    /** Entity class of service. */
    protected final Class<? extends IEntity> entityClass;

    /** JPA entity manager. */
    @PersistenceContext
    protected EntityManager em;

    // CHECKSTYLE:ON

    /**
     * Default constructor. Loads entity class from super service information.
     * It is used
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public BaseService() {
        Class clazz = getClass();
        while (!(clazz.getGenericSuperclass() instanceof ParameterizedType)) {
            clazz = clazz.getSuperclass();
        }
        Object o = ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];

        if (o instanceof TypeVariable) {
            this.entityClass = (Class<T>) ((TypeVariable) o).getBounds()[0];
        } else {
            this.entityClass = (Class<T>) o;
        }
    }

    /**
     * Repository object provided by spring data which makes querying and
     * operating on entities much easier.
     */
    protected abstract JpaRepository<T, Long> getRepository();

    /**
     * @see ${package}.services.base.IService${symbol_pound}add(${package}.domain.base.IEntity)
     */
    @Override
    @Transactional(readOnly = false)
    public void add(T entity) {
        getRepository().save(entity);
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}update(${package}.domain.base.IEntity)
     */
    @Override
    @Transactional(readOnly = false)
    public void update(T entity) {
        getRepository().save(entity);
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}delete(${package}.domain.base.IEntity)
     */
    @Override
    @Transactional(readOnly = false)
    public void delete(T entity) {
        getRepository().delete(entity);
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}delete(java.lang.Long)
     */
    @Override
    @Transactional(readOnly = false)
    public void delete(Long id) {
        getRepository().delete(id);
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}deleteMany(java.lang.Iterable)
     */
    @Override
    @Transactional(readOnly = false)
    public void deleteMany(Iterable<Long> ids) {
        for (Long id : ids) {
            getRepository().delete(id);
        }
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}findById(java.lang.Long)
     */
    @Override
    public T findById(Long id) {
        return getRepository().findOne(id);
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}findById(java.lang.Long,
     *      java.util.List)
     */
    @Override
    public T findById(Long id, List<String> fetchFields) {
        return ((GenericRepository<T, Long>) getRepository()).findOne(id, fetchFields);
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}list()
     */
    @Override
    public List<T> list() {
        return getRepository().findAll();
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}count()
     */
    @Override
    public long count() {
        return getRepository().count();
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}list(${package}.jsf.datatable.PaginationConfiguration)
     */
    @Override
    public List<T> list(final PaginationConfiguration config) {
        Predicate predicate = getPredicate(config);
        Pageable pageable = new PageRequest(config.getFirstRow() / config.getNumberOfRows(), config.getNumberOfRows(),
                config.getSortField() != null ? new Sort(new Sort.Order(config.getSortDirection(), config.getSortField())) : null);
        return ((GenericRepository<T, Long>) getRepository()).findAll(predicate, pageable, config.getFetchFields()).getContent();
    }

    /**
     * @see ${package}.services.base.IService${symbol_pound}count(${package}.jsf.datatable.PaginationConfiguration)
     */
    @Override
    public long count(PaginationConfiguration config) {
        Predicate predicate = getPredicate(config);
        return ((GenericRepository<T, Long>) getRepository()).count(predicate);
    }

    /**
     * Creates a Predicate from list of BooleanExpression predicates which
     * represents all search filters.
     *
     * @param config
     *            PaginationConfiguration data holding object
     * @return query to filter entities according pagination configuration data.
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected Predicate getPredicate(PaginationConfiguration config) {

        PathBuilder<T> entityPath = new PathBuilder(entityClass, getAliasName(entityClass));
        BooleanExpression predicate = null;

        Map<String, Object> filters = config.getFilters();
        if (filters != null) {
          // first we process nonstandard filters
            List<String> filtersToRemove = new ArrayList<String>();
            predicate = processNonStandardFilters(filters, filtersToRemove, entityPath);
            removeUsedFilters(filtersToRemove, filters);
            if (!filters.isEmpty()) {
                for (Map.Entry<String, Object> entry : filters.entrySet()) {
                    String key = entry.getKey();
                    Object filter = entry.getValue();
                    if (filter != null) {

                        // if ranged search (from - to fields)
                        if (key.contains("fromRange-")) {
                            // CHECKSTYLE:OFF
                            String parsedKey = key.substring(10);
                            // CHECKSTYLE:ON
                            if (filter instanceof Number) {
                                NumberPath path = createNumberPath(entityPath, parsedKey, filter);
                                predicate = and(predicate, path.goe((Number) filter));
                            } else if (filter instanceof Date) {
                                DatePath path = entityPath.getDate(parsedKey, Date.class);
                                predicate = and(predicate, path.goe((Date) filter));
                            }
                        } else if (key.contains("toRange-")) {
                            // CHECKSTYLE:OFF
                            String parsedKey = key.substring(8);
                            // CHECKSTYLE:ON
                            if (filter instanceof Number) {
                                NumberPath path = createNumberPath(entityPath, parsedKey, filter);
                                predicate = and(predicate, path.loe((Number) filter));
                            } else if (filter instanceof Date) {
                                DatePath path = entityPath.getDate(parsedKey, Date.class);
                                predicate = and(predicate, path.loe((Date) filter));
                            }
                        } else if (key.contains("list-")) {
                            // CHECKSTYLE:OFF
                            // if searching elements from list
                            String parsedKey = key.substring(5);
                            // CHECKSTYLE:ON
                            ListPath path = entityPath.getList(parsedKey, filter.getClass());
                            predicate = and(predicate, path.contains(filter));
                        } else { // if not ranged search
                            if (filter instanceof String) {
                                StringPath path = entityPath.getString(key);
                                String filterString = (String) filter;
                                predicate = and(predicate, path.startsWithIgnoreCase(filterString));
                            } else if (filter instanceof Date) {
                                DatePath path = entityPath.getDate(key, Date.class);
                                predicate = and(predicate, path.eq(filter));
                            } else if (filter instanceof Number) {
                                NumberPath path = createNumberPath(entityPath, key, filter);
                                predicate = and(predicate, path.eq(filter));
                            } else if (filter instanceof Boolean) {
                                BooleanPath path = entityPath.getBoolean(key);
                                predicate = and(predicate, path.eq((Boolean) filter));
                            } else if (filter instanceof Enum) {
                                EnumPath path = entityPath.getEnum(key, Enum.class);
                                predicate = and(predicate, path.eq(filter));
                            } else if (BaseEntity.class.isAssignableFrom(filter.getClass())) {
                                PathBuilder path = entityPath.get(key);
                                predicate = and(predicate, path.eq(filter));
                            }
                        }

                    }
                }
            }
        }
        return predicate;
    }

    /**
     * This method groups some filters to one. This might be needed when several filters are dependent on each other,
     * for example when we have several text fields and we want all of them to participate in search and we need OR
     * functionality between them. Do not forget to remove filters so getPredicate() method would not try to process them again.
     *
     * @return processed filters keys.
     */
    protected BooleanExpression processNonStandardFilters(Map<String, Object> filters, List<String> filtersToRemove,
            @SuppressWarnings("rawtypes") PathBuilder pathBuilder) {
        return null;
    }

    /**
     * Remove filters from further processing.
     */
    private Map<String, Object> removeUsedFilters(List<String> filtersToRemove, Map<String, Object> filtersMap) {
        for (String key : filtersToRemove) {
            filtersMap.remove(key);
        }
        return filtersMap;
    }

    /**
     * Class name in lower case as alias is used for spring data.
     */
    private String getAliasName(@SuppressWarnings("rawtypes") Class clazz) {
        return Introspector.decapitalize(clazz.getSimpleName());
    }

    /**
     * Join all predicates with and clause.
     */
    private BooleanExpression and(BooleanExpression old, BooleanExpression newPredidcate) {
        if (old != null) {
            return old.and(newPredidcate);
        } else {
            return newPredidcate;
        }
    }

    /**
     * If filter is number its required to know its concrete class so this
     * private helper method creates and returns predicate based on concrete
     * class.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private NumberPath createNumberPath(PathBuilder entityPath, String key, Object filter) {
        if (filter instanceof BigDecimal) {
            return entityPath.getNumber(key, BigDecimal.class);
        } else if (filter instanceof Long) {
            return entityPath.getNumber(key, Long.class);
        } else if (filter instanceof Integer) {
            return entityPath.getNumber(key, Integer.class);
        } else if (filter instanceof Double) {
            return entityPath.getNumber(key, Double.class);
        } else if (filter instanceof Float) {
            return entityPath.getNumber(key, Float.class);
        } else if (filter instanceof Byte) {
            return entityPath.getNumber(key, Byte.class);
        } else if (filter instanceof Short) {
            return entityPath.getNumber(key, Short.class);
        } else {
            throw new IllegalStateException("Unknown number type in search filter. Supported type: BigDecimal, Long, Integer, Double, Float, Byte, Short");
        }
    }
}
TOP

Related Classes of $.BaseService

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.