utils.jpa.EntityResource.java Source code

Java tutorial

Introduction

Here is the source code for utils.jpa.EntityResource.java

Source

/* 
 * The MIT License
 *
 * Copyright 2014 Richard Casar <caricsvk@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package utils.jpa;

import com.fasterxml.jackson.annotation.JsonView;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.Valid;
import javax.ws.rs.BeanParam;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import utils.enums.EntityFilterType;
import utils.enums.OrderType;
import utils.jpa.ejb.EntityFilter;
import utils.jpa.ejb.TableSearchQuery;

public abstract class EntityResource<T> {

    private final Class<T> entityClass;

    @PersistenceContext
    protected EntityManager em;

    public EntityResource(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    @POST
    public void create(@Valid T entity) {
        em.persist(entity);
    }

    @PUT
    public void edit(@Valid T entity) {
        em.merge(entity);
    }

    @GET
    @JsonView(JsonViews.Classic.class)
    @Path("{id}")
    public T find(@PathParam("id") Long id) {
        return em.find(entityClass, id);
    }

    @GET
    @JsonView(JsonViews.Detailed.class)
    @Path("{id}/detail")
    public T findDetail(@PathParam("id") Long id) {
        return em.find(entityClass, id);
    }

    @DELETE
    @Path("{id}")
    public void remove(@PathParam("id") Long id) {
        em.remove(em.find(entityClass, id));
    }

    @GET
    @Path("count")
    public String count(@BeanParam TableSearchQuery tb) {
        return "{\"count\":" + getAllCount(tb) + "}";
    }

    @GET
    @Path("entity-field-types")
    public Map<String, String> types() {
        HashMap<String, String> types = new HashMap<>();
        for (Field field : entityClass.getDeclaredFields()) {
            types.put(field.getName(), field.getGenericType().toString());
        }
        return types;
    }

    /**
     *
     * @param tb
     * @param fieldsSearchBy fields by which is search triggered
     * @return list of EntityClass's objects
     */
    @GET
    @JsonView(JsonViews.Classic.class)
    public List<T> getAll(@BeanParam TableSearchQuery tb, List<String> fieldsSearchBy) {
        return getAllPriv(tb, fieldsSearchBy);
    }

    @GET
    @JsonView(JsonViews.Detailed.class)
    @Path("detail")
    public List<T> getAllDetail(@BeanParam TableSearchQuery tb, List<String> fieldsSearchBy) {
        return getAllPriv(tb, fieldsSearchBy);
    }

    private List<T> getAllPriv(@BeanParam TableSearchQuery tb, List<String> fieldsSearchBy) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> cq = cb.createQuery(entityClass);
        Root<T> root = cq.from(entityClass);

        cq.select(root);

        //setting order
        if (tb.getOrderType().equals(OrderType.DESC)) {
            cq.orderBy(cb.desc(root.get(tb.getOrder())));
        } else {
            cq.orderBy(cb.asc(root.get(tb.getOrder())));
        }

        Query query = tb.createQuery(em, cb, cq, root);
        if (query == null) {
            query = createCommonQuery(cb, cq, root, tb, fieldsSearchBy);
        }

        if (tb.getOffset() > 0) {
            query.setFirstResult(tb.getOffset());
        }
        if (tb.getLimit() > 0) {
            query.setMaxResults(tb.getLimit());
        }

        return query.getResultList();
    }

    public int getAllCount(TableSearchQuery tb) {
        return getAllCount(tb, null);
    }

    public int getAllCount(TableSearchQuery tb, List<String> fieldsSearchBy) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery cq = cb.createQuery();
        Root<T> root = cq.from(entityClass);
        cq.select(cb.count(root));
        Query query = tb.createQuery(em, cb, cq, root);
        if (query == null) {
            query = createCommonQuery(cb, cq, root, tb, fieldsSearchBy);
        }
        try {
            return ((Long) query.getSingleResult()).intValue();
        } catch (NoResultException ex) {
            return 0;
        }
    }

    private Query createCommonQuery(CriteriaBuilder cb, CriteriaQuery cq, Root root, TableSearchQuery tb,
            List<String> fieldsSearchBy) {

        List<Predicate> orPredicates = new ArrayList<>();
        List<Predicate> andPredicates = new ArrayList<>();

        //setting where conditions      
        if (fieldsSearchBy != null && !fieldsSearchBy.isEmpty()) {
            for (String field : fieldsSearchBy) {
                if (tb.getFilter() != null && !tb.getFilter().isEmpty()) {
                    orPredicates.add(cb.like(cb.lower(cb.concat(root.<String>get(field), "::text")),
                            "%" + tb.getFilter().toLowerCase() + "%"));
                }
            }
        } else {
            List<Field> filterColumns = SearchFields.getAll(entityClass);
            for (Field field : filterColumns) {
                EntityFilter entityFilter = tb.getFilterParameters().get(field.getName());

                if ((Collection.class.isAssignableFrom(field.getType())
                        || List.class.isAssignableFrom(field.getType()))
                        && (entityFilter == null
                                || !entityFilter.getEntityFilterType().equals(EntityFilterType.EMPTY))) {
                    continue;
                }

                if (entityFilter == null) {
                    if (tb.getFilter() != null && !tb.getFilter().isEmpty()) {
                        orPredicates.add(cb.like(cb.lower(cb.concat(root.<String>get(field.getName()), "::text")),
                                "%" + tb.getFilter().toLowerCase() + "%"));
                    }
                    continue;
                }

                switch (entityFilter.getEntityFilterType()) {
                case WILDCARD:
                    andPredicates.add(cb.like(cb.lower(cb.concat(root.<String>get(field.getName()), "::text")),
                            "%" + entityFilter.getValue().toLowerCase() + "%"));
                    break;
                case EMPTY:
                    if (Collection.class.isAssignableFrom(field.getType())
                            || List.class.isAssignableFrom(field.getType())) {
                        andPredicates.add(entityFilter.getValue().equals("hide")
                                ? cb.isEmpty(root.<Collection>get(field.getName()))
                                : cb.isNotEmpty(root.<Collection>get(field.getName())));
                    } else {
                        andPredicates.add(
                                entityFilter.getValue().equals("hide") ? root.<Object>get(field.getName()).isNull()
                                        : root.<Object>get(field.getName()).isNotNull());
                    }

                    break;
                case MIN_MAX:
                    andPredicates.add(cb.greaterThanOrEqualTo(root.<Date>get(field.getName()),
                            new Date(Long.valueOf(entityFilter.getValues().get(0)))));
                    andPredicates.add(cb.lessThanOrEqualTo(root.<Date>get(field.getName()),
                            new Date(Long.valueOf(entityFilter.getValues().get(1)))));
                    break;
                case MIN:
                    andPredicates.add(cb.greaterThanOrEqualTo(root.<Date>get(field.getName()),
                            new Date(Long.valueOf(entityFilter.getValue()))));
                    break;
                case MAX:
                    andPredicates.add(cb.lessThanOrEqualTo(root.<Date>get(field.getName()),
                            new Date(Long.valueOf(entityFilter.getValue()))));
                    break;
                }

            }
        }
        if (orPredicates.size() > 0 && andPredicates.size() > 0) {
            cq.where(cb.or(cb.or(orPredicates.toArray(new Predicate[0])),
                    cb.and(andPredicates.toArray(new Predicate[0]))));
        } else if (orPredicates.size() > 0) {
            cq.where(cb.or(orPredicates.toArray(new Predicate[0])));
        } else if (andPredicates.size() > 0) {
            cq.where(cb.and(andPredicates.toArray(new Predicate[0])));
        }

        return em.createQuery(cq);

    }

}