package eu.dnetlib.openaire.dsm.dao; import java.util.Arrays; import java.util.List; import java.util.Map.Entry; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.jpa.domain.Specification; import eu.dnetlib.enabling.datasources.common.DsmRuntimeException; import eu.dnetlib.openaire.dsm.domain.FilterName; import eu.dnetlib.openaire.dsm.domain.RequestFilter; import eu.dnetlib.openaire.dsm.domain.RequestSort; import eu.dnetlib.openaire.dsm.domain.RequestSortOrder; import eu.dnetlib.openaire.dsm.domain.db.DatasourceApiDbEntry; import eu.dnetlib.openaire.dsm.domain.db.DatasourceDbEntry; public class DatasourceSpecs { private static final Log log = LogFactory.getLog(DatasourceSpecs.class); public static final String WILDCARD = "%"; public static Specification dsRegisteredbyNotNullSpec() { return (ds, query, cb) -> cb.and(cb.isNull(ds.get(FilterName.registeredby.name())).not(), cb.isNull(ds.get("registrationdate")).not()); } public static Specification dsSpec(final RequestSort requestSortBy, final RequestSortOrder order, final RequestFilter requestFilter) { log.debug(String.format("RequestFilter:'%s', RequestSort:'%s', RequestSortOrder:'%s'", requestFilter, requestSortBy, order)); return (ds, query, cb) -> { final Predicate p = cb.conjunction(); final List> expressions = p.getExpressions(); expressions.add(cb.equal(ds.get("eoscType"), "Data Source")); expressions.add(cb.equal(ds.get("dedupMainService"), true)); if (requestFilter != null) { requestFilter.entrySet() .stream() .forEach(e -> { switch (FilterName.type(e.getKey())) { case exact: expressions.add(exactSearch(ds, cb, e)); break; case search: expressions.add(likeSearch(ds, cb, e)); break; case multiSearch: expressions.add(likeSearchList(ds, cb, e)); break; case searchOrgs: // search by case insensitive organization's country expressions.add(cb.equal(cb.lower(ds.join("organizations").get(FilterName.country.name())), getValue(e))); break; } }); } if (requestSortBy != null) { if (order != null) { final Path orderField = ds.get(requestSortBy.name()); switch (order) { case ASCENDING: query.orderBy(cb.asc(orderField)); break; case DESCENDING: query.orderBy(cb.desc(orderField)); break; } } } query.distinct(true); return p; }; } public static Specification apiSpec(final RequestFilter requestFilter) { log.debug(String.format("RequestFilter:'%s'", requestFilter)); return (api, query, cb) -> { final Predicate p = cb.conjunction(); if (requestFilter != null) { final List> expressions = p.getExpressions(); requestFilter.entrySet() .stream() .forEach(e -> { switch (FilterName.type(e.getKey())) { case exact: expressions.add(exactSearch(api, cb, e)); break; case search: expressions.add(likeSearch(api, cb, e)); break; case multiSearch: expressions.add(likeSearchList(api, cb, e)); break; case searchOrgs: throw new DsmRuntimeException("not implemented"); } }); } query.distinct(true); return p; }; } // HELPERS // substring, case insensitive, like based search private static Predicate likeSearch(final Root r, final CriteriaBuilder cb, final Entry e) { return cb.like(cb.lower(r.get(e.getKey().name())), WILDCARD + getValue(e) + WILDCARD); } // substring, case insensitive, like based search private static Predicate likeSearchList(final Root r, final CriteriaBuilder cb, final Entry e) { final String key = e.getKey().name(); final Predicate[] arr = Arrays.stream(e.getValue().toString().split(",")) .map(String::trim) .map(String::toLowerCase) .filter(StringUtils::isNotBlank) .map(s -> cb.like(cb.lower(r.get(key)), WILDCARD + s + WILDCARD)) .toArray(size -> new Predicate[size]); return cb.or(arr); } // search by ID, managed. exact match private static Predicate exactSearch(final Root r, final CriteriaBuilder cb, final Entry e) { return cb.equal(r.get(e.getKey().name()), getValue(e)); } private static Object getValue(final Entry e) { if (e.getValue() instanceof String) { final String s = (String) e.getValue(); if (!e.getKey().equals(FilterName.country)) { final Boolean b = BooleanUtils.toBooleanObject(s); if (b != null) { return b; } } return e.getKey().equals(FilterName.id) ? s : StringUtils.lowerCase(s); } if (e.getValue() instanceof Boolean) { return e.getValue(); } return e.getValue(); } }