@Test public void testGetAndTagNoHits() { when(writer.getAndTag(q1, "tag")).thenReturn(null); when(cache.getAndTag(q1, "tag")).thenReturn(null); assertNull(io.getAndTag(q1, "tag")); verify(cache, never()).add(any(DatabaseDocument.class)); verify(cache, atLeastOnce()).getAndTag(q1, "tag"); verify(writer, atLeastOnce()).getAndTag(eq(q1), (String[]) Mockito.anyVararg()); }
@Override public DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags) { DatabaseDocument<T> doc = cache.getAndTag(query, tags); if (doc == null) { for (String t : tags) { query.requireNotFetchedByStage(t); } doc = writer.getAndTag(query, addCacheTag(tags)); if (doc != null) { for (String t : tags) { doc.setFetchedBy(t, new Date()); } cache.add(doc); } } return getCopy(doc); }
CachingDocumentNIO implements
		DocumentReader<T>, DocumentWriter<T> { @Override public DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags) { DatabaseDocument<T> doc = cache.getAndTag(query, tags); if (doc == null) { for (String t : tags) { query.requireNotFetchedByStage(t); } doc = writer.getAndTag(query, addCacheTag(tags)); if (doc != null) { for (String t : tags) { doc.setFetchedBy(t, new Date()); } cache.add(doc); } } return getCopy(doc); } }
CachingDocumentNIO implements
		DocumentReader<T>, DocumentWriter<T> { @Override public DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags) { DatabaseDocument<T> doc = cache.getAndTag(query, tags); if (doc == null) { for (String t : tags) { query.requireNotFetchedByStage(t); } doc = writer.getAndTag(query, addCacheTag(tags)); if (doc != null) { for (String t : tags) { doc.setFetchedBy(t, new Date()); } cache.add(doc); } } return getCopy(doc); } CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache);  CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache,
			boolean startMonitorThread);  CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache,
			boolean startMonitorThread, int cacheTimeout); }
CachingDocumentNIO implements
		DocumentReader<T>, DocumentWriter<T> { @Override public DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags) { DatabaseDocument<T> doc = cache.getAndTag(query, tags); if (doc == null) { for (String t : tags) { query.requireNotFetchedByStage(t); } doc = writer.getAndTag(query, addCacheTag(tags)); if (doc != null) { for (String t : tags) { doc.setFetchedBy(t, new Date()); } cache.add(doc); } } return getCopy(doc); } CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache);  CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache,
			boolean startMonitorThread);  CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache,
			boolean startMonitorThread, int cacheTimeout); @Override DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags); @Override Collection<DatabaseDocument<T>> getAndTag(DatabaseQuery<T> query,
			int n, String... tags); @Override boolean markTouched(DocumentID<T> id, String tag); @Override boolean markProcessed(DatabaseDocument<T> d, String stage); @Override boolean markDiscarded(DatabaseDocument<T> d, String stage); @Override boolean markFailed(DatabaseDocument<T> d, String stage); @Override boolean markPending(DatabaseDocument<T> d, String stage); @Override boolean insert(DatabaseDocument<T> d); @Override boolean insert(DatabaseDocument<T> d, List<DocumentFile<T>> attachments); @Override boolean update(DatabaseDocument<T> d); @Override void delete(DatabaseDocument<T> d); @Override boolean deleteDocumentFile(DatabaseDocument<T> d, String fileName); @Override void deleteAll(); @Override void write(DocumentFile<T> df); @Override void prepare(); @Override DatabaseDocument<T> getDocument(DatabaseQuery<T> q); @Override DatabaseDocument<T> getDocumentById(DocumentID<T> id); @Override DatabaseDocument<T> getDocumentById(DocumentID<T> id,
			boolean includeInactive); @Override TailableIterator<T> getInactiveIterator(); @Override TailableIterator<T> getInactiveIterator(DatabaseQuery<T> query); @Override List<DatabaseDocument<T>> getDocuments(DatabaseQuery<T> q, int limit); @Override List<DatabaseDocument<T>> getDocuments(DatabaseQuery<T> q,
			int limit, int skip); @Override long getNumberOfDocuments(DatabaseQuery<T> q); @Override DocumentFile<T> getDocumentFile(DatabaseDocument<T> d,
			String fileName); @Override List<String> getDocumentFileNames(DatabaseDocument<T> d); @Override long getActiveDatabaseSize(); @Override long getInactiveDatabaseSize(); @Override DocumentID<T> toDocumentId(Object jsonPrimitive); @Override DocumentID<T> toDocumentIdFromJson(String json); void connect(); DatabaseDocument<T> convert(LocalDocument localDocument); DatabaseQuery<T> convert(LocalQuery localQuery); void flush(); void flush(int staleTimeout); void setCacheTimeout(int cacheTimeout); int getCacheTimeout(); CacheMonitor getCacheMonitor(); DatabaseConnector<T> getDatabaseConnector(); void getDatabaseConnector(DatabaseConnector<T> backing); DatabaseDocument<T> getCopy(DatabaseDocument<T> doc); }
CachingDocumentNIO implements
		DocumentReader<T>, DocumentWriter<T> { @Override public DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags) { DatabaseDocument<T> doc = cache.getAndTag(query, tags); if (doc == null) { for (String t : tags) { query.requireNotFetchedByStage(t); } doc = writer.getAndTag(query, addCacheTag(tags)); if (doc != null) { for (String t : tags) { doc.setFetchedBy(t, new Date()); } cache.add(doc); } } return getCopy(doc); } CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache);  CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache,
			boolean startMonitorThread);  CachingDocumentNIO(DatabaseConnector<T> backing, Cache<T> cache,
			boolean startMonitorThread, int cacheTimeout); @Override DatabaseDocument<T> getAndTag(DatabaseQuery<T> query, String... tags); @Override Collection<DatabaseDocument<T>> getAndTag(DatabaseQuery<T> query,
			int n, String... tags); @Override boolean markTouched(DocumentID<T> id, String tag); @Override boolean markProcessed(DatabaseDocument<T> d, String stage); @Override boolean markDiscarded(DatabaseDocument<T> d, String stage); @Override boolean markFailed(DatabaseDocument<T> d, String stage); @Override boolean markPending(DatabaseDocument<T> d, String stage); @Override boolean insert(DatabaseDocument<T> d); @Override boolean insert(DatabaseDocument<T> d, List<DocumentFile<T>> attachments); @Override boolean update(DatabaseDocument<T> d); @Override void delete(DatabaseDocument<T> d); @Override boolean deleteDocumentFile(DatabaseDocument<T> d, String fileName); @Override void deleteAll(); @Override void write(DocumentFile<T> df); @Override void prepare(); @Override DatabaseDocument<T> getDocument(DatabaseQuery<T> q); @Override DatabaseDocument<T> getDocumentById(DocumentID<T> id); @Override DatabaseDocument<T> getDocumentById(DocumentID<T> id,
			boolean includeInactive); @Override TailableIterator<T> getInactiveIterator(); @Override TailableIterator<T> getInactiveIterator(DatabaseQuery<T> query); @Override List<DatabaseDocument<T>> getDocuments(DatabaseQuery<T> q, int limit); @Override List<DatabaseDocument<T>> getDocuments(DatabaseQuery<T> q,
			int limit, int skip); @Override long getNumberOfDocuments(DatabaseQuery<T> q); @Override DocumentFile<T> getDocumentFile(DatabaseDocument<T> d,
			String fileName); @Override List<String> getDocumentFileNames(DatabaseDocument<T> d); @Override long getActiveDatabaseSize(); @Override long getInactiveDatabaseSize(); @Override DocumentID<T> toDocumentId(Object jsonPrimitive); @Override DocumentID<T> toDocumentIdFromJson(String json); void connect(); DatabaseDocument<T> convert(LocalDocument localDocument); DatabaseQuery<T> convert(LocalQuery localQuery); void flush(); void flush(int staleTimeout); void setCacheTimeout(int cacheTimeout); int getCacheTimeout(); CacheMonitor getCacheMonitor(); DatabaseConnector<T> getDatabaseConnector(); void getDatabaseConnector(DatabaseConnector<T> backing); DatabaseDocument<T> getCopy(DatabaseDocument<T> doc); static final int DEFAULT_CACHE_TIMEOUT; static final String CACHED_TIME_METADATA_KEY; static final String CACHE_TAG; }