package com.bagri.xdm.access.coherence.impl; import static com.bagri.xdm.cache.api.XDMCacheConstants.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import com.bagri.common.idgen.IdGenerator; import com.bagri.xdm.api.impl.ModelManagementBase; import com.bagri.xdm.domain.XDMDocumentType; import com.bagri.xdm.domain.XDMNamespace; import com.bagri.xdm.domain.XDMPath; import com.oracle.coherence.common.sequencegenerators.ClusteredSequenceGenerator; import com.tangosol.net.CacheFactory; import com.tangosol.net.ConfigurableCacheFactory; import com.tangosol.net.NamedCache; import com.tangosol.util.Filter; import com.tangosol.util.extractor.IdentityExtractor; import com.tangosol.util.extractor.KeyExtractor; import com.tangosol.util.filter.AndFilter; import com.tangosol.util.filter.EqualsFilter; import com.tangosol.util.filter.RegexFilter; public class CoherenceSchemaDictionary extends ModelManagementBase { private Map<String, XDMNamespace> nsCache; private Map<String, XDMPath> pathCache; private Map<String, XDMDocumentType> typeCache; private IdGenerator<Long> nsGen; private IdGenerator<Long> pathGen; private IdGenerator<Long> typeGen; private ConfigurableCacheFactory factory; public CoherenceSchemaDictionary() { super(); } public CoherenceSchemaDictionary(ConfigurableCacheFactory factory) { super(); this.factory = factory; initialize(); } //public void setCacheFactory(ConfigurableCacheFactory factory) { // this.factory = factory; //} protected Map<String, XDMNamespace> getNamespaceCache() { if (nsCache == null) { nsCache = CacheFactory.getCache(CN_XDM_NAMESPACE_DICT); } return nsCache; } protected Map<String, XDMPath> getPathCache() { if (pathCache == null) { pathCache = CacheFactory.getCache(CN_XDM_PATH_DICT); } return pathCache; } protected Map<String, XDMDocumentType> getTypeCache() { if (typeCache == null) { typeCache = CacheFactory.getCache(CN_XDM_DOCTYPE_DICT); } return typeCache; } protected IdGenerator<Long> getNamespaceGen() { if (nsGen == null) { nsGen = new ClusteredIdGenerator(new ClusteredSequenceGenerator(SQN_NAMESPACE, 1)); } return nsGen; } protected IdGenerator<Long> getPathGen() { if (pathGen == null) { pathGen = new ClusteredIdGenerator(new ClusteredSequenceGenerator(SQN_PATH, 1)); } return pathGen; } protected IdGenerator<Long> getTypeGen() { if (typeGen == null) { typeGen = new ClusteredIdGenerator(new ClusteredSequenceGenerator(SQN_DOCTYPE, 1)); } return typeGen; } //@SuppressWarnings("unchecked") private void initialize() { nsCache = factory.ensureCache(CN_XDM_NAMESPACE_DICT, Thread.currentThread().getContextClassLoader()); pathCache = factory.ensureCache(CN_XDM_PATH_DICT, Thread.currentThread().getContextClassLoader()); typeCache = factory.ensureCache(CN_XDM_DOCTYPE_DICT, Thread.currentThread().getContextClassLoader()); nsGen = new ClusteredIdGenerator(new ClusteredSequenceGenerator(SQN_NAMESPACE, 1)); pathGen = new ClusteredIdGenerator(new ClusteredSequenceGenerator(SQN_PATH, 1)); typeGen = new ClusteredIdGenerator(new ClusteredSequenceGenerator(SQN_DOCTYPE, 1)); } @Override public XDMPath getPath(int pathId) { Filter f = new EqualsFilter("getPathId", pathId); Set<Map.Entry<String, XDMPath>> entries = getNamedCache(getPathCache()).entrySet(f); if (entries.isEmpty()) { return null; } // check size > 1 ?? return entries.iterator().next().getValue(); } @Override public Collection<XDMPath> getTypePaths(int typeId) { Filter f = new EqualsFilter("getTypeId", typeId); Set<Map.Entry<String, XDMPath>> entries = getNamedCache(getPathCache()).entrySet(f); if (entries.isEmpty()) { return Collections.EMPTY_LIST; } // check size > 1 ?? List<XDMPath> result = new ArrayList<XDMPath>(entries.size()); for (Map.Entry<String, XDMPath> e: entries) { result.add(e.getValue()); } Collections.sort(result); if (getLogger().isTraceEnabled()) { getLogger().trace("getTypePath; returning {} for type {}", result, typeId); } return result; } @Override protected XDMDocumentType getDocumentTypeById(int typeId) { Filter f = new EqualsFilter("getTypeId", typeId); Set<Map.Entry<String, XDMDocumentType>> types = getNamedCache(getTypeCache()).entrySet(f); if (types.size() == 0) { return null; } return (XDMDocumentType) types.iterator().next().getValue(); } @Override protected Set getTypedPathEntries(int typeId) { Filter f = new EqualsFilter("getTypeId", typeId); Set<Map.Entry<String, XDMPath>> entries = getNamedCache(getPathCache()).entrySet(f); return entries; } @Override protected Set getTypedPathWithRegex(String regex, int typeId) { Filter f = new AndFilter(new RegexFilter(new KeyExtractor(IdentityExtractor.INSTANCE), regex), new EqualsFilter("getTypeId", typeId)); Set<Map.Entry> entries = getNamedCache(getPathCache()).entrySet(f); return entries; } private NamedCache getNamedCache(Map cache) { return (NamedCache) cache; } @Override protected boolean lock(Map cache, Object key) { return getNamedCache(cache).lock(key, timeout); } @Override protected void unlock(Map cache, Object key) { getNamedCache(cache).unlock(key); } @Override protected <K, V> V putIfAbsent(Map<K, V> map, K key, V value) { NamedCache cache = (NamedCache) map; try { boolean locked = cache.lock(key, timeout); if (!locked) { throw new IllegalStateException("Can't get lock on cache " + cache.getCacheName() + " for key " + key); } V val2 = (V) cache.get(key); if (val2 == null) { map.put(key, value); return value; } getLogger().debug("putIfAbsent; got collision on cache: {}, key: {}; returning: {}", new Object[] {cache.getCacheName(), key, val2}); return val2; } finally { cache.unlock(key); } } }