edu.pitt.dbmi.ccd.db.specification.AnnotationTargetSpecification.java Source code

Java tutorial

Introduction

Here is the source code for edu.pitt.dbmi.ccd.db.specification.AnnotationTargetSpecification.java

Source

/*
 * Copyright (C) 2015 University of Pittsburgh.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */
package edu.pitt.dbmi.ccd.db.specification;

import edu.pitt.dbmi.ccd.db.entity.AnnotationTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
import static org.springframework.util.StringUtils.isEmpty;

/**
 * @author Mark Silvis (marksilvis@pitt.edu)
 */
public final class AnnotationTargetSpecification {

    private static final String USER = "user";
    private static final String USERNAME = "username";
    private static final String TITLE = "title";
    private static final String ADDRESS = "address";
    private static final String FILE = "file";
    private static final String NAME = "name";
    private static final String URL = "url";

    private AnnotationTargetSpecification() {
    }

    public static Specification<AnnotationTarget> filterSpec(String username, String type) {
        return (root, query, cb) -> {
            return buildFilterSpec(root, cb, username, type);
        };
    }

    /**
     * find uploads that contain search terms
     *
     * @param username user
     * @param type upload type (url or file)
     * @param matches contains terms
     * @param nots does not contain terms
     * @return specification
     */
    public static Specification<AnnotationTarget> searchSpec(String username, String type, Set<String> matches,
            Set<String> nots) {
        return (root, query, cb) -> {
            return buildSearchSpec(root, cb, username, type, matches, nots);
        };
    }

    private static Predicate buildFilterSpec(Root<AnnotationTarget> root, CriteriaBuilder cb, String username,
            String type) {
        List<Predicate> predicates = new ArrayList<>(0);
        if (!isEmpty(username)) {
            predicates.add(belongsToUser(root, cb, username));
        }
        if (!isEmpty(type)) {
            if (type.equalsIgnoreCase(FILE)) {
                predicates.add(isFile(root, cb));
            } else if (type.equalsIgnoreCase(URL)) {
                predicates.add(isURL(root, cb));
            }
        }
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }

    // build search predicates
    private static Predicate buildSearchSpec(Root<AnnotationTarget> root, CriteriaBuilder cb, String username,
            String type, Set<String> matches, Set<String> nots) {
        List<Predicate> predicates = new ArrayList<>(0);
        predicates.add(buildFilterSpec(root, cb, username, type));
        if (!isEmpty(matches)) {
            predicates.addAll(inTitleOrAddressOrName(root, cb, matches));
        }
        if (!isEmpty(nots)) {
            predicates.addAll(notInTitleOrAddressOrName(root, cb, nots));
        }
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }

    // belongs to user predicate
    private static Predicate belongsToUser(Root<AnnotationTarget> root, CriteriaBuilder cb, String username) {
        return cb.like(cb.lower(root.get(USER).get(USERNAME)), username.toLowerCase());
    }

    // is file predicate
    private static Predicate isFile(Root<AnnotationTarget> root, CriteriaBuilder cb) {
        return cb.isNull(root.get(ADDRESS));
    }

    // is url predicate
    private static Predicate isURL(Root<AnnotationTarget> root, CriteriaBuilder cb) {
        return cb.isNotNull(root.get(ADDRESS));
    }

    // build (title or address or file name contains term) predicate for each search term
    private static List<Predicate> inTitleOrAddressOrName(Root<AnnotationTarget> root, CriteriaBuilder cb,
            Set<String> terms) {
        return terms.stream().map(t -> containsLike(t))
                .map(t -> cb.or(titleContains(root, cb, t),
                        (root.get(ADDRESS) != null) ? addressContains(root, cb, t) : fileNameContains(root, cb, t)))
                .collect(Collectors.toList());
    }

    // build (neither name or description contains term) predicate for each search term
    private static List<Predicate> notInTitleOrAddressOrName(Root<AnnotationTarget> root, CriteriaBuilder cb,
            Set<String> terms) {
        return terms
                .stream().map(
                        t -> containsLike(t))
                .map(t -> cb.not(
                        cb.or(titleContains(root, cb, t), (root.get(ADDRESS) != null) ? addressContains(root, cb, t)
                                : fileNameContains(root, cb, t))))
                .collect(Collectors.toList());
    }

    // build title contains term predicate
    private static Predicate titleContains(Root<AnnotationTarget> root, CriteriaBuilder cb, String term) {
        return cb.like(cb.lower(root.get(TITLE)), term);
    }

    // build address contains term predicate
    private static Predicate addressContains(Root<AnnotationTarget> root, CriteriaBuilder cb, String term) {
        return cb.like(cb.lower(root.get(ADDRESS)), term);
    }

    // build file name contains term predicate
    private static Predicate fileNameContains(Root<AnnotationTarget> root, CriteriaBuilder cb, String term) {
        return cb.like(cb.lower(root.get(FILE).get(NAME)), term);
    }

    // wrap term in wildcards
    private static String containsLike(String term) {
        if (isEmpty(term)) {
            return "%";
        } else {
            return "%" + term.toLowerCase() + "%";
        }
    }
}