@Override
  public List<List<Node<String>>> search() {
    boolean canStart = checkWords(wordsPair);
    canStart &= checkDictionary(dictionary);
    if (!canStart) {
      return null;
    }

    Tree.Node<String> root = new Tree.Node<>();
    root.setData(wordsPair[0]);

    Tree<String> tree = new Tree<>();
    tree.setRootElement(root);

    String word = root.getItem();
    dictionary.remove(word);

    Node<String> currentNode = root;
    List<Node<String>> nodes = new ArrayList<>();

    while (!word.equals(wordsPair[1]) && currentNode != null) {
      // потенциальные слова
      List<String> words = generateCandidates(word);

      // отсекаем слова, которых нет в словаре
      for (Iterator<String> iterator = words.iterator(); iterator.hasNext(); ) {
        String s = iterator.next();
        if (!dictionary.contains(s)) {
          iterator.remove();
        }
      }

      // удаляем полученные слова из словаря (для исключения цикличности поиска)
      for (String c : words) {
        if (!c.equals(wordsPair[1])) {
          dictionary.remove(c);
        }
      }

      // формируем очередной уровень дерева
      for (String c : words) {
        Node<String> n = new Node<>(c);
        currentNode.addChild(n);

        if (c.equals(wordsPair[1])) {
          nodes.add(n);
        }
      }

      currentNode = tree.getNextElement(currentNode, !nodes.isEmpty());

      if (currentNode != null) {
        word = currentNode.getItem();
      } else if (nodes.isEmpty()) {
        return null;
      }
    }

    return tree.getPaths(nodes);
  }
 public String remove(Object key) {
   return headers.remove(key);
 }
 public void removeAttribute(String attributeName) {
   Dictionary<String, Object> attributes = proxyContext.getContextAttributes(httpContext);
   attributes.remove(attributeName);
 }