private ICharmTemplate getNativeCharmTemplate(ITemplateRegistry registry) {
   IBasicCharacterData basicCharacterContext = context.getBasicCharacterContext();
   ITemplateType templateType = basicCharacterContext.getTemplateType();
   ICharacterTemplate template = registry.getTemplate(templateType);
   IMagicTemplate magicTemplate = template.getMagicTemplate();
   return magicTemplate.getCharmTemplate();
 }
 @Override
 public ISpecialCharm[] getSpecialCharms() {
   return provider.getSpecialCharms(
       context.getBasicCharacterContext().getRuleSet().getEdition(),
       new MartialArtsLearnableArbitrator(martialArtsCharmTree),
       getCharmIdMap(),
       getNativeCharacterType());
 }
 private ICharmTemplate getCharmTemplate(ITemplateRegistry registry, ICharacterType type) {
   ICharacterTemplate defaultTemplate =
       registry.getDefaultTemplate(type, context.getBasicCharacterContext().getEdition());
   if (defaultTemplate == null || defaultTemplate instanceof IUnsupportedTemplate) {
     return null;
   }
   return defaultTemplate.getMagicTemplate().getCharmTemplate();
 }
 private ICharmTemplate getNativeCharmTemplate(ITemplateRegistry registry) {
   IBasicCharacterData basicCharacterContext = context.getBasicCharacterContext();
   ITemplateType templateType = basicCharacterContext.getTemplateType();
   IExaltedEdition edition = basicCharacterContext.getRuleSet().getEdition();
   ICharacterTemplate template = registry.getTemplate(templateType, edition);
   IMagicTemplate magicTemplate = template.getMagicTemplate();
   return magicTemplate.getCharmTemplate();
 }
 public EssencePoolConfiguration(
     IEssenceTemplate essenceTemplate,
     IAdditionalRules additionalRules,
     ICharacterModelContext context) {
   this.additionalRules = additionalRules;
   this.essenceTemplate = essenceTemplate;
   if (!isEssenceUser()) {
     return;
   }
   poolStrategy =
       new EssencePoolStrategy(
           essenceTemplate,
           context,
           context.getTraitCollection(),
           context.getMagicCollection(),
           context.getCharmContext().getCharmConfiguration(),
           additionalRules);
 }
 @Override
 public final boolean isLearnable(ICharm charm) {
   if (isAlienCharm(charm)) {
     ICasteType casteType = context.getBasicCharacterContext().getCasteType();
     if (!getCharmTemplateForCharacterType().isAllowedAlienCharms(casteType)) {
       return false;
     }
     if (charm.hasAttribute(ICharmData.NATIVE)) {
       return false;
     }
   }
   if (charm.isBlockedByAlternative(context.getMagicCollection())) {
     return false;
   }
   if (isMartialArtsCharm(charm)) {
     boolean isSiderealFormCharm = isFormCharm(charm) && hasLevel(Sidereal, charm);
     MartialArtsCharmConfiguration martialArtsConfiguration =
         new DefaultMartialArtsCharmConfiguration(
             this, context.getMagicCollection(), context.getBasicCharacterContext());
     if (isSiderealFormCharm && !martialArtsConfiguration.isAnyCelestialStyleCompleted()) {
       return false;
     }
     if (!getMartialArtsRulesForCharacterType()
         .isCharmAllowed(charm, martialArtsConfiguration, isExperienced())) {
       return false;
     }
   }
   ICharm[] learnedCharms = getLearnedCharms(true);
   for (IndirectCharmRequirement requirement : charm.getAttributeRequirements()) {
     if (!requirement.isFulfilled(learnedCharms)) {
       return false;
     }
   }
   if (!(new CharmTraitRequirementChecker(getPrerequisiteModifyingCharms(), context, this)
       .areTraitMinimumsSatisfied(charm))) {
     return false;
   }
   for (ICharm parentCharm : charm.getLearnPrerequisitesCharms(this)) {
     if (!isLearnable(parentCharm)) {
       return false;
     }
   }
   return true;
 }
 private IPrerequisiteModifyingCharm[] getPrerequisiteModifyingCharms() {
   if (prerequisiteModifyingCharms == null) {
     List<IPrerequisiteModifyingCharm> charms = new ArrayList<IPrerequisiteModifyingCharm>();
     for (ISpecialCharm charm : getSpecialCharms())
       // assuming all of these are native for now
       if (charm instanceof IPrerequisiteModifyingCharm
           && getCharmIdMap().getCharmById(charm.getCharmId()).getCharacterType()
               == context.getBasicCharacterContext().getCharacterType())
         charms.add((IPrerequisiteModifyingCharm) charm);
     prerequisiteModifyingCharms = new IPrerequisiteModifyingCharm[charms.size()];
     charms.toArray(prerequisiteModifyingCharms);
   }
   return prerequisiteModifyingCharms;
 }
 private void verifyCharms() {
   if (!context.isFullyLoaded()) {
     return;
   }
   List<ICharm> charmsToUnlearn = new ArrayList<ICharm>();
   for (ICharm charm : this.getLearnedCharms(true)) {
     boolean prerequisitesForCharmAreNoLongerMet = !isLearnable(charm);
     boolean charmCanBeUnlearned = isUnlearnable(charm);
     if (prerequisitesForCharmAreNoLongerMet && charmCanBeUnlearned) {
       charmsToUnlearn.add(charm);
     }
   }
   for (ICharm charm : charmsToUnlearn) {
     ILearningCharmGroup group = learningCharmGroupContainer.getLearningCharmGroup(charm);
     boolean learnedAtCreation = group.isLearned(charm, false);
     boolean learnedWithExperience = !learnedAtCreation;
     group.forgetCharm(charm, learnedWithExperience);
   }
 }
 public CharmConfiguration(
     IHealthConfiguration health,
     ICharacterModelContext context,
     ITemplateRegistry registry,
     ICharmProvider provider) {
   this.manager = new SpecialCharmManager(this, health, context);
   this.context = context;
   this.provider = provider;
   IExaltedRuleSet rules = context.getBasicCharacterContext().getRuleSet();
   List<ICharacterType> allCharacterTypes = new ArrayList<ICharacterType>();
   ICharmTemplate nativeCharmTemplate = getNativeCharmTemplate(registry);
   this.arbitrator = new LearningCharmGroupArbitrator(nativeCharmTemplate, context);
   this.martialArtsCharmTree = new MartialArtsCharmTree(nativeCharmTemplate, rules);
   this.martialArtsGroups = createGroups(martialArtsCharmTree.getAllCharmGroups());
   initCharacterType(nativeCharmTemplate, rules, getNativeCharacterType());
   allCharacterTypes.add(getNativeCharacterType());
   initAlienTypes(registry, rules, allCharacterTypes);
   initSpecialCharmConfigurations();
   types = allCharacterTypes.toArray(new ICharacterType[allCharacterTypes.size()]);
 }
 // TODO: Available dots limit max. value
 public SpiritFormAttribute(IGenericTrait baseTrait, final ICharacterModelContext charContext) {
   ITraitContext context = charContext.getTraitContext();
   ITraitTemplate template = SimpleTraitTemplate.createStaticLimitedTemplate(1, 12);
   TraitRules traitRules =
       new TraitRules(baseTrait.getType(), template, context.getLimitationContext());
   IValueChangeChecker incrementChecker =
       new IValueChangeChecker() {
         @Override
         public boolean isValidNewValue(int value) {
           return value != spiritTrait.getCurrentValue()
               && !charContext.getBasicCharacterContext().isExperienced();
         }
       };
   spiritTrait = new DefaultTrait(traitRules, context, incrementChecker);
   spiritTrait.addCurrentValueListener(
       new IIntValueChangedListener() {
         @Override
         public void valueChanged(int newValue) {
           SpiritFormAttribute.this.newValue = newValue;
         }
       });
 }
  public void initListening() {
    context
        .getCharacterListening()
        .addChangeListener(
            new GlobalCharacterChangeAdapter() {
              @Override
              public void characterChanged() {
                verifyCharms();
                fireLearnConditionsChanged();
              }
            });
    addCharmLearnListener(
        new CharmLearnAdapter() {
          @Override
          public void charmForgotten(ICharm charm) {
            fireLearnConditionsChanged();
          }

          @Override
          public void charmLearned(ICharm charm) {
            fireLearnConditionsChanged();
          }
        });
  }
 public CharmConfiguration(
     IHealthConfiguration health,
     ICharacterModelContext context,
     ITemplateRegistry registry,
     ICharmProvider provider) {
   this.manager = new SpecialCharmManager(this, health, context);
   this.context = context;
   this.provider = provider;
   List<ICharacterType> allCharacterTypes = new ArrayList<ICharacterType>();
   ICharmTemplate nativeCharmTemplate = getNativeCharmTemplate(registry);
   this.arbitrator = new LearningCharmGroupArbitrator(nativeCharmTemplate, context);
   this.martialArtsCharmTree = new MartialArtsCharmTree(nativeCharmTemplate);
   this.martialArtsGroups = createGroups(martialArtsCharmTree.getAllCharmGroups());
   initCharacterType(nativeCharmTemplate, getNativeCharacterType());
   allCharacterTypes.add(getNativeCharacterType());
   initAlienTypes(registry, allCharacterTypes);
   initUniqueTypes(nativeCharmTemplate);
   initSpecialCharmConfigurations();
   types = allCharacterTypes.toArray(new ICharacterType[allCharacterTypes.size()]);
   filterSet.add(new ObtainableCharmFilter(this));
   filterSet.add(
       new CharacterSourceBookFilter(context.getBasicCharacterContext().getEdition(), this));
   filterSet.add(new EssenceLevelCharmFilter());
 }
 public final boolean isCompulsiveCharm(ICharm charm) {
   String[] compulsiveCharmIDs = context.getAdditionalRules().getCompulsiveCharmIDs();
   return ArrayUtilities.containsValue(compulsiveCharmIDs, charm.getId());
 }
  public final boolean isLearnable(ICharm charm) {
    if (isAlienCharm(charm)) {
      ICasteType casteType = context.getBasicCharacterContext().getCasteType();
      if (!getCharmTemplate(getNativeCharacterType()).isAllowedAlienCharms(casteType)) {
        return false;
      }
      if (charm.hasAttribute(ICharmData.NOT_ALIEN_LEARNABLE)) {
        return false;
      }
    }
    if (charm.isBlockedByAlternative(context.getMagicCollection())) {
      return false;
    }
    if (MartialArtsUtilities.isMartialArtsCharm(charm)) {
      boolean isSiderealFormCharm =
          MartialArtsUtilities.isFormCharm(charm)
              && MartialArtsUtilities.hasLevel(MartialArtsLevel.Sidereal, charm);
      if (isSiderealFormCharm
          && !arbitrator.isCelestialMartialArtsGroupCompleted(getMartialArtsGroups())) {
        return false;
      }
      if (!getCharmTemplate(getNativeCharacterType())
          .getMartialArtsRules()
          .isCharmAllowed(
              charm,
              context.getCharmContext().getCharmConfiguration(),
              context.getBasicCharacterContext().isExperienced())) {
        return false;
      }
    }
    for (ICharmAttributeRequirement requirement : charm.getAttributeRequirements()) {
      if (!requirement.isFulfilled(getLearnedCharms(true))) {
        return false;
      }
    }
    for (IGenericTrait prerequisite : charm.getPrerequisites()) {
      IGenericTrait prerequisiteTrait =
          context.getTraitCollection().getTrait(prerequisite.getType());
      int prereq = prerequisite.getCurrentValue();
      for (ISpecialCharm specialCharm : getPrerequisiteModifyingCharms())
        if (specialCharm instanceof IPrerequisiteModifyingCharm
            && isLearned(specialCharm.getCharmId()))
          prereq =
              ((IPrerequisiteModifyingCharm) specialCharm)
                  .getTraitModifier(charm, prerequisiteTrait.getType(), prereq);

      if (prerequisiteTrait == null || prereq > prerequisiteTrait.getCurrentValue()) {
        return false;
      }
    }
    IGenericTrait essenceTrait = context.getTraitCollection().getTrait(OtherTraitType.Essence);
    int essencePrereq = charm.getEssence().getCurrentValue();
    for (ISpecialCharm specialCharm : getPrerequisiteModifyingCharms())
      if (specialCharm instanceof IPrerequisiteModifyingCharm
          && isLearned(specialCharm.getCharmId()))
        essencePrereq =
            ((IPrerequisiteModifyingCharm) specialCharm)
                .getTraitModifier(charm, OtherTraitType.Essence, essencePrereq);
    if (essencePrereq > essenceTrait.getCurrentValue()) {
      return false;
    }
    for (ICharm parentCharm : charm.getLearnPrerequisitesCharms(this)) {
      if (!isLearnable(parentCharm)) {
        return false;
      }
    }
    return true;
  }
 private ICharmLearnStrategy getLearnStrategy() {
   return context.getCharmContext().getCharmLearnStrategy();
 }
 private ICharacterType getNativeCharacterType() {
   return context.getBasicCharacterContext().getCharacterType();
 }
 public String getCharmTrueName(String charmId) {
   return provider.getCharmRename(context.getBasicCharacterContext().getRuleSet(), charmId);
 }
 public SpecialtiesAdditionalModel(
     IAdditionalTemplate additionalTemplate, ICharacterModelContext context) {
   this.additionalTemplate = additionalTemplate;
   IGenericTraitCollection traitCollection = context.getTraitCollection();
   this.model = ((ICoreTraitConfiguration) traitCollection).getSpecialtyConfiguration();
 }
 private boolean isExperienced() {
   return context.getBasicCharacterContext().isExperienced();
 }
 @Override
 public final boolean isCompulsiveCharm(ICharm charm) {
   String[] compulsiveCharmIDs = context.getAdditionalRules().getCompulsiveCharmIDs();
   return net.sf.anathema.lib.lang.ArrayUtilities.containsValue(compulsiveCharmIDs, charm.getId());
 }