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;
 }
 public void inherit(LocalSearchSolverPhaseConfig inheritedConfig) {
   super.inherit(inheritedConfig);
   moveSelectorConfigList =
       ConfigUtils.inheritMergeableListProperty(
           moveSelectorConfigList, inheritedConfig.getMoveSelectorConfigList());
   if (acceptorConfig == null) {
     acceptorConfig = inheritedConfig.getAcceptorConfig();
   } else if (inheritedConfig.getAcceptorConfig() != null) {
     acceptorConfig.inherit(inheritedConfig.getAcceptorConfig());
   }
   if (foragerConfig == null) {
     foragerConfig = inheritedConfig.getForagerConfig();
   } else if (inheritedConfig.getForagerConfig() != null) {
     foragerConfig.inherit(inheritedConfig.getForagerConfig());
   }
 }