private ILearningCharmGroup[] createGroups(ICharmGroup[] charmGroups) {
    List<ILearningCharmGroup> newGroups = new ArrayList<ILearningCharmGroup>();
    ICharmLearnListener mergedListener =
        new CharmLearnAdapter() {
          @Override
          public void charmLearned(ICharm charm) {
            for (ICharm mergedCharm : charm.getMergedCharms()) {
              if (!isLearned(mergedCharm)
                  && isLearnableWithoutPrereqs(mergedCharm)
                  && CharmConfiguration.this.getSpecialCharmConfiguration(mergedCharm) == null) {
                getGroup(mergedCharm)
                    .learnCharm(mergedCharm, context.getBasicCharacterContext().isExperienced());
              }
            }

            for (ICharm child : charm.getLearnChildCharms()) {
              boolean learnedMerged = false;
              for (ICharm mergedCharm : child.getMergedCharms())
                learnedMerged = learnedMerged || isLearned(mergedCharm);
              if (learnedMerged && isLearnable(child))
                getGroup(child)
                    .learnCharm(child, context.getBasicCharacterContext().isExperienced());
            }
          }

          @Override
          public void charmForgotten(ICharm charm) {
            boolean forgetMerges = true;
            for (ICharm parentCharm : charm.getParentCharms())
              forgetMerges = forgetMerges && isLearned(parentCharm);
            if (forgetMerges)
              for (ICharm mergedCharm : charm.getMergedCharms()) {
                if (isLearned(mergedCharm) && isUnlearnableWithoutConsequences(mergedCharm)) {
                  getGroup(mergedCharm)
                      .forgetCharm(mergedCharm, context.getBasicCharacterContext().isExperienced());
                }
              }
          }

          @Override
          public void recalculateRequested() {
            for (ICharm charm : getLearnedCharms(true)) {
              boolean prereqsMet = true;
              for (ICharm parent : charm.getParentCharms())
                for (String subeffectRequirement : charm.getParentSubeffects())
                  if (getSubeffectParent(subeffectRequirement).equals(parent.getId())) {
                    ISpecialCharmConfiguration config =
                        getSpecialCharmConfiguration(getSubeffectParent(subeffectRequirement));
                    if (config instanceof IMultipleEffectCharmConfiguration) {
                      IMultipleEffectCharmConfiguration mConfig =
                          (IMultipleEffectCharmConfiguration) config;
                      prereqsMet =
                          prereqsMet
                              && mConfig
                                  .getEffectById(getSubeffect(subeffectRequirement))
                                  .isLearned();
                    }
                    if (config instanceof IMultiLearnableCharmConfiguration) {
                      IMultiLearnableCharmConfiguration mConfig =
                          (IMultiLearnableCharmConfiguration) config;
                      String effect = getSubeffect(subeffectRequirement);
                      int requiredCount = Integer.parseInt(effect.replace("Repurchase", ""));
                      prereqsMet = mConfig.getCurrentLearnCount() >= requiredCount;
                    }
                  }
              if (!prereqsMet)
                getGroup(charm)
                    .forgetCharm(charm, context.getBasicCharacterContext().isExperienced());
            }
          }
        };
    for (ICharmGroup charmGroup : charmGroups) {
      ILearningCharmGroup group =
          new LearningCharmGroup(
              getLearnStrategy(), charmGroup, this, learningCharmGroupContainer, this);
      newGroups.add(group);

      group.addCharmLearnListener(mergedListener);
    }
    return newGroups.toArray(new LearningCharmGroup[newGroups.size()]);
  }
 public void addCharmLearnListener(ICharmLearnListener listener) {
   for (ILearningCharmGroup group : getAllGroups()) {
     group.addCharmLearnListener(listener);
   }
 }