public void inherit(SolverConfig inheritedConfig) {
   if (environmentMode == null) {
     environmentMode = inheritedConfig.getEnvironmentMode();
   }
   if (randomSeed == null) {
     randomSeed = inheritedConfig.getRandomSeed();
   }
   if (solutionClass == null) {
     solutionClass = inheritedConfig.getSolutionClass();
   }
   planningEntityClassList =
       ConfigUtils.inheritMergeableListProperty(
           planningEntityClassList, inheritedConfig.getPlanningEntityClassList());
   if (scoreDirectorFactoryConfig == null) {
     scoreDirectorFactoryConfig = inheritedConfig.getScoreDirectorFactoryConfig();
   } else if (inheritedConfig.getScoreDirectorFactoryConfig() != null) {
     scoreDirectorFactoryConfig.inherit(inheritedConfig.getScoreDirectorFactoryConfig());
   }
   if (terminationConfig == null) {
     terminationConfig = inheritedConfig.getTerminationConfig();
   } else if (inheritedConfig.getTerminationConfig() != null) {
     terminationConfig.inherit(inheritedConfig.getTerminationConfig());
   }
   solverPhaseConfigList =
       ConfigUtils.inheritMergeableListProperty(
           solverPhaseConfigList, inheritedConfig.getSolverPhaseConfigList());
 }
 public Solver buildSolver() {
   DefaultSolver solver = new DefaultSolver();
   BasicPlumbingTermination basicPlumbingTermination = new BasicPlumbingTermination();
   solver.setBasicPlumbingTermination(basicPlumbingTermination);
   EnvironmentMode environmentMode =
       this.environmentMode == null ? EnvironmentMode.REPRODUCIBLE : this.environmentMode;
   if (randomSeed != null) {
     solver.setRandomSeed(randomSeed);
   } else {
     if (environmentMode != EnvironmentMode.PRODUCTION) {
       solver.setRandomSeed(DEFAULT_RANDOM_SEED);
     }
   }
   SolutionDescriptor solutionDescriptor = buildSolutionDescriptor();
   ScoreDirectorFactoryConfig scoreDirectorFactoryConfig_ =
       scoreDirectorFactoryConfig == null
           ? new ScoreDirectorFactoryConfig()
           : scoreDirectorFactoryConfig;
   ScoreDirectorFactory scoreDirectorFactory =
       scoreDirectorFactoryConfig_.buildScoreDirectorFactory(environmentMode, solutionDescriptor);
   solver.setScoreDirectorFactory(scoreDirectorFactory);
   ScoreDefinition scoreDefinition = scoreDirectorFactory.getScoreDefinition();
   TerminationConfig terminationConfig_ =
       terminationConfig == null ? new TerminationConfig() : terminationConfig;
   Termination termination =
       terminationConfig_.buildTermination(scoreDefinition, basicPlumbingTermination);
   solver.setTermination(termination);
   BestSolutionRecaller bestSolutionRecaller = buildBestSolutionRecaller(environmentMode);
   solver.setBestSolutionRecaller(bestSolutionRecaller);
   if (CollectionUtils.isEmpty(solverPhaseConfigList)) {
     throw new IllegalArgumentException(
         "Configure at least 1 phase (for example <localSearch>) in the solver configuration.");
   }
   List<SolverPhase> solverPhaseList = new ArrayList<SolverPhase>(solverPhaseConfigList.size());
   int phaseIndex = 0;
   for (SolverPhaseConfig solverPhaseConfig : solverPhaseConfigList) {
     SolverPhase solverPhase =
         solverPhaseConfig.buildSolverPhase(
             phaseIndex, environmentMode, solutionDescriptor, scoreDefinition, termination);
     ((AbstractSolverPhase) solverPhase).setBestSolutionRecaller(bestSolutionRecaller);
     solverPhaseList.add(solverPhase);
     phaseIndex++;
   }
   solver.setSolverPhaseList(solverPhaseList);
   return solver;
 }