/** * */ package org.openntf.domino.big.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Observable; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import org.openntf.domino.Database; import org.openntf.domino.DbDirectory; import org.openntf.domino.Document; import org.openntf.domino.DocumentCollection; import org.openntf.domino.Item; import org.openntf.domino.Session; import org.openntf.domino.View; import org.openntf.domino.ViewColumn; import org.openntf.domino.ViewEntry; import org.openntf.domino.ViewNavigator; import org.openntf.domino.helpers.DocumentScanner; import org.openntf.domino.helpers.DocumentSorter; import org.openntf.domino.types.CaseInsensitiveString; /** * @author Nathan T. Freeman * */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class IndexDatabase implements IScannerStateManager, org.openntf.domino.big.IndexDatabase { private static final Logger log_ = Logger.getLogger(IndexDatabase.class.getName()); protected transient Database indexDb_; // protected transient DatabaseHolder dbHolder_; // protected transient View termView_; // protected transient View dbView_; protected Set<CharSequence> stopList_; protected boolean caseSensitive_ = false; protected boolean continue_ = true; /*public static Set<CharSequence> toStringSet(final Object value) { Set<CharSequence> result = new HashSet<CharSequence>(); if (value == null) return result; if (value instanceof Iterable) { Iterable values = (Iterable) value; for (Object o : values) { if (o instanceof String) { result.add((String) o); } else if (o instanceof CaseInsensitiveString) { result.add(((CaseInsensitiveString) o).toString()); } else { result.add(String.valueOf(o)); } } } else if (value instanceof String) { result.add((String) value); } else if (value instanceof CharSequence) { result.add(((CharSequence) value).toString()); } else { result.add(String.valueOf(value)); } return result; } public static Set<CharSequence> toCISSet(final Object value) { Set<CharSequence> result = new HashSet<CharSequence>(); if (value == null) return result; if (value instanceof Iterable) { Iterable values = (Iterable) value; for (Object o : values) { if (o instanceof CaseInsensitiveString) { result.add((CaseInsensitiveString) o); } else if (o instanceof CharSequence) { result.add(new CaseInsensitiveString(((CharSequence) o).toString())); } else { result.add(new CaseInsensitiveString(String.valueOf(o))); } } } else if (value instanceof CaseInsensitiveString) { result.add((CaseInsensitiveString) value); } else if (value instanceof CharSequence) { result.add(new CaseInsensitiveString(((CharSequence) value).toString())); } else { result.add(new CaseInsensitiveString(String.valueOf(value))); } return result; }*/ public IndexDatabase() { } public IndexDatabase(final Database indexDb) { indexDb_ = indexDb; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#setCaseSensitive(boolean) */ @Override public void setCaseSensitive(final boolean value) { caseSensitive_ = value; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getCaseSensitive() */ @Override public boolean getCaseSensitive() { return caseSensitive_; } @SuppressWarnings("unused") private String indexApiPath_; /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#setDatabase(org.openntf.domino.Database) */ @Override public void setDatabase(final Database indexDb) { indexDb_ = indexDb; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getIndexDb() */ @Override public Database getIndexDb() { // if (indexDb_ == null) { // if (indexApiPath_ != null) { // indexDb_ = Factory.getSession(SessionType.CURRENT).getDatabase(indexApiPath_); // } else { // indexDb_ = Factory.getSession(SessionType.CURRENT).getCurrentDatabase(); // } // } return indexDb_; } protected View initIndexDb() { View indexView = getIndexDb().getView(TERM_VIEW_NAME); if (indexView == null) { indexView = getIndexDb().createView(TERM_VIEW_NAME, "Form=\"" + TERM_FORM_NAME + "\""); for (ViewColumn column : indexView.getColumns()) { column.setFormula(TERM_KEY_NAME); column.setTitle("Term"); column.setSorted(true); column.setSortDescending(false); } } View dbView = getIndexDb().getView(DB_VIEW_NAME); if (dbView == null) { dbView = getIndexDb().createView(DB_VIEW_NAME, "Form=\"" + DB_FORM_NAME + "\""); for (ViewColumn column : dbView.getColumns()) { column.setFormula(DB_KEY_NAME); column.setTitle("ID"); column.setSorted(true); column.setSortDescending(false); } ViewColumn titleColumn = dbView.createColumn(); titleColumn.setFormula(DB_TITLE_NAME); titleColumn.setTitle("TITLE"); } return indexView; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getStopList() */ @Override public Set<CharSequence> getStopList() { if (stopList_ == null) { stopList_ = new HashSet<CharSequence>(); for (String s : DEFAULT_STOP_WORDS_EN) { stopList_.add(s); } } return stopList_; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#setStopList(java.util.Set) */ @Override public void setStopList(final Set<CharSequence> list) { stopList_ = list; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermView() */ @Override public View getTermView() { View result = null; result = getIndexDb().getView(TERM_VIEW_NAME); if (result == null) { result = initIndexDb(); } return result; // if (dbView_ == null) { // dbView_ = ; // } // return dbView_; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermStarts(java.lang.String, int) */ @Override public List<String> getTermStarts(final String startsWith, final int count) { List<String> result = new ArrayList<String>(); ViewEntry startEntry = getTermView().getFirstEntryByKey(startsWith, false); if (startEntry == null) { if (log_.isLoggable(Level.FINE)) log_.log(Level.FINE, "Unable to find ViewEntry for key " + startsWith); // ViewEntryCollection vec = getTermView().getAllEntriesByKey(startsWith, false); // System.out.println("ViewEntryCollection strategy returned " + vec.getCount() + " entries."); return result; } String val = startEntry.getColumnValue(IndexDatabase.TERM_KEY_NAME, String.class); result.add(val); ViewNavigator nav = getTermView().createViewNavFrom(startEntry, count); for (int i = 1; i < count; i++) { ViewEntry nextEntry = nav.getNextSibling(); val = nextEntry.getColumnValue(IndexDatabase.TERM_KEY_NAME, String.class); result.add(val); } return result; } @SuppressWarnings("unused") private List<String> getTermContains(final String contains) { List<String> result = new ArrayList<String>(); return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getDbView() */ @Override public View getDbView() { View result = null; result = getIndexDb().getView(DB_VIEW_NAME); if (result == null) { initIndexDb(); result = getIndexDb().getView(DB_VIEW_NAME); } return result; // if (termView_ == null) { // initIndexDb(); // termView_ = getIndexDb().getView(DB_VIEW_NAME); // } // return termView_; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getDbDocument(java.lang.CharSequence) */ @Override public Document getDbDocument(final CharSequence dbid) { String key = dbid.toString().toUpperCase(); Document result = getIndexDb().getDocumentWithKey(key, true); if (result.isNewNote()) { result.replaceItemValue("Form", DB_FORM_NAME); result.replaceItemValue(DB_KEY_NAME, dbid); result.save(); } return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermDocument(java.lang.CharSequence) */ @Override public Document getTermDocument(final CharSequence token) { String key = caseSensitive_ ? token.toString() : token.toString().toLowerCase(); Document result = getIndexDb().getDocumentWithKey(key, true); if (result != null && result.isNewNote()) { result.replaceItemValue("Form", TERM_FORM_NAME); result.replaceItemValue(TERM_KEY_NAME, token); result.save(); } return result; } @Override public Document getValueDocument(final CharSequence value) { String key = caseSensitive_ ? value.toString() : value.toString().toLowerCase(); Document result = getIndexDb().getDocumentWithKey(key, true); if (result != null && result.isNewNote()) { result.replaceItemValue("Form", VALUE_FORM_NAME); result.replaceItemValue(VALUE_KEY_NAME, value); result.save(); } return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getNameDocument(java.lang.CharSequence) */ @Override public Document getNameDocument(final CharSequence name) { String key = caseSensitive_ ? name.toString() : name.toString().toLowerCase(); Document result = getIndexDb().getDocumentWithKey(key, true); if (result.isNewNote()) { result.replaceItemValue("Form", TERM_FORM_NAME); result.replaceItemValue("isName", "1"); result.replaceItemValue(TERM_KEY_NAME, name); result.save(); } return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#scanServer(org.openntf.domino.Session, java.lang.String) */ @Override public void scanServer(final Session session, final String serverName) { initIndexDb(); DbDirectory dir = session.getDbDirectory(serverName); dir.setDirectoryType(DbDirectory.Type.DATABASE); for (Database db : dir) { if (!db.getReplicaID().equals(getIndexDb().getReplicaID())) { // System.out.println("Scanning database " + db.getApiPath()); // if (!db.getFilePath().equalsIgnoreCase("redpill\\graph.nsf")) { try { scanDatabase(db); } catch (Throwable t) { t.printStackTrace(); } // } } if (!continue_) { System.out.println("Escaping process early due to continue_ == false"); return; } } System.out.println("Completed scan of server " + serverName); } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#scanDatabase(org.openntf.domino.Database) */ @Override @SuppressWarnings("unused") public DocumentScanner scanDatabase(final Database db) { Document dbDoc = getDbDocument(db.getReplicaID()); DocumentScanner scanner = new DocumentScanner(); scanner.setTrackFieldTokens(false); scanner.setTrackFieldTypes(false); scanner.setTrackFieldValues(false); scanner.setTrackTokenFreq(false); scanner.setTrackTokenLocation(true); scanner.setTrackNameLocation(true); scanner.setStopTokenList(getStopList()); scanner.setIgnoreDollar(true); scanner.setStateManager(this, db.getReplicaID()); scanner.setCaseSensitive(getCaseSensitive()); dbDoc.replaceItemValue(IndexDatabase.DB_TITLE_NAME, db.getTitle()); if (dbDoc.hasItem(DB_LAST_INDEX_NAME)) { scanner.setLastScanDate(dbDoc.getItemValue(DB_LAST_INDEX_NAME, Date.class)); // scanner.setStopTokenList(getStopList()); // scanner.setIgnoreDollar(true); // Object tokenLocationObject = dbDoc.getItemValue(DB_TOKEN_LOCATION_NAME, Map.class); // if (tokenLocationObject != null && !((Map) tokenLocationObject).isEmpty()) { // scanner.setTokenLocationMap(tokenLocationObject); // } } if (dbDoc.hasItem(IndexDatabase.DB_DOC_LIST_NAME)) { scanner.setCollection(dbDoc.getItemValue(IndexDatabase.DB_DOC_LIST_NAME, org.openntf.domino.DocumentCollection.class)); } Date scanDate = new Date(); scanDatabase(db, scanner); String dbid = db.getReplicaID(); // writeResults(dbid, scanner); dbDoc.replaceItemValue(DB_LAST_INDEX_NAME, scanDate); // dbDoc.replaceItemValue(DB_FIELD_TOKEN_NAME, scanner.getFieldTokenMap()); // dbDoc.replaceItemValue(DB_TOKEN_LOCATION_NAME, scanner.getTokenLocationMap()); dbDoc.save(); return scanner; } @SuppressWarnings("unused") private int totalErrCount_ = 0; private static final List<String> MOD_SORT_LIST = new ArrayList<String>(); static { MOD_SORT_LIST.add("@modified"); } @SuppressWarnings("unused") private int curDocCount_ = 0; @SuppressWarnings("unused") private int sortedDocCount_ = 0; /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#scanDatabase(org.openntf.domino.Database, org.openntf.domino.helpers.DocumentScanner) */ @Override public DocumentScanner scanDatabase(final Database db, final DocumentScanner scanner) { // System.out.println("Scanning database " + db.getApiPath()); curDocCount_ = 0; scanner.setCaseSensitive(getCaseSensitive()); scanner.setStateManager(this, db.getReplicaID()); Date last = scanner.getLastScanDate(); if (last == null) last = new Date(0); int count = db.getModifiedNoteCount(last); if (count > 0) { DocumentCollection rawColl = db.getModifiedDocuments(last); DocumentSorter sorter = new DocumentSorter(rawColl, MOD_SORT_LIST); System.out.println("Scanning database " + db.getApiPath() + " with last date of " + last.getTime() + " and found " + rawColl.getCount() + " updates to scan"); scanner.processSorter(sorter); } return scanner; } // public void writeResults(final CharSequence dbid, final DocumentScanner scanner) { // Map<CharSequence, Map<CharSequence, Set<CharSequence>>> tlMap = scanner.getTokenLocationMap(); // saveTokenLocationMap(dbid, tlMap, scanner); // } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermDbids(java.lang.CharSequence) */ @Override public List<String> getTermDbids(final CharSequence term) { List<String> result = new ArrayList<String>(); Document doc = getTermDocument(term); for (Item item : doc.getItems()) { String itemName = item.getName(); if (itemName.startsWith(TERM_MAP_PREFIX)) { String dbid = itemName.substring(TERM_MAP_PREFIX.length()); result.add(dbid); } } return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermHitCount(java.lang.String) */ @Override public int getTermHitCount(final String term) { int result = 0; Document doc = getTermDocument(term); for (Item item : doc.getItems()) { String itemName = item.getName(); if (itemName.startsWith(TERM_MAP_PREFIX)) { Map termMap = doc.getItemValue(itemName, Map.class); for (Object key : termMap.keySet()) { Object val = termMap.get(key); if (val instanceof Collection) { result += ((Collection) val).size(); } } } } return result; } protected int getTermDbidHitCount(final Document doc, final CharSequence dbid) { int result = 0; String itemName = TERM_MAP_PREFIX + dbid; if (doc.hasItem(itemName)) { Map termMap = doc.getItemValue(itemName, Map.class); for (Object key : termMap.keySet()) { Object val = termMap.get(key); if (val instanceof Collection) { result += ((Collection) val).size(); } } } return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermItemsInDbids(java.lang.String, java.util.Collection) */ @Override public Set<CharSequence> getTermItemsInDbids(final String term, final Collection<String> dbids) { Set<CharSequence> result = new HashSet<CharSequence>(); Document doc = getTermDocument(term); for (String dbid : dbids) { String itemName = TERM_MAP_PREFIX + dbid; if (doc.hasItem(itemName)) { Map termMap = doc.getItemValue(itemName, Map.class); result.addAll(termMap.keySet()); } } return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermResults(java.lang.CharSequence, int, java.util.Set, java.util.Set, java.util.Set) */ @Override public List<IndexHit> getTermResults(final CharSequence term, final int limit, final Set<CharSequence> dbids, final Set<CharSequence> itemNames, final Set<CharSequence> forms) { List<IndexHit> results = new ArrayList<IndexHit>(); Document doc = getTermDocument(term); int dbCount = 0; if (dbids == null || dbids.isEmpty()) { for (Item item : doc.getItems()) { String itemName = item.getName(); if (itemName.startsWith(TERM_MAP_PREFIX)) { dbCount++; String dbid = itemName.substring(TERM_MAP_PREFIX.length()); Map termMap = doc.getItemValue(itemName, Map.class); results.addAll(getTermResultsForItemsForms(termMap, itemNames, forms, term, dbid)); if (limit != 0 && results.size() >= limit) { return results; } } } } else { for (CharSequence dbid : dbids) { String itemName = TERM_MAP_PREFIX + dbid; if (doc.hasItem(itemName)) { dbCount++; Map termMap = doc.getItemValue(itemName, Map.class); results.addAll(getTermResultsForItemsForms(termMap, itemNames, forms, term, dbid)); if (limit != 0 && results.size() >= limit) { return results; } } } } if (dbCount < 1) { System.out.println("No databases found that contain term " + term + " in document " + doc.getNoteID() + ": " + doc.getAncestorDatabase().getApiPath()); } return results; } protected List<IndexHit> getTermResultsForItemsForms(final Map map, final Set<CharSequence> itemNames, final Set<CharSequence> forms, final CharSequence term, final CharSequence dbid) { List<IndexHit> results = new ArrayList<IndexHit>(); if (itemNames == null || itemNames.isEmpty()) { if (map.keySet() != null) { for (Object key : map.keySet()) { Object val = map.get(key); List<IndexHit> hits = null; if (val instanceof Set) { // System.out.println("Already have a set of " + ((Set) val).size() + " elements"); hits = getTermResultsForForms((Set) val, forms, term, dbid, key.toString()); } else { // System.out.println("Converting to a set from a " + (val == null ? "null" : val.getClass().getName())); hits = getTermResultsForForms(org.openntf.domino.big.IndexDatabase.Utils.toStringSet(val), forms, term, dbid, key.toString()); } results.addAll(hits); } } } else { for (CharSequence key : itemNames) { // System.out.println("Adding hit results for item " + key); Object val = map.get(key); List<IndexHit> hits = null; if (val instanceof Set) { hits = getTermResultsForForms((Set) val, forms, term, dbid, key.toString()); } else { hits = getTermResultsForForms(org.openntf.domino.big.IndexDatabase.Utils.toStringSet(val), forms, term, dbid, key.toString()); } results.addAll(hits); } } return results; } protected List<IndexHit> getTermResultsForForms(final Set<CharSequence> unids, final Set<CharSequence> forms, final CharSequence term, final CharSequence dbid, final CharSequence item) { List<IndexHit> results = new ArrayList<IndexHit>(); if (forms == null || forms.isEmpty()) { if (unids != null && !unids.isEmpty()) { for (CharSequence unid : unids) { try { results.add(createHit(term, dbid, item, unid)); } catch (Exception e) { System.out.println("Exception occured trying to create a hit for db " + dbid + " on term " + term + " with a string of " + String.valueOf(unid) + " from a set of " + unids.size()); } } } } else { for (CharSequence unid : unids) { String formName = unid.toString().substring(33); for (CharSequence form : forms) { if (formName.equalsIgnoreCase(form.toString())) { results.add(createHit(term, dbid, item, unid)); break; } } } } return results; } protected IndexHit createHit(final CharSequence term, final CharSequence dbid, final CharSequence item, final CharSequence unid) { return new IndexHit(term, dbid, item, unid); } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermUnidInDbsItems(java.lang.String, java.util.Collection, java.util.Collection) */ @Override public Set<CharSequence> getTermUnidInDbsItems(final String term, final Collection<String> dbids, final Collection<?> itemNames) { Set<CharSequence> unids = new HashSet<CharSequence>(); Document doc = getTermDocument(term); for (String dbid : dbids) { String itemName = TERM_MAP_PREFIX + dbid; if (doc.hasItem(itemName)) { Map termMap = doc.getItemValue(itemName, Map.class); for (Object key : itemNames) { CaseInsensitiveString ciskey = null; if (key instanceof CaseInsensitiveString) { ciskey = (CaseInsensitiveString) key; } else if (key instanceof String) { ciskey = new CaseInsensitiveString((String) key); } else { ciskey = new CaseInsensitiveString(String.valueOf(key)); } Object termObj = termMap.get(ciskey); if (termObj != null) { if (termObj instanceof Collection) { unids.addAll((Collection) termObj); } else if (termObj instanceof CharSequence) { unids.add(((CharSequence) termObj).toString()); } else { unids.add(String.valueOf(termObj)); } } } } } return unids; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermLinksInDbsItems(org.openntf.domino.Session, java.lang.String, java.lang.String, java.util.Collection, java.util.Collection) */ @Override public Set<String> getTermLinksInDbsItems(final Session session, final String serverName, final String term, final Collection<CharSequence> dbids, final Collection<?> itemNames) { Set<String> unids = new HashSet<String>(); Document doc = getTermDocument(term); for (CharSequence dbid : dbids) { String itemName = TERM_MAP_PREFIX + dbid; if (doc.hasItem(itemName)) { Map termMap = doc.getItemValue(itemName, Map.class); // Database db = session.getDatabaseByReplicaID(serverName, dbid); // if (db != null) { for (Object key : itemNames) { CaseInsensitiveString ciskey = null; if (key instanceof CaseInsensitiveString) { ciskey = (CaseInsensitiveString) key; } else if (key instanceof String) { ciskey = new CaseInsensitiveString((String) key); } else { ciskey = new CaseInsensitiveString(String.valueOf(key)); } Object termObj = termMap.get(ciskey); if (termObj != null) { if (termObj instanceof Collection) { for (Object unid : (Collection) termObj) { // Document curDoc = db.getDocumentByUNID((String) unid); unids.add("http://localhost/__" + dbid + ".nsf/0/" + unid); } // unids.addAll((Collection) termObj); } else if (termObj instanceof CharSequence) { // Document curDoc = db.getDocumentByUNID((String) ((CharSequence) termObj).toString()); unids.add("http://localhost/__" + dbid + ".nsf/0/" + ((CharSequence) termObj).toString()); // unids.add(((CharSequence) termObj).toString()); } else { unids.add(String.valueOf(termObj)); } } } // } } } return unids; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermUnidInItems(java.lang.CharSequence, java.util.Collection) */ @Override public Set<CharSequence> getTermUnidInItems(final CharSequence term, final Collection<String> itemNames) { Set<CharSequence> unids = new HashSet<CharSequence>(); Document doc = getTermDocument(term); for (Item item : doc.getItems()) { String itemName = item.getName(); if (itemName.startsWith(TERM_MAP_PREFIX)) { // String dbid = itemName.substring(TERM_MAP_PREFIX.length()); Map termMap = doc.getItemValue(itemName, Map.class); for (String key : itemNames) { CaseInsensitiveString ciskey = new CaseInsensitiveString(key); Object termObj = termMap.get(ciskey); if (termObj != null) { if (termObj instanceof Collection) { unids.addAll((Collection) termObj); } else if (termObj instanceof CharSequence) { unids.add(((CharSequence) termObj).toString()); } else { unids.add(String.valueOf(termObj)); } } } } } return unids; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermUnidInDbids(java.lang.CharSequence, java.util.Collection) */ @Override public Set<String> getTermUnidInDbids(final CharSequence term, final Collection<String> dbids) { Set<String> unids = new HashSet<String>(); Document doc = getTermDocument(term); for (String dbid : dbids) { String itemName = TERM_MAP_PREFIX + dbid; if (doc.hasItem(itemName)) { Map termMap = doc.getItemValue(itemName, Map.class); for (Object key : termMap.keySet()) { Object termObj = termMap.get(key); if (termObj != null) { if (termObj instanceof Collection) { unids.addAll((Collection) termObj); } else if (termObj instanceof CharSequence) { unids.add(((CharSequence) termObj).toString()); } else { unids.add(String.valueOf(termObj)); } } } } } return unids; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermItemMap(java.lang.String) */ @Override public Map<String, Set<CharSequence>> getTermItemMap(final String term) { Map<String, Set<CharSequence>> result = new LinkedHashMap<String, Set<CharSequence>>(); Document doc = getTermDocument(term); for (Item item : doc.getItems()) { String itemName = item.getName(); if (itemName.startsWith(TERM_MAP_PREFIX)) { String dbid = itemName.substring(TERM_MAP_PREFIX.length()); Map termMap = doc.getItemValue(itemName, Map.class); result.put(dbid, termMap.keySet()); } } return result; } /*public static List<String> dbidCollToTitle(final Session session, final String serverName, final Collection<String> dbids) { List<String> result = new ArrayList<String>(); for (String dbid : dbids) { Database db = session.getDatabase(serverName, dbid); if (db != null) { result.add(db.getTitle() + "|" + dbid); } } return result; } public static List<String> dbMapToCheckbox(final Session session, final String serverName, final Map<String, AtomicInteger> dbMap) { List<String> result = new ArrayList<String>(); for (String dbid : dbMap.keySet()) { Database db = session.getDatabase(serverName, dbid); if (db != null) { result.add(db.getTitle() + " (" + dbMap.get(dbid) + ")|" + dbid); } } return result; } public static List<String> itemMapToCheckbox(final Map<String, AtomicInteger> itemMap) { List<String> result = new ArrayList<String>(); for (String item : itemMap.keySet()) { result.add(item.substring(16) + " (" + itemMap.get(item) + ")|" + item.substring(16)); } return result; } public static List<String> formMapToCheckbox(final Map<String, AtomicInteger> formMap) { List<String> result = new ArrayList<String>(); for (String form : formMap.keySet()) { result.add(form.substring(16) + " (" + formMap.get(form) + ")|" + form.substring(16)); } return result; }*/ /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getTermUnidMap(java.lang.CharSequence) */ @Override public Map<CharSequence, Set<CharSequence>> getTermUnidMap(final CharSequence term) { Map<CharSequence, Set<CharSequence>> result = new LinkedHashMap<CharSequence, Set<CharSequence>>(); Document doc = getTermDocument(term); for (Item item : doc.getItems()) { String itemName = item.getName(); if (itemName.startsWith(TERM_MAP_PREFIX)) { String dbid = itemName.substring(TERM_MAP_PREFIX.length()); Set<CharSequence> unids = new HashSet<CharSequence>(); Map termMap = doc.getItemValue(itemName, Map.class); for (Object key : termMap.keySet()) { Object termObj = termMap.get(key); if (termObj != null) { if (termObj instanceof Collection) { unids.addAll((Collection) termObj); } else if (termObj instanceof CharSequence) { unids.add(((CharSequence) termObj).toString()); } else { unids.add(String.valueOf(termObj)); } } } result.put(dbid, unids); } } return result; } public CharSequence lastToken_ = null; /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#restoreTokenLocationMap(java.lang.CharSequence, java.lang.Object) */ @Override public Map<CharSequence, Set<CharSequence>> restoreTokenLocationMap(final CharSequence token, final Object mapKey) { Map result = null; Document doc = getTermDocument(token.toString()); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); if (doc.hasItem(itemName)) { result = doc.getItemValue(itemName, Map.class); // System.out.println("Found existing term match for: " + token.toString() + " with " + result.size() + " items"); } else { result = new ConcurrentHashMap<CaseInsensitiveString, Set<String>>(8, 0.9f, 1); } return result; } @Override public Map<CharSequence, Set<CharSequence>> restoreValueLocationMap(final CharSequence token, final Object mapKey) { Map result = null; Document doc = getValueDocument(token.toString()); String itemName = VALUE_MAP_PREFIX + String.valueOf(mapKey); if (doc.hasItem(itemName)) { result = doc.getItemValue(itemName, Map.class); } else { result = new ConcurrentHashMap<CaseInsensitiveString, Set<String>>(8, 0.9f, 1); } return result; } // @Override // public void saveTokenLocationMap(final CharSequence token, final Object mapKey, final Map<CharSequence, Set<CharSequence>> map) { // String term = token.toString(); // Document termDoc = getTermDocument(term); // termDoc.replaceItemValue(TERM_MAP_PREFIX + String.valueOf(mapKey), map); // termDoc.save(); // } // @Override // public void saveValueLocationMap(final CharSequence value, final Object mapKey, final Map<CharSequence, Set<CharSequence>> map) { // String term = value.toString(); // Document termDoc = getTermDocument(term); // termDoc.replaceItemValue(TERM_MAP_PREFIX + String.valueOf(mapKey), map); // termDoc.save(); // } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#setLastIndexDate(java.lang.Object, java.util.Date) */ @Override public void setLastIndexDate(final Object mapKey, final Date date) { Document dbDoc = getDbDocument((String) mapKey); dbDoc.replaceItemValue(DB_LAST_INDEX_NAME, date); dbDoc.save(); } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#getLastIndexDate(java.lang.Object) */ @Override public Date getLastIndexDate(final Object mapKey) { Document dbDoc = getDbDocument((String) mapKey); Date result = dbDoc.getItemValue(DB_LAST_INDEX_NAME, java.util.Date.class); if (result == null) result = new Date(0); return result; } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#saveTokenLocationMap(java.lang.Object, java.util.Map, org.openntf.domino.helpers.DocumentScanner) */ @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 term = cis.toString(); Document termDoc = getTermDocument(term); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); termDoc.replaceItemValue(itemName, tlValue); if (termDoc.save()) { // System.out.println("DEBUG: Saved term doc for " + term); } else { System.out.println("DEBUG: Did not save term doc for " + term); } } } else { // System.out.println("DEBUG: keyset was empty for index tokens"); } } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#update(java.util.Observable, java.lang.Object) */ @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) { // System.out.println("DEBUG: Received update with status " + status.name()); 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.isTrackFieldValues()) { Map fieldValueMap = scanner.getFieldValueMap(); int fvsize = fieldValueMap.size(); if (fvsize >= 1024) { synchronized (fieldValueMap) { saveValueLocationMap(scanner.getStateManagerKey(), fieldValueMap, scanner); fieldValueMap.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(); } } 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(); } } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#restoreNameLocationMap(java.lang.CharSequence, java.lang.Object) */ @Override public Map<CharSequence, Set<CharSequence>> restoreNameLocationMap(final CharSequence name, final Object mapKey) { Map result = null; Document doc = getNameDocument(name.toString()); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); if (doc.hasItem(itemName)) { result = doc.getItemValue(itemName, Map.class); } else { result = new ConcurrentHashMap<CaseInsensitiveString, Set<String>>(8, 0.9f, 1); } return result; } // @Override // public void saveNameLocationMap(final CharSequence name, final Object mapKey, final Map<CharSequence, Set<CharSequence>> map) { // String lname = name.toString(); // Document nameDoc = getNameDocument(lname); // nameDoc.replaceItemValue(TERM_MAP_PREFIX + String.valueOf(mapKey), map); // nameDoc.save(); // } /* (non-Javadoc) * @see org.openntf.domino.big.impl.IIndexDatabase#saveNameLocationMap(java.lang.Object, java.util.Map, org.openntf.domino.helpers.DocumentScanner) */ @Override public void saveNameLocationMap(final Object mapKey, final Map<CharSequence, Map<CharSequence, Set<CharSequence>>> fullMap, final DocumentScanner scanner) { // Document dbDoc = getDbDocument((String) mapKey); // if (scanner.getCollection() != null) { // dbDoc.replaceItemValue(IndexDatabase.DB_DOC_LIST_NAME, scanner.getCollection()); // } // // if (scanner.getSorter() != null) { // dbDoc.replaceItemValue(IndexDatabase.DB_DOC_SORTER_NAME, scanner.getSorter()); // } // dbDoc.save(); Set<CharSequence> keySet = fullMap.keySet(); for (CharSequence cis : keySet) { Map<CharSequence, Set<CharSequence>> tlValue = fullMap.get(cis); String name = cis.toString(); Document nameDoc = getNameDocument(name); String itemName = TERM_MAP_PREFIX + String.valueOf(mapKey); nameDoc.replaceItemValue(itemName, tlValue); if (nameDoc.save()) { // System.out.println("Saved term doc for " + term); } } } @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 term = cis.toString(); Document termDoc = getValueDocument(term); String itemName = VALUE_MAP_PREFIX + String.valueOf(mapKey); termDoc.replaceItemValue(itemName, tlValue); if (termDoc.save()) { // System.out.println("DEBUG: Saved term doc for " + term); } else { System.out.println("DEBUG: Did not save term doc for " + term); } } } else { // System.out.println("DEBUG: keyset was empty for index tokens"); } } }