<commit_before>/**    / \____  _    ______   _____ / \____   ____  _____
 *    /  \__  \/ \  / \__  \ /  __//  \__  \ /    \/ __  \   Javaslang
 *  _/  // _\  \  \/  / _\  \\_  \/  // _\  \  /\  \__/  /   Copyright 2014 <NAME>
 * /___/ \_____/\____/\_____/____/\___\_____/_/  \_/____/    Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import static javaslang.Requirements.require;

import java.io.Serializable;

public final class Tree<T> implements Serializable {

	private static final long serialVersionUID = 3366047180513233623L;

	final Tree<T> parent;
	final T value;
	final List<Tree<T>> children;

	public Tree(T value) {
		this.parent = null;
		this.value = value;
		this.children = List.empty();
	}

	protected Tree(Tree<T> parent, T value, List<Tree<T>> children) {
		this.parent = parent;
		this.value = value;
		this.children = children.replaceAll(child -> setParent(child, this));
	}

	// -- accessors

	public Tree<T> getParent() {
		require(parent != null, "root has no parent");
		return parent;
	}

	public T getValue() {
		return value;
	}

	public List<Tree<T>> getChildren() {
		return children;
	}

	public boolean isRoot() {
		return parent == null;
	}

	public boolean isLeaf() {
		return children.isEmpty();
	}

	// -- mutators

	@SafeVarargs
	public final Tree<T> attach(Tree<T> tree1, Tree<T>... trees) {
		return new Tree<T>(parent, value, List.of(tree1, trees).prependAll(children));
	}

	@SafeVarargs
	public final Tree<T> detach(Tree<T> tree1, Tree<T>... trees) {
		return new Tree<T>(parent, value, children.removeAll(List.of(tree1, trees)));
	}

	private static <T> Tree<T> setParent(Tree<T> tree, Tree<T> parent) {
		return (tree.parent == parent) ? tree : new Tree<>(parent, tree.value, tree.children);
	}
<commit_msg>A more mature second version of the immutable Tree implementation, optimizing tree re-calculation on write access. Use unidirectional trees to build structures bottom-up, then call bidirectional() to add parent references in O(n), if needed.<commit_after>/**    / \____  _    ______   _____ / \____   ____  _____
 *    /  \__  \/ \  / \__  \ /  __//  \__  \ /    \/ __  \   Javaslang
 *  _/  // _\  \  \/  / _\  \\_  \/  // _\  \  /\  \__/  /   Copyright 2014 <NAME>
 * /___/ \_____/\____/\_____/____/\___\_____/_/  \_/____/    Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import static javaslang.Requirements.require;

import java.io.Serializable;
import java.util.function.UnaryOperator;

import javaslang.option.Option;

public class Tree<T> implements Serializable {

	private static final long serialVersionUID = 3366047180513233623L;

	private static final String UNIDIRECTIONAL_ERROR = "unidirectional tree has no parent ref";

	private final boolean bidirectional;
	private final Tree<T> parent;
	private final T value;
	private final List<Tree<T>> children;

	public Tree(T value) {
		this(value, false);
	}

	public Tree(T value, boolean bidirectional) {
		this.bidirectional = bidirectional;
		this.parent = null;
		this.value = value;
		this.children = List.empty();
	}

	protected Tree(Tree<T> parent, T value, List<Tree<T>> children, boolean bidirectional) {
		this.bidirectional = bidirectional;
		this.parent = parent; // TODO: (bidirectional && parent != null) ? parent.updateChild(oldChild, newChild) : parent;
		this.value = value;
		if (bidirectional) {
			final UnaryOperator<Tree<T>> f = child -> new Tree<>(this, child.value, child.children, bidirectional);
			this.children = children.replaceAll(f);
		} else {
			this.children = children;
		}
	}

	// -- accessors

	public boolean isBidirectional() {
		return bidirectional;
	}

	public Option<Tree<T>> getParent() {
		require(bidirectional, UNIDIRECTIONAL_ERROR);
		return Option.of(parent);
	}

	public T getValue() {
		return value;
	}

	public List<Tree<T>> getChildren() {
		return children;
	}

	public boolean isRoot() {
		require(bidirectional, UNIDIRECTIONAL_ERROR);
		return parent == null;
	}

	public boolean isLeaf() {
		return children.isEmpty();
	}

	// -- mutators

	public Tree<T> attach(Tree<T> tree1, @SuppressWarnings("unchecked") Tree<T>... trees) {
		return new Tree<>(parent, value, List.of(tree1, trees).prependAll(children), bidirectional);
	}

	public Tree<T> detach(Tree<T> tree1, @SuppressWarnings("unchecked") Tree<T>... trees) {
		return new Tree<>(parent, value, children.removeAll(List.of(tree1, trees)), bidirectional);
	}

	public Tree<T> setChildren(List<Tree<T>> children) {
		return new Tree<>(parent, value, children, bidirectional);
	}

	public Tree<T> subtree() {
		final boolean hasParentRef = bidirectional && parent != null;
		if (hasParentRef) {
			return new Tree<>(null, value, children, bidirectional);
		} else {
			return this;
		}
	}

	public Tree<T> bidirectional() {
		return bidirectional ? this : new Tree<>(null, value, children, true);
	}

	public Tree<T> unidirectional() {
		return bidirectional ? new Tree<>(null, value, children, false) : this;
	}

{'fraction_non_alphanumeric': 0.14057507987220447, 'fraction_numerical': 0.0115814696485623, 'mean_word_length': 3.4406028368794326, 'pattern_counts': {'":': 0, '<': 60, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7477542', 'n_tokens_mistral': 1830, 'n_tokens_neox': 1668, 'n_words': 409}