PathPacker-java/src/main/java/com/redhat/trie/HuffNode.java

183 lines
4.9 KiB
Java

/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.trie;
public class HuffNode {
/**
* Empty node to be referenced as the authority on what is an "end node"
*/
public static final Object END_NODE = new Object();
private long id = 0;
private Object value = null;
private int weight = 0;
private HuffNode left = null;
private HuffNode right = null;
private NodeContext ctx = null;
/**
* storage of Object value, it's weighting, and children, assumes new NodeContext
*/
public HuffNode(Object value, int weight, HuffNode left, HuffNode right) {
this(new NodeContext(), value, weight, left, right);
}
/**
* storage of Object value, it's weighting, and children, and existing NodeContext.
*
* This will increment the NodeContext
*/
public HuffNode(NodeContext ctx, Object value, int weight, HuffNode left, HuffNode right) {
this.ctx = ctx;
this.value = value;
this.weight = weight;
this.left = left;
this.right = right;
this.id = this.ctx.nextId();
}
/**
* storage of Object's value, and its weighting, assumes new NodeContext
*/
public HuffNode(Object value, int weight) {
this(new NodeContext(), value, weight);
}
/**
* storage of Object's value, and its weighting, and existing NodeContext.
*
* This will increment the NodeContext
*/
public HuffNode(NodeContext ctx, Object value, int weight) {
this.ctx = ctx;
this.value = value;
this.weight = weight;
this.id = this.ctx.nextId();
}
/**
* return the NodeContext incrementor
*/
public NodeContext getContext() {
return this.ctx;
}
/**
* return this node's id, per the NodeContext incrementor
*/
public long getId() {
return this.id;
}
/**
* return the stored Object
*/
public Object getValue() {
return this.value;
}
/**
* return the node's weight
*/
public int getWeight() {
return this.weight;
}
/**
* node on the left
*/
public HuffNode getLeft() {
return this.left;
}
/**
* node on the right
*/
public HuffNode getRight() {
return this.right;
}
/**
* search down the tree, for the node,
* at address of String bits
*/
public HuffNode findByBits(String bits) {
return this.findByBits(this, bits);
}
/**
* search down the tree, for the node,
* at address of String bits, on HuffNode trie
*/
private HuffNode findByBits(HuffNode trie, String bits) {
if (bits.length() == 0) {
return trie;
}
char bit = bits.charAt(0);
if (bit == '0') {
if (getLeft() == null) { throw new RuntimeException("Encoded path not in trie"); }
return getLeft().findByBits(bits.substring(1));
}
else if (bit == '1') {
if (getRight() == null) { throw new RuntimeException("Encoded path not in trie"); }
return getRight().findByBits(bits.substring(1));
}
return null;
}
public String getBitPath(Object need) {
return getBitPath(this, need);
}
/**
* get a String of the bits, that map to Object need
*/
private String getBitPath(HuffNode trie, Object need) {
HuffNode leftNode = trie.getLeft();
HuffNode rightNode = trie.getRight();
if (leftNode != null && leftNode.getValue() != null && need.equals(leftNode.getValue())) {
return "0";
}
if (rightNode != null && rightNode.getValue() != null && need.equals(rightNode.getValue())) {
return "1";
}
if (leftNode != null) {
String leftPath = getBitPath(leftNode, need);
if (leftPath.length() > 0) {
return "0" + leftPath;
}
}
if (rightNode != null) {
String rightPath = getBitPath(rightNode, need);
if (rightPath.length() > 0) {
return "1" + rightPath;
}
}
return "";
}
/**
* pretty information
*/
public String toString() {
return "ID: " + id +
", Value " + value +
", Weight: " + weight +
", Left: " + left +
", Right: " + right;
}
}