Package org.optaplanner.core.impl.score.director

## Interface ScoreDirector<Solution_>

- Type Parameters:
    `Solution_` - the solution type, the class with the `PlanningSolution` annotation
  All Superinterfaces:
    `AutoCloseable`
  All Known Subinterfaces:
    `InnerScoreDirector<Solution_>`
  All Known Implementing Classes:
    `AbstractScoreDirector`, `ConstraintStreamScoreDirector`, `DroolsScoreDirector`, `EasyScoreDirector`, `IncrementalScoreDirector`, `TestGenDroolsScoreDirector`

      public interface ScoreDirector<Solution_>
      extends AutoCloseable

  The ScoreDirector holds the `working solution` and calculates the `Score` for it.

- - ### Method Summary

    All Methods Instance Methods Abstract Methods Default Methods Deprecated Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `afterEntityAdded​(Object entity)` |
    `void` | `afterEntityRemoved​(Object entity)` |
    `void` | `afterProblemFactAdded​(Object problemFact)` |
    `void` | `afterProblemFactRemoved​(Object problemFact)` |
    `void` | `afterProblemPropertyChanged​(Object problemFactOrEntity)` |
    `void` | `afterVariableChanged​(Object entity, String variableName)` |
    `void` | `afterVariableChanged​(VariableDescriptor variableDescriptor, Object entity)` |
    `void` | `beforeEntityAdded​(Object entity)` |
    `void` | `beforeEntityRemoved​(Object entity)` |
    `void` | `beforeProblemFactAdded​(Object problemFact)` |
    `void` | `beforeProblemFactRemoved​(Object problemFact)` |
    `void` | `beforeProblemPropertyChanged​(Object problemFactOrEntity)` |
    `void` | `beforeVariableChanged​(Object entity, String variableName)` |
    `void` | `beforeVariableChanged​(VariableDescriptor variableDescriptor, Object entity)` |
    `Score` | `calculateScore()` | Calculates the `Score` and updates the `working solution` accordingly.
    `void` | `changeVariableFacade​(VariableDescriptor variableDescriptor, Object entity, Object newValue)` |
    `void` | `close()` | Needs to be called after use because some implementations need to clean up their resources.
    `default void` | `dispose()` | Deprecated. in favor of `close()`
    `String` | `explainScore()` | Returns a diagnostic text that explains the `Score` through the `ConstraintMatch` API to identify which constraints or planning entities cause that score quality.
    `Map<String,​ConstraintMatchTotal>` | `getConstraintMatchTotalMap()` | Explains the `Score` of `calculateScore()` by splitting it up per `Constraint`.
    `Collection<ConstraintMatchTotal>` | `getConstraintMatchTotals()` | Explains the `Score` of `calculateScore()` by splitting it up per `Constraint`.
    `Map<Object,​Indictment>` | `getIndictmentMap()` | Explains the impact of each planning entity or problem fact on the `Score`.
    `Solution_` | `getWorkingSolution()` | The `PlanningSolution` that is used to calculate the `Score`.
    `boolean` | `isConstraintMatchEnabled()` |
    `<E> E` | `lookUpWorkingObject​(E externalObject)` | Translates an entity or fact instance (often from another `Thread` or JVM) to this `ScoreDirector`'s internal working instance.
    `<E> E` | `lookUpWorkingObjectOrReturnNull​(E externalObject)` | As defined by `lookUpWorkingObject(Object)`, but doesn't fail fast if no workingObject was ever added for the externalObject.
    `void` | `setWorkingSolution​(Solution_ workingSolution)` | The `working solution` must never be the same instance as the `best solution`, it should be a (un)changed clone.
    `void` | `triggerVariableListeners()` |

- - ### Method Detail

    - #### getWorkingSolution

          Solution_ getWorkingSolution()

      The `PlanningSolution` that is used to calculate the `Score`.

      Because a `Score` is best calculated incrementally (by deltas), the `ScoreDirector` needs to be notified when its `working solution` changes.

      If the `working solution` has been changed since `calculateScore()` was called, its `Score` won't be correct.

      Returns:
        never null

    - #### setWorkingSolution

          void setWorkingSolution​(Solution_ workingSolution)

      The `working solution` must never be the same instance as the `best solution`, it should be a (un)changed clone.

      Only call this method on a separate `ScoreDirector` instance, built by `SolverFactory.getScoreDirectorFactory()`, not on the one used inside the `Solver` itself.

      Parameters:
        `workingSolution` - never null

    - #### calculateScore

          Score calculateScore()

      Calculates the `Score` and updates the `working solution` accordingly.
      Returns:
        never null, the `Score` of the `working solution`

    - #### isConstraintMatchEnabled

          boolean isConstraintMatchEnabled()

      Returns:
        true if `getConstraintMatchTotals()`, `getConstraintMatchTotalMap()` and `getIndictmentMap()` can be called

    - #### getConstraintMatchTotals

          Collection<ConstraintMatchTotal> getConstraintMatchTotals()

      Explains the `Score` of `calculateScore()` by splitting it up per `Constraint`.

      The sum of `ConstraintMatchTotal.getScore()` equals `calculateScore()`.

      Call `calculateScore()` before calling this method, unless that method has already been called since the last `PlanningVariable` changes.

      Returns:
        never null
      Throws:
        `IllegalStateException` - if `isConstraintMatchEnabled()` returns false
      See Also:
        `getConstraintMatchTotalMap()`, `getIndictmentMap()`

    - #### getConstraintMatchTotalMap

          Map<String,​ConstraintMatchTotal> getConstraintMatchTotalMap()

      Explains the `Score` of `calculateScore()` by splitting it up per `Constraint`.

      The sum of `ConstraintMatchTotal.getScore()` equals `calculateScore()`.

      Call `calculateScore()` before calling this method, unless that method has already been called since the last `PlanningVariable` changes.

      Returns:
        never null, the key is the `constraintId` (to create one, use `ConstraintMatchTotal.composeConstraintId(String, String)`).
      Throws:
        `IllegalStateException` - if `isConstraintMatchEnabled()` returns false
      See Also:
        `getIndictmentMap()`

    - #### getIndictmentMap

          Map<Object,​Indictment> getIndictmentMap()

      Explains the impact of each planning entity or problem fact on the `Score`. An `Indictment` is basically the inverse of a `ConstraintMatchTotal`: it is a `Score` total for each justification `Object` in `ConstraintMatch.getJustificationList()`.

      The sum of `ConstraintMatchTotal.getScore()` differs from `calculateScore()` because each `ConstraintMatch.getScore()` is counted for each justification in `ConstraintMatch.getJustificationList()`.

      Call `calculateScore()` before calling this method, unless that method has already been called since the last `PlanningVariable` changes.

      Returns:
        never null, the key is a `problem fact` or a `planning entity`
      Throws:
        `IllegalStateException` - if `isConstraintMatchEnabled()` returns false
      See Also:
        `getConstraintMatchTotalMap()`

    - #### explainScore

          String explainScore()

      Returns a diagnostic text that explains the `Score` through the `ConstraintMatch` API to identify which constraints or planning entities cause that score quality. In case of an `infeasible` solution, this can help diagnose the cause of that.

      Do not parse this string. Instead, to provide this information in a UI or a service, use `getConstraintMatchTotalMap()` and `getIndictmentMap()` and convert those into a domain specific API.

      This automatically calls `calculateScore()` first.

      Returns:
        never null
      Throws:
        `IllegalStateException` - if `isConstraintMatchEnabled()` returns false

    - #### beforeEntityAdded

          void beforeEntityAdded​(Object entity)

    - #### afterEntityAdded

          void afterEntityAdded​(Object entity)

    - #### beforeVariableChanged

          void beforeVariableChanged​(Object entity,
                                     String variableName)

    - #### afterVariableChanged

          void afterVariableChanged​(Object entity,
                                    String variableName)

    - #### triggerVariableListeners

          void triggerVariableListeners()

    - #### beforeEntityRemoved

          void beforeEntityRemoved​(Object entity)

    - #### afterEntityRemoved

          void afterEntityRemoved​(Object entity)

    - #### beforeProblemFactAdded

          void beforeProblemFactAdded​(Object problemFact)

    - #### afterProblemFactAdded

          void afterProblemFactAdded​(Object problemFact)

    - #### beforeProblemPropertyChanged

          void beforeProblemPropertyChanged​(Object problemFactOrEntity)

    - #### afterProblemPropertyChanged

          void afterProblemPropertyChanged​(Object problemFactOrEntity)

    - #### beforeProblemFactRemoved

          void beforeProblemFactRemoved​(Object problemFact)

    - #### afterProblemFactRemoved

          void afterProblemFactRemoved​(Object problemFact)

    - #### lookUpWorkingObject

          <E> E lookUpWorkingObject​(E externalObject)

      Translates an entity or fact instance (often from another `Thread` or JVM) to this `ScoreDirector`'s internal working instance. Useful for `Move.rebase(ScoreDirector)` and in a `ProblemFactChange`.

      Matching is determined by the `LookUpStrategyType` on `PlanningSolution`. Matching uses a `PlanningId` by default.

      Type Parameters:
        `E` - the object type
      Parameters:
        `externalObject` - sometimes null
      Returns:
        null if externalObject is null
      Throws:
        `IllegalArgumentException` - if there is no workingObject for externalObject, if it cannot be looked up or if the externalObject's class is not supported
        `IllegalStateException` - if it cannot be looked up

    - #### lookUpWorkingObjectOrReturnNull

          <E> E lookUpWorkingObjectOrReturnNull​(E externalObject)

      As defined by `lookUpWorkingObject(Object)`, but doesn't fail fast if no workingObject was ever added for the externalObject. It's recommended to use `lookUpWorkingObject(Object)` instead, especially in a `Move.rebase(ScoreDirector)` code.
      Type Parameters:
        `E` - the object type
      Parameters:
        `externalObject` - sometimes null
      Returns:
        null if externalObject is null or if there is no workingObject for externalObject
      Throws:
        `IllegalArgumentException` - if it cannot be looked up or if the externalObject's class is not supported
        `IllegalStateException` - if it cannot be looked up

    - #### close

          void close()

      Needs to be called after use because some implementations need to clean up their resources.
      Specified by:
        `close` in interface `AutoCloseable`

    - #### dispose

          @Deprecated
          default void dispose()

      Deprecated.
      in favor of `close()`

    - #### beforeVariableChanged

          void beforeVariableChanged​(VariableDescriptor variableDescriptor,
                                     Object entity)

    - #### afterVariableChanged

          void afterVariableChanged​(VariableDescriptor variableDescriptor,
                                    Object entity)

    - #### changeVariableFacade

          void changeVariableFacade​(VariableDescriptor variableDescriptor,
                                    Object entity,
                                    Object newValue)