docs: public V getCachedObject(TaskRequest req, TaskResponse res, K key, Factory<K, V> factory) {
          final CacheMode cacheMode = CacheMode.valueOf((String) this.cacheModelPhrase.evaluate(req, res));
          
          if (this.logger.isDebugEnabled()) {
              this.logger.debug("Getting cached object for '" + key + "' using cache mode " + cacheMode + " and factory " + factory);
          }
          
          //Load the cache only if cache-all is enabled
          final ConcurrentMap<Tuple<Serializable, K>, Object> cache;
          final Tuple<Serializable, K> compoundCacheKey;
          switch (cacheMode) {
              case NONE: {
                  return factory.createObject(key);
              }
              
              default:
              case ONE: {
                  cache = null;
                  compoundCacheKey = null;
              }
              break;
              
              case ALL: {
                  cache = (ConcurrentMap<Tuple<Serializable, K>, Object>) this.cachePhrase.evaluate(req, res);
                  final Serializable cacheNamespace = factory.getCacheNamespace(key);
                  compoundCacheKey = new Tuple<Serializable, K>(cacheNamespace, key);
              }
              break;
          }
          
          //Determine the object to synchronize around
          final Object syncTarget = factory.getMutex(key);
  
          //get or create & cache the target object
          V instance = null;
          synchronized (syncTarget) {
              //Get the object from the local variables if no cache is available
              if (cache == null) {
                  //Try for a thread-local instance first
                  if (this.compareKeys(key, this.threadKeyHolder.get())) {
                      instance = this.threadInstanceHolder.get();
                  }
                  //Next try for a singleton instance
                  else if (this.compareKeys(key, this.key)) {
                      instance = this.instance;
                  } 
              }
              //Look in the passed cache for the instance
              else {
                  final Object object = cache.get(compoundCacheKey);
                  
                  //If the cached object is a ThreadLocal use it for the instance
                  if (object instanceof ThreadLocal<?>) {
                      instance = ((ThreadLocal<V>) object).get();
                  }
                  //If not assume it is the instance 
                  else {
                      instance = (V) object;
                  }
              }
              
              //If no instance was found create and cache one
              if (instance == null) {
                  instance = factory.createObject(key);
                  final boolean threadSafe = factory.isThreadSafe(key, instance);
                  
                  if (this.logger.isDebugEnabled()) {
                      this.logger.debug("Cache miss for '" + key + "' created '" + instance + "' threadSafe=" + threadSafe);
                  }
                  
                  //If no cache is available store the instance in the local variables
                  if (cache == null) {
                      if (threadSafe) {
                          this.instance = instance;
                          this.key = key;
                      }
                      else {
                          this.threadInstanceHolder.set(instance);
                          this.threadKeyHolder.set(key);
                      }
                  }
                  //Cache available store there
                  else {
                      if (threadSafe) {
                          cache.put(compoundCacheKey, instance);
                      }
                      else {
                          ThreadLocal<V> threadInstanceHolder = (ThreadLocal<V>)cache.get(compoundCacheKey);
                          if (threadInstanceHolder == null) {
                              threadInstanceHolder = new ThreadLocal<V>();
                              
                              while (true) {
                                  Object existing = cache.putIfAbsent(compoundCacheKey, threadInstanceHolder);
                                  if (existing == null) {
                                      //nothing existed for that key, put was successful
                                      break;
                                  }
                                  
                                  if (existing instanceof ThreadLocal) {
                                      //Existing ThreadLocal, just use it
                                      threadInstanceHolder = (ThreadLocal)existing;
                                      break;
                                  }
                                  
                                  //something other than a ThreadLocal already exists, try replacing with the ThreadLocal
                                  final boolean replaced = cache.replace(compoundCacheKey, threadInstanceHolder, existing);
                                  if (replaced) {
                                      //Replace worked!
                                      break;
                                  }
                                  
                                  //Replace didn't work, try the whole process again, yay non-blocking!
                              }
                              
                              if (cache instanceof EvictionAwareCache) {
                                  ((EvictionAwareCache) cache).registerCacheEvictionListener(ThreadLocalCacheEvictionListener.INSTANCE);
                              }
                          }
  
                          threadInstanceHolder.set(instance);
                      }
                  }
              }
              else if (this.logger.isDebugEnabled()) {
                  this.logger.debug("Cache hit for '" + key + "' using '" + instance + "'");
              }
          }
          
          return instance;
      }