class DrlScoreDirectorFactory<Solution_, Score_ extends Score<Score_>>
        extends AbstractScoreDirectorFactory<Solution_, Score_> {

    private final KieBase kieBase;

    protected Map<Rule, Function<Solution_, Score_>> ruleToConstraintWeightExtractorMap;

    /**
     * @param solutionDescriptor never null
     * @param kieBase never null
     */
    public DrlScoreDirectorFactory(SolutionDescriptor<Solution_> solutionDescriptor, KieBase kieBase) {
        super(solutionDescriptor);
        this.kieBase = kieBase;
        assertGlobalScoreHolderExists(kieBase);
        createRuleToConstraintWeightExtractorMap(kieBase);
        solutionDescriptor.assertProblemFactsExist();
    }

    protected void assertGlobalScoreHolderExists(KieBase kieBase) {<FILL_FUNCTION_BODY>}

    protected void createRuleToConstraintWeightExtractorMap(KieBase kieBase) {
        ConstraintConfigurationDescriptor<Solution_> constraintConfigurationDescriptor = solutionDescriptor
                .getConstraintConfigurationDescriptor();
        if (constraintConfigurationDescriptor == null) {
            ruleToConstraintWeightExtractorMap = new LinkedHashMap<>(0);
            return;
        }
        Collection<ConstraintWeightDescriptor<Solution_>> constraintWeightDescriptors = constraintConfigurationDescriptor
                .getConstraintWeightDescriptors();
        ruleToConstraintWeightExtractorMap = new LinkedHashMap<>(constraintWeightDescriptors.size());
        for (ConstraintWeightDescriptor<Solution_> constraintWeightDescriptor : constraintWeightDescriptors) {
            String constraintPackage = constraintWeightDescriptor.getConstraintPackage();
            String constraintName = constraintWeightDescriptor.getConstraintName();
            Rule rule = kieBase.getRule(constraintPackage, constraintName);
            if (rule == null) {
                Rule potentialRule = kieBase.getKiePackages().stream().flatMap(kiePackage -> kiePackage.getRules().stream())
                        .filter(selectedRule -> selectedRule.getName().equals(constraintName)).findFirst().orElse(null);
                throw new IllegalStateException("The constraintConfigurationClass ("
                        + constraintConfigurationDescriptor.getConstraintConfigurationClass()
                        + ") has a @" + ConstraintWeight.class.getSimpleName()
                        + " annotated member (" + constraintWeightDescriptor.getMemberAccessor()
                        + ") with constraintPackage/rulePackage (" + constraintPackage
                        + ") and constraintName/ruleName (" + constraintName
                        + ") for which no Drools rule exist in the DRL.\n"
                        + (potentialRule != null ? "Maybe the constraintPackage (" + constraintPackage + ") is wrong,"
                                + " because there is a rule with the same ruleName (" + constraintName
                                + "), but in a different rulePackage (" + potentialRule.getPackageName() + ")."
                                : "Maybe there is a typo in the constraintName (" + constraintName
                                        + ") so it not identical to the constraint's ruleName."));
            }
            Function<Solution_, Score_> constraintWeightExtractor =
                    (Function<Solution_, Score_>) constraintWeightDescriptor.createExtractor();
            ruleToConstraintWeightExtractorMap.put(rule, constraintWeightExtractor);
        }
    }

    public Map<Rule, Function<Solution_, Score_>> getRuleToConstraintWeightExtractorMap() {
        return ruleToConstraintWeightExtractorMap;
    }

    // ************************************************************************
    // Complex methods
    // ************************************************************************

    @Override
    public DrlScoreDirector<Solution_, Score_> buildScoreDirector(
            boolean lookUpEnabled, boolean constraintMatchEnabledPreference) {
        return new DrlScoreDirector<>(this, lookUpEnabled, constraintMatchEnabledPreference);
    }

    public KieSession newKieSession() {
        return kieBase.newKieSession();
    }

}

        boolean hasGlobalScoreHolder = false;
        for (KiePackage kiePackage : kieBase.getKiePackages()) {
            for (Global global : kiePackage.getGlobalVariables()) {
                if (DrlScoreDirector.GLOBAL_SCORE_HOLDER_KEY.equals(global.getName())) {
                    hasGlobalScoreHolder = true;
                    // TODO Fail fast once global.getType() can be turned into a Class instead of a String
                    //                    if (!ScoreHolder.class.isAssignableFrom(global.getType())) {
                    //                        throw new IllegalStateException("The global with name (" + global.getName()
                    //                                + ") has a type (" + global.getType()
                    //                                + ") that does not implement " + ScoreHolder.class.getSimpleName() + ".");
                    //                    }
                    break;
                }
            }
        }
        if (!hasGlobalScoreHolder) {
            throw new IllegalArgumentException("The kieBase with kiePackages (" + kieBase.getKiePackages()
                    + ") has no global field called " + DrlScoreDirector.GLOBAL_SCORE_HOLDER_KEY + ".\n"
                    + "Check if the rule files are found and if the global field is spelled correctly.");
        }
    
<methods>public void <init>(SolutionDescriptor<Solution_>) ,public void assertScoreFromScratch(Solution_) ,public InnerScoreDirector<Solution_,Score_> buildScoreDirector() ,public InnerScoreDirectorFactory<Solution_,Score_> getAssertionScoreDirectorFactory() ,public org.optaplanner.core.impl.score.trend.InitializingScoreTrend getInitializingScoreTrend() ,public ScoreDefinition<Score_> getScoreDefinition() ,public SolutionDescriptor<Solution_> getSolutionDescriptor() ,public boolean isAssertClonedSolution() ,public void setAssertClonedSolution(boolean) ,public void setAssertionScoreDirectorFactory(InnerScoreDirectorFactory<Solution_,Score_>) ,public void setInitializingScoreTrend(org.optaplanner.core.impl.score.trend.InitializingScoreTrend) <variables>protected boolean assertClonedSolution,protected InnerScoreDirectorFactory<Solution_,Score_> assertionScoreDirectorFactory,protected org.optaplanner.core.impl.score.trend.InitializingScoreTrend initializingScoreTrend,protected final transient Logger logger,protected SolutionDescriptor<Solution_> solutionDescriptor