protected AbstractScoreDirectorFactory decideMultipleScoreDirectorFactories()

in core/optaplanner-core-impl/src/main/java/org/optaplanner/core/impl/score/director/ScoreDirectorFactoryFactory.java [86:191]


    protected AbstractScoreDirectorFactory<Solution_, Score_> decideMultipleScoreDirectorFactories(
            ClassLoader classLoader, SolutionDescriptor<Solution_> solutionDescriptor, EnvironmentMode environmentMode) {
        // Load all known Score Director Factories via SPI.
        ServiceLoader<ScoreDirectorFactoryService> scoreDirectorFactoryServiceLoader =
                ServiceLoader.load(ScoreDirectorFactoryService.class);
        Map<ScoreDirectorType, Supplier<AbstractScoreDirectorFactory<Solution_, Score_>>> scoreDirectorFactorySupplierMap =
                new EnumMap<>(ScoreDirectorType.class);
        boolean isBavet = false;
        for (ScoreDirectorFactoryService<Solution_, Score_> service : scoreDirectorFactoryServiceLoader) {
            Supplier<AbstractScoreDirectorFactory<Solution_, Score_>> factory =
                    service.buildScoreDirectorFactory(classLoader, solutionDescriptor, config, environmentMode);
            if (service.getSupportedScoreDirectorType() == CONSTRAINT_STREAMS) {
                /*
                 * CS-D will be available if on the classpath and user did not request BAVET.
                 * CS-B will be available if on the classpath and user did not request DROOLS.
                 * The following logic deals with the decision of which CS impl to pick if both available.
                 */
                switch (service.getPriority()) {
                    case Integer.MAX_VALUE:
                        if (config.getConstraintStreamImplType() == BAVET) {
                            // Drools should be skipped.
                            continue;
                        } else {
                            // Drools will be registered as the CS impl.
                            isBavet = false;
                        }
                        break;
                    case Integer.MIN_VALUE:
                        if (scoreDirectorFactorySupplierMap.containsKey(CONSTRAINT_STREAMS)) {
                            /*
                             * We already have a CS service registered, and it is of a higher priority.
                             * This means Drools was loaded first, but Bavet is available too.
                             * Such situation can only happen if the user did not specify an impl type.
                             * Therefore, we skip Bavet as Drools is the default and already registered.
                             */
                            continue;
                        } else {
                            // Bavet will be registered as the CS impl.
                            isBavet = true;
                        }
                        break;
                    default:
                        throw new IllegalStateException(
                                "Impossible state: Unknown service priority (" + service.getPriority() + ")");
                }
            }
            if (factory != null) {
                scoreDirectorFactorySupplierMap.put(service.getSupportedScoreDirectorType(), factory);
            }
        }

        Supplier<AbstractScoreDirectorFactory<Solution_, Score_>> easyScoreDirectorFactorySupplier =
                scoreDirectorFactorySupplierMap.get(EASY);
        Supplier<AbstractScoreDirectorFactory<Solution_, Score_>> constraintStreamScoreDirectorFactorySupplier =
                scoreDirectorFactorySupplierMap.get(CONSTRAINT_STREAMS);
        Supplier<AbstractScoreDirectorFactory<Solution_, Score_>> incrementalScoreDirectorFactorySupplier =
                scoreDirectorFactorySupplierMap.get(INCREMENTAL);
        Supplier<AbstractScoreDirectorFactory<Solution_, Score_>> drlScoreDirectorFactorySupplier =
                scoreDirectorFactorySupplierMap.get(DRL);

        // Every non-null supplier means that ServiceLoader successfully loaded and configured a score director factory.
        assertOnlyOneScoreDirectorFactory(easyScoreDirectorFactorySupplier,
                constraintStreamScoreDirectorFactorySupplier, incrementalScoreDirectorFactorySupplier,
                drlScoreDirectorFactorySupplier);

        if (easyScoreDirectorFactorySupplier != null) {
            validateNoDroolsAlphaNetworkCompilation();
            validateNoGizmoKieBaseSupplier();
            return easyScoreDirectorFactorySupplier.get();
        } else if (incrementalScoreDirectorFactorySupplier != null) {
            validateNoDroolsAlphaNetworkCompilation();
            validateNoGizmoKieBaseSupplier();
            return incrementalScoreDirectorFactorySupplier.get();
        }

        if (constraintStreamScoreDirectorFactorySupplier != null) {
            if (isBavet) {
                validateNoDroolsAlphaNetworkCompilation();
                validateNoGizmoKieBaseSupplier();
            }
            return constraintStreamScoreDirectorFactorySupplier.get();
        } else if (config.getConstraintProviderClass() != null) {
            String expectedModule = config.getConstraintStreamImplType() == BAVET
                    ? "optaplanner-constraint-streams-bavet"
                    : "optaplanner-constraint-streams-drools";
            throw new IllegalStateException("Constraint Streams requested via constraintProviderClass (" +
                    config.getConstraintProviderClass() + ") but the supporting classes were not found on the classpath.\n"
                    + "Maybe include org.optaplanner:" + expectedModule + " dependency in your project?\n"
                    + "Maybe ensure your uberjar bundles META-INF/services from included JAR files?");
        }

        if (drlScoreDirectorFactorySupplier != null) {
            return drlScoreDirectorFactorySupplier.get();
        } else {
            if (!ConfigUtils.isEmptyCollection(config.getScoreDrlList())
                    || !ConfigUtils.isEmptyCollection(config.getScoreDrlFileList())) {
                throw new IllegalStateException("DRL constraints requested via scoreDrlList (" + config.getScoreDrlList()
                        + ") or scoreDrlFileList (" + config.getScoreDrlFileList() + "), "
                        + "but the supporting classes were not found on the classpath.\n"
                        + "Maybe include org.optaplanner:optaplanner-constraint-drl dependency in your project?\n"
                        + "Maybe ensure your uberjar bundles META-INF/services from included JAR files?");
            }
        }
        throw new IllegalArgumentException("The scoreDirectorFactory lacks configuration for "
                + "either constraintProviderClass, easyScoreCalculatorClass or incrementalScoreCalculatorClass.");
    }