class JustificationsSupplier {

    public static JustificationsSupplier empty() {
        return new JustificationsSupplier(DefaultConstraintJustification::of, Collections::emptyList);
    }

    public static <A> JustificationsSupplier of(Constraint constraint,
            BiFunction<A, Score<?>, ConstraintJustification> justificationMapping,
            Function<A, Collection<Object>> indictedObjectsMapping,
            A a) {
        Function<Score<?>, ConstraintJustification> explainingJustificationMapping = impact -> {
            try {
                return justificationMapping.apply(a, impact);
            } catch (Exception e) {
                throw createJustificationException(constraint, e, a);
            }
        };
        Supplier<Collection<Object>> explainingIndictedObjectsSupplier = () -> {
            try {
                return indictedObjectsMapping.apply(a);
            } catch (Exception e) {
                throw createIndictmentException(constraint, e, a);
            }
        };
        return new JustificationsSupplier(explainingJustificationMapping, explainingIndictedObjectsSupplier);
    }

    private static RuntimeException createJustificationException(Constraint constraint, Exception cause, Object... facts) {
        throw new IllegalStateException("Consequence of a constraint (" + constraint.getConstraintId()
                + ") threw an exception creating constraint justification from a tuple (" + factsToString(facts) + ").", cause);
    }

    private static String factsToString(Object... facts) {
        return Arrays.stream(facts)
                .map(Object::toString)
                .collect(Collectors.joining(", ", "{", "}"));
    }

    private static RuntimeException createIndictmentException(Constraint constraint, Exception cause, Object... facts) {
        throw new IllegalStateException("Consequence of a constraint (" + constraint.getConstraintId()
                + ") threw an exception collecting indicted objects from a tuple (" + factsToString(facts) + ").", cause);
    }

    public static <A, B> JustificationsSupplier of(Constraint constraint,
            TriFunction<A, B, Score<?>, ConstraintJustification> justificationMapping,
            BiFunction<A, B, Collection<Object>> indictedObjectsMapping,
            A a, B b) {
        Function<Score<?>, ConstraintJustification> explainingJustificationMapping = impact -> {
            try {
                return justificationMapping.apply(a, b, impact);
            } catch (Exception e) {
                throw createJustificationException(constraint, e, a, b);
            }
        };
        Supplier<Collection<Object>> explainingIndictedObjectsSupplier = () -> {
            try {
                return indictedObjectsMapping.apply(a, b);
            } catch (Exception e) {
                throw createIndictmentException(constraint, e, a, b);
            }
        };
        return new JustificationsSupplier(explainingJustificationMapping, explainingIndictedObjectsSupplier);
    }

    public static <A, B, C> JustificationsSupplier of(Constraint constraint,
            QuadFunction<A, B, C, Score<?>, ConstraintJustification> justificationMapping,
            TriFunction<A, B, C, Collection<Object>> indictedObjectsMapping,
            A a, B b, C c) {<FILL_FUNCTION_BODY>}

    public static <A, B, C, D> JustificationsSupplier of(Constraint constraint,
            PentaFunction<A, B, C, D, Score<?>, ConstraintJustification> justificationMapping,
            QuadFunction<A, B, C, D, Collection<Object>> indictedObjectsMapping,
            A a, B b, C c, D d) {
        Function<Score<?>, ConstraintJustification> explainingJustificationMapping = impact -> {
            try {
                return justificationMapping.apply(a, b, c, d, impact);
            } catch (Exception e) {
                throw createJustificationException(constraint, e, a, b, c, d);
            }
        };
        Supplier<Collection<Object>> explainingIndictedObjectsSupplier = () -> {
            try {
                return indictedObjectsMapping.apply(a, b, c, d);
            } catch (Exception e) {
                throw createIndictmentException(constraint, e, a, b, c, d);
            }
        };
        return new JustificationsSupplier(explainingJustificationMapping, explainingIndictedObjectsSupplier);
    }

    private final Function<Score<?>, ConstraintJustification> constraintJustificationSupplier;
    private final Supplier<Collection<Object>> indictedObjectsSupplier;

    private JustificationsSupplier(Function<Score<?>, ConstraintJustification> constraintJustificationSupplier,
            Supplier<Collection<Object>> indictedObjectsSupplier) {
        this.constraintJustificationSupplier = Objects.requireNonNull(constraintJustificationSupplier);
        this.indictedObjectsSupplier = Objects.requireNonNull(indictedObjectsSupplier);
    }

    public ConstraintJustification createConstraintJustification(Score<?> impact) {
        return constraintJustificationSupplier.apply(impact);
    }

    public Collection<Object> createIndictedObjects() {
        return indictedObjectsSupplier.get();
    }

}

        Function<Score<?>, ConstraintJustification> explainingJustificationMapping = impact -> {
            try {
                return justificationMapping.apply(a, b, c, impact);
            } catch (Exception e) {
                throw createJustificationException(constraint, e, a, b, c);
            }
        };
        Supplier<Collection<Object>> explainingIndictedObjectsSupplier = () -> {
            try {
                return indictedObjectsMapping.apply(a, b, c);
            } catch (Exception e) {
                throw createIndictmentException(constraint, e, a, b, c);
            }
        };
        return new JustificationsSupplier(explainingJustificationMapping, explainingIndictedObjectsSupplier);
    
<no_super_class>