<commit_before>/*
 * Copyright (c) 2013 - 2015 xxyy (<NAME>; <EMAIL>). All rights reserved.
 *
 * Any usage, including, but not limited to, compiling, running, redistributing, printing,
 *  copying and reverse-engineering is strictly prohibited without explicit written permission
 *  from the original author and may result in legal steps being taken.
 *
 * See the included LICENSE file (core/src/main/resources) or email <EMAIL> for details.
 */

package li.l1t.common.tree;

import com.google.common.base.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * Simple implementation of a tree node.
 *
 * @param <N> the node type of the tree this node is part of
 * @param <V> the value type of the tree this node is part of
 * @author <a href="http://xxyy.github.io/">xxyy</a>
 * @since 2016-06-22
 */
@SuppressWarnings("WeakerAccess")
public class SimpleTreeNode<N extends TreeNode<N, V>, V> implements TreeNode<N, V> {

    private final N parent;
    private final Class<N> nodeClass; //for checking of nodes
    private final List<N> children = new ArrayList<>(4); //and even that is an exaggeration
    private V value;
    private int[] position;

    public SimpleTreeNode(N parent, Class<N> nodeClass) {
        this.nodeClass = nodeClass;
        checkNodeType(getClass());
        this.parent = parent;
        if (parent != null) {
            position = Arrays.copyOf(parent.getPosition(), parent.getPosition().length + 1);
            position[position.length - 1] = parent.getChildren().size(); //must be id of next child, that's us
        } else {
            position = new int[0]; //We're the root node
        }
    }

    @Override
    public N getParent() {
        return parent;
    }

    @Override
    public List<N> getChildren() {
        return children;
    }

    @Override
    public void addChild(N newChild) {
        Preconditions.checkArgument(newChild.getClass().isAssignableFrom(nodeClass), "");
        children.add(newChild);
    }

    @Override
    public void removeChild(N oldChild) {
        //no type check necessary: child type gets checked on add, anything else won't have any effect
        children.remove(oldChild);
        forEachNode(TreeNode::updatePosition); //update children positions
    }

    @Override
    public boolean isRoot() {
        return parent == null;
    }<commit_msg>Fix unable to add subclasses of <N> to tree nodes<commit_after>/*
 * Copyright (c) 2013 - 2015 xxyy (<NAME>; <EMAIL>). All rights reserved.
 *
 * Any usage, including, but not limited to, compiling, running, redistributing, printing,
 *  copying and reverse-engineering is strictly prohibited without explicit written permission
 *  from the original author and may result in legal steps being taken.
 *
 * See the included LICENSE file (core/src/main/resources) or email <EMAIL> for details.
 */

package li.l1t.common.tree;

import com.google.common.base.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * Simple implementation of a tree node.
 *
 * @param <N> the node type of the tree this node is part of
 * @param <V> the value type of the tree this node is part of
 * @author <a href="http://xxyy.github.io/">xxyy</a>
 * @since 2016-06-22
 */
@SuppressWarnings("WeakerAccess")
public class SimpleTreeNode<N extends TreeNode<N, V>, V> implements TreeNode<N, V> {

    private final N parent;
    private final Class<N> nodeClass; //for checking of nodes
    private final List<N> children = new ArrayList<>(4); //and even that is an exaggeration
    private V value;
    private int[] position;

    public SimpleTreeNode(N parent, Class<N> nodeClass) {
        this.nodeClass = nodeClass;
        checkNodeType(getClass());
        this.parent = parent;
        if (parent != null) {
            position = Arrays.copyOf(parent.getPosition(), parent.getPosition().length + 1);
            position[position.length - 1] = parent.getChildren().size(); //must be id of next child, that's us
        } else {
            position = new int[0]; //We're the root node
        }
    }

    @Override
    public N getParent() {
        return parent;
    }

    @Override
    public List<N> getChildren() {
        return children;
    }

    @Override
    public void addChild(N newChild) {
        Preconditions.checkArgument(nodeClass.isAssignableFrom(newChild.getClass()), "");
        children.add(newChild);
    }

    @Override
    public void removeChild(N oldChild) {
        //no type check necessary: child type gets checked on add, anything else won't have any effect
        children.remove(oldChild);
        forEachNode(TreeNode::updatePosition); //update children positions
    }

    @Override
    public boolean isRoot() {
        return parent == null;
    }
{'fraction_non_alphanumeric': 0.10847589424572317, 'fraction_numerical': 0.008164852255054433, 'mean_word_length': 3.0898251192368837, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 34, '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': '370660', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1445, 'n_words': 491}