class FilterableTreeItem<T> extends TreeItem<T> {
	private final ObservableList<TreeItem<T>> sourceChildren = FXCollections.observableArrayList();
	private final ObjectProperty<Predicate<TreeItem<T>>> predicate = new SimpleObjectProperty<>();

	/**
	 * @param value
	 * 		Item value
	 */
	public FilterableTreeItem(T value) {
		super(value);
		// Support filtering by using a filtered list backing.
		// - Apply predicate to items
		FilteredList<TreeItem<T>> filteredChildren = new FilteredList<>(sourceChildren);
		filteredChildren.predicateProperty().bind(Bindings.createObjectBinding(() -> child -> {
			if(child instanceof FilterableTreeItem)
				((FilterableTreeItem<T>) child).predicateProperty().set(predicate.get());
			if(predicate.get() == null || !child.getChildren().isEmpty())
				return true;
			return predicate.get().test(child);
		}, predicate));
		// Reflection hackery
		setUnderlyingChildren(filteredChildren);
	}

	/**
	 * Use reflection to directly set the underlying {@link TreeItem#children} field.
	 * The javadoc for that field literally says:
	 * <pre>
	 *  It is important that interactions with this list go directly into the
	 *  children property, rather than via getChildren(), as this may be
	 *  a very expensive call.
	 * </pre>
	 * This will additionally add the current tree-item's {@link TreeItem#childrenListener} to
	 * the given list's listeners.
	 *
	 * @param list
	 * 		Children list.
	 */
	@SuppressWarnings("unchecked")
	private void setUnderlyingChildren(ObservableList<TreeItem<T>> list) {
		try {
			// Add our change listener to the passed list.
			Field childrenListener = TreeItem.class.getDeclaredField("childrenListener");
			childrenListener.setAccessible(true);
			list.addListener((ListChangeListener<? super TreeItem<T>>) childrenListener.get(this));
			// Directly set "TreeItem.children"
			Field children = TreeItem.class.getDeclaredField("children");
			children.setAccessible(true);
			children.set(this, list);
		} catch(ReflectiveOperationException ex) {
			Log.error(ex, "Failed to update filterable children");
		}
	}

	/**
	 * Add an unfiltered child to this item.
	 *
	 * @param item
	 * 		Child item to add.
	 */
	public void addSourceChild(TreeItem<T> item) {<FILL_FUNCTION_BODY>}

	/**
	 * Remove an unfiltered child from this item.
	 *
	 * @param child
	 * 		Child item to remove.
	 */
	public void removeSourceChild(TreeItem<T> child) {
		sourceChildren.remove(child);
	}

	/**
	 * @return Predicate property.
	 */
	public ObjectProperty<Predicate<TreeItem<T>>> predicateProperty() {
		return predicate;
	}
}

		int index = Arrays.binarySearch(getChildren().toArray(), item);
		if(index < 0)
			index = -(index + 1);
		sourceChildren.add(index, item);
	
<methods>public void <init>() ,public void <init>(T) ,public void <init>(T, javafx.scene.Node) ,public void addEventFilter(EventType<E>, EventHandler<? super E>) ,public void addEventHandler(EventType<E>, EventHandler<? super E>) ,public static EventType<TreeModificationEvent<T>> branchCollapsedEvent() ,public static EventType<TreeModificationEvent<T>> branchExpandedEvent() ,public javafx.event.EventDispatchChain buildEventDispatchChain(javafx.event.EventDispatchChain) ,public static EventType<TreeModificationEvent<T>> childrenModificationEvent() ,public static EventType<TreeModificationEvent<T>> expandedItemCountChangeEvent() ,public final javafx.beans.property.BooleanProperty expandedProperty() ,public ObservableList<TreeItem<T>> getChildren() ,public final javafx.scene.Node getGraphic() ,public final TreeItem<T> getParent() ,public final T getValue() ,public static EventType<TreeModificationEvent<T>> graphicChangedEvent() ,public final ObjectProperty<javafx.scene.Node> graphicProperty() ,public final boolean isExpanded() ,public boolean isLeaf() ,public final javafx.beans.property.ReadOnlyBooleanProperty leafProperty() ,public TreeItem<T> nextSibling() ,public TreeItem<T> nextSibling(TreeItem<T>) ,public final ReadOnlyObjectProperty<TreeItem<T>> parentProperty() ,public TreeItem<T> previousSibling() ,public TreeItem<T> previousSibling(TreeItem<T>) ,public void removeEventFilter(EventType<E>, EventHandler<? super E>) ,public void removeEventHandler(EventType<E>, EventHandler<? super E>) ,public final void setExpanded(boolean) ,public final void setGraphic(javafx.scene.Node) ,public final void setValue(T) ,public java.lang.String toString() ,public static EventType<TreeModificationEvent<T>> treeNotificationEvent() ,public static EventType<TreeModificationEvent<T>> valueChangedEvent() ,public final ObjectProperty<T> valueProperty() <variables>private static final EventType<?> BRANCH_COLLAPSED_EVENT,private static final EventType<?> BRANCH_EXPANDED_EVENT,private static final EventType<?> CHILDREN_MODIFICATION_EVENT,private static final EventType<?> EXPANDED_ITEM_COUNT_CHANGE_EVENT,private static final EventType<?> GRAPHIC_CHANGED_EVENT,private static final EventType<?> TREE_NOTIFICATION_EVENT,private static final EventType<?> VALUE_CHANGED_EVENT,ObservableList<TreeItem<T>> children,private ListChangeListener<TreeItem<T>> childrenListener,private final com.sun.javafx.event.EventHandlerManager eventHandlerManager,private javafx.beans.property.BooleanProperty expanded,private int expandedDescendentCount,private boolean expandedDescendentCountDirty,private ObjectProperty<javafx.scene.Node> graphic,private boolean ignoreSortUpdate,private final EventHandler<TreeModificationEvent<java.lang.Object>> itemListener,Comparator<TreeItem<T>> lastComparator,javafx.scene.control.TreeSortMode lastSortMode,private javafx.beans.property.ReadOnlyBooleanWrapper leaf,private ReadOnlyObjectWrapper<TreeItem<T>> parent,private int parentLinkCount,int previousExpandedDescendentCount,private ObjectProperty<T> value