@SuppressWarnings("unchecked")
	private <T> T evaluateDataOnce(IManagedData<T> managedData) throws Exception {

		lm.lockID(managedData.getID());

		try {
			ICache[] allCaches = new ICache[] { firstLevelCache, secondLevelCache };
			ICache[] memoryCachesOnly = new ICache[] { firstLevelCache };

			String key = managedData.getID();

			if (firstLevelCache.hasObjectForKey(key)) {
				// object is already in memory

				T cachedObject = (T) firstLevelCache.getObject(key);
				IDataBrowser<T> browser = getInMemoryDataBrowser(cachedObject);

				boolean canUseCached = managedData.getCacheManager().canUsePreviouslyCachedData(browser,
						firstLevelCache.getDateObjectStored(key), firstLevelCache.getStoredSizeEstimate(key));

				if (canUseCached) {
					return cachedObject;
				} else {
					return createAndStoreData(managedData, allCaches);
				}

			} else if (secondLevelCache.hasObjectForKey(managedData.getID())) {
				// object is not in memory, but possibly in a file

				IDataBrowser<T> browser = getOnDemandDataBrowser(secondLevelCache, key);

				boolean canUseCached = managedData.getCacheManager().canUsePreviouslyCachedData(browser,
						secondLevelCache.getDateObjectStored(key), secondLevelCache.getStoredSizeEstimate(key));

				if (canUseCached) {
					T object = browser.browseData();
					storeData(object, key, memoryCachesOnly);
					return object;
				} else {
					return createAndStoreData(managedData, allCaches);
				}

			} else {
				// object needs to be created and cached from scratch
				logger.debugf("creating object from scratch: %s", managedData.getID());
				return createAndStoreData(managedData, allCaches);
			}
		} finally {
			lm.unlockID(managedData.getID());
		}
	}