public static Object remove(Object root, DataIterator it)
  {
    DataElement element;

    // construct the list of Data objects to remove
    // don't remove in place because iterator behavior with removals while iterating is undefined
    ArrayList<ToRemove> removeList = new ArrayList<>();
    while ((element = it.next()) != null)
    {
      ToRemove toRemove = new ToRemove(element);
      removeList.add(toRemove);
    }

    // perform actual removal in reverse order to make sure deleting array elements starts with higher indices
    for (int i = removeList.size() - 1; i >= 0; i--)
    {
      ToRemove toRemove = removeList.get(i);
      if (toRemove.isRoot())
      {
        root = null;
      }
      else
      {
        toRemove.remove();
      }
    }
    return root;
  }
@Test
  public void testRemoveByPredicateAtPath() throws Exception
  {
    SimpleTestData data = IteratorTestData.createSimpleTestData();
    
    SimpleDataElement el = data.getDataElement();
    Builder.create(el.getValue(), el.getSchema(), IterationOrder.PRE_ORDER)
        .filterBy(Predicates.and(Predicates.pathMatchesPathSpec(IteratorTestData.PATH_TO_ID), IteratorTestData.LESS_THAN_3_CONDITION))
        .remove();
    
    assertTrue(data.getValue().getDataList("foo").getDataMap(0).getInteger("id") == null);
    assertTrue(data.getValue().getDataList("foo").getDataMap(1).getInteger("id") == null);
    assertEquals(3, data.getValue().getDataList("foo").getDataMap(2).getInteger("id").intValue());
  }