alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

JMeter example source code file (HashTree.java)

This example JMeter source code file (HashTree.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - JMeter tags/keywords

collection, collection, converttostring, hashmap, hashtree, hashtree, io, iterator, iterator, object, object, override, string, stringbuilder, treesearcher, util

The JMeter HashTree.java source code

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.jorphan.collections;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * This class is used to create a tree structure of objects. Each element in the
 * tree is also a key to the next node down in the tree. It provides many ways
 * to add objects and branches, as well as many ways to retrieve.
 * <p>
 * HashTree implements the Map interface for convenience reasons. The main
 * difference between a Map and a HashTree is that the HashTree organizes the
 * data into a recursive tree structure, and provides the means to manipulate
 * that structure.
 * <p>
 * Of special interest is the {@link #traverse(HashTreeTraverser)} method, which
 * provides an expedient way to traverse any HashTree by implementing the
 * {@link HashTreeTraverser} interface in order to perform some operation on the
 * tree, or to extract information from the tree.
 *
 * @see HashTreeTraverser
 * @see SearchByClass
 */
public class HashTree implements Serializable, Map, Cloneable {

    private static final long serialVersionUID = 240L;

    // GetLoggerForClass() uses ClassContext, which
    // causes a Security violation in RemoteJMeterImpl
    // so we use getLoggerFor() instead
//    private static final Logger log = LoggingManager.getLoggerFor(HashTree.class.getName());

    // Used for the RuntimeException to short-circuit the traversal
    private static final String FOUND = "found"; // $NON-NLS-1$

    protected final Map<Object, HashTree> data;

    /**
     * Creates an empty new HashTree.
     */
    public HashTree() {
        data = new HashMap<Object, HashTree>();
    }

    /**
     * Allow subclasses to provide their own Map.
     */
    protected HashTree(Map<Object, HashTree> _map) {
        data = _map;
    }

    /**
     * Creates a new HashTree and adds the given object as a top-level node.
     *
     * @param key
     */
    public HashTree(Object key) {
        data = new HashMap<Object, HashTree>();
        data.put(key, new HashTree());
    }

    /**
     * The Map given must also be a HashTree, otherwise an
     * UnsupportedOperationException is thrown. If it is a HashTree, this is
     * like calling the add(HashTree) method.
     *
     * @see #add(HashTree)
     * @see java.util.Map#putAll(Map)
     */
    public void putAll(Map map) {
        if (map instanceof HashTree) {
            this.add((HashTree) map);
        } else {
            throw new UnsupportedOperationException("can only putAll other HashTree objects");
        }
    }

    /**
     * Exists to satisfy the Map interface.
     *
     * @see java.util.Map#entrySet()
     */
    public Set<?> entrySet() {
        return data.entrySet();
    }

    /**
     * Implemented as required by the Map interface, but is not very useful
     * here. All 'values' in a HashTree are HashTree's themselves.
     *
     * @param value
     *            Object to be tested as a value.
     * @return True if the HashTree contains the value, false otherwise.
     * @see java.util.Map#containsValue(Object)
     */
    public boolean containsValue(Object value) {
        return data.containsValue(value);
    }

    /**
     * This is the same as calling HashTree.add(key,value).
     *
     * @param key
     *            to use
     * @param value
     *            to store against key
     * @see java.util.Map#put(Object, Object)
     */
    public Object put(Object key, Object value) {
        Object previous = data.get(key);
        add(key, value);
        return previous;
    }

    /**
     * Clears the HashTree of all contents.
     *
     * @see java.util.Map#clear()
     */
    public void clear() {
        data.clear();
    }

    /**
     * Returns a collection of all the sub-trees of the current tree.
     *
     * @see java.util.Map#values()
     */
    public Collection<HashTree> values() {
        return data.values();
    }

    /**
     * Adds a key as a node at the current level and then adds the given
     * HashTree to that new node.
     *
     * @param key
     *            key to create in this tree
     * @param subTree
     *            sub tree to add to the node created for the first argument.
     */
    public void add(Object key, HashTree subTree) {
        add(key);
        getTree(key).add(subTree);
    }

    /**
     * Adds all the nodes and branches of the given tree to this tree. Is like
     * merging two trees. Duplicates are ignored.
     *
     * @param newTree
     */
    public void add(HashTree newTree) {
        Iterator<?> iter = newTree.list().iterator();
        while (iter.hasNext()) {
            Object item = iter.next();
            add(item);
            getTree(item).add(newTree.getTree(item));
        }
    }

    /**
     * Creates a new HashTree and adds all the objects in the given collection
     * as top-level nodes in the tree.
     *
     * @param keys
     *            a collection of objects to be added to the created HashTree.
     */
    public HashTree(Collection<?> keys) {
        data = new HashMap<Object, HashTree>();
        Iterator<?> it = keys.iterator();
        while (it.hasNext()) {
            data.put(it.next(), new HashTree());
        }
    }

    /**
     * Creates a new HashTree and adds all the objects in the given array as
     * top-level nodes in the tree.
     */
    public HashTree(Object[] keys) {
        data = new HashMap<Object, HashTree>();
        for (int x = 0; x < keys.length; x++) {
            data.put(keys[x], new HashTree());
        }
    }

    /**
     * If the HashTree contains the given object as a key at the top level, then
     * a true result is returned, otherwise false.
     *
     * @param o
     *            Object to be tested as a key.
     * @return True if the HashTree contains the key, false otherwise.
     * @see java.util.Map#containsKey(Object)
     */
    public boolean containsKey(Object o) {
        return data.containsKey(o);
    }

    /**
     * If the HashTree is empty, true is returned, false otherwise.
     *
     * @return True if HashTree is empty, false otherwise.
     */
    public boolean isEmpty() {
        return data.isEmpty();
    }

    /**
     * Sets a key and it's value in the HashTree. It actually sets up a key, and
     * then creates a node for the key and sets the value to the new node, as a
     * key. Any previous nodes that existed under the given key are lost.
     *
     * @param key
     *            key to be set up
     * @param value
     *            value to be set up as a key in the secondary node
     */
    public void set(Object key, Object value) {
        data.put(key, createNewTree(value));
    }

    /**
     * Sets a key into the current tree and assigns it a HashTree as its
     * subtree. Any previous entries under the given key are removed.
     *
     * @param key
     *            key to be set up
     * @param t
     *            HashTree that the key maps to
     */
    public void set(Object key, HashTree t) {
        data.put(key, t);
    }

    /**
     * Sets a key and its values in the HashTree. It sets up a key in the
     * current node, and then creates a node for that key, and sets all the
     * values in the array as keys in the new node. Any keys previously held
     * under the given key are lost.
     *
     * @param key
     *            Key to be set up
     * @param values
     *            Array of objects to be added as keys in the secondary node
     */
    public void set(Object key, Object[] values) {
        data.put(key, createNewTree(Arrays.asList(values)));
    }

    /**
     * Sets a key and its values in the HashTree. It sets up a key in the
     * current node, and then creates a node for that key, and set all the
     * values in the array as keys in the new node. Any keys previously held
     * under the given key are removed.
     *
     * @param key
     *            key to be set up
     * @param values
     *            Collection of objects to be added as keys in the secondary
     *            node
     */
    public void set(Object key, Collection<?> values) {
        data.put(key, createNewTree(values));
    }

    /**
     * Sets a series of keys into the HashTree. It sets up the first object in
     * the key array as a key in the current node, recurses into the next
     * HashTree node through that key and adds the second object in the array.
     * Continues recursing in this manner until the end of the first array is
     * reached, at which point all the values of the second array are set as
     * keys to the bottom-most node. All previous keys of that bottom-most node
     * are removed.
     *
     * @param treePath
     *            array of keys to put into HashTree
     * @param values
     *            array of values to be added as keys to bottom-most node
     */
    public void set(Object[] treePath, Object[] values) {
        if (treePath != null && values != null) {
            set(Arrays.asList(treePath), Arrays.asList(values));
        }
    }

    /**
     * Sets a series of keys into the HashTree. It sets up the first object in
     * the key array as a key in the current node, recurses into the next
     * HashTree node through that key and adds the second object in the array.
     * Continues recursing in this manner until the end of the first array is
     * reached, at which point all the values of the Collection of values are
     * set as keys to the bottom-most node. Any keys previously held by the
     * bottom-most node are lost.
     *
     * @param treePath
     *            array of keys to put into HashTree
     * @param values
     *            Collection of values to be added as keys to bottom-most node
     */
    public void set(Object[] treePath, Collection<?> values) {
        if (treePath != null) {
            set(Arrays.asList(treePath), values);
        }
    }

    /**
     * Sets a series of keys into the HashTree. It sets up the first object in
     * the key list as a key in the current node, recurses into the next
     * HashTree node through that key and adds the second object in the list.
     * Continues recursing in this manner until the end of the first list is
     * reached, at which point all the values of the array of values are set as
     * keys to the bottom-most node. Any previously existing keys of that bottom
     * node are removed.
     *
     * @param treePath
     *            collection of keys to put into HashTree
     * @param values
     *            array of values to be added as keys to bottom-most node
     */
    public void set(Collection<?> treePath, Object[] values) {
        HashTree tree = addTreePath(treePath);
        tree.set(Arrays.asList(values));
    }

    /**
     * Sets the nodes of the current tree to be the objects of the given
     * collection. Any nodes previously in the tree are removed.
     *
     * @param values
     *            Collection of objects to set as nodes.
     */
    public void set(Collection<?> values) {
        clear();
        this.add(values);
    }

    /**
     * Sets a series of keys into the HashTree. It sets up the first object in
     * the key list as a key in the current node, recurses into the next
     * HashTree node through that key and adds the second object in the list.
     * Continues recursing in this manner until the end of the first list is
     * reached, at which point all the values of the Collection of values are
     * set as keys to the bottom-most node. Any previously existing keys of that
     * bottom node are lost.
     *
     * @param treePath
     *            list of keys to put into HashTree
     * @param values
     *            collection of values to be added as keys to bottom-most node
     */
    public void set(Collection<?> treePath, Collection values) {
        HashTree tree = addTreePath(treePath);
        tree.set(values);
    }

    /**
     * Adds an key into the HashTree at the current level.
     *
     * @param key
     *            key to be added to HashTree
     */
    public HashTree add(Object key) {
        if (!data.containsKey(key)) {
            HashTree newTree = createNewTree();
            data.put(key, newTree);
            return newTree;
        }
        return getTree(key);
    }

    /**
     * Adds all the given objects as nodes at the current level.
     *
     * @param keys
     *            Array of Keys to be added to HashTree.
     */
    public void add(Object[] keys) {
        for (int x = 0; x < keys.length; x++) {
            add(keys[x]);
        }
    }

    /**
     * Adds a bunch of keys into the HashTree at the current level.
     *
     * @param keys
     *            Collection of Keys to be added to HashTree.
     */
    public void add(Collection<?> keys) {
        Iterator<?> it = keys.iterator();
        while (it.hasNext()) {
            add(it.next());
        }
    }

    /**
     * Adds a key and it's value in the HashTree. The first argument becomes a
     * node at the current level, and the second argument becomes a node of it.
     *
     * @param key
     *            key to be added
     * @param value
     *            value to be added as a key in the secondary node
     */
    public HashTree add(Object key, Object value) {
        add(key);
        return getTree(key).add(value);
    }

    /**
     * Adds a key and it's values in the HashTree. The first argument becomes a
     * node at the current level, and adds all the values in the array to the
     * new node.
     *
     * @param key
     *            key to be added
     * @param values
     *            array of objects to be added as keys in the secondary node
     */
    public void add(Object key, Object[] values) {
        add(key);
        getTree(key).add(values);
    }

    /**
     * Adds a key as a node at the current level and then adds all the objects
     * in the second argument as nodes of the new node.
     *
     * @param key
     *            key to be added
     * @param values
     *            Collection of objects to be added as keys in the secondary
     *            node
     */
    public void add(Object key, Collection<?> values) {
        add(key);
        getTree(key).add(values);
    }

    /**
     * Adds a series of nodes into the HashTree using the given path. The first
     * argument is an array that represents a path to a specific node in the
     * tree. If the path doesn't already exist, it is created (the objects are
     * added along the way). At the path, all the objects in the second argument
     * are added as nodes.
     *
     * @param treePath
     *            an array of objects representing a path
     * @param values
     *            array of values to be added as keys to bottom-most node
     */
    public void add(Object[] treePath, Object[] values) {
        if (treePath != null) {
            add(Arrays.asList(treePath), Arrays.asList(values));
        }
    }

    /**
     * Adds a series of nodes into the HashTree using the given path. The first
     * argument is an array that represents a path to a specific node in the
     * tree. If the path doesn't already exist, it is created (the objects are
     * added along the way). At the path, all the objects in the second argument
     * are added as nodes.
     *
     * @param treePath
     *            an array of objects representing a path
     * @param values
     *            collection of values to be added as keys to bottom-most node
     */
    public void add(Object[] treePath, Collection<?> values) {
        if (treePath != null) {
            add(Arrays.asList(treePath), values);
        }
    }

    public HashTree add(Object[] treePath, Object value) {
        return add(Arrays.asList(treePath), value);
    }

    /**
     * Adds a series of nodes into the HashTree using the given path. The first
     * argument is a List that represents a path to a specific node in the tree.
     * If the path doesn't already exist, it is created (the objects are added
     * along the way). At the path, all the objects in the second argument are
     * added as nodes.
     *
     * @param treePath
     *            a list of objects representing a path
     * @param values
     *            array of values to be added as keys to bottom-most node
     */
    public void add(Collection<?> treePath, Object[] values) {
        HashTree tree = addTreePath(treePath);
        tree.add(Arrays.asList(values));
    }

    /**
     * Adds a series of nodes into the HashTree using the given path. The first
     * argument is a List that represents a path to a specific node in the tree.
     * If the path doesn't already exist, it is created (the objects are added
     * along the way). At the path, the object in the second argument is added
     * as a node.
     *
     * @param treePath
     *            a list of objects representing a path
     * @param value
     *            Object to add as a node to bottom-most node
     */
    public HashTree add(Collection<?> treePath, Object value) {
        HashTree tree = addTreePath(treePath);
        return tree.add(value);
    }

    /**
     * Adds a series of nodes into the HashTree using the given path. The first
     * argument is a SortedSet that represents a path to a specific node in the
     * tree. If the path doesn't already exist, it is created (the objects are
     * added along the way). At the path, all the objects in the second argument
     * are added as nodes.
     *
     * @param treePath
     *            a SortedSet of objects representing a path
     * @param values
     *            Collection of values to be added as keys to bottom-most node
     */
    public void add(Collection<?> treePath, Collection values) {
        HashTree tree = addTreePath(treePath);
        tree.add(values);
    }

    protected HashTree addTreePath(Collection<?> treePath) {
        HashTree tree = this;
        Iterator<?> iter = treePath.iterator();
        while (iter.hasNext()) {
            Object temp = iter.next();
            tree.add(temp);
            tree = tree.getTree(temp);
        }
        return tree;
    }

    /**
     * Gets the HashTree mapped to the given key.
     *
     * @param key
     *            Key used to find appropriate HashTree()
     */
    public HashTree getTree(Object key) {
        return data.get(key);
    }

    /**
     * Returns the HashTree object associated with the given key. Same as
     * calling {@link #getTree(Object)}.
     *
     * @see java.util.Map#get(Object)
     */
    public Object get(Object key) {
        return getTree(key);
    }

    /**
     * Gets the HashTree object mapped to the last key in the array by recursing
     * through the HashTree structure one key at a time.
     *
     * @param treePath
     *            array of keys.
     * @return HashTree at the end of the recursion.
     */
    public HashTree getTree(Object[] treePath) {
        if (treePath != null) {
            return getTree(Arrays.asList(treePath));
        }
        return this;
    }

    /**
     * Create a clone of this HashTree. This is not a deep clone (ie, the
     * contents of the tree are not cloned).
     *
     */
    @Override
    public Object clone() {
        HashTree newTree = new HashTree();
        cloneTree(newTree);
        return newTree;
    }

    protected void cloneTree(HashTree newTree) {
        Iterator<?> iter = list().iterator();
        while (iter.hasNext()) {
            Object key = iter.next();
            newTree.set(key, (HashTree) getTree(key).clone());
        }
    }

    /**
     * Creates a new tree. This method exists to allow inheriting classes to
     * generate the appropriate types of nodes. For instance, when a node is
     * added, it's value is a HashTree. Rather than directly calling the
     * HashTree() constructor, the createNewTree() method is called. Inheriting
     * classes should override these methods and create the appropriate subclass
     * of HashTree.
     *
     * @return HashTree
     */
    protected HashTree createNewTree() {
        return new HashTree();
    }

    /**
     * Creates a new tree. This method exists to allow inheriting classes to
     * generate the appropriate types of nodes. For instance, when a node is
     * added, it's value is a HashTree. Rather than directly calling the
     * HashTree() constructor, the createNewTree() method is called. Inheriting
     * classes should override these methods and create the appropriate subclass
     * of HashTree.
     *
     * @return HashTree
     */
    protected HashTree createNewTree(Object key) {
        return new HashTree(key);
    }

    /**
     * Creates a new tree. This method exists to allow inheriting classes to
     * generate the appropriate types of nodes. For instance, when a node is
     * added, it's value is a HashTree. Rather than directly calling the
     * HashTree() constructor, the createNewTree() method is called. Inheriting
     * classes should override these methods and create the appropriate subclass
     * of HashTree.
     *
     * @return HashTree
     */
    protected HashTree createNewTree(Collection<?> values) {
        return new HashTree(values);
    }

    /**
     * Gets the HashTree object mapped to the last key in the SortedSet by
     * recursing through the HashTree structure one key at a time.
     *
     * @param treePath
     *            Collection of keys
     * @return HashTree at the end of the recursion
     */
    public HashTree getTree(Collection<?> treePath) {
        return getTreePath(treePath);
    }

    /**
     * Gets a Collection of all keys in the current HashTree node. If the
     * HashTree represented a file system, this would be like getting a
     * collection of all the files in the current folder.
     *
     * @return Set of all keys in this HashTree
     */
    public Collection list() {
        return data.keySet();
    }

    /**
     * Gets a Set of all keys in the HashTree mapped to the given key of the
     * current HashTree object (in other words, one level down. If the HashTree
     * represented a file system, this would like getting a list of all files in
     * a sub-directory (of the current directory) specified by the key argument.
     *
     * @param key
     *            key used to find HashTree to get list of
     * @return Set of all keys in found HashTree.
     */
    public Collection list(Object key) {
        HashTree temp = data.get(key);
        if (temp != null) {
            return temp.list();
        }
        return new HashTree().list();
    }

    /**
     * Removes the entire branch specified by the given key.
     *
     * @see java.util.Map#remove(Object)
     */
    public Object remove(Object key) {
        return data.remove(key);
    }

    /**
     * Recurses down into the HashTree stucture using each subsequent key in the
     * array of keys, and returns the Set of keys of the HashTree object at the
     * end of the recursion. If the HashTree represented a file system, this
     * would be like getting a list of all the files in a directory specified by
     * the treePath, relative from the current directory.
     *
     * @param treePath
     *            Array of keys used to recurse into HashTree structure
     * @return Set of all keys found in end HashTree
     */
    public Collection list(Object[] treePath) {
        if (treePath != null) {
            return list(Arrays.asList(treePath));
        }
        return list();
    }

    /**
     * Recurses down into the HashTree stucture using each subsequent key in the
     * List of keys, and returns the Set of keys of the HashTree object at the
     * end of the recursion. If the HashTree represented a file system, this
     * would be like getting a list of all the files in a directory specified by
     * the treePath, relative from the current directory.
     *
     * @param treePath
     *            List of keys used to recurse into HashTree structure
     * @return Set of all keys found in end HashTree
     */
    public Collection list(Collection<?> treePath) {
        HashTree tree = getTreePath(treePath);
        if (tree != null) {
            return tree.list();
        }
        return new HashTree().list();
    }

    /**
     * Finds the given current key, and replaces it with the given new key. Any
     * tree structure found under the original key is moved to the new key.
     */
    public void replace(Object currentKey, Object newKey) {
        HashTree tree = getTree(currentKey);
        data.remove(currentKey);
        data.put(newKey, tree);
    }

    /**
     * Gets an array of all keys in the current HashTree node. If the HashTree
     * represented a file system, this would be like getting an array of all the
     * files in the current folder.
     *
     * @return array of all keys in this HashTree.
     */
    public Object[] getArray() {
        return data.keySet().toArray();
    }

    /**
     * Gets an array of all keys in the HashTree mapped to the given key of the
     * current HashTree object (in other words, one level down). If the HashTree
     * represented a file system, this would like getting a list of all files in
     * a sub-directory (of the current directory) specified by the key argument.
     *
     * @param key
     *            key used to find HashTree to get list of
     * @return array of all keys in found HashTree
     */
    public Object[] getArray(Object key) {
        HashTree t = getTree(key);
        if (t != null) {
            return t.getArray();
        }
        return null;
    }

    /**
     * Recurses down into the HashTree stucture using each subsequent key in the
     * array of keys, and returns an array of keys of the HashTree object at the
     * end of the recursion. If the HashTree represented a file system, this
     * would be like getting a list of all the files in a directory specified by
     * the treePath, relative from the current directory.
     *
     * @param treePath
     *            array of keys used to recurse into HashTree structure
     * @return array of all keys found in end HashTree
     */
    public Object[] getArray(Object[] treePath) {
        if (treePath != null) {
            return getArray(Arrays.asList(treePath));
        }
        return getArray();
    }

    /**
     * Recurses down into the HashTree stucture using each subsequent key in the
     * treePath argument, and returns an array of keys of the HashTree object at
     * the end of the recursion. If the HashTree represented a file system, this
     * would be like getting a list of all the files in a directory specified by
     * the treePath, relative from the current directory.
     *
     * @param treePath
     *            list of keys used to recurse into HashTree structure
     * @return array of all keys found in end HashTree
     */
    public Object[] getArray(Collection<?> treePath) {
        HashTree tree = getTreePath(treePath);
        return (tree != null) ? tree.getArray() : null;
    }

    protected HashTree getTreePath(Collection<?> treePath) {
        HashTree tree = this;
        Iterator<?> iter = treePath.iterator();
        while (iter.hasNext()) {
            if (tree == null) {
                return null;
            }
            Object temp = iter.next();
            tree = tree.getTree(temp);
        }
        return tree;
    }

    /**
     * Returns a hashcode for this HashTree.
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return data.hashCode() * 7;
    }

    /**
     * Compares all objects in the tree and verifies that the two trees contain
     * the same objects at the same tree levels. Returns true if they do, false
     * otherwise.
     *
     * @param o
     *            Object to be compared against
     * @see java.lang.Object#equals(Object)
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof HashTree)) {
            return false;
        }
        HashTree oo = (HashTree) o;
        if (oo.size() != this.size()) {
            return false;
        }
        return data.equals(oo.data);

        // boolean flag = true;
        // if (o instanceof HashTree)
        // {
        // HashTree oo = (HashTree) o;
        // Iterator it = data.keySet().iterator();
        // while (it.hasNext())
        // {
        // if (!oo.containsKey(it.next()))
        // {
        // flag = false;
        // break;
        // }
        // }
        // if (flag)
        // {
        // it = data.keySet().iterator();
        // while (it.hasNext())
        // {
        // Object temp = it.next();
        // flag = get(temp).equals(oo.get(temp));
        // if (!flag)
        // {
        // break;
        // }
        // }
        // }
        // }
        // else
        // {
        // flag = false;
        // }
        // return flag;
    }

    /**
     * Returns a Set of all the keys in the top-level of this HashTree.
     *
     * @see java.util.Map#keySet()
     */
    public Set keySet() {
        return data.keySet();
    }

    /**
     * Searches the HashTree structure for the given key. If it finds the key,
     * it returns the HashTree mapped to the key. If it finds nothing, it
     * returns null.
     *
     * @param key
     *            Key to search for
     * @return HashTree mapped to key, if found, otherwise <code>null
     */
    public HashTree search(Object key) {// TODO does not appear to be used
        HashTree result = getTree(key);
        if (result != null) {
            return result;
        }
        TreeSearcher searcher = new TreeSearcher(key);
        try {
            traverse(searcher);
        } catch (RuntimeException e) {
            if (!e.getMessage().equals(FOUND)){
                throw e;
            }
            // do nothing - means object is found
        }
        return searcher.getResult();
    }

    /**
     * Method readObject.
     */
    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
    }

    /**
     * Returns the number of top-level entries in the HashTree.
     *
     * @see java.util.Map#size()
     */
    public int size() {
        return data.size();
    }

    /**
     * Allows any implementation of the HashTreeTraverser interface to easily
     * traverse (depth-first) all the nodes of the HashTree. The Traverser
     * implementation will be given notification of each node visited.
     *
     * @see HashTreeTraverser
     */
    public void traverse(HashTreeTraverser visitor) {
        Iterator<?> iter = list().iterator();
        while (iter.hasNext()) {
            Object item = iter.next();
            visitor.addNode(item, getTree(item));
            getTree(item).traverseInto(visitor);
        }
    }

    /**
     * The recursive method that accomplishes the tree-traversal and performs
     * the callbacks to the HashTreeTraverser.
     */
    private void traverseInto(HashTreeTraverser visitor) {

        if (list().size() == 0) {
            visitor.processPath();
        } else {
            Iterator<?> iter = list().iterator();
            while (iter.hasNext()) {
                Object item = iter.next();
                final HashTree treeItem = getTree(item);
                visitor.addNode(item, treeItem);
                treeItem.traverseInto(visitor);
            }
        }
        visitor.subtractNode();
    }

    /**
     * Generate a printable representation of the tree.
     *
     * @return a representation of the tree
     */
    @Override
    public String toString() {
        ConvertToString converter = new ConvertToString();
        try {
            traverse(converter);
        } catch (Exception e) { // Just in case
            converter.reportError(e);
        }
        return converter.toString();
    }

    private static class TreeSearcher implements HashTreeTraverser {

        private final Object target;

        private HashTree result;

        public TreeSearcher(Object t) {
            target = t;
        }

        public HashTree getResult() {
            return result;
        }

        /** {@inheritDoc} */
        public void addNode(Object node, HashTree subTree) {
            result = subTree.getTree(target);
            if (result != null) {
                // short circuit traversal when found
                throw new RuntimeException(FOUND);
            }
        }

        /** {@inheritDoc} */
        public void processPath() {
            // Not used
        }

        /** {@inheritDoc} */
        public void subtractNode() {
            // Not used
        }
    }

    private static class ConvertToString implements HashTreeTraverser {
        private final StringBuilder string = new StringBuilder(getClass().getName() + "{");

        private final StringBuilder spaces = new StringBuilder();

        private int depth = 0;

        public void addNode(Object key, HashTree subTree) {
            depth++;
            string.append("\n").append(getSpaces()).append(key);
            string.append(" {");
        }

        public void subtractNode() {
            string.append("\n" + getSpaces() + "}");
            depth--;
        }

        public void processPath() {
        }

        @Override
        public String toString() {
            string.append("\n}");
            return string.toString();
        }

        void reportError(Throwable t){
            string.append("Error: ").append(t.toString());
        }

        private String getSpaces() {
            if (spaces.length() < depth * 2) {
                while (spaces.length() < depth * 2) {
                    spaces.append("  ");
                }
            } else if (spaces.length() > depth * 2) {
                spaces.setLength(depth * 2);
            }
            return spaces.toString();
        }
    }
}

Other JMeter examples (source code examples)

Here is a short list of links related to this JMeter HashTree.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.