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

de.frachtwerk.essencium.backend.controller.access.SpecAnnotationFactory 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.controller.access;

import de.frachtwerk.essencium.backend.model.AbstractBaseUser;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.function.Function;
import net.kaczmarzyk.spring.data.jpa.web.Utils;
import net.kaczmarzyk.spring.data.jpa.web.Utils.Resolvers;
import net.kaczmarzyk.spring.data.jpa.web.WebRequestProcessingContext;
import net.kaczmarzyk.spring.data.jpa.web.annotation.And;
import net.kaczmarzyk.spring.data.jpa.web.annotation.Conjunction;
import net.kaczmarzyk.spring.data.jpa.web.annotation.Disjunction;
import net.kaczmarzyk.spring.data.jpa.web.annotation.Or;
import net.kaczmarzyk.spring.data.jpa.web.annotation.Spec;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.data.jpa.domain.Specification;

public class SpecAnnotationFactory, ID extends Serializable> {
  private final Resolvers resolvers;
  private final List> specs;
  private final WebRequestProcessingContext context;
  private final SimpleSpecFactory simpleSpecFactory;

  public SpecAnnotationFactory(
      AbstractApplicationContext applicationContext,
      final WebRequestProcessingContext context,
      USER user,
      List> specs) {
    this.specs = specs;
    this.context = context;
    this.resolvers = Utils.getResolvers(null, applicationContext);
    this.simpleSpecFactory =
        new SimpleSpecFactory<>(
            resolvers,
            specs,
            context,
            user,
            new EmbeddedValueResolver(applicationContext.getBeanFactory()));
  }

  public void addSpec(final OwnershipSpec ownershipSpec)
      throws NoSuchFieldException, IllegalAccessException {
    resolveAndAdd(simpleSpecFactory.getSimpleAccessSpec(ownershipSpec));
  }

  public void addSpec(final OwnershipSpec.And and)
      throws NoSuchFieldException, IllegalAccessException {
    resolveAndAdd(getAndAccessSpec(and));
  }

  public void addSpec(final OwnershipSpec.Or or)
      throws NoSuchFieldException, IllegalAccessException {
    resolveAndAdd(getOrAccessSpec(or));
  }

  public void addSpec(final OwnershipSpec.Disjunction dis)
      throws NoSuchFieldException, IllegalAccessException {
    resolveAndAdd(getDisjunctionAccessSpec(dis));
  }

  public void addSpec(final OwnershipSpec.Conjunction con)
      throws NoSuchFieldException, IllegalAccessException {
    resolveAndAdd(getConjunctionAccessSpec(con));
  }

  private And getAndAccessSpec(final OwnershipSpec.And and)
      throws NoSuchFieldException, IllegalAccessException {
    Spec[] result = getSpecs(and.value());
    return new And() {

      @Override
      public Class annotationType() {
        return And.class;
      }

      @Override
      public Spec[] value() {
        return result;
      }
    };
  }

  private Or getOrAccessSpec(final OwnershipSpec.Or and)
      throws NoSuchFieldException, IllegalAccessException {
    Spec[] result = getSpecs(and.value());
    return new Or() {
      @Override
      public Class annotationType() {
        return Or.class;
      }

      @Override
      public Spec[] value() {
        return result;
      }
    };
  }

  private Conjunction getConjunctionAccessSpec(final OwnershipSpec.Conjunction con)
      throws NoSuchFieldException, IllegalAccessException {
    Or[] specs = getSpecs(con.value(), this::getOrAccessSpec, Or[]::new);
    final Spec[] and = getSpecs(con.and());
    return new Conjunction() {
      @Override
      public Class annotationType() {
        return Conjunction.class;
      }

      @Override
      public Or[] value() {
        return specs;
      }

      @Override
      public Spec[] and() {
        return and;
      }
    };
  }

  private Disjunction getDisjunctionAccessSpec(final OwnershipSpec.Disjunction dis)
      throws NoSuchFieldException, IllegalAccessException {
    And[] specs = getSpecs(dis.value(), this::getAndAccessSpec, And[]::new);
    final Spec[] or = getSpecs(dis.or());
    return new Disjunction() {
      @Override
      public Class annotationType() {
        return Disjunction.class;
      }

      @Override
      public And[] value() {
        return specs;
      }

      @Override
      public Spec[] or() {
        return or;
      }
    };
  }

  private Spec[] getSpecs(final OwnershipSpec[] specs)
      throws NoSuchFieldException, IllegalAccessException {
    return getSpecs(specs, simpleSpecFactory::getSimpleAccessSpec, Spec[]::new);
  }

  private  O[] getSpecs(
      final I[] specs, ThrowingFunction resolver, Function arrayInitializer)
      throws NoSuchFieldException, IllegalAccessException {
    O[] result = arrayInitializer.apply(specs.length);
    for (int i = 0; i < specs.length; i++) {
      result[i] = resolver.apply(specs[i]);
    }
    return result;
  }

  @FunctionalInterface
  interface ThrowingFunction {
    O apply(I i) throws NoSuchFieldException, IllegalAccessException;
  }

  private  void resolveAndAdd(T annotation) {
    resolvers.resolve(annotation, context).ifPresent(specs::add);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy