package org.mobicents.slee.runtime.activity;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.slee.facilities.TimerID;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.mobicents.cache.CacheData;
import org.mobicents.cluster.MobicentsCluster;
/**
*
* Proxy object for activity context factory data management through JBoss Cache
*
* @author martins
*
*/
public class ActivityContextCacheData extends CacheData {
/**
* the fqn of the node that holds all activity context cache child nodes
*/
public final static String parentNodeFqn = "ac";
// --- child cache nodes naming
private static final String ATTACHED_SBBs_NODE_NAME = "attached-sbbs";
private static final String ATTACHED_TIMERS_NODE_NAME = "attached-timers";
private static final String NAMES_BOUND_NODE_NAME = "names-bound";
private static final String CMP_ATTRIBUTES_NODE_NAME = "cmp-attributes";
private static final String IS_ENDING_NODE_NAME = "is-ending";
private static final String IS_CHECKING_REFS_NODE_NAME = "is-checking-refs";
private static final Fqn ATTACHED_SBBs_FQN = Fqn
.fromElements(ATTACHED_SBBs_NODE_NAME);
private static final Fqn ATTACHED_TIMERS_FQN = Fqn
.fromElements(ATTACHED_TIMERS_NODE_NAME);
private static final Fqn NAMES_BOUND_FQN = Fqn.fromElements(NAMES_BOUND_NODE_NAME);
private static final Fqn CMP_ATTRIBUTES_FQN = Fqn
.fromElements(CMP_ATTRIBUTES_NODE_NAME);
private static final Fqn IS_ENDING_FQN = Fqn
.fromElements(IS_ENDING_NODE_NAME);
private static final Fqn IS_CHECKING_REFS_FQN = Fqn
.fromElements(IS_CHECKING_REFS_NODE_NAME);
private static final Object CMP_ATTRIBUTES_NODE_MAP_KEY = new Object();
private Node _attachedSbbsNode;
private Node getAttachedSbbsNode(boolean createIfNotExists) {
if (_attachedSbbsNode == null) {
final Node node = getNode();
_attachedSbbsNode = node.getChild(ATTACHED_SBBs_NODE_NAME);
if (_attachedSbbsNode == null && createIfNotExists) {
_attachedSbbsNode = node.addChild(ATTACHED_SBBs_FQN);
}
}
return _attachedSbbsNode;
}
private Node _attachedTimersNode;
private Node getAttachedTimersNode(boolean createIfNotExists) {
if (_attachedTimersNode == null) {
final Node node = getNode();
_attachedTimersNode = node.getChild(ATTACHED_TIMERS_NODE_NAME);
if (_attachedTimersNode == null && createIfNotExists) {
_attachedTimersNode = node.addChild(ATTACHED_TIMERS_FQN);
}
}
return _attachedTimersNode;
}
private Node _namesBoundNode;
private Node getNamesBoundNode(boolean createIfNotExists) {
if (_namesBoundNode == null) {
final Node node = getNode();
_namesBoundNode = node.getChild(NAMES_BOUND_NODE_NAME);
if (_namesBoundNode == null && createIfNotExists) {
_namesBoundNode = node.addChild(NAMES_BOUND_FQN);
}
}
return _namesBoundNode;
}
private Node _cmpAttributesNode;
private Node getCmpAttributesNode(boolean createIfNotExists) {
if (_cmpAttributesNode == null) {
final Node node = getNode();
_cmpAttributesNode = node.getChild(CMP_ATTRIBUTES_NODE_NAME);
if (_cmpAttributesNode == null && createIfNotExists) {
_cmpAttributesNode = node.addChild(CMP_ATTRIBUTES_FQN);
}
}
return _cmpAttributesNode;
}
/**
*
* @param activityContextHandle
*/
public ActivityContextCacheData(Object activityContextHandle,
MobicentsCluster cluster) {
super(Fqn.fromElements(parentNodeFqn, activityContextHandle),
cluster.getMobicentsCache());
}
/**
* Puts an object in cache data
*
* @param key
* @param value
* @return the old object for the specified key, null if key was not mapped
*/
public Object putObject(Object key, Object value) {
return getNode().put(key, value);
}
/**
* Retrieves an object in cache data mapped to the specified key
*
* @param key
* @return
*/
public Object getObject(Object key) {
return getNode().get(key);
}
/**
* Removes an object in cache data mapped to the specified key
*
* @param key
* @return the object removed, null if the key was not mapped
*/
public Object removeObject(Object key) {
return getNode().remove(key);
}
public boolean isEnding() {
return getNode().hasChild(IS_ENDING_NODE_NAME);
}
public boolean setEnding(boolean value) {
if (value) {
if (!isEnding()) {
getNode().addChild(IS_ENDING_FQN);
return true;
}
else {
return false;
}
}
else {
if (isEnding()) {
getNode().removeChild(IS_ENDING_NODE_NAME);
return true;
}
else {
return false;
}
}
}
public boolean isCheckingReferences() {
return getNode().hasChild(IS_CHECKING_REFS_NODE_NAME);
}
public boolean setCheckingReferences(boolean value) {
if (value) {
Node node = getNode();
if (!node.hasChild(IS_CHECKING_REFS_NODE_NAME)) {
node.addChild(IS_CHECKING_REFS_FQN);
return true;
}
else {
return false;
}
}
else {
Node node = getNode();
if (node.hasChild(IS_CHECKING_REFS_NODE_NAME)) {
node.removeChild(IS_CHECKING_REFS_NODE_NAME);
return true;
}
else {
return false;
}
}
}
/**
* Tries to attaches an sbb entity
*
* @param sbbEntityId
* @return true if it was attached, false if already was attached
*/
public boolean attachSbbEntity(String sbbEntityId) {
final Node node = getAttachedSbbsNode(true);
if (!node.hasChild(sbbEntityId)) {
node.addChild(Fqn.fromElements(sbbEntityId));
return true;
} else {
return false;
}
}
/**
* Detaches an sbb entity
*
* @param sbbEntityId
*/
public boolean detachSbbEntity(String sbbEntityId) {
final Node node = getAttachedSbbsNode(false);
return node != null ? node.removeChild(sbbEntityId) : false;
}
/**
* Verifies if there at least one sbb entity attached
*
* @return false is there are no sbb entities attached, true otherwise
*/
public boolean noSbbEntitiesAttached() {
final Node node = getAttachedSbbsNode(false);
return node != null ? node.isLeaf() : true;
}
/**
* Return a set with all sbb entities attached.
*
* @return
*/
public Set getSbbEntitiesAttached() {
final Node node = getAttachedSbbsNode(false);
return node != null ? node.getChildrenNames() : Collections.EMPTY_SET;
}
/**
* Attaches a timer
*
* @param timerID
*/
public boolean attachTimer(TimerID timerID) {
final Node node = getAttachedTimersNode(true);
if (!node.hasChild(timerID)) {
node.addChild(Fqn.fromElements(timerID));
return true;
}
else {
return false;
}
}
/**
* Detaches a timer
*
* @param timerID
*/
public boolean detachTimer(TimerID timerID) {
final Node node = getAttachedTimersNode(false);
return node != null ? node.removeChild(timerID) : false;
}
/**
* Verifies if there at least one timer attached
*
* @return false is there are no timers attached, true otherwise
*/
public boolean noTimersAttached() {
final Node node = getAttachedTimersNode(false);
return node != null ? node.isLeaf() : true;
}
/**
* Returns the set of timers attached to the ac
*
* @return
*/
public Set getAttachedTimers() {
final Node node = getAttachedTimersNode(false);
return node != null ? node.getChildrenNames() : Collections.EMPTY_SET;
}
/**
* Adds the specified name to the set of names bound to the ac
*
* @param name
*/
public void nameBound(String name) {
final Node node = getNamesBoundNode(true);
if (!node.hasChild(name)) {
node.addChild(Fqn.fromElements(name));
}
}
/**
* Removes the specified name from the set of names bound to the ac
*
* @param name
*/
public boolean nameUnbound(String name) {
final Node node = getNamesBoundNode(false);
return node != null ? node.removeChild(name) : false;
}
/**
* Verifies if there at least one name bound to the ac
*
* @return false is there are no names bound, true otherwise
*/
public boolean noNamesBound() {
final Node node = getNamesBoundNode(false);
return node != null ? node.isLeaf() : true;
}
/**
* Returns the set of names bound to the ac
*
* @return
*/
public Set getNamesBoundCopy() {
final Node node = getNamesBoundNode(false);
return node != null ? node.getChildrenNames() : Collections.EMPTY_SET;
}
/**
* Sets the aci cmp attribute
*
* @param attrName
* @param attrValue
*/
public void setCmpAttribute(String attrName, Object attrValue) {
final Node node = getCmpAttributesNode(true);
Node cmpNode = node.getChild(attrName);
if (cmpNode == null) {
cmpNode = node.addChild(Fqn.fromElements(attrName));
}
cmpNode.put(CMP_ATTRIBUTES_NODE_MAP_KEY, attrValue);
}
/**
* Retrieves the aci cmp attribute
*
* @param attrName
* @return
*/
public Object getCmpAttribute(String attrName) {
final Node node = getCmpAttributesNode(false);
if(node == null) {
return null;
}
else {
final Node cmpNode = node.getChild(attrName);
if (cmpNode != null) {
return cmpNode.get(CMP_ATTRIBUTES_NODE_MAP_KEY);
}
else {
return null;
}
}
}
/**
* Retrieves a map copy of the aci attributes set
*
* @return
*/
public Map getCmpAttributesCopy() {
final Node node = getCmpAttributesNode(false);
if(node == null) {
return Collections.EMPTY_MAP;
}
else {
Map result = new HashMap();
Node cmpNode = null;
for (Object obj : node.getChildren()) {
cmpNode = (Node) obj;
result.put(cmpNode.getFqn().getLastElement(), cmpNode
.get(CMP_ATTRIBUTES_NODE_MAP_KEY));
}
return result;
}
}
}