/* * JBoss, Home of Professional Open Source * Copyright 2009 Red Hat Inc. and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.tree; import net.jcip.annotations.ThreadSafe; import org.infinispan.Cache; import org.infinispan.context.Flag; import java.util.Map; import java.util.Set; /** * A Node is a {@link Fqn named} logical grouping of data in the {@link TreeCache} API of JBoss {@link Cache}. A node * should be used to contain data for a single data record, for example information about a particular person or * account. * <p/> * One purpose of grouping cache data into separate nodes is to minimize transaction locking interference, and increase * concurrency. So for example, when multiple threads or possibly distributed caches are acccessing different accounts * simultaneously. * <p/> * A node has references to its children, parent (each node except the root - defined by {@link Fqn#ROOT} - has a single * parent) and data contained within the node (as key/value pairs). The data access methods are similar to the * collections {@link Map} interface, but some are read-only or return copies of the underlying the data. * <p/> * * @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik AT jboss DOT org)</a> * @see TreeCache * @since 4.0 */ @ThreadSafe public interface Node<K, V> { /** * Returns the parent node. If this is the root node, this method returns <code>null</code>. * * @return the parent node, or null if this is the root node */ Node<K, V> getParent(); Node<K, V> getParent(Flag... flags); /** * Returns an immutable set of children nodes. * * @return an immutable {@link Set} of child nodes. Empty {@link Set} if there aren't any children. */ Set<Node<K, V>> getChildren(); Set<Node<K, V>> getChildren(Flag... flags); /** * Returns an immutable set of children node names. * * @return an immutable {@link Set} of child node names. Empty {@link Set} if there aren't any children. */ Set<Object> getChildrenNames(); Set<Object> getChildrenNames(Flag... flags); /** * Returns a map containing the data in this {@link Node}. * * @return a {@link Map} containing the data in this {@link Node}. If there is no data, an empty {@link Map} is * returned. The {@link Map} returned is always immutable. */ Map<K, V> getData(); Map<K, V> getData(Flag... flags); /** * Returns a {@link Set} containing the data in this {@link Node}. * * @return a {@link Set} containing the data in this {@link Node}. If there is no data, an empty {@link Set} is * returned. The {@link Set} returned is always immutable. */ Set<K> getKeys(); Set<K> getKeys(Flag... flags); /** * Returns the {@link Fqn} which represents the location of this {@link Node} in the cache structure. The {@link * Fqn} returned is absolute. * * @return The {@link Fqn} which represents the location of this {@link Node} in the cache structure. The {@link * Fqn} returned is absolute. */ Fqn getFqn(); /** * Adds a child node with the given {@link Fqn} under the current node. Returns the newly created node. * <p/> * If the child exists returns the child node anyway. Guaranteed to return a non-null node. * <p/> * The {@link Fqn} passed in is relative to the current node. The new child node will have an absolute fqn * calculated as follows: <pre>new Fqn(getFqn(), f)</pre>. See {@link Fqn} for the operation of this constructor. * * @param f {@link Fqn} of the child node, relative to the current node. * @return the newly created node, or the existing node if one already exists. */ Node<K, V> addChild(Fqn f); Node<K, V> addChild(Fqn f, Flag... flags); /** * Removes a child node specified by the given relative {@link Fqn}. * <p/> * If you wish to remove children based on absolute {@link Fqn}s, use the {@link TreeCache} interface instead. * * @param f {@link Fqn} of the child node, relative to the current node. * @return true if the node was found and removed, false otherwise */ boolean removeChild(Fqn f); boolean removeChild(Fqn f, Flag... flags); /** * Removes a child node specified by the given name. * * @param childName name of the child node, directly under the current node. * @return true if the node was found and removed, false otherwise */ boolean removeChild(Object childName); boolean removeChild(Object childName, Flag... flags); /** * Returns the child node * * @param f {@link Fqn} of the child node * @return null if the child does not exist. */ Node<K, V> getChild(Fqn f); Node<K, V> getChild(Fqn f, Flag... flags); /** * @param name name of the child * @return a direct child of the current node. */ Node<K, V> getChild(Object name); Node<K, V> getChild(Object name, Flag... flags); /** * Associates the specified value with the specified key for this node. If this node previously contained a mapping * for this key, the old value is replaced by the specified value. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return Returns the old value contained under this key. Null if key doesn't exist. */ V put(K key, V value); V put(K key, V value, Flag... flags); /** * If the specified key is not already associated with a value, associate it with the given value, and returns the * Object (if any) that occupied the space, or null. * <p/> * Equivalent to calling * <pre> * if (!node.getKeys().contains(key)) * return node.put(key, value); * else * return node.get(key); * </pre> * <p/> * except that this is atomic. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or null if there was no mapping for key. */ V putIfAbsent(K key, V value); V putIfAbsent(K key, V value, Flag... flags); /** * Replace entry for key only if currently mapped to some value. Acts as * <pre> * if ((node.getKeys().contains(key)) * { * return node.put(key, value); * } * else * return null; * </pre> * <p/> * except that this is atomic. * * @param key key with which the specified value is associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or <tt>null</tt> if there was no mapping for key. */ V replace(K key, V value); V replace(K key, V value, Flag... flags); /** * Replace entry for key only if currently mapped to given value. Acts as * <pre> * if (node.get(key).equals(oldValue)) * { * node.put(key, newValue); * return true; * } * else * return false; * </pre> * <p/> * except that this is atomic. * * @param key key with which the specified value is associated. * @param oldValue value expected to be associated with the specified key. * @param newValue value to be associated with the specified key. * @return true if the value was replaced */ boolean replace(K key, V oldValue, V newValue); boolean replace(K key, V oldValue, V value, Flag... flags); /** * Copies all of the mappings from the specified map to this node's map. If any data exists, existing keys are * overwritten with the keys in the new map. The behavior is equivalent to: * <pre> * Node node; * for (Map.Entry me : map.entrySet()) * node.put(me.getKey(), me.getValue()); * </pre> * * @param map map to copy from */ void putAll(Map<? extends K, ? extends V> map); void putAll(Map<? extends K, ? extends V> map, Flag... flags); /** * Similar to {@link #putAll(java.util.Map)} except that it removes any entries that exists in the data map first. * Note that this happens atomically, under a single lock. This is the analogous to doing a {@link #clearData()} * followed by a {@link #putAll(java.util.Map)} in the same transaction. * * @param map map to copy from */ void replaceAll(Map<? extends K, ? extends V> map); void replaceAll(Map<? extends K, ? extends V> map, Flag... flags); /** * Returns the value to which this node maps the specified key. Returns <code>null</code> if the node contains no * mapping for this key. * * @param key key of the data to return * @return the value to which this node maps the specified key, or <code>null</code> if the map contains no mapping * for this key */ V get(K key); V get(K key, Flag... flags); /** * Removes the mapping for this key from this node if it is present. Returns the value to which the node previously * associated the key, or <code>null</code> if the node contained no mapping for this key * * @param key key whose mapping is to be removed * @return previous value associated with specified key, or <code>null</code> if there was no mapping for key */ V remove(K key); V remove(K key, Flag... flags); /** * Removes all mappings from the node's data map. */ void clearData(); void clearData(Flag... flags); /** * @return the number of elements (key/value pairs) in the node's data map. */ int dataSize(); int dataSize(Flag... flags); /** * Returns true if the child node denoted by the relative {@link Fqn} passed in exists. * * @param f {@link Fqn} relative to the current node of the child you are testing the existence of. * @return true if the child node denoted by the relative {@link Fqn} passed in exists. */ boolean hasChild(Fqn f); boolean hasChild(Fqn f, Flag... flags); /** * Returns true if the child node denoted by the Object name passed in exists. * * @param o name of the child, relative to the current node * @return true if the child node denoted by the name passed in exists. */ boolean hasChild(Object o); boolean hasChild(Object o, Flag... flags); /** * Tests if a node reference is still valid. A node reference may become invalid if it has been removed, invalidated * or moved, either locally or remotely. If a node is invalid, it should be fetched again from the cache or a valid * parent node. Operations on invalid nodes will throw a {@link org.infinispan.tree.NodeNotValidException}. * * @return true if the node is valid. */ boolean isValid(); void removeChildren(); void removeChildren(Flag... flags); }