private ActionCallback processAjusted(
      final Map<Object, Condition> adjusted, final Set<Object> originallySelected) {
    final ActionCallback result = new ActionCallback();

    final Set<Object> allSelected = myUi.getSelectedElements();

    Set<Object> toSelect = new HashSet<Object>();
    for (Map.Entry<Object, Condition> entry : adjusted.entrySet()) {
      if (entry.getValue().value(entry.getKey())) continue;

      for (final Object eachSelected : allSelected) {
        if (isParentOrSame(entry.getKey(), eachSelected)) continue;
        toSelect.add(entry.getKey());
      }
      if (allSelected.isEmpty()) {
        toSelect.add(entry.getKey());
      }
    }

    final Object[] newSelection = ArrayUtil.toObjectArray(toSelect);

    if (newSelection.length > 0) {
      myUi._select(
          newSelection,
          new Runnable() {
            @Override
            public void run() {
              final Set<Object> hangByParent = new HashSet<Object>();
              processUnsuccessfulSelections(
                  newSelection,
                  new Function<Object, Object>() {
                    @Override
                    public Object fun(final Object o) {
                      if (myUi.isInStructure(o) && !adjusted.get(o).value(o)) {
                        hangByParent.add(o);
                      } else {
                        addAdjustedSelection(o, adjusted.get(o), null);
                      }
                      return null;
                    }
                  },
                  originallySelected);

              processHangByParent(hangByParent).notify(result);
            }
          },
          false,
          true,
          true);
    } else {
      result.setDone();
    }

    return result;
  }
  public boolean restore(@Nullable DefaultMutableTreeNode actionNode) {
    if (isProcessingNow() || !myCanRunRestore || myUi.hasNodesToUpdate()) {
      return false;
    }

    invalidateToSelectWithRefsToParent(actionNode);

    setProcessingNow(true);

    final Object[] toSelect = getToSelect();
    final Object[] toExpand = getToExpand();

    final Map<Object, Condition> adjusted = new WeakHashMap<Object, Condition>();
    adjusted.putAll(myAdjustedSelection);

    clearSelection();
    clearExpansion();

    final Set<Object> originallySelected = myUi.getSelectedElements();

    myUi._select(
        toSelect,
        new Runnable() {
          @Override
          public void run() {
            processUnsuccessfulSelections(
                toSelect,
                new Function<Object, Object>() {
                  @Override
                  public Object fun(final Object o) {
                    if (myUi.getTree().isRootVisible()
                        || !myUi.getTreeStructure().getRootElement().equals(o)) {
                      addSelection(o);
                    }
                    return o;
                  }
                },
                originallySelected);

            processAjusted(adjusted, originallySelected)
                .doWhenDone(
                    new Runnable() {
                      @Override
                      public void run() {
                        myUi.expand(
                            toExpand,
                            new Runnable() {
                              @Override
                              public void run() {
                                myUi.clearUpdaterState();
                                setProcessingNow(false);
                              }
                            },
                            true);
                      }
                    });
          }
        },
        false,
        true,
        true,
        false);

    return true;
  }