@Override
 public boolean isMatch(CandidatePattern candidate) {
   l337Context context = candidate.getDecorator(l337Context.class);
   if (context == null) return false;
   if (context != null && context.isIncompleteLeetSequence()) {
     // if we are still seeking to complete a leet sequence then it isn't a match (yet)
     return false;
   }
   return context.leetCount > 0;
 }
  @Override
  public List<CandidatePattern> buildNextSubStrings(CandidatePattern subs, char c) {
    LinkedList<CandidatePattern> list = new LinkedList<CandidatePattern>();
    l337Context context = subs.getDecorator(l337Context.class);
    if (context == null) {
      context = new l337Context();
      subs.addDecorator(l337Context.class, context);
    }

    // if we are already looking to complete a leet sequence
    if (context.isIncompleteLeetSequence()) {
      if (context.isMatch(c)) {
        CandidatePattern newsubs = subs.copy();
        // add the candidate for the next round
        list.add(newsubs);

        // addvance the character in the context
        l337Context newContext = newsubs.getDecorator(l337Context.class);
        char candidateLeetChar = newContext.currentLeetChar.normalChar;
        newContext.nextChar(c);
        if (!newContext.isIncompleteLeetSequence()) {
          // we found a completed leet sequence, add the substiture char
          newsubs.add(candidateLeetChar);
        }
      }
    } else if (leetList.containsKey(c)) {
      // if are not in a leet sequence but want to start one
      Set<LeetChar> sequences = leetList.get(c);
      for (LeetChar leetSequence : sequences) {
        CandidatePattern newsubs = subs.copy();
        l337Context newContext = newsubs.getDecorator(l337Context.class);
        newContext.setCurrentLeetCandidate(leetSequence);
        newContext.nextChar(c);

        if (!newContext.isIncompleteLeetSequence()) {
          // we found a single character leet sequence, add the substiture char
          newsubs.add(leetSequence.normalChar);
        }
        list.add(newsubs);
      }
    }
    if (Character.isLetter(c)) {
      // we need to clone the substring for the next generation, as it is possible it will be used
      // externally
      CandidatePattern newsubs = subs.copy();
      newsubs.add(c);
      list.add(newsubs);
    }
    return list;
  }