protected UsingFilter createUsingFilter(String filterName) {
   TestsEntityFactory tef = TestsEntityFactory.instance;
   UsingFilter usingFilter = tef.createUsingFilter();
   usingFilter.setFilter(
       tef.createFilter(tef.createName(GENERATED_FAMILY_NAME + '.' + filterName)));
   return usingFilter;
 }
  @Override
  public void visit(TestSuite entity) {
    if (isLearning()) {
      Map<IEntity, List<IEntity>> learntMap = getLearntMap();

      IEntity result = null;
      for (int cycle = 1; cycle <= learnCycles(); cycle++) {
        printWriter().printf("*** Learning cycle %d ***\n\n", cycle);
        ITransactionScope resettableScope = BindingManagerFactory.instance.createTransactionScope();
        getBindings().wEnterScope(resettableScope);
        try {
          getBindings().wDefValue("learnCycle", cycle);
          super.visit(entity);
          result = getBindings().getResult();
        } finally {
          resettableScope.rollback();
          getBindings().wExitScope();
        }
      }
      getBindings().setResult(result);

      FilterFamily filterFamily = getFilterFamily(entity);
      FilterRules filterRules = filterFamily.getFilterRules();
      FreshNameGenerator fnGen = new FreshNameGenerator();
      for (IEntity name :
          BehaviorUtils.compileAndLazyEvaluate(createFindAllFilterRuleNamesQuery(), filterFamily))
        fnGen.addBoundName(name.wStringValue());

      for (IEntity adapter : learntMap.keySet()) {
        List<IEntity> learntEntities = learntMap.get(adapter);

        IEntity value = learntEntities.get(0);
        if (learntEntities.size() > 1 && EntityUtils.isData(value)) {
          for (IEntity learntEntity : learntEntities) if (!learntEntity.wEquals(value)) continue;
        } else if (learntEntities.size() > 1) {
          for (IEntity learntEntity2 : learntEntities)
            if (EntityUtils.isData(learntEntity2)) continue;

          // generate filter rule
          FilterRule filterRule = TestsHelpers.createFilterRule(learntEntities);
          if (EntityUtils.isNotResolver(filterRule)) {
            String filterName;
            IEntity filterBody;
            if ((filterBody = Matcher.find(filterRule.getBody(), filterRules, false)) != null) {
              // try to reuse a generated filter
              filterName = ((FilterRule) filterBody.wGetParent()).getName().getValue();
            } else {
              // add the filter rule to the filter family
              filterName = fnGen.nextFreshName(GENERATED_FILTER_NAME);
              ITransactionScope resettableScope =
                  BindingManagerFactory.instance.createTransactionScope();
              getBindings().wEnterScope(resettableScope);
              try {
                getBindings().wDefValue("filterName", filterName);
                Matcher.substitute(filterRule, getBindings(), false);
                filterRules.wAdd(filterRule);
              } finally {
                resettableScope.rollback();
                getBindings().wExitScope();
              }
            }

            // wrap SubjectStatement with a UsingFilter
            ITransactionScope resettableScope =
                BindingManagerFactory.instance.createTransactionScope();
            getBindings().wEnterScope(resettableScope);
            try {
              SubjectStatement statement =
                  BehaviorUtils.evaluateFirstResult(
                      createFindAncestorSubjectStatement(), adapter, getBindings());
              UsingFilter usingFilter = createUsingFilter(filterName);
              statement.wGetParent().wSet(statement, usingFilter);
              usingFilter.setSubjectStatement(statement);
            } finally {
              resettableScope.rollback();
              getBindings().wExitScope();
            }
          }
        }

        TestsHelpers.replace(adapter, value);
      }
      // add the newly generated family
      if (!EntityUtils.hasParent(filterFamily) && !filterRules.wIsEmpty())
        entity.getFilterFamilies().wAdd(filterFamily);
    } else super.visit(entity);
  }