package com.bagri.xdm.access.coherence.impl; import static com.bagri.xdm.cache.api.XDMCacheConstants.*; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.xml.transform.Source; import com.bagri.common.query.ExpressionBuilder; import com.bagri.common.query.ExpressionContainer; import com.bagri.common.query.PathExpression; import com.bagri.xdm.api.XDMException; import com.bagri.xdm.api.impl.DocumentManagementBase; //import com.bagri.xdm.cache.data.PathParentDocumentKey; //import com.bagri.xdm.cache.data.PathValueDocumentKey; import com.bagri.xdm.access.coherence.process.DocumentBuilder; import com.bagri.xdm.access.coherence.process.DocumentCreator; import com.bagri.xdm.access.coherence.process.DocumentRemover; import com.bagri.xdm.common.XDMDataKey; import com.bagri.xdm.domain.XDMDocument; import com.bagri.xdm.domain.XDMNodeKind; import com.oracle.coherence.common.sequencegenerators.ClusteredSequenceGenerator; import com.oracle.coherence.common.sequencegenerators.SequenceGenerator; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; import com.tangosol.util.Filter; import com.tangosol.util.ValueExtractor; import com.tangosol.util.extractor.PofExtractor; import com.tangosol.util.extractor.ReflectionExtractor; import com.tangosol.util.filter.AndFilter; import com.tangosol.util.filter.EqualsFilter; import com.tangosol.util.filter.GreaterEqualsFilter; import com.tangosol.util.filter.GreaterFilter; import com.tangosol.util.filter.LessEqualsFilter; import com.tangosol.util.filter.LessFilter; public class DocumentManagementClient extends DocumentManagementBase { private NamedCache xddCache; private NamedCache xdmCache; private SequenceGenerator dGen; // must be configurable... private int batchSize = 100; public DocumentManagementClient() { super(); //initializeHazelcast(); mFactory = new CoherenceXDMFactory(); //CacheFactory.getConfigurableCacheFactory() mDictionary = new CoherenceSchemaDictionary(CacheFactory.getConfigurableCacheFactory()); initializeServices(); } @Override public void close() { CacheFactory.shutdown(); } private void initializeServices() { xddCache = CacheFactory.getCache(CN_XDM_DOCUMENT); xdmCache = CacheFactory.getCache(CN_XDM_ELEMENT); //xpvCache = getCache(CN_XDM_PATH_VALUE_INDEX); dGen = new ClusteredSequenceGenerator(SQN_DOCUMENT, 100); logger.trace("initialize; got cache: {}", xdmCache); } NamedCache getDataCache() { return xdmCache; } NamedCache getDocumentCache() { return xddCache; } @Override public Long getDocumentId(String uri) { Filter f = new EqualsFilter(new PofExtractor(String.class, 1), uri); Set<Long> docKeys = new HashSet<Long>(xddCache.keySet(f)); if (docKeys.size() == 0) { return null; } // todo: check if too many docs ?? return docKeys.iterator().next(); } @Override public XDMDocument getDocument(long docId) { return (XDMDocument) xddCache.get(docId); } @Override public XDMDocument storeDocument(String xml) { long docId = dGen.next(); String uri = "/library/" + docId; return storeDocument(docId, uri, xml); } @Override public XDMDocument storeDocument(long docId, String uri, String xml) { // todo: override existing document -> create a new version ? logger.trace("storeDocument.enter; xml: {}; uri: {}, docId: {}", xml.length(), uri, docId); DocumentCreator proc = new DocumentCreator(uri, xml); Object result = xddCache.invoke(docId, proc); logger.trace("storeDocument.exit; returning: {}", result); return (XDMDocument) result; } //@Override public void removeDocument(long docId) { logger.trace("removeDocument.enter; docId: {}", docId); DocumentRemover proc = new DocumentRemover(); Object result = xddCache.invoke(docId, proc); logger.trace("removeDocument.exit; removed: {}", result); } @Override public Collection<String> getXML(ExpressionContainer query, String template, Map params) { long stamp = System.currentTimeMillis(); Collection<String> uris = getDocumentURIs(query); if (uris.size() > 0) { DocumentBuilder ta = new DocumentBuilder(query.getExpression().getRoot().getDocType(), template, params); Object result = xddCache.aggregate(uris, ta); logger.trace("getXml.exit; got aggregation results: {}; time taken {}", result, System.currentTimeMillis() - stamp); return (Collection<String>) result; } return Collections.emptyList(); } //@Override public String getDocumentAsString(long docId) { long stamp = System.currentTimeMillis(); XDMDocument xdoc = (XDMDocument) xddCache.get(docId); int docType = xdoc.getTypeId(); String path = mDictionary.getDocumentRoot(docType); Map<String, String> params = new HashMap<String, String>(); params.put(":doc", path); DocumentBuilder ta = new DocumentBuilder(docType, ":doc", params); Object result = xddCache.aggregate(Collections.singletonList(docId), ta); logger.trace("getDocumentAsString.exit; got aggregation results: {}; time taken {}", result, System.currentTimeMillis() - stamp); Collection<String> c = (Collection<String>) result; if (c.isEmpty()) { return null; } return c.iterator().next(); } @SuppressWarnings("rawtypes") private Filter getValueFilter(PathExpression pex, Object value) { //Object value = pex.getValue(); ValueExtractor ve; if (value instanceof Integer) { ve = new ReflectionExtractor("asInt"); } else if (value instanceof Long) { ve = new ReflectionExtractor("asLong"); } else if (value instanceof Boolean) { ve = new ReflectionExtractor("asBoolean"); } else if (value instanceof Byte) { ve = new ReflectionExtractor("asByte"); } else if (value instanceof Short) { ve = new ReflectionExtractor("asShort"); } else if (value instanceof Float) { ve = new ReflectionExtractor("asFloat"); } else if (value instanceof Double) { ve = new ReflectionExtractor("asDouble"); } else { value = value.toString(); ve = new PofExtractor(String.class, 6); } switch (pex.getCompType()) { case EQ: return new EqualsFilter(ve, value); case LE: return new LessEqualsFilter(ve, (Comparable) value); case LT: return new LessFilter(ve, (Comparable) value); case GE: return new GreaterEqualsFilter(ve, (Comparable) value); case GT: return new GreaterFilter(ve, (Comparable) value); default: return null; } } //@Override protected Set<Long> queryPathKeys(Set<Long> found, PathExpression pex, Object value) { int pathId = -1; if (pex.isRegex()) { Set<Integer> pathIds = mDictionary.translatePathFromRegex(pex.getDocType(), pex.getRegex()); logger.trace("queryPathKeys; regex: {}; pathIds: {}", pex.getRegex(), pathIds); if (pathIds.size() > 0) { pathId = pathIds.iterator().next(); } } else { String path = pex.getFullPath(); logger.trace("queryPathKeys; path: {}; comparison: {}", path, pex.getCompType()); pathId = mDictionary.translatePath(pex.getDocType(), path, XDMNodeKind.fromPath(path)).getPathId(); } //String val = value.toString(); Filter valueFilter = getValueFilter(pex, value); if (valueFilter == null) { throw new IllegalArgumentException("Can't construct filter for expression: " + pex); } Filter f = new AndFilter( new EqualsFilter(new PofExtractor(Integer.class, 4), pathId), valueFilter); Set<XDMDataKey> keys = xdmCache.keySet(f); logger.trace("queryPathKeys; path: {}, value: {}; got keys: {}; cache size: {}", pathId, value, keys.size(), xdmCache.size()); if (keys.size() > 0) { Set<Long> docIds = new HashSet<Long>(); for (XDMDataKey key: keys) { docIds.add(key.getDocumentId()); } found.retainAll(docIds); } else { found.clear(); } return found; } @Override public Collection<Long> getDocumentIDs(ExpressionContainer query) { //Filter f = new EqualsFilter(new PofExtractor(Integer.class, 2), query.getRoot().getDocType()); //Set<Long> keys = new HashSet<Long>(xddCache.keySet(f)); //return queryKeys(keys, query.getRoot()); // moved to the server side.. return null; } @Override public Collection<String> getDocumentURIs(ExpressionContainer query) { // moved to the server side.. return null; } @Override public Object executeXCommand(String command, Map bindings, Properties props) { // TODO Auto-generated method stub return null; } @Override public Object executeXQuery(String query, Map bindings, Properties props) { // TODO Auto-generated method stub return null; } @Override public Source getDocumentAsSource(long arg0) { // TODO Auto-generated method stub return null; } @Override public XDMDocument storeDocumentSource(long arg0, Source arg1) { // TODO Auto-generated method stub return null; } @Override public String getDocumentAsString(String arg0) throws XDMException { // TODO Auto-generated method stub return null; } @Override public XDMDocument storeDocumentFromString(String arg0, String arg1, Properties arg2) throws XDMException { // TODO Auto-generated method stub return null; } }