public void setElementChildren()

in stetho/src/main/java/com/facebook/stetho/inspector/elements/ShadowDocument.java [104:194]


    public void setElementChildren(Object element, List<Object> children) {
      // If we receive redundant information, then nothing needs to be done.
      ElementInfo changesElementInfo = mElementToInfoChangesMap.get(element);
      if (changesElementInfo != null &&
          ListUtil.identityEquals(children, changesElementInfo.children)) {
        return;
      }

      ElementInfo oldElementInfo = mElementToInfoMap.get(element);
      if (changesElementInfo == null &&
          oldElementInfo != null &&
          ListUtil.identityEquals(children, oldElementInfo.children)) {
        return;
      }

      ElementInfo newElementInfo;
      if (changesElementInfo != null &&
          oldElementInfo != null &&
          oldElementInfo.parentElement == changesElementInfo.parentElement &&
          ListUtil.identityEquals(children, oldElementInfo.children)) {
        // setElementChildren() was already called for element with changes during this
        // transaction, but now we're being told that the children should match the old view.
        // So we should actually remove the change entry.
        newElementInfo = mElementToInfoMap.get(element);
        mElementToInfoChangesMap.remove(element);
      } else {
        Object parentElement = (changesElementInfo != null)
            ? changesElementInfo.parentElement
            : (oldElementInfo != null)
            ? oldElementInfo.parentElement
            : null;

        newElementInfo = new ElementInfo(element, parentElement, children);

        mElementToInfoChangesMap.put(element, newElementInfo);
      }

      // At this point, newElementInfo is either equal to oldElementInfo because we've reverted
      // back to the same data that's in the old view of the tree, or it's a brand new object with
      // brand new changes (it's different than both of oldElementInfo and changesElementInfo).

      // Next, set the parentElement to null for child elements that have been removed from
      // element's children. We must be careful not to set a parentElement to null if that child has
      // already been moved to be the child of a different element. e.g.,
      //     setElementChildren(E, { A, B, C})
      //     ...
      //     setElementChildren(F, { A })
      //     setElementChildren(E, { B, C })    (don't mark A's parent as null in this case)

      // notNewChildrenSet = (oldChildren + changesChildren) - newChildren
      HashSet<Object> notNewChildrenSet = acquireNotNewChildrenHashSet();

      if (oldElementInfo != null &&
          oldElementInfo.children != newElementInfo.children) {
        for (int i = 0, N = oldElementInfo.children.size(); i < N; ++i) {
          final Object childElement = oldElementInfo.children.get(i);
          notNewChildrenSet.add(childElement);
        }
      }

      if (changesElementInfo != null &&
          changesElementInfo.children != newElementInfo.children) {
        for (int i = 0, N = changesElementInfo.children.size(); i < N; ++i) {
          final Object childElement = changesElementInfo.children.get(i);
          notNewChildrenSet.add(childElement);
        }
      }

      for (int i = 0, N = newElementInfo.children.size(); i < N; ++i) {
        final Object childElement = newElementInfo.children.get(i);
        setElementParent(childElement, element);
        notNewChildrenSet.remove(childElement);
      }

      for (Object childElement : notNewChildrenSet) {
        final ElementInfo childChangesElementInfo = mElementToInfoChangesMap.get(childElement);
        if (childChangesElementInfo != null &&
            childChangesElementInfo.parentElement != element) {
          // do nothing. this childElement was moved to be the child of another element.
          continue;
        }

        final ElementInfo oldChangesElementInfo = mElementToInfoMap.get(childElement);
        if (oldChangesElementInfo != null &&
            oldChangesElementInfo.parentElement == element) {
          setElementParent(childElement, null);
        }
      }

      releaseNotNewChildrenHashSet(notNewChildrenSet);
    }