/*
* 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 org.infinispan.Cache;
import org.infinispan.CacheException;
import org.infinispan.context.Flag;
import org.infinispan.lifecycle.ComponentStatus;
import org.infinispan.lifecycle.Lifecycle;
import java.util.Map;
import java.util.Set;
/**
* This is a tree-like facade around a {@link Cache} allowing for efficient tree-style access to cached data.
* <p/>
* The primary purpose of this interface is to allow for efficient caching of tree-like structures such as directories,
* as well as to provide a compatibility layer with JBoss Cache 3.x and earlier.
* <p/>
* For most purposes, we expect people to use the {@link Cache} interface directly as it is simpler.
* <p/>
* The tree API assumes that a collection of {@link Node}s, organized in a tree structure underneath a root node,
* contains key/value attributes of data.
* <p/>
* Any locking happens on a node-level granularity, which means that all attributes on a node are atomic and in terms of
* locking, is coarse grained. At the same time, replication is fine grained, and only modified attributes in a Node
* are replicated.
* <p/>
* Obtaining a TreeCache is done using the {@link TreeCacheFactory}.
* <pre>
* Cache cache = new DefaultCacheFactory().getCache();
* TreeCacheFactory tcf = new TreeCacheFactory();
* TreeCache tree = tcf.createTreeCache(cache);
* </pre>
*
* @author Manik Surtani (<a href="mailto:manik AT jboss DOT org">manik AT jboss DOT org</a>)
* @see Node
* @since 4.0
*/
public interface TreeCache<K, V> extends Lifecycle {
/**
* Returns the root node of this cache.
*
* @return the root node
*/
Node<K, V> getRoot();
Node<K, V> getRoot(Flag... flags);
/**
* Associates the specified value with the specified key for a {@link Node} in this cache. If the {@link Node}
* previously contained a mapping for this key, the old value is replaced by the specified value.
*
* @param fqn <b><i>absolute</i></b> {@link Fqn} to the {@link Node} to be accessed.
* @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 <code>null</code> if there was no mapping for key. A
* <code>null</code> return can also indicate that the Node previously associated <code>null</code> with the
* specified key, if the implementation supports null values.
* @throws IllegalStateException if the cache is not in a started state.
*/
V put(Fqn fqn, K key, V value);
V put(Fqn fqn, K key, V value, Flag... flags);
/**
* Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #put(Fqn, Object,
* Object)}
*
* @param fqn String representation of the Fqn
* @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 <code>null</code> if there was no mapping for key. A
* <code>null</code> return can also indicate that the Node previously associated <code>null</code> with the
* specified key, if the implementation supports null values.
* @throws IllegalStateException if the cache is not in a started state
*/
V put(String fqn, K key, V value);
V put(String fqn, K key, V value, Flag... flags);
/**
* Copies all of the mappings from the specified map to a {@link Node}.
*
* @param fqn <b><i>absolute</i></b> {@link Fqn} to the {@link Node} to copy the data to
* @param data mappings to copy
* @throws IllegalStateException if the cache is not in a started state
*/
void put(Fqn fqn, Map<? extends K, ? extends V> data);
void put(Fqn fqn, Map<? extends K, ? extends V> data, Flag... flags);
/**
* Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #put(Fqn,
* java.util.Map)}
*
* @param fqn String representation of the Fqn
* @param data data map to insert
* @throws IllegalStateException if the cache is not in a started state
*/
void put(String fqn, Map<? extends K, ? extends V> data);
void put(String fqn, Map<? extends K, ? extends V> data, Flag... flags);
/**
* Removes the mapping for this key from a Node. 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 fqn <b><i>absolute</i></b> {@link Fqn} to the {@link Node} to be accessed.
* @param key key whose mapping is to be removed from the Node
* @return previous value associated with specified Node's key
* @throws IllegalStateException if the cache is not in a started state
*/
V remove(Fqn fqn, K key);
V remove(Fqn fqn, K key, Flag... flags);
/**
* Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #remove(Fqn,
* Object)}
*
* @param fqn string representation of the Fqn to retrieve
* @param key key to remove
* @return old value removed, or null if the fqn does not exist
* @throws IllegalStateException if the cache is not in a started state
*/
V remove(String fqn, K key);
V remove(String fqn, K key, Flag... flags);
/**
* Removes a {@link Node} indicated by absolute {@link Fqn}.
*
* @param fqn {@link Node} to remove
* @return true if the node was removed, false if the node was not found
* @throws IllegalStateException if the cache is not in a started state
*/
boolean removeNode(Fqn fqn);
boolean removeNode(Fqn fqn, Flag... flags);
/**
* Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #removeNode(Fqn)}
*
* @param fqn string representation of the Fqn to retrieve
* @return true if the node was found and removed, false otherwise
* @throws IllegalStateException if the cache is not in a started state
*/
boolean removeNode(String fqn);
boolean removeNode(String fqn, Flag... flags);
/**
* A convenience method to retrieve a node directly from the cache. Equivalent to calling
* cache.getRoot().getChild(fqn).
*
* @param fqn fqn of the node to retrieve
* @return a Node object, or a null if the node does not exist.
* @throws IllegalStateException if the cache is not in a started state
*/
Node<K, V> getNode(Fqn fqn);
Node<K, V> getNode(Fqn fqn, Flag... flags);
/**
* Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #getNode(Fqn)}
*
* @param fqn string representation of the Fqn to retrieve
* @return node, or null if the node does not exist
* @throws IllegalStateException if the cache is not in a started state
*/
Node<K, V> getNode(String fqn);
Node<K, V> getNode(String fqn, Flag... flags);
/**
* Convenience method that allows for direct access to the data in a {@link Node}.
*
* @param fqn <b><i>absolute</i></b> {@link Fqn} to the {@link Node} to be accessed.
* @param key key under which value is to be retrieved.
* @return returns data held under specified key in {@link Node} denoted by specified Fqn.
* @throws IllegalStateException if the cache is not in a started state
*/
V get(Fqn fqn, K key);
V get(Fqn fqn, K key, Flag... flags);
/**
* Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #get(Fqn,
* Object)}
*
* @param fqn string representation of the Fqn to retrieve
* @param key key to fetch
* @return value, or null if the fqn does not exist.
* @throws IllegalStateException if the cache is not in a started state
*/
V get(String fqn, K key);
V get(String fqn, K key, Flag... flags);
/**
* Moves a part of the cache to a different subtree.
* <p/>
* E.g.:
* <p/>
* assume a cache structure such as:
* <p/>
* <pre>
* /a/b/c
* /a/b/d
* /a/b/e
* <p/>
* <p/>
* Fqn f1 = Fqn.fromString("/a/b/c");
* Fqn f2 = Fqn.fromString("/a/b/d");
* <p/>
* cache.move(f1, f2);
* </pre>
* <p/>
* Will result in:
* <pre>
* <p/>
* /a/b/d/c
* /a/b/e
* <p/>
* </pre>
* <p/>
* and now
* <p/>
* <pre>
* Fqn f3 = Fqn.fromString("/a/b/e");
* Fqn f4 = Fqn.fromString("/a");
* cache.move(f3, f4);
* </pre>
* <p/>
* will result in:
* <pre>
* /a/b/d/c
* /a/e
* </pre>
* No-op if the node to be moved is the root node.
* <p/>
* <b>Note</b>: As of 3.0.0 and when using MVCC locking, more specific behaviour is defined as follows: <ul> <li>A
* no-op if the node is moved unto itself. E.g., <tt>move(fqn, fqn.getParent())</tt> will not do anything.</li>
* <li>If a target node does not exist it will be created silently, to be more consistent with other APIs such as
* <tt>put()</tt> on a nonexistent node.</li> <li>If the source node does not exist this is a no-op, to be more
* consistent with other APIs such as <tt>get()</tt> on a nonexistent node.</li> </ul>
*
* @param nodeToMove the Fqn of the node to move.
* @param newParent new location under which to attach the node being moved.
* @throws NodeNotExistsException may throw one of these if the target node does not exist or if a different thread
* has moved this node elsewhere already.
* @throws IllegalStateException if {@link Cache#getStatus()} would not return {@link ComponentStatus#RUNNING}.
*/
void move(Fqn nodeToMove, Fqn newParent) throws NodeNotExistsException;
void move(Fqn nodeToMove, Fqn newParent, Flag... flags) throws NodeNotExistsException;
/**
* Convenience method that takes in string representations of Fqns. Otherwise identical to {@link #move(Fqn, Fqn)}
*
* @throws IllegalStateException if {@link Cache#getStatus()} would not return {@link ComponentStatus#RUNNING}.
*/
void move(String nodeToMove, String newParent) throws NodeNotExistsException;
void move(String nodeToMove, String newParent, Flag... flags) throws NodeNotExistsException;
/**
* Retrieves a defensively copied data map of the underlying node. A convenience method to retrieving a node and
* getting data from the node directly.
*
* @param fqn
* @return map of data, or an empty map
* @throws CacheException
* @throws IllegalStateException if {@link Cache#getStatus()} would not return {@link ComponentStatus#RUNNING}.
*/
Map<K, V> getData(Fqn fqn);
Map<K, V> getData(Fqn fqn, Flag... flags);
/**
* Convenience method that takes in a String represenation of the Fqn. Otherwise identical to {@link
* #getKeys(Fqn)}.
*/
Set<K> getKeys(String fqn);
Set<K> getKeys(String fqn, Flag... flags);
/**
* Returns a set of attribute keys for the Fqn. Returns null if the node is not found, otherwise a Set. The set is a
* copy of the actual keys for this node.
* <p/>
* A convenience method to retrieving a node and getting keys from the node directly.
*
* @param fqn name of the node
* @throws IllegalStateException if {@link Cache#getStatus()} would not return {@link ComponentStatus#RUNNING}.
*/
Set<K> getKeys(Fqn fqn);
Set<K> getKeys(Fqn fqn, Flag... flags);
/**
* Convenience method that takes in a String represenation of the Fqn. Otherwise identical to {@link
* #clearData(Fqn)}.
*
* @throws IllegalStateException if {@link Cache#getStatus()} would not return {@link ComponentStatus#RUNNING}.
*/
void clearData(String fqn);
void clearData(String fqn, Flag... flags);
/**
* Removes the keys and properties from a named node.
* <p/>
* A convenience method to retrieving a node and getting keys from the node directly.
*
* @param fqn name of the node
* @throws IllegalStateException if {@link Cache#getStatus()} would not return {@link ComponentStatus#RUNNING}.
*/
void clearData(Fqn fqn);
void clearData(Fqn fqn, Flag... flags);
/**
* @return a reference to the underlying cache instance
*/
Cache<?, ?> getCache();
/**
* Tests if an Fqn exists. Convenience method for {@link #exists(Fqn)}
*
* @param fqn string representation of an Fqn
* @return true if the fqn exists, false otherwise
*/
boolean exists(String fqn);
boolean exists(String fqn, Flag... flags);
/**
* Tests if an Fqn exists.
*
* @param fqn Fqn to test
* @return true if the fqn exists, false otherwise
*/
boolean exists(Fqn fqn);
boolean exists(Fqn fqn, Flag... flags);
}