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

de.frachtwerk.essencium.backend.repository.specification.LikeConcatenated Maven / Gradle / Ivy

Go to download

Essencium Backend is a software library built on top of Spring Boot that allows developers to quickly get started on new software projects. Essencium provides, for example, a fully implemented role-rights concept as well as various field-tested solutions for access management and authentication.

The newest version!
/*
 * Copyright (C) 2024 Frachtwerk GmbH, Leopoldstraße 7C, 76133 Karlsruhe.
 *
 * This file is part of essencium-backend.
 *
 * essencium-backend 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 3 of the License, or
 * (at your option) any later version.
 *
 * essencium-backend 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 essencium-backend. If not, see .
 */

package de.frachtwerk.essencium.backend.repository.specification;

import jakarta.persistence.criteria.*;
import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.util.Arrays;
import java.util.Locale;
import lombok.NonNull;
import net.kaczmarzyk.spring.data.jpa.utils.Converter;
import net.kaczmarzyk.spring.data.jpa.utils.QueryContext;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.data.jpa.domain.Specification;

public class LikeConcatenated implements Specification {

  @Serial private static final long serialVersionUID = 1L;

  private final String[] allowedValues;
  private final Converter converter;
  private final String path;
  private final QueryContext queryContext;

  public LikeConcatenated(
      QueryContext queryContext, String path, String[] httpParamValues, Converter converter) {
    if (httpParamValues == null || httpParamValues.length < 1) {
      throw new IllegalArgumentException();
    }
    this.path = path;
    this.allowedValues = httpParamValues;
    this.converter = converter;
    this.queryContext = queryContext;
  }

  @Override
  public Predicate toPredicate(
      @NonNull @NotNull Root root,
      @NonNull @NotNull CriteriaQuery query,
      @NotNull CriteriaBuilder cb) {
    String[] pathElements = this.path.split(",");

    String[] reversedPathElements = Arrays.copyOf(pathElements, pathElements.length);
    String[] reversedAllowedValues = Arrays.copyOf(allowedValues, allowedValues.length);

    ArrayUtils.reverse(reversedPathElements);
    ArrayUtils.reverse(reversedAllowedValues);

    Expression concatPath = createConcatenatedPathExpression(root, cb, pathElements);
    Expression reversedConcatPath =
        createConcatenatedPathExpression(root, cb, reversedPathElements);

    String concatAllowedValues = String.join(" ", allowedValues).toLowerCase(Locale.ROOT);
    String reversedConcatAllowedValues =
        String.join(" ", reversedAllowedValues).toLowerCase(Locale.ROOT);

    return cb.or(
        cb.or(
            cb.like(cb.lower(concatPath), "%" + concatAllowedValues + "%"),
            cb.like(cb.lower(reversedConcatPath), "%" + concatAllowedValues + "%")),
        cb.or(
            cb.like(cb.lower(concatPath), "%" + reversedConcatAllowedValues + "%"),
            cb.like(cb.lower(reversedConcatPath), "%" + reversedConcatAllowedValues + "%")));
  }

  private Expression createConcatenatedPathExpression(
      @NotNull Root root, CriteriaBuilder cb, String[] pathElements) {
    Expression exp = this.path(root, pathElements[0]);
    String[] pathElementsTail = Arrays.copyOfRange(pathElements, 1, pathElements.length);

    for (String element : pathElementsTail) {
      Path path = this.path(root, element);
      exp = cb.concat(exp, " ");
      exp = cb.concat(exp, path);
    }
    return exp;
  }

  @SuppressWarnings("unchecked")
  protected  Path path(Root root, String element) {
    Path expr = null;
    for (String field : element.split("\\.")) {
      if (expr == null) {
        if (queryContext != null && queryContext.getEvaluated(field, root) != null) {
          expr = queryContext.getEvaluated(field, root);
        } else {
          expr = root.get(field);
        }
      } else {
        expr = expr.get(field);
      }
    }
    return (Path) expr;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = super.hashCode();
    result = prime * result + Arrays.hashCode(allowedValues);
    result = prime * result + ((converter == null) ? 0 : converter.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (!super.equals(obj)) return false;
    if (getClass() != obj.getClass()) return false;
    LikeConcatenated other = (LikeConcatenated) obj;
    if (!Arrays.equals(allowedValues, other.allowedValues)) return false;
    if (converter == null) {
      return other.converter == null;
    } else return converter.equals(other.converter);
  }

  @Override
  public String toString() {
    return "LikeIn [allowedValues="
        + Arrays.toString(allowedValues)
        + ", converter="
        + converter
        + "]";
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy