package org.atricore.idbus.kernel.main.mediation.state; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.kernel.main.util.UUIDGenerator; import java.util.*; /** * @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a> * @version $Id$ */ public class MemoryProviderStateManagerImpl implements ProviderStateManager { private static final Log logger = LogFactory.getLog(MemoryProviderStateManagerImpl.class); // TODO : Cleanup cache when expires! private Cache cache; private UUIDGenerator idGen = new UUIDGenerator(); private String namespace; public MemoryProviderStateManagerImpl () { cache = new Cache(idGen.generateId()); logger.debug("Created internal cache instance with ID " + cache.getId()); } public String getNamespace() { return namespace; } public void setNamespace(String namespace) { this.namespace = namespace; } public void store(ProviderStateContext ctx, LocalState value) { cache.put(new Element(ctx.getProvider().getName(), value.getId(), value)); } public LocalState retrieve(ProviderStateContext ctx, String stateId) { Element e = cache.get(new Key(ctx.getProvider().getName(), stateId)); if (e != null) return e.getState(); return null; } public LocalState retrieve(ProviderStateContext ctx, String keyName, String keyValue) { Element e = cache.get(new Key(ctx.getProvider().getName(), keyName, keyValue)); if (e != null) return e.getState(); return null; } public void remove(ProviderStateContext ctx, String key) { cache.remove(new Key(ctx.getProvider().getName(), key)); } public LocalState createState(ProviderStateContext ctx) { LocalStateImpl state = new LocalStateImpl(idGen.generateId()); store(ctx, state); if (logger.isDebugEnabled()) logger.debug("Created new LocalState instance with Key " + state.getId()); return state; } public Collection<LocalState> retrieveAll(ProviderStateContext ctx) { throw new UnsupportedOperationException("Not Implemented!"); } protected class Cache { private String id; private Map<String, Map<String, Element>> alternativeKeys; private Map<String, Element> elements; public Cache(String id) { this.id = id; elements = new HashMap<String, Element>(); alternativeKeys = new HashMap<String, Map<String,Element>>(); } public String getId() { return id; } public void put(Element e) { elements.put(e.getKey().getValue(), e); if (logger.isTraceEnabled()) logger.trace("PUT:" + e.getKey() + " " + e); for (Key alternativeKey : e.getAlternativeKeys()) { Map<String, Element> alternativeMap = alternativeKeys.get(alternativeKey.getQName()); if ( alternativeMap == null) { alternativeMap = new HashMap<String, Element>(); alternativeKeys.put(alternativeKey.getQName(), alternativeMap); } if (logger.isTraceEnabled()) logger.trace("PUT:"+alternativeKey + " " + e); alternativeMap.put(alternativeKey.getValue(), e); } } public Element get(Key key) { Element e = null; if (key.isPrimary()) { e = elements.get(key.getValue()); } else { Map<String, Element> alternativeMap = alternativeKeys.get(key.getQName()); if (alternativeMap != null) { e = alternativeMap.get(key.getValue()); } } if (logger.isTraceEnabled()) logger.trace("GET:{" + key.getQName() + "}" + key.getValue()+ "=" + e); return e; } public void remove(Key key) { Element e = elements.get(key.getValue()); if (logger.isTraceEnabled()) logger.trace("REMOVE:" + key + "=" + e); if (e != null) { for (Key ak : e.getAlternativeKeys()) { Map<String, Element> am = alternativeKeys.get(ak.getQName()); if (am != null) am.remove(ak.getValue()); } elements.remove(key.getValue()); } } } protected class Element { private Key key; private Set<Key> alternativeKeys; private LocalState state; public Element(String ns, String id, LocalState state) { // Setup Keys this.key = new Key(ns, id); this.alternativeKeys = new HashSet<Key>(); for (String keyName : state.getAlternativeIdNames()) { String alternativeId = state.getAlternativeId(keyName); Key alternativeKey = new Key(ns, keyName, alternativeId); alternativeKeys.add(alternativeKey); } this.state = state; } public Key getKey() { return key; } public Collection<Key> getAlternativeKeys() { return alternativeKeys; } public LocalState getState() { return state; } @Override public String toString() { return "ELEMENT : [key=" + key.toString() + ",stateId='"+(state != null ? state.getId() : "<NO-STATE>")+"']"; } } protected class Key { private String nameSpace; private String value; private String qName; private boolean primary = true; public Key(String nameSpace, String name, String value) { this.nameSpace = nameSpace; this.value = value; this.qName = nameSpace + ":" + name; this.primary = false; } public Key(String nameSpace, String value) { this(nameSpace, "PRIMARY", value); this.primary = true; } public boolean isPrimary() { return primary; } public String getQName() { return qName; } public String getValue() { return value; } @Override public String toString() { return "KEY : [qname='"+qName+"',value='"+value+"']"; } } }