src/main/java/com/workplacesystems/utilsj/collections/TransactionalBidiTreeMap.java
@Override
    public V put(final K key, final V value)
            throws ClassCastException, NullPointerException,
                   IllegalArgumentException, ConcurrentModificationException {

        checkKeyAndValue(key, value);

        Node<K,V> node = rootNode[KEY];

        String thread_id = getCurrentThreadId();

        if (node == null) {
            Node<K,V> root = new Node<K,V>(key, value);

            rootNode[KEY]   = root;
            rootNode[VALUE] = root;

            if (!auto_commit)
                root.setStatus(Node.ADDED, thread_id);

            grow();
        } else {
            while (true) {
                int cmp = compare(Node.ADDED, key, node.getStatus(), node.getData(KEY), KEY);

                if (cmp == 0) {
                    if (nextEqualValid(getFloorEqualNode(node, KEY), KEY, thread_id) != null)
                    {
                        String debug_message = "Cannot store a duplicate key (\"" + key + "\") in this Map";
                        log.debug (debug_message);             
                        throw new IllegalArgumentException(debug_message); 
                    }
                    
                    if (node.is(Node.ADDED, null))
                        throw new ConcurrentModificationException();
                    
                    if (node.getRight(KEY) != null) {
                        node = node.getRight(KEY);
                    } else if (node.getLeft(KEY) != null) {
                        node = node.getLeft(KEY);
                    } else {
                        Node<K,V> newNode = new Node<K,V>(key, value);

                        insertValue(newNode, thread_id);
                        node.setRight(newNode, KEY);
                        newNode.setParent(node, KEY);
                        doRedBlackInsert(newNode, KEY);
                        grow();

                        if (!auto_commit)
                            newNode.setStatus(Node.ADDED, thread_id);

                        break;
                    }
                } else if (cmp < 0) {
                    if (node.getLeft(KEY) != null) {
                        node = node.getLeft(KEY);
                    } else {
                        Node<K,V> newNode = new Node<K,V>(key, value);

                        insertValue(newNode, thread_id);
                        node.setLeft(newNode, KEY);
                        newNode.setParent(node, KEY);
                        doRedBlackInsert(newNode, KEY);
                        grow();

                        if (!auto_commit)
                            newNode.setStatus(Node.ADDED, thread_id);

                        break;
                    }
                } else {    // cmp > 0
                    if (node.getRight(KEY) != null) {
                        node = node.getRight(KEY);
                    } else {
                        Node<K,V> newNode = new Node<K,V>(key, value);

                        insertValue(newNode, thread_id);
                        node.setRight(newNode, KEY);
                        newNode.setParent(node, KEY);
                        doRedBlackInsert(newNode, KEY);
                        grow();

                        if (!auto_commit)
                            newNode.setStatus(Node.ADDED, thread_id);

                        break;
                    }
                }
            }
        }

        return null;
    }
@Override
    public V put(final K key, final V value)
            throws ClassCastException, NullPointerException,
                   IllegalArgumentException, ConcurrentModificationException {

        checkKeyAndValue(key, value);

        Node<K,V> node = rootNode[KEY];

        String thread_id = getCurrentThreadId();

        if (node == null) {
            Node<K,V> root = new Node<K,V>(key, value);

            rootNode[KEY]   = root;
            rootNode[VALUE] = root;

            if (!auto_commit)
                root.setStatus(Node.ADDED, thread_id);

            grow();
        } else {
            while (true) {
                int cmp = compare(Node.ADDED, key, node.getStatus(), node.getData(KEY), KEY);

                if (cmp == 0) {
                    if (nextEqualValid(getFloorEqualNode(node, KEY), KEY, thread_id) != null)
                    {
                        String debug_message = "Cannot store a duplicate key (\"" + key + "\") in this Map";
                        log.debug (debug_message);             
                        throw new IllegalArgumentException(debug_message); 
                    }
                    
                    if (node.is(Node.ADDED, null))
                        throw new ConcurrentModificationException();
                    
                    if (node.getRight(KEY) != null) {
                        node = node.getRight(KEY);
                    } else if (node.getLeft(KEY) != null) {
                        node = node.getLeft(KEY);
                    } else {
                        Node<K,V> newNode = new Node<K,V>(key, value);

                        insertValue(newNode, thread_id);
                        node.setRight(newNode, KEY);
                        newNode.setParent(node, KEY);
                        doRedBlackInsert(newNode, KEY);
                        grow();

                        if (!auto_commit)
                            newNode.setStatus(Node.ADDED, thread_id);

                        break;
                    }
                } else if (cmp < 0) {
                    if (node.getLeft(KEY) != null) {
                        node = node.getLeft(KEY);
                    } else {
                        Node<K,V> newNode = new Node<K,V>(key, value);

                        insertValue(newNode, thread_id);
                        node.setLeft(newNode, KEY);
                        newNode.setParent(node, KEY);
                        doRedBlackInsert(newNode, KEY);
                        grow();

                        if (!auto_commit)
                            newNode.setStatus(Node.ADDED, thread_id);

                        break;
                    }
                } else {    // cmp > 0
                    if (node.getRight(KEY) != null) {
                        node = node.getRight(KEY);
                    } else {
                        Node<K,V> newNode = new Node<K,V>(key, value);

                        insertValue(newNode, thread_id);
                        node.setRight(newNode, KEY);
                        newNode.setParent(node, KEY);
                        doRedBlackInsert(newNode, KEY);
                        grow();

                        if (!auto_commit)
                            newNode.setStatus(Node.ADDED, thread_id);

                        break;
                    }
                }
            }
        }

        return null;
    }
Associates the specified value with the specified key in this
map.

@param key key with which the specified value is to be
associated.
@param value value to be associated with the specified key.

@return null

@throws ClassCastException if the class of the specified key
or value prevents it from being
stored in this map.
@throws NullPointerException if the specified key or value
is null
@throws IllegalArgumentException if the key duplicates an
existing key, or if the
value duplicates an
existing value