/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.arakhne.afc.math.tree; import java.io.IOException; import java.io.ObjectInputStream; import org.eclipse.xtext.xbase.lib.Pure; /** * This is the generic implementation of a * tree based on linked lists. * * <p>This tree assumes that the nodes are linked with there * references. * * @param <D> is the type of the data inside the tree * @param <N> is the type of the tree nodes. * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ public class LinkedTree<D, N extends TreeNode<D, N>> extends AbstractTree<D, N> { private static final long serialVersionUID = 8805713324128349425L; /** Root of the tree. */ private N root; /** Count of nodes. */ private int nodeCount; /** Count of user data. */ private int dataCount; /** Event listener. */ private transient Listener listener; /** * Create an emtpy tree. */ public LinkedTree() { this(null); } /** Create a tree with the given node. * * @param root1 is the root. */ public LinkedTree(N root1) { init(root1); } private void init(N rootNode) { this.listener = new Listener(); setRoot(rootNode); } /** Invoked when this object must be deserialized. * * @param in is the input stream. * @throws IOException in case of input stream access error. * @throws ClassNotFoundException if some class was not found. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (this.root != null) { this.root.removeFromParent(); this.root.addTreeNodeListener(this.listener); } } @Override @Pure public N getRoot() { return this.root; } @Override public void setRoot(N newRoot) { if (newRoot == this.root) { return; } if (this.root != null) { this.root.removeTreeNodeListener(this.listener); } this.root = newRoot; if (this.root != null) { this.root.removeFromParent(); this.nodeCount = this.root.getDeepNodeCount(); this.dataCount = this.root.getDeepUserDataCount(); this.root.addTreeNodeListener(this.listener); } else { this.nodeCount = 0; this.dataCount = 0; } } /** Clear the tree. * * <p>Caution: this method also destroyes the * links between the nodes inside the tree. * If you want to unlink the root node with * this tree but leave the nodes' links * unchanged, please call <code>setRoot(null)</code>. */ @Override public void clear() { if (this.root != null) { this.root.clear(); setRoot(null); } } @Override @Pure public int getNodeCount() { return this.nodeCount; } @Override @Pure public int getUserDataCount() { return this.dataCount; } /** Force the computation of the user data count. * * @return the count of data. */ public int computeUserDataCount() { if (this.root != null) { this.dataCount = this.root.getDeepUserDataCount(); } else { this.dataCount = 0; } return this.dataCount; } @Override @Pure public int getMinHeight() { return (this.root != null) ? this.root.getMinHeight() : 0; } @Override @Pure public int getMaxHeight() { return (this.root != null) ? this.root.getMaxHeight() : 0; } @Override @Pure public int[] getHeights() { return (this.root != null) ? this.root.getHeights() : new int[] {0}; } /** * This is the generic implementation of a * tree based on linked lists. * * <p>This tree assumes that the nodes are linked with there * references. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ private class Listener implements TreeNodeListener { /** Construct a listener. */ Listener() { // } @Override @SuppressWarnings("synthetic-access") public void treeNodeChildAdded(TreeNodeAddedEvent event) { final TreeNode<?, ?> childNode = event.getChild(); LinkedTree.this.nodeCount += childNode.getDeepNodeCount(); LinkedTree.this.dataCount += childNode.getDeepUserDataCount(); } @Override @SuppressWarnings("synthetic-access") public void treeNodeChildRemoved(TreeNodeRemovedEvent event) { final TreeNode<?, ?> childNode = event.getChild(); LinkedTree.this.nodeCount -= childNode.getDeepNodeCount(); LinkedTree.this.dataCount -= childNode.getDeepUserDataCount(); } @Override @SuppressWarnings("synthetic-access") public void treeNodeDataChanged(TreeDataEvent event) { final int oldCount = event.getRemovedValueCount(); final int newCount = event.getAddedValueCount(); if (oldCount < newCount) { LinkedTree.this.dataCount += newCount - oldCount; } else if (oldCount > newCount) { LinkedTree.this.dataCount -= oldCount - newCount; } } @Override public void treeNodeParentChanged(TreeNodeParentChangedEvent event) { // } } }