Package org.optaplanner.core.config.score.director

Source Code of org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig

/*
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.optaplanner.core.config.score.director;

import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Map;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import org.kie.api.KieBase;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.io.KieResources;
import org.kie.api.runtime.KieContainer;
import org.optaplanner.core.config.score.definition.ScoreDefinitionType;
import org.optaplanner.core.config.score.trend.InitializingScoreTrendLevel;
import org.optaplanner.core.config.solver.EnvironmentMode;
import org.optaplanner.core.config.util.ConfigUtils;
import org.optaplanner.core.config.util.KeyAsElementMapConverter;
import org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor;
import org.optaplanner.core.impl.score.buildin.bendable.BendableScoreDefinition;
import org.optaplanner.core.impl.score.buildin.bendablebigdecimal.BendableBigDecimalScoreDefinition;
import org.optaplanner.core.impl.score.buildin.hardmediumsoft.HardMediumSoftScoreDefinition;
import org.optaplanner.core.impl.score.buildin.hardmediumsoftlong.HardMediumSoftLongScoreDefinition;
import org.optaplanner.core.impl.score.buildin.hardsoft.HardSoftScoreDefinition;
import org.optaplanner.core.impl.score.buildin.hardsoftbigdecimal.HardSoftBigDecimalScoreDefinition;
import org.optaplanner.core.impl.score.buildin.hardsoftdouble.HardSoftDoubleScoreDefinition;
import org.optaplanner.core.impl.score.buildin.hardsoftlong.HardSoftLongScoreDefinition;
import org.optaplanner.core.impl.score.buildin.simple.SimpleScoreDefinition;
import org.optaplanner.core.impl.score.buildin.simplebigdecimal.SimpleBigDecimalScoreDefinition;
import org.optaplanner.core.impl.score.buildin.simpledouble.SimpleDoubleScoreDefinition;
import org.optaplanner.core.impl.score.buildin.simplelong.SimpleLongScoreDefinition;
import org.optaplanner.core.impl.score.definition.ScoreDefinition;
import org.optaplanner.core.impl.score.director.AbstractScoreDirectorFactory;
import org.optaplanner.core.impl.score.director.InnerScoreDirectorFactory;
import org.optaplanner.core.impl.score.director.drools.DroolsScoreDirectorFactory;
import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
import org.optaplanner.core.impl.score.director.easy.EasyScoreDirectorFactory;
import org.optaplanner.core.impl.score.director.incremental.IncrementalScoreCalculator;
import org.optaplanner.core.impl.score.director.incremental.IncrementalScoreDirectorFactory;
import org.optaplanner.core.impl.score.trend.InitializingScoreTrend;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@XStreamAlias("scoreDirectorFactory")
public class ScoreDirectorFactoryConfig {

    private static final Logger logger = LoggerFactory.getLogger(ScoreDirectorFactoryConfig.class);

    protected Class<? extends ScoreDefinition> scoreDefinitionClass = null;
    protected ScoreDefinitionType scoreDefinitionType = null;
    protected Integer bendableHardLevelsSize = null;
    protected Integer bendableSoftLevelsSize = null;

    protected Class<? extends EasyScoreCalculator> easyScoreCalculatorClass = null;

    protected Class<? extends IncrementalScoreCalculator> incrementalScoreCalculatorClass = null;

    @XStreamOmitField
    protected KieBase kieBase = null;
    @XStreamImplicit(itemFieldName = "scoreDrl")
    protected List<String> scoreDrlList = null;
    @XStreamImplicit(itemFieldName = "scoreDrlFile")
    protected List<File> scoreDrlFileList = null;
    @XStreamConverter(value = KeyAsElementMapConverter.class)
    protected Map<String, String> kieBaseConfigurationProperties = null;

    protected String initializingScoreTrend = null;

    @XStreamAlias("assertionScoreDirectorFactory")
    protected ScoreDirectorFactoryConfig assertionScoreDirectorFactory = null;

    public Class<? extends ScoreDefinition> getScoreDefinitionClass() {
        return scoreDefinitionClass;
    }

    public void setScoreDefinitionClass(Class<? extends ScoreDefinition> scoreDefinitionClass) {
        this.scoreDefinitionClass = scoreDefinitionClass;
    }

    public ScoreDefinitionType getScoreDefinitionType() {
        return scoreDefinitionType;
    }

    public void setScoreDefinitionType(ScoreDefinitionType scoreDefinitionType) {
        this.scoreDefinitionType = scoreDefinitionType;
    }

    public Integer getBendableHardLevelsSize() {
        return bendableHardLevelsSize;
    }

    public void setBendableHardLevelsSize(Integer bendableHardLevelsSize) {
        this.bendableHardLevelsSize = bendableHardLevelsSize;
    }

    public Integer getBendableSoftLevelsSize() {
        return bendableSoftLevelsSize;
    }

    public void setBendableSoftLevelsSize(Integer bendableSoftLevelsSize) {
        this.bendableSoftLevelsSize = bendableSoftLevelsSize;
    }

    public Class<? extends EasyScoreCalculator> getEasyScoreCalculatorClass() {
        return easyScoreCalculatorClass;
    }

    public void setEasyScoreCalculatorClass(Class<? extends EasyScoreCalculator> easyScoreCalculatorClass) {
        this.easyScoreCalculatorClass = easyScoreCalculatorClass;
    }

    public Class<? extends IncrementalScoreCalculator> getIncrementalScoreCalculatorClass() {
        return incrementalScoreCalculatorClass;
    }

    public void setIncrementalScoreCalculatorClass(Class<? extends IncrementalScoreCalculator> incrementalScoreCalculatorClass) {
        this.incrementalScoreCalculatorClass = incrementalScoreCalculatorClass;
    }

    public KieBase getKieBase() {
        return kieBase;
    }

    public void setKieBase(KieBase kieBase) {
        this.kieBase = kieBase;
    }

    public List<String> getScoreDrlList() {
        return scoreDrlList;
    }

    public void setScoreDrlList(List<String> scoreDrlList) {
        this.scoreDrlList = scoreDrlList;
    }

    public List<File> getScoreDrlFileList() {
        return scoreDrlFileList;
    }

    public void setScoreDrlFileList(List<File> scoreDrlFileList) {
        this.scoreDrlFileList = scoreDrlFileList;
    }

    public Map<String, String> getKieBaseConfigurationProperties() {
        return kieBaseConfigurationProperties;
    }

    public void setKieBaseConfigurationProperties(Map<String, String> kieBaseConfigurationProperties) {
        this.kieBaseConfigurationProperties = kieBaseConfigurationProperties;
    }

    public String getInitializingScoreTrend() {
        return initializingScoreTrend;
    }

    public void setInitializingScoreTrend(String initializingScoreTrend) {
        this.initializingScoreTrend = initializingScoreTrend;
    }

    public ScoreDirectorFactoryConfig getAssertionScoreDirectorFactory() {
        return assertionScoreDirectorFactory;
    }

    public void setAssertionScoreDirectorFactory(ScoreDirectorFactoryConfig assertionScoreDirectorFactory) {
        this.assertionScoreDirectorFactory = assertionScoreDirectorFactory;
    }

    // ************************************************************************
    // Builder methods
    // ************************************************************************

    public InnerScoreDirectorFactory buildScoreDirectorFactory(EnvironmentMode environmentMode,
            SolutionDescriptor solutionDescriptor) {
        ScoreDefinition scoreDefinition = buildScoreDefinition();
        return buildScoreDirectorFactory(environmentMode, solutionDescriptor, scoreDefinition);
    }

    protected InnerScoreDirectorFactory buildScoreDirectorFactory(EnvironmentMode environmentMode,
            SolutionDescriptor solutionDescriptor, ScoreDefinition scoreDefinition) {
        AbstractScoreDirectorFactory scoreDirectorFactory;
        // TODO this should fail-fast if multiple scoreDirectorFactory's are configured or if none are configured
        scoreDirectorFactory = buildEasyScoreDirectorFactory();
        if (scoreDirectorFactory == null) {
            scoreDirectorFactory = buildIncrementalScoreDirectorFactory();
        }
        if (scoreDirectorFactory == null) {
            scoreDirectorFactory = buildDroolsScoreDirectorFactory();
        }
        scoreDirectorFactory.setSolutionDescriptor(solutionDescriptor);
        scoreDirectorFactory.setScoreDefinition(scoreDefinition);
        if (assertionScoreDirectorFactory != null) {
            if (assertionScoreDirectorFactory.getAssertionScoreDirectorFactory() != null) {
                throw new IllegalArgumentException("A assertionScoreDirectorFactory ("
                        + assertionScoreDirectorFactory + ") cannot have a non-null assertionScoreDirectorFactory ("
                        + assertionScoreDirectorFactory.getAssertionScoreDirectorFactory() + ").");
            }
            if (assertionScoreDirectorFactory.getScoreDefinitionClass() != null
                    || assertionScoreDirectorFactory.getScoreDefinitionType() != null) {
                throw new IllegalArgumentException("A assertionScoreDirectorFactory ("
                        + assertionScoreDirectorFactory + ") must reuse the scoreDefinition of its parent." +
                        " It cannot have a non-null scoreDefinition* property.");
            }
            if (environmentMode.compareTo(EnvironmentMode.FAST_ASSERT) > 0) {
                throw new IllegalArgumentException("A non-null assertionScoreDirectorFactory ("
                        + assertionScoreDirectorFactory + ") requires an environmentMode ("
                        + environmentMode + ") of " + EnvironmentMode.FAST_ASSERT + " or lower.");
            }
            scoreDirectorFactory.setAssertionScoreDirectorFactory(
                    assertionScoreDirectorFactory.buildScoreDirectorFactory(
                            EnvironmentMode.PRODUCTION, solutionDescriptor, scoreDefinition));
        }
        scoreDirectorFactory.setInitializingScoreTrend(InitializingScoreTrend.parseTrend(
                initializingScoreTrend == null ? InitializingScoreTrendLevel.ANY.name() : initializingScoreTrend,
                scoreDefinition.getLevelsSize()));
        return scoreDirectorFactory;
    }

    public ScoreDefinition buildScoreDefinition() {
        if (scoreDefinitionType != ScoreDefinitionType.BENDABLE
                && scoreDefinitionType != ScoreDefinitionType.BENDABLE_BIG_DECIMAL
                && (bendableHardLevelsSize != null || bendableSoftLevelsSize != null)) {
            throw new IllegalArgumentException("With scoreDefinitionType (" + scoreDefinitionType
                    + ") there must be no bendableHardLevelsSize (" + bendableHardLevelsSize
                    + ") or bendableSoftLevelsSize (" + bendableSoftLevelsSize + ").");
        }
        if (scoreDefinitionClass != null) {
            if (scoreDefinitionType != null || bendableHardLevelsSize != null || bendableSoftLevelsSize != null) {
                throw new IllegalStateException("With scoreDefinitionClass (" + scoreDefinitionClass
                        + ") there must be no scoreDefinitionType (" + scoreDefinitionType
                        + ") or bendableHardLevelsSize (" + bendableHardLevelsSize
                        + ") or bendableSoftLevelsSize (" + bendableSoftLevelsSize + ").");
            }
            return ConfigUtils.newInstance(this, "scoreDefinitionClass", scoreDefinitionClass);
        }
        if (scoreDefinitionType != null) {
            switch (scoreDefinitionType) {
                case SIMPLE:
                    return new SimpleScoreDefinition();
                case SIMPLE_LONG:
                    return new SimpleLongScoreDefinition();
                case SIMPLE_DOUBLE:
                    return new SimpleDoubleScoreDefinition();
                case SIMPLE_BIG_DECIMAL:
                    return new SimpleBigDecimalScoreDefinition();
                case HARD_SOFT:
                    return new HardSoftScoreDefinition();
                case HARD_SOFT_LONG:
                    return new HardSoftLongScoreDefinition();
                case HARD_SOFT_DOUBLE:
                    return new HardSoftDoubleScoreDefinition();
                case HARD_SOFT_BIG_DECIMAL:
                    return new HardSoftBigDecimalScoreDefinition();
                case HARD_MEDIUM_SOFT:
                    return new HardMediumSoftScoreDefinition();
                case HARD_MEDIUM_SOFT_LONG:
                    return new HardMediumSoftLongScoreDefinition();
                case BENDABLE:
                    if (bendableHardLevelsSize == null || bendableSoftLevelsSize == null) {
                        throw new IllegalArgumentException("With scoreDefinitionType (" + scoreDefinitionType
                                + ") there must be a bendableHardLevelsSize (" + bendableHardLevelsSize
                                + ") and a bendableSoftLevelsSize (" + bendableSoftLevelsSize + ").");
                    }
                    return new BendableScoreDefinition(bendableHardLevelsSize, bendableSoftLevelsSize);
                case BENDABLE_BIG_DECIMAL:
                    if (bendableHardLevelsSize == null || bendableSoftLevelsSize == null) {
                        throw new IllegalArgumentException("With scoreDefinitionType (" + scoreDefinitionType
                                + ") there must be a bendableHardLevelsSize (" + bendableHardLevelsSize
                                + ") and a bendableSoftLevelsSize (" + bendableSoftLevelsSize + ").");
                    }
                    return new BendableBigDecimalScoreDefinition(bendableHardLevelsSize, bendableSoftLevelsSize);
                default:
                    throw new IllegalStateException("The scoreDefinitionType (" + scoreDefinitionType
                            + ") is not implemented.");
            }
        } else {
            return new SimpleScoreDefinition();
        }
    }

    private AbstractScoreDirectorFactory buildEasyScoreDirectorFactory() {
        if (easyScoreCalculatorClass != null) {
            EasyScoreCalculator easyScoreCalculator = ConfigUtils.newInstance(this,
                    "easyScoreCalculatorClass", easyScoreCalculatorClass);
            return new EasyScoreDirectorFactory(easyScoreCalculator);
        } else {
            return null;
        }
    }

    private AbstractScoreDirectorFactory buildIncrementalScoreDirectorFactory() {
        if (incrementalScoreCalculatorClass != null) {
            if (!IncrementalScoreCalculator.class.isAssignableFrom(incrementalScoreCalculatorClass)) {
                throw new IllegalArgumentException(
                        "The incrementalScoreCalculatorClass (" + incrementalScoreCalculatorClass
                        + ") does not implement " + IncrementalScoreCalculator.class.getSimpleName() + ".");
            }
            return new IncrementalScoreDirectorFactory(incrementalScoreCalculatorClass);
        } else {
            return null;
        }
    }

    private AbstractScoreDirectorFactory buildDroolsScoreDirectorFactory() {
        DroolsScoreDirectorFactory scoreDirectorFactory = new DroolsScoreDirectorFactory(buildKieBase());
        return scoreDirectorFactory;
    }

    private KieBase buildKieBase() {
        if (kieBase != null) {
            if (!ConfigUtils.isEmptyCollection(scoreDrlList) || !ConfigUtils.isEmptyCollection(scoreDrlFileList)) {
                throw new IllegalArgumentException("If kieBase is not null, the scoreDrlList (" + scoreDrlList
                        + ") and the scoreDrlFileList (" + scoreDrlFileList + ") must be empty.");
            }
            if (kieBaseConfigurationProperties != null) {
                throw new IllegalArgumentException("If kieBase is not null, the kieBaseConfigurationProperties ("
                        + kieBaseConfigurationProperties + ") must be null.");
            }
            return kieBase;
        } else {
            if (ConfigUtils.isEmptyCollection(scoreDrlList) && ConfigUtils.isEmptyCollection(scoreDrlFileList)) {
                throw new IllegalArgumentException("The scoreDrlList (" + scoreDrlList
                        + ") and the scoreDrlFileList (" + scoreDrlFileList + ") cannot both be empty.");
            }
            if (!ConfigUtils.isEmptyCollection(scoreDrlList) && !ConfigUtils.isEmptyCollection(scoreDrlFileList)) {
                throw new IllegalArgumentException("The scoreDrlList (" + scoreDrlList
                        + ") and the scoreDrlFileList (" + scoreDrlFileList + ") cannot both be non empty.");
            }
            KieServices kieServices = KieServices.Factory.get();
            KieResources kieResources = kieServices.getResources();
            KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
            if (!ConfigUtils.isEmptyCollection(scoreDrlList)) {
                for (String scoreDrl : scoreDrlList) {
                    if (scoreDrl == null) {
                        throw new IllegalArgumentException("The scoreDrl (" + scoreDrl + ") cannot be null.");
                    }
                    URL scoreDrlURL = getClass().getClassLoader().getResource(scoreDrl);
                    if (scoreDrlURL == null) {
                        String errorMessage = "The scoreDrl (" + scoreDrl + ") does not exist as a classpath resource.";
                        if (scoreDrl.startsWith("/")) {
                            errorMessage += "\nAs from 6.1, a classpath resource should not start with a slash (/)."
                                    + " A scoreDrl now adheres to ClassLoader.getResource(String)."
                                    + " Remove the leading slash from the scoreDrl if you're upgrading from 6.0.";
                        }
                        throw new IllegalArgumentException(errorMessage);
                    }
                    kieFileSystem.write(kieResources.newClassPathResource(scoreDrl, "UTF-8"));
                }
            }
            if (!ConfigUtils.isEmptyCollection(scoreDrlFileList)) {
                for (File scoreDrlFile : scoreDrlFileList) {
                    if (scoreDrlFile == null) {
                        throw new IllegalArgumentException("The scoreDrlFile (" + scoreDrlFile + ") cannot be null.");
                    }
                    if (!scoreDrlFile.exists()) {
                        throw new IllegalArgumentException("The scoreDrlFile (" + scoreDrlFile
                                + ") does not exist.");
                    }
                    kieFileSystem.write(kieResources.newFileSystemResource(scoreDrlFile, "UTF-8"));
                }
            }
            KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
            kieBuilder.buildAll();
            Results results = kieBuilder.getResults();
            if (results.hasMessages(Message.Level.ERROR)) {
                throw new IllegalStateException("There are errors in a score DRL:\n"
                        + results.toString());
            } else if (results.hasMessages(Message.Level.WARNING)) {
                logger.warn("There are warning in a score DRL:\n"
                        + results.toString());
            }
            KieContainer kieContainer = kieServices.newKieContainer(kieBuilder.getKieModule().getReleaseId());

            KieBaseConfiguration kieBaseConfiguration = kieServices.newKieBaseConfiguration();
            if (kieBaseConfigurationProperties != null) {
                for (Map.Entry<String, String> entry : kieBaseConfigurationProperties.entrySet()) {
                    kieBaseConfiguration.setProperty(entry.getKey(), entry.getValue());
                }
            }
            KieBase kieBase = kieContainer.newKieBase(kieBaseConfiguration);

            return kieBase;
        }
    }

    public void inherit(ScoreDirectorFactoryConfig inheritedConfig) {
        if (scoreDefinitionClass == null && scoreDefinitionType == null
                && bendableHardLevelsSize == null && bendableSoftLevelsSize == null) {
            scoreDefinitionClass = inheritedConfig.getScoreDefinitionClass();
            scoreDefinitionType = inheritedConfig.getScoreDefinitionType();
            bendableHardLevelsSize = inheritedConfig.getBendableHardLevelsSize();
            bendableSoftLevelsSize = inheritedConfig.getBendableSoftLevelsSize();
        }
        easyScoreCalculatorClass = ConfigUtils.inheritOverwritableProperty(
                easyScoreCalculatorClass, inheritedConfig.getEasyScoreCalculatorClass());
        incrementalScoreCalculatorClass = ConfigUtils.inheritOverwritableProperty(
                incrementalScoreCalculatorClass, inheritedConfig.getIncrementalScoreCalculatorClass());
        kieBase = ConfigUtils.inheritOverwritableProperty(
                kieBase, inheritedConfig.getKieBase());
        scoreDrlList = ConfigUtils.inheritMergeableListProperty(
                scoreDrlList, inheritedConfig.getScoreDrlList());
        scoreDrlFileList = ConfigUtils.inheritMergeableListProperty(
                scoreDrlFileList, inheritedConfig.getScoreDrlFileList());
        kieBaseConfigurationProperties = ConfigUtils.inheritMergeableMapProperty(
                kieBaseConfigurationProperties, inheritedConfig.getKieBaseConfigurationProperties());
        initializingScoreTrend = ConfigUtils.inheritOverwritableProperty(
                initializingScoreTrend, inheritedConfig.getInitializingScoreTrend());

        assertionScoreDirectorFactory = ConfigUtils.inheritOverwritableProperty(
                assertionScoreDirectorFactory, inheritedConfig.getAssertionScoreDirectorFactory());
    }

}
TOP

Related Classes of org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.