/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* 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.api.solver;
import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import org.kie.api.KieServices;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.config.SolverConfigContext;
import org.optaplanner.core.config.solver.SolverConfig;
import org.optaplanner.core.impl.solver.EmptySolverFactory;
import org.optaplanner.core.impl.solver.XStreamXmlSolverFactory;
/**
* Builds {@link Solver} instances.
* <p>
* To build an instance, use {@link #createFromXmlResource(String)} or any of the other creation methods.
* <p>
* Supports tweaking the configuration programmatically before a {@link Solver} instance is build.
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation
*/
public abstract class SolverFactory<Solution_> {
// ************************************************************************
// Static creation methods: XML
// ************************************************************************
/**
* Uses {@link KieServices#getKieClasspathContainer()}.
* @param solverConfigResource never null, a classpath resource in the {@link KieContainer}
* as defined by {@link ClassLoader#getResource(String)}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromKieContainerXmlResource(
String solverConfigResource) {
KieContainer kieContainer = KieServices.Factory.get().getKieClasspathContainer();
return new XStreamXmlSolverFactory<Solution_>(new SolverConfigContext(kieContainer))
.configure(solverConfigResource);
}
/**
* @param releaseId never null
* @param solverConfigResource never null, a classpath resource in the {@link KieContainer}
* as defined by {@link ClassLoader#getResource(String)}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromKieContainerXmlResource(
ReleaseId releaseId, String solverConfigResource) {
KieContainer kieContainer = KieServices.Factory.get().newKieContainer(releaseId);
return createFromKieContainerXmlResource(kieContainer, solverConfigResource);
}
/**
* @param kieContainer never null
* @param solverConfigResource never null, a classpath resource in the {@link KieContainer}
* as defined by {@link ClassLoader#getResource(String)}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromKieContainerXmlResource(
KieContainer kieContainer, String solverConfigResource) {
return new XStreamXmlSolverFactory<Solution_>(new SolverConfigContext(kieContainer))
.configure(solverConfigResource);
}
/**
* @param solverConfigResource never null, a classpath resource
* as defined by {@link ClassLoader#getResource(String)}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlResource(String solverConfigResource) {
return new XStreamXmlSolverFactory<Solution_>()
.configure(solverConfigResource);
}
/**
* See {@link #createFromXmlResource(String)}.
* @param solverConfigResource never null, a classpath resource
* as defined by {@link ClassLoader#getResource(String)}
* @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es,
* null to use the default {@link ClassLoader}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlResource(String solverConfigResource, ClassLoader classLoader) {
return new XStreamXmlSolverFactory<Solution_>(new SolverConfigContext(classLoader))
.configure(solverConfigResource);
}
/**
* @param solverConfigFile never null
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlFile(File solverConfigFile) {
return new XStreamXmlSolverFactory<Solution_>()
.configure(solverConfigFile);
}
/**
* @param solverConfigFile never null
* @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es,
* null to use the default {@link ClassLoader}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlFile(File solverConfigFile, ClassLoader classLoader) {
return new XStreamXmlSolverFactory<Solution_>(new SolverConfigContext(classLoader))
.configure(solverConfigFile);
}
/**
* @param in never null, gets closed
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlInputStream(InputStream in) {
return new XStreamXmlSolverFactory<Solution_>()
.configure(in);
}
/**
* @param in never null, gets closed
* @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es,
* null to use the default {@link ClassLoader}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlInputStream(InputStream in, ClassLoader classLoader) {
return new XStreamXmlSolverFactory<Solution_>(new SolverConfigContext(classLoader))
.configure(in);
}
/**
* @param reader never null, gets closed
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlReader(Reader reader) {
return new XStreamXmlSolverFactory<Solution_>()
.configure(reader);
}
/**
* @param reader never null, gets closed
* @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es,
* null to use the default {@link ClassLoader}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createFromXmlReader(Reader reader, ClassLoader classLoader) {
return new XStreamXmlSolverFactory<Solution_>(new SolverConfigContext(classLoader))
.configure(reader);
}
// ************************************************************************
// Static creation methods: empty
// ************************************************************************
/**
* Useful to build configuration programmatically, although it's almost always recommended
* to instead load a partial configuration with {@link #createFromXmlResource(String)}
* and configure the remainder programmatically with {@link #getSolverConfig()}.
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createEmpty() {
return new EmptySolverFactory<>();
}
/**
* See {@link #createEmpty()}.
* @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es,
* null to use the default {@link ClassLoader}
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createEmpty(ClassLoader classLoader) {
return new EmptySolverFactory<>(new SolverConfigContext(classLoader));
}
/**
* @param releaseId never null
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createEmptyFromKieContainer(ReleaseId releaseId) {
KieContainer kieContainer = KieServices.Factory.get().newKieContainer(releaseId);
return createEmptyFromKieContainer(kieContainer);
}
/**
* @param kieContainer never null
* @return never null
*/
public static <Solution_> SolverFactory<Solution_> createEmptyFromKieContainer(KieContainer kieContainer) {
return new EmptySolverFactory<>(new SolverConfigContext(kieContainer));
}
// ************************************************************************
// Interface methods
// ************************************************************************
/**
* Allows you to programmatically change the {@link SolverConfig} at runtime before building the {@link Solver}.
* <p>
* This method is not thread-safe. To configure a {@link SolverConfig} differently for parallel requests,
* build a template {@link SolverFactory} from XML
* and clone it {@link SolverFactory#cloneSolverFactory()} for each request, before before calling this method.
* @return never null
*/
public abstract SolverConfig getSolverConfig();
/**
* Build a {@link SolverFactory} quickly (without parsing XML) that builds the exact same {@link Solver}
* with {@link #buildSolver()}, but can also be modified with {@link #getSolverConfig()} to build a different
* {@link Solver} without affecting the original {@link SolverFactory}.
* @return never null, often a different {@link SolverFactory} subclass implementation than this instance
*/
public abstract SolverFactory<Solution_> cloneSolverFactory();
/**
* Creates a new {@link Solver} instance.
* @return never null
*/
public abstract Solver<Solution_> buildSolver();
}