package org.openntf.domino.graph2.builtin.search; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Observable; import java.util.Scanner; import java.util.Set; import org.openntf.domino.Database; import org.openntf.domino.Document; import org.openntf.domino.Session; import org.openntf.domino.View; import org.openntf.domino.big.IndexDatabase; import org.openntf.domino.big.impl.IScannerStateManager; import org.openntf.domino.big.impl.IndexHit; import org.openntf.domino.graph2.DGraph; import org.openntf.domino.graph2.DVertex; import org.openntf.domino.graph2.builtin.identity.Name; import org.openntf.domino.graph2.impl.DElementStore; import org.openntf.domino.graph2.impl.DFramedTransactionalGraph; import org.openntf.domino.helpers.DocumentScanner; import org.openntf.domino.types.CaseInsensitiveString; import com.tinkerpop.blueprints.Graph; @SuppressWarnings({ "unchecked", "rawtypes" }) public class IndexStore extends DElementStore implements IndexDatabase, IScannerStateManager { private IndexDatabase indexDb_; public IndexStore() { } private IndexDatabase getInternalIndexDatabase() { if (indexDb_ == null) { indexDb_ = new org.openntf.domino.big.impl.IndexDatabase((Database) getStoreDelegate()); indexDb_.setCaseSensitive(false); } return indexDb_; } @Override public void setCaseSensitive(final boolean value) { getInternalIndexDatabase().setCaseSensitive(value); } @Override public boolean getCaseSensitive() { return getInternalIndexDatabase().getCaseSensitive(); } @Override public void setDatabase(final Database indexDb) { getInternalIndexDatabase().setDatabase(indexDb); } @Override public Database getIndexDb() { return getInternalIndexDatabase().getIndexDb(); } @Override public Set<CharSequence> getStopList() { return getInternalIndexDatabase().getStopList(); } @Override public void setStopList(final Set<CharSequence> list) { getInternalIndexDatabase().setStopList(list); } @Override public View getTermView() { return getInternalIndexDatabase().getTermView(); } @Override public List<String> getTermStarts(final String startsWith, final int count) { return getInternalIndexDatabase().getTermStarts(startsWith, count); } @Override public View getDbView() { return getInternalIndexDatabase().getDbView(); } @Override public Document getDbDocument(final CharSequence dbid) { return getInternalIndexDatabase().getDbDocument(dbid); } @Override public Document getTermDocument(final CharSequence token) { Term term = (Term) getGraph().getVertex(token.toString().toLowerCase(), Term.class); return term.asDocument(); } @Override public Document getNameDocument(final CharSequence name) { Name nameV = (Name) getGraph().getVertex(name.toString(), Name.class); return nameV.asDocument(); } @Override public Document getValueDocument(final CharSequence value) { Value valueV = (Value) getGraph().getVertex(value.toString().toLowerCase(), Value.class); return valueV.asDocument(); } @Override public void scanServer(final Session session, final String serverName) { getInternalIndexDatabase().scanServer(session, serverName); } @Override public DocumentScanner scanDatabase(final Database db) { return getInternalIndexDatabase().scanDatabase(db); } @Override public DocumentScanner scanDatabase(final Database db, final DocumentScanner scanner) { return getInternalIndexDatabase().scanDatabase(db, scanner); } @Override public List<String> getTermDbids(final CharSequence term) { return getInternalIndexDatabase().getTermDbids(term); } @Override public int getTermHitCount(final String term) { return getInternalIndexDatabase().getTermHitCount(term); } @Override public Set<CharSequence> getTermItemsInDbids(final String term, final Collection<String> dbids) { return getInternalIndexDatabase().getTermItemsInDbids(term, dbids); } @Override public List<IndexHit> getTermResults(final CharSequence term, final int limit, final Set<CharSequence> dbids, final Set<CharSequence> itemNames, final Set<CharSequence> forms) { return getInternalIndexDatabase().getTermResults(term, limit, dbids, itemNames, forms); } @Override public Set<CharSequence> getTermUnidInDbsItems(final String term, final Collection<String> dbids, final Collection<?> itemNames) { return getInternalIndexDatabase().getTermUnidInDbsItems(term, dbids, itemNames); } @Override public Set<String> getTermLinksInDbsItems(final Session session, final String serverName, final String term, final Collection<CharSequence> dbids, final Collection<?> itemNames) { return getInternalIndexDatabase().getTermLinksInDbsItems(session, serverName, term, dbids, itemNames); } @Override public Set<CharSequence> getTermUnidInItems(final CharSequence term, final Collection<String> itemNames) { return getInternalIndexDatabase().getTermUnidInItems(term, itemNames); } @Override public Set<String> getTermUnidInDbids(final CharSequence term, final Collection<String> dbids) { return getInternalIndexDatabase().getTermUnidInDbids(term, dbids); } @Override public Map<String, Set<CharSequence>> getTermItemMap(final String term) { return getInternalIndexDatabase().getTermItemMap(term); } @Override public Map<CharSequence, Set<CharSequence>> getTermUnidMap(final CharSequence term) { return getInternalIndexDatabase().getTermUnidMap(term); } @Override public Map<CharSequence, Set<CharSequence>> restoreTokenLocationMap(final CharSequence token, final Object mapKey) { Map result = null; Term tokenV = (Term) getGraph().addVertex(token.toString(), Term.class); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); DVertex dv = (DVertex) tokenV.asVertex(); if (dv.hasProperty(itemName)) { Object raw = dv.getProperty(itemName); if (raw instanceof Map) { result = (Map) raw; } else { result = new HashMap<CaseInsensitiveString, Set<String>>(); } } else { result = new HashMap<CaseInsensitiveString, Set<String>>(); } return result; } @Override public Map<CharSequence, Set<CharSequence>> restoreValueLocationMap(final CharSequence value, final Object mapKey) { Map result = null; Value valueV = (Value) getGraph().addVertex(value.toString(), Value.class); String itemName = VALUE_MAP_PREFIX + String.valueOf(mapKey); DVertex dv = (DVertex) valueV.asVertex(); if (dv.hasProperty(itemName)) { Object raw = dv.getProperty(itemName); if (raw instanceof Map) { result = (Map) raw; } else { result = new HashMap<CaseInsensitiveString, Set<String>>(); } } else { result = new HashMap<CaseInsensitiveString, Set<String>>(); } return result; } protected DFramedTransactionalGraph getGraph() { DGraph graph = getConfiguration().getGraph(); Graph extGraph = graph.getExtendedGraph(); if (extGraph instanceof DFramedTransactionalGraph) { return (DFramedTransactionalGraph) extGraph; } else { throw new IllegalStateException("Graph is a " + graph.getClass().getName()); } } // @Override // public void saveTokenLocationMap(final CharSequence token, final Object mapKey, final Map<CharSequence, Set<CharSequence>> map) { // String strValue = token.toString(); // Term tokenV = (Term) getGraph().getVertex(strValue.toLowerCase(), Term.class); // DVertex dv = (DVertex) tokenV.asVertex(); // dv.setProperty(TERM_MAP_PREFIX + String.valueOf(mapKey), map); // if (tokenV.getValue() == null || tokenV.getValue().length() == 0) { // tokenV.setValue(strValue); // } // } @Override public void saveTokenLocationMap(final Object mapKey, final Map<CharSequence, Map<CharSequence, Set<CharSequence>>> fullMap, final DocumentScanner scanner) { setLastIndexDate(mapKey, scanner.getLastDocModDate()); Set<CharSequence> keySet = fullMap.keySet(); if (keySet.size() > 0) { for (CharSequence cis : keySet) { Map<CharSequence, Set<CharSequence>> tlValue = fullMap.get(cis); String strValue = cis.toString(); Term tokenV = (Term) getGraph().addVertex(strValue.toLowerCase(), Term.class); DVertex dv = (DVertex) tokenV.asVertex(); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); dv.setProperty(itemName, tlValue); if (tokenV.getValue() == null || tokenV.getValue().length() == 0) { tokenV.setValue(strValue); } } } else { // System.out.println("DEBUG: keyset was empty for index tokens"); } } @Override public void setLastIndexDate(final Object mapKey, final Date date) { getInternalIndexDatabase().setLastIndexDate(mapKey, date); } @Override public Date getLastIndexDate(final Object mapKey) { return getInternalIndexDatabase().getLastIndexDate(mapKey); } @Override public void update(final Observable o, final Object arg) { try { IScannerStateManager.ScanStatus status = null; if (arg instanceof IScannerStateManager.ScanStatus) { status = (IScannerStateManager.ScanStatus) arg; } DocumentScanner scanner = null; if (o instanceof DocumentScanner) { scanner = (DocumentScanner) o; } else { System.out .println("Observable object was not a DocumentScanner. It was a " + (o == null ? "null" : o.getClass().getName())); } if (status != null) { switch (status) { case NEW: break; case RUNNING: // System.out.println("DEBUG: branched to running status..."); if (scanner != null) { if (scanner.isTrackTokenLocation()) { Map tokenLocationMap = scanner.getTokenLocationMap(); int tlsize = tokenLocationMap.size(); if (tlsize >= 1024) { // System.out.println("Processed " + scanner.getDocCount() + " documents so far, " + scanner.getItemCount() // + " items and " + scanner.getTokenCount()); synchronized (tokenLocationMap) { saveTokenLocationMap(scanner.getStateManagerKey(), tokenLocationMap, scanner); tokenLocationMap.clear(); } } } else { // System.out.println("TokenLocation not being tracked by scanner"); } if (scanner.isTrackNameLocation()) { Map nameLocationMap = scanner.getNameLocationMap(); int nlsize = nameLocationMap.size(); if (nlsize >= 128) { synchronized (nameLocationMap) { saveNameLocationMap(scanner.getStateManagerKey(), nameLocationMap, scanner); nameLocationMap.clear(); } } } if (scanner.isTrackValueLocation()) { Map valueLocationMap = scanner.getValueLocationMap(); int tlsize = valueLocationMap.size(); if (tlsize >= 1024) { // System.out.println("Processed " + scanner.getDocCount() + " documents so far, " + scanner.getItemCount() // + " items and " + scanner.getTokenCount()); synchronized (valueLocationMap) { saveValueLocationMap(scanner.getStateManagerKey(), valueLocationMap, scanner); valueLocationMap.clear(); } } } } else { System.out.println("Scanner is null from notifications"); } break; case COMPLETE: // System.out.println("DEBUG: branched to complete status..."); if (scanner != null) { if (scanner.isTrackTokenLocation()) { Map tokenLocationMap = scanner.getTokenLocationMap(); synchronized (tokenLocationMap) { saveTokenLocationMap(scanner.getStateManagerKey(), tokenLocationMap, scanner); tokenLocationMap.clear(); } } else { // System.out.println("TokenLocation not being tracked by scanner"); } if (scanner.isTrackNameLocation()) { Map nameLocationMap = scanner.getNameLocationMap(); synchronized (nameLocationMap) { saveNameLocationMap(scanner.getStateManagerKey(), nameLocationMap, scanner); nameLocationMap.clear(); } } if (scanner.isTrackValueLocation()) { Map valueLocationMap = scanner.getValueLocationMap(); synchronized (valueLocationMap) { saveValueLocationMap(scanner.getStateManagerKey(), valueLocationMap, scanner); valueLocationMap.clear(); } } } else { System.out.println("ALERT! Scanner was null??"); } break; case ERROR: break; case INTERRUPTED: break; } } else { System.out.println("Scan status was null?"); } } catch (Throwable t) { t.printStackTrace(); } } @Override public Map<CharSequence, Set<CharSequence>> restoreNameLocationMap(final CharSequence name, final Object mapKey) { Map result = null; Name nameV = (Name) getGraph().addVertex(name.toString(), Name.class); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); DVertex dv = (DVertex) nameV.asVertex(); if (dv.hasProperty(itemName)) { Object raw = dv.getProperty(itemName); if (raw instanceof Map) { result = (Map) raw; } else { result = new HashMap<CaseInsensitiveString, Set<String>>(); } } else { result = new HashMap<CaseInsensitiveString, Set<String>>(); } return result; } // @Override // public void saveNameLocationMap(final CharSequence name, final Object mapKey, final Map<CharSequence, Set<CharSequence>> map) { // Name nameV = (Name) getGraph().getVertex(name.toString(), Name.class); // DVertex dv = (DVertex) nameV.asVertex(); // dv.setProperty(TERM_MAP_PREFIX + String.valueOf(mapKey), map); // } @Override public void saveNameLocationMap(final Object mapKey, final Map<CharSequence, Map<CharSequence, Set<CharSequence>>> fullMap, final DocumentScanner scanner) { Set<CharSequence> keySet = fullMap.keySet(); for (CharSequence cis : keySet) { Map<CharSequence, Set<CharSequence>> tlValue = fullMap.get(cis); String name = cis.toString(); Name nameV = (Name) getGraph().addVertex(name, Name.class); DVertex dv = (DVertex) nameV.asVertex(); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); dv.setProperty(itemName, tlValue); Scanner s = new Scanner(name); s.useDelimiter(DocumentScanner.REGEX_NONALPHANUMERIC); while (s.hasNext()) { CharSequence token = DocumentScanner.scrubToken(s.next(), scanner.isCaseSensitive()); if (token != null && (token.length() > 2)) { Term tokenV = (Term) getGraph().addVertex(token.toString().toLowerCase(), Term.class); if (tokenV.getValue() == null || tokenV.getValue().length() == 0) { tokenV.setValue(token.toString()); } nameV.addPart(tokenV); } } } } @Override public void saveValueLocationMap(final Object mapKey, final Map<CharSequence, Map<CharSequence, Set<CharSequence>>> fullMap, final DocumentScanner scanner) { setLastIndexDate(mapKey, scanner.getLastDocModDate()); Set<CharSequence> keySet = fullMap.keySet(); if (keySet.size() > 0) { for (CharSequence cis : keySet) { Map<CharSequence, Set<CharSequence>> tlValue = fullMap.get(cis); String strValue = cis.toString(); Value valueV = (Value) getGraph().addVertex(strValue.toLowerCase(), Value.class); DVertex dv = (DVertex) valueV.asVertex(); String itemName = VALUE_MAP_PREFIX + String.valueOf(mapKey); dv.setProperty(itemName, tlValue); valueV.setValue(strValue); Scanner s = new Scanner(strValue); s.useDelimiter(DocumentScanner.REGEX_NONALPHANUMERIC); while (s.hasNext()) { CharSequence token = DocumentScanner.scrubToken(s.next(), scanner.isCaseSensitive()); if (token != null && (token.length() > 2)) { Term tokenV = (Term) getGraph().addVertex(token.toString().toLowerCase(), Term.class); if (tokenV.getValue() == null || tokenV.getValue().length() == 0) { tokenV.setValue(token.toString()); } valueV.addTerm(tokenV); } } } } else { // System.out.println("DEBUG: keyset was empty for index tokens"); } } // @Override // public void saveValueLocationMap(final CharSequence value, final Object mapKey, final Map<CharSequence, Set<CharSequence>> map) { // String strValue = value.toString(); // Value valueV = (Value) getGraph().getVertex(strValue.toLowerCase(), Value.class); // DVertex dv = (DVertex) valueV.asVertex(); // dv.setProperty(VALUE_MAP_PREFIX + String.valueOf(mapKey), map); // valueV.setValue(strValue); // Scanner s = new Scanner(strValue); // s.useDelimiter(DocumentScanner.REGEX_NONALPHANUMERIC); // while (s.hasNext()) { // CharSequence token = DocumentScanner.scrubToken(s.next(), scanner.isCaseSensitive()); // if (token != null && (token.length() > 2)) { // Term tokenV = (Term) getGraph().getVertex(token.toString().toLowerCase(), Term.class); // if (tokenV.getValue() == null || tokenV.getValue().length() == 0) { // tokenV.setValue(token.toString()); // } // valueV.addTerm(tokenV); // } // } // } }