public void insertInTrailingEntityMap(
     PlanningVariableDescriptor variableDescriptor, Object entity) {
   if (hasChainedVariables && variableDescriptor.isChained()) {
     Map<Object, Set<Object>> valueToTrailingEntityMap =
         trailingEntitiesMap.get(variableDescriptor);
     if (valueToTrailingEntityMap == null) {
       throw new IllegalStateException(
           "The ScoreDirector ("
               + getClass()
               + ") is bugged,"
               + " because the chained planningVariable ("
               + variableDescriptor.getVariableName()
               + ") was not found in the trailingEntitiesMap.");
     }
     Object value = variableDescriptor.getValue(entity);
     Set<Object> trailingEntities = valueToTrailingEntityMap.get(value);
     if (trailingEntities == null) {
       trailingEntities = Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>());
       valueToTrailingEntityMap.put(value, trailingEntities);
     }
     boolean addSucceeded = trailingEntities.add(entity);
     if (!addSucceeded) {
       throw new IllegalStateException(
           "The ScoreDirector ("
               + getClass()
               + ") is corrupted,"
               + " because the entity ("
               + entity
               + ") for chained planningVariable ("
               + variableDescriptor.getVariableName()
               + ") cannot be inserted: it was already inserted.");
     }
   }
 }
 public void retractFromTrailingEntityMap(
     PlanningVariableDescriptor variableDescriptor, Object entity) {
   if (hasChainedVariables && variableDescriptor.isChained()) {
     Map<Object, Set<Object>> valueToTrailingEntityMap =
         trailingEntitiesMap.get(variableDescriptor);
     if (valueToTrailingEntityMap == null) {
       throw new IllegalStateException(
           "The ScoreDirector ("
               + getClass()
               + ") is bugged,"
               + " because the chained planningVariable ("
               + variableDescriptor.getVariableName()
               + ") was not found in the trailingEntitiesMap.");
     }
     Object value = variableDescriptor.getValue(entity);
     Set<Object> trailingEntities = valueToTrailingEntityMap.get(value);
     boolean removeSucceeded = trailingEntities != null && trailingEntities.remove(entity);
     if (!removeSucceeded) {
       throw new IllegalStateException(
           "The ScoreDirector ("
               + getClass()
               + ") is corrupted,"
               + " because the entity ("
               + entity
               + ") for chained planningVariable ("
               + variableDescriptor.getVariableName()
               + ") cannot be retracted: it was never inserted.");
     }
     if (trailingEntities.isEmpty()) {
       valueToTrailingEntityMap.put(value, null);
     }
   }
 }
 private void retractFromTrailingEntityMap(Object entity) {
   if (hasChainedVariables) {
     for (Map.Entry<PlanningVariableDescriptor, Map<Object, Set<Object>>> entry :
         chainedVariableToTrailingEntitiesMap.entrySet()) {
       PlanningVariableDescriptor variableDescriptor = entry.getKey();
       if (variableDescriptor.getPlanningEntityDescriptor().appliesToPlanningEntity(entity)) {
         Object value = variableDescriptor.getValue(entity);
         Map<Object, Set<Object>> valueToTrailingEntityMap = entry.getValue();
         Set<Object> trailingEntities = valueToTrailingEntityMap.get(value);
         boolean removeSucceeded = trailingEntities != null && trailingEntities.remove(entity);
         if (!removeSucceeded) {
           throw new IllegalStateException(
               "The ScoreDirector ("
                   + getClass()
                   + ") is corrupted,"
                   + " because the entity ("
                   + entity
                   + ") for chained planningVariable ("
                   + variableDescriptor.getVariableName()
                   + ") cannot be retracted: it was never inserted.");
         }
         if (trailingEntities.isEmpty()) {
           valueToTrailingEntityMap.put(value, null);
         }
       }
     }
   }
 }
 private void insertInTrailingEntityMap(Object entity) {
   if (hasChainedVariables) {
     for (Map.Entry<PlanningVariableDescriptor, Map<Object, Set<Object>>> entry :
         chainedVariableToTrailingEntitiesMap.entrySet()) {
       PlanningVariableDescriptor variableDescriptor = entry.getKey();
       if (variableDescriptor.getPlanningEntityDescriptor().appliesToPlanningEntity(entity)) {
         Object value = variableDescriptor.getValue(entity);
         Map<Object, Set<Object>> valueToTrailingEntityMap = entry.getValue();
         Set<Object> trailingEntities = valueToTrailingEntityMap.get(value);
         if (trailingEntities == null) {
           trailingEntities = Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>());
           valueToTrailingEntityMap.put(value, trailingEntities);
         }
         boolean addSucceeded = trailingEntities.add(entity);
         if (!addSucceeded) {
           throw new IllegalStateException(
               "The ScoreDirector ("
                   + getClass()
                   + ") is corrupted,"
                   + " because the entity ("
                   + entity
                   + ") for chained planningVariable ("
                   + variableDescriptor.getVariableName()
                   + ") cannot be inserted: it was already inserted.");
         }
       }
     }
   }
 }
 public Object getTrailingEntity(
     PlanningVariableDescriptor chainedVariableDescriptor, Object planningValue) {
   Set<Object> trailingEntities =
       trailingEntitiesMap.get(chainedVariableDescriptor).get(planningValue);
   if (trailingEntities == null) {
     return null;
   }
   // trailingEntities can never be an empty list
   if (trailingEntities.size() > 1) {
     throw new IllegalStateException(
         "The planningValue ("
             + planningValue
             + ") has multiple trailing entities ("
             + trailingEntities
             + ") pointing to it for chained planningVariable ("
             + chainedVariableDescriptor.getVariableName()
             + ").");
   }
   return trailingEntities.iterator().next();
 }