All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jhotdraw8.icollection.impl.champmap.ChampTrieGraphviz Maven / Gradle / Ivy

/*
 * @(#)ChampTrieGraphviz.java
 * Copyright © 2022 The authors and contributors of JHotDraw. MIT License.
 */

package org.jhotdraw8.icollection.impl.champmap;


import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Objects;

import static java.lang.Math.min;

/**
 * Dumps a CHAMP trie in the Graphviz DOT language.
 * 

* References: *

*
Graphviz. DOT Language.
*
graphviz.org
*
* * @param the key type * @param the value type */ public class ChampTrieGraphviz { private void dumpBitmapIndexedNodeSubTree(Appendable a, BitmapIndexedNode node, int entryLength, boolean printValue, boolean printSequenceNumber, int shift, int keyHash) throws IOException { // Print the node as a record with a compartment for each child element (node or data) String id = toNodeId(keyHash, shift); a.append('n'); a.append(id); a.append(" [label=\""); boolean first = true; int nodeMap = node.nodeMap(); int dataMap = node.dataMap(); int combinedMap = nodeMap | dataMap; for (int i = 0, n = Integer.bitCount(combinedMap); i < n; i++) { int mask = combinedMap & (1 << i); } for (int mask = 0; mask <= Node.BIT_PARTITION_MASK; mask++) { int bitpos = Node.bitpos(mask); if (((nodeMap | dataMap) & bitpos) != 0) { if (first) { first = false; } else { a.append('|'); } a.append("'); if ((dataMap & bitpos) != 0) { a.append(Objects.toString(node.getKey(Node.index(dataMap, bitpos)))); if (printValue) { a.append('='); a.append(Objects.toString(node.getValue(Node.index(dataMap, bitpos)))); } } else { a.append("·"); } } } a.append("\"];\n"); for (int mask = 0; mask <= Node.BIT_PARTITION_MASK; mask++) { int bitpos = Node.bitpos(mask); int subNodeKeyHash = (mask << shift) | keyHash; if ((nodeMap & bitpos) != 0) { // node (not value) // Print the sub-node final Node subNode = node.nodeAt(bitpos); dumpSubTrie(a, subNode, entryLength, printValue, printSequenceNumber, shift + Node.BIT_PARTITION_SIZE, subNodeKeyHash); // Print an arrow to the sub-node a.append('n'); a.append(id); a.append(":f"); a.append(Integer.toString(mask)); a.append(" -> n"); a.append(toNodeId(subNodeKeyHash, shift + Node.BIT_PARTITION_SIZE)); a.append(" [label=\""); a.append(toArrowId(mask, shift)); a.append("\"];\n"); } } } private void dumpHashCollisionNodeSubTree(Appendable a, HashCollisionNode node, int entryLength, boolean printValue, boolean printSequenceNumber, int shift, int keyHash) throws IOException { // Print the node as a record a.append("n").append(toNodeId(keyHash, shift)); a.append(" [color=red;label=\""); boolean first = true; Object[] nodes = node.entries; for (int i = 0, index = 0; i < nodes.length; i += entryLength, index++) { if (first) { first = false; } else { a.append('|'); } a.append("'); a.append(Objects.toString(nodes[i])); if (printValue) { a.append('='); a.append(Objects.toString(nodes[i + 1])); } if (printSequenceNumber) { a.append(" #"); a.append(((Integer) nodes[i + entryLength - 1]).toString()); } } a.append("\"];\n"); } private void dumpSubTrie(Appendable a, Node node, int entryLength, boolean printValue, boolean printSequenceNumber, int shift, int keyHash) throws IOException { if (node instanceof BitmapIndexedNode) { dumpBitmapIndexedNodeSubTree(a, (BitmapIndexedNode) node, entryLength, printValue, printSequenceNumber, shift, keyHash); } else { dumpHashCollisionNodeSubTree(a, (HashCollisionNode) node, entryLength, printValue, printSequenceNumber, shift, keyHash); } } /** * Dumps a CHAMP Trie in the Graphviz DOT language. * * @param a an {@link Appendable} * @param root the root node of the trie * @param entryLength the entry length * @param printValue whether to print the value of an entry * @param printSequenceNumber whether to print the sequence number of an entry */ public void dumpTrie(Appendable a, Node root, int entryLength, boolean printValue, boolean printSequenceNumber) throws IOException { a.append("digraph ChampTrie {\n"); a.append("node [shape=record];\n"); dumpSubTrie(a, root, entryLength, printValue, printSequenceNumber, 0, 0); a.append("}\n"); } /** * Dumps a CHAMP Trie in the Graphviz DOT language. * * @param root the root node of the trie * @param entryLength the entry length * @param printValue whether to print the value of an entry * @param printSequenceNumber whether to print the sequence number of an entry * @return the dumped trie */ public String dumpTrie(Node root, int entryLength, boolean printValue, boolean printSequenceNumber) { StringBuilder a = new StringBuilder(); try { dumpTrie(a, root, entryLength, printValue, printSequenceNumber); } catch (IOException e) { throw new UncheckedIOException(e); } return a.toString(); } private String toArrowId(int mask, int shift) { String id = Integer.toBinaryString((mask) & Node.BIT_PARTITION_MASK); StringBuilder buf = new StringBuilder(); //noinspection StringRepeatCanBeUsed for (int i = id.length(); i < min(Node.HASH_CODE_LENGTH - shift, Node.BIT_PARTITION_SIZE); i++) { buf.append('0'); } buf.append(id); return buf.toString(); } private String toNodeId(int keyHash, int shift) { if (shift == 0) { return "root"; } String id = Integer.toBinaryString(keyHash); StringBuilder buf = new StringBuilder(); //noinspection StringRepeatCanBeUsed for (int i = id.length(); i < shift; i++) { buf.append('0'); } buf.append(id); return buf.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy