Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java
40948 views
/*1* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package nsk.share;2425import java.util.*;2627/**28* This denotation provides naming and indexing for nodes29* of a binary, or ternary, or <tt>n</tt>-ary tree.30*31* <p>Here, <tt>n</tt> would be the length of a symbols32* string used as an alphabeth for nodes naming. For a33* binary tree, <tt>n=2</tt>, and an aplhabeth could be34* the <tt>"LR"</tt> string. This implies the following35* naming for tree nodes:36* <pre>37* (empty)38* / \39* L R40* / \ / \41* LL LR RL RR42* / \ / \ / \ / \43* </pre>44*45* <p>Anyway, the tree root node is named with the empty46* string <tt>""</tt> and is indexed with 2-zeroes array47* <tt>{0,0}</tt>.48*49* <p>Index for a tree node is 2-elements <tt>int[]</tt>50* array. The 1st element is the node's level in a tree.51* The 2nd element is the item's number among all nodes of52* that level; provided that node items are enumerated from53* <tt>0</tt> to <tt>n</tt><sup>level</sup><tt>-1</tt>.54* Given a level, lexicographic order is assumed for the55* nodes of the same level.56*57* <p>For example: given the above sample tree, the node58* <tt>"L"</tt> has the index <tt>{1,0}</tt>, while the59* node <tt>"RL"</tt> has the index <tt>{2,2}</tt>.60*61* <p>In general case, ordering of characters used for nodes62* naming is implied by the given alphabeth. This may differ63* from the ``natural'' ordering. For example, if alphabeth64* is <tt>"ZYX...CBA"</tt>, then ordering for nodes would be65* opposite to ``natural''.66*/67public class TreeNodesDenotation extends Denotation {68/**69* Symbols to denote tree nodes.70*71* @see #TreeNodeDenotation(String)72*/73private String alphabeth;7475/**76* Standard denotation for a binary tree; alphabeth77* is <tt>"LR"</tt>.78*79* @see #TreeNodesDenotation(String)80*/81public TreeNodesDenotation() {82this("LR");83}8485/**86* Denotation for nodes of a tree.87*88* <p>Each tree node is marked with a string of symbols89* from the given <tt>alphabeth</tt>. A string length90* equals to the node's level. The root node is always91* denoted with the empty string.92*93* <p>For example, an <tt>alphabeth</tt> for a binary94* tree could be <tt>"LR"</tt>, or <tt>"01"</tt>, or95* any 2-symbols string. However, <tt>"lL"</tt> or96* <tt>"rR"</tt> would be illegal because of collision97* between upper- and lower- case letters.98*99* <p>In general case, it is illegal for <tt>alphabeth</tt>100* to contain two or several copies of the same symbol.101* This constructor deems lower- and upper-case variants102* of the same letter are the same symbol.103*104* @throws IllegalArgumentException If the <tt>alphabeth</tt>105* looks illegal.106*/107public TreeNodesDenotation(String alphabeth) {108if (alphabeth.length() == 0)109throw new IllegalArgumentException("empty alphabeth");110// Check for lower- to upper- case collision:111this.alphabeth = alphabeth.toUpperCase();112int length = this.alphabeth.length();113Set<Character> pool = new HashSet<Character>(); // still empty114for (int i=0; i<length; i++)115pool.add(Character.valueOf(this.alphabeth.charAt(i)));116if (pool.size() != length)117throw new IllegalArgumentException("collision: " + alphabeth);118}119120/**121* Check if the <tt>name</tt> is legal, and return the122* numeric index for the tree node denoted by the given123* <tt>name</tt>.124*125* @throws IllegalArgumentException If the <tt>name</tt>126* is illegal.127*/128public int[] indexFor(String name) {129int level = name.length();130int factor = alphabeth.length();131long item = 0;132for (int i=0; i<level; i++) {133char symbol = Character.toUpperCase(name.charAt(i));134int position = alphabeth.indexOf(symbol);135if (position < 0)136throw new IllegalArgumentException("unknown symbol: " + name);137item = item*factor + position;138if (item < 0 || item > Integer.MAX_VALUE)139throw new IllegalArgumentException("too long name: " + name);140};141int[] index = new int [] { level, (int)item };142return index;143}144145/**146* Check if the <tt>index[]</tt> is legal, and return147* a symbolic name for the tree node denoted by the148* given <tt>index[]</tt>.149*150* @throws IllegalArgumentException If the <tt>index[]</tt>151* is illegal.152*/153public String nameFor(int[] index) {154if (index.length != 2)155throw new IllegalArgumentException(156"index dimention: " + index.length);157StringBuffer name = new StringBuffer(); // still empty158int level = index[0];159int item = index[1];160if (level < 0 || item < 0)161throw new IllegalArgumentException(162"negative index: " + level + ", " + item);163int factor = alphabeth.length();164for (int i=0; i<level; i++) {165int k = item % factor;166name.append(alphabeth.charAt(k));167item = item / factor;168};169if (item != 0)170throw new IllegalArgumentException(171"out of range: {"+ index[0] + "," + index[1] + "}");172return new String(name.reverse());173}174}175176177