// Path: hibernate4-memcached-core/src/main/java/kr/pe/kwonnam/hibernate4memcached/regions/GeneralDataMemcachedRegion.java
// public class GeneralDataMemcachedRegion extends MemcachedRegion implements GeneralDataRegion {
//     private Logger log = LoggerFactory.getLogger(GeneralDataMemcachedRegion.class);
// 
//     private int expirySeconds;
// 
//     public GeneralDataMemcachedRegion(CacheNamespace cacheNamespace, OverridableReadOnlyProperties properties, CacheDataDescription metadata,
//                                       Settings settings, MemcachedAdapter memcachedAdapter, HibernateCacheTimestamper hibernateCacheTimestamper) {
//         super(cacheNamespace, properties, metadata, settings, memcachedAdapter, hibernateCacheTimestamper);
//         populateExpirySeconds(properties);
//     }
// 
//     void populateExpirySeconds(OverridableReadOnlyProperties properties) {
//         String regionExpirySecondsKey = REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX + "." + getCacheNamespace().getName();
//         String expirySecondsProperty = properties.getProperty(regionExpirySecondsKey);
//         if (expirySecondsProperty == null) {
//             expirySecondsProperty = properties.getProperty(REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX);
//         }
//         if (expirySecondsProperty == null) {
//             throw new IllegalStateException(regionExpirySecondsKey + " or " + REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX
//                     + "(for default expiry seconds) required!");
//         }
// 
//         expirySeconds = Integer.parseInt(expirySecondsProperty);
//         log.info("expirySeconds of cache region [{}] - {} seconds.", getCacheNamespace().getName(), expirySeconds);
//     }
// 
//     @Override
//     public Object get(Object key) throws CacheException {
//         String refinedKey = refineKey(key);
// 
//         log.debug("Cache get [{}] : key[{}]", getCacheNamespace(), refinedKey);
// 
//         Object cachedData;
//         try {
//             cachedData = getMemcachedAdapter().get(getCacheNamespace(), refinedKey);
//         } catch (Exception ex) {
//             log.warn("Failed to get from memcached.", ex);
//             cachedData = null;
//         }
// 
//         if (cachedData == null) {
//             return null;
//         }
// 
//         if (!(cachedData instanceof CacheItem)) {
//             log.debug("get cachedData is not CacheItem.");
//             return cachedData;
//         }
// 
//         CacheItem cacheItem = (CacheItem) cachedData;
//         boolean targetClassAndCurrentJvmTargetClassMatch = cacheItem.isTargetClassAndCurrentJvmTargetClassMatch();
//         log.debug("cacheItem and targetClassAndCurrentJvmTargetClassMatch : {} / {}", targetClassAndCurrentJvmTargetClassMatch, cacheItem);
// 
//         if (cacheItem.isTargetClassAndCurrentJvmTargetClassMatch()) {
//             return cacheItem.getCacheEntry();
//         }
// 
//         return null;
//     }
// 
//     @Override
//     public void put(Object key, Object value) throws CacheException {
// 
//         Object valueToCache = value;
// 
//         boolean classVersionApplicable = CacheItem.checkIfClassVersionApplicable(value, getSettings().isStructuredCacheEntriesEnabled());
// 
//         if (classVersionApplicable) {
//             valueToCache = new CacheItem(value, getSettings().isStructuredCacheEntriesEnabled());
//         }
// 
//         String refinedKey = refineKey(key);
//         log.debug("Cache put [{}] : key[{}], value[{}], classVersionApplicable : {}", getCacheNamespace(), refinedKey,
//                 valueToCache, classVersionApplicable);
//         try {
//             getMemcachedAdapter().set(getCacheNamespace(), refinedKey, valueToCache, getExpiryInSeconds());
//         } catch (Exception ex) {
//             log.warn("Failed to set memcached value.", ex);
//         }
//     }
// 
//     @Override
//     public void evict(Object key) throws CacheException {
//         String refinedKey = refineKey(key);
//         log.debug("Cache evict[{}] : key[{}]", getCacheNamespace(), refinedKey);
//         try {
//             getMemcachedAdapter().delete(getCacheNamespace(), refinedKey);
//         } catch (Exception ex) {
//             log.warn("Failed to delete memcached value.", ex);
//         }
//     }
// 
//     @Override
//     public void evictAll() throws CacheException {
//         log.debug("Cache evictAll [{}].", getCacheNamespace());
//         try {
//             getMemcachedAdapter().evictAll(getCacheNamespace());
//         } catch (Exception ex) {
//             log.warn("Failed to evictAll.", ex);
//         }
//     }
// 
//     /**
//      * Read expiry seconds from configuration properties
//      */
//     protected int getExpiryInSeconds() {
//         return expirySeconds;
//     }
// 
//     /**
//      * Memcached has limitation of key size. Shorten the key to avoid the limitation if needed.
//      */
//     protected String refineKey(Object key) {
//         return String.valueOf(key);
//     }
// }


import kr.pe.kwonnam.hibernate4memcached.regions.GeneralDataMemcachedRegion;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.access.RegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
package kr.pe.kwonnam.hibernate4memcached.strategies;


/**
 * Basic Memcached Region Access Strategy.
 * <p/>
 * This strategy is for READ_ONLY and NONSTRICT_READ_WRITE.
 * This is not suitable for READ_WRITE and TRANSACTIONAL.
 * READ_WRITE, TRANSACTION strategy must override this class's methods.
 *
 * @author KwonNam Son (kwon37xi@gmail.com)
 */
public class MemcachedRegionAccessStrategy implements RegionAccessStrategy {
    private Logger log = LoggerFactory.getLogger(MemcachedRegionAccessStrategy.class);

// Path: hibernate4-memcached-core/src/main/java/kr/pe/kwonnam/hibernate4memcached/regions/GeneralDataMemcachedRegion.java
// public class GeneralDataMemcachedRegion extends MemcachedRegion implements GeneralDataRegion {
//     private Logger log = LoggerFactory.getLogger(GeneralDataMemcachedRegion.class);
// 
//     private int expirySeconds;
// 
//     public GeneralDataMemcachedRegion(CacheNamespace cacheNamespace, OverridableReadOnlyProperties properties, CacheDataDescription metadata,
//                                       Settings settings, MemcachedAdapter memcachedAdapter, HibernateCacheTimestamper hibernateCacheTimestamper) {
//         super(cacheNamespace, properties, metadata, settings, memcachedAdapter, hibernateCacheTimestamper);
//         populateExpirySeconds(properties);
//     }
// 
//     void populateExpirySeconds(OverridableReadOnlyProperties properties) {
//         String regionExpirySecondsKey = REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX + "." + getCacheNamespace().getName();
//         String expirySecondsProperty = properties.getProperty(regionExpirySecondsKey);
//         if (expirySecondsProperty == null) {
//             expirySecondsProperty = properties.getProperty(REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX);
//         }
//         if (expirySecondsProperty == null) {
//             throw new IllegalStateException(regionExpirySecondsKey + " or " + REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX
//                     + "(for default expiry seconds) required!");
//         }
// 
//         expirySeconds = Integer.parseInt(expirySecondsProperty);
//         log.info("expirySeconds of cache region [{}] - {} seconds.", getCacheNamespace().getName(), expirySeconds);
//     }
// 
//     @Override
//     public Object get(Object key) throws CacheException {
//         String refinedKey = refineKey(key);
// 
//         log.debug("Cache get [{}] : key[{}]", getCacheNamespace(), refinedKey);
// 
//         Object cachedData;
//         try {
//             cachedData = getMemcachedAdapter().get(getCacheNamespace(), refinedKey);
//         } catch (Exception ex) {
//             log.warn("Failed to get from memcached.", ex);
//             cachedData = null;
//         }
// 
//         if (cachedData == null) {
//             return null;
//         }
// 
//         if (!(cachedData instanceof CacheItem)) {
//             log.debug("get cachedData is not CacheItem.");
//             return cachedData;
//         }
// 
//         CacheItem cacheItem = (CacheItem) cachedData;
//         boolean targetClassAndCurrentJvmTargetClassMatch = cacheItem.isTargetClassAndCurrentJvmTargetClassMatch();
//         log.debug("cacheItem and targetClassAndCurrentJvmTargetClassMatch : {} / {}", targetClassAndCurrentJvmTargetClassMatch, cacheItem);
// 
//         if (cacheItem.isTargetClassAndCurrentJvmTargetClassMatch()) {
//             return cacheItem.getCacheEntry();
//         }
// 
//         return null;
//     }
// 
//     @Override
//     public void put(Object key, Object value) throws CacheException {
// 
//         Object valueToCache = value;
// 
//         boolean classVersionApplicable = CacheItem.checkIfClassVersionApplicable(value, getSettings().isStructuredCacheEntriesEnabled());
// 
//         if (classVersionApplicable) {
//             valueToCache = new CacheItem(value, getSettings().isStructuredCacheEntriesEnabled());
//         }
// 
//         String refinedKey = refineKey(key);
//         log.debug("Cache put [{}] : key[{}], value[{}], classVersionApplicable : {}", getCacheNamespace(), refinedKey,
//                 valueToCache, classVersionApplicable);
//         try {
//             getMemcachedAdapter().set(getCacheNamespace(), refinedKey, valueToCache, getExpiryInSeconds());
//         } catch (Exception ex) {
//             log.warn("Failed to set memcached value.", ex);
//         }
//     }
// 
//     @Override
//     public void evict(Object key) throws CacheException {
//         String refinedKey = refineKey(key);
//         log.debug("Cache evict[{}] : key[{}]", getCacheNamespace(), refinedKey);
//         try {
//             getMemcachedAdapter().delete(getCacheNamespace(), refinedKey);
//         } catch (Exception ex) {
//             log.warn("Failed to delete memcached value.", ex);
//         }
//     }
// 
//     @Override
//     public void evictAll() throws CacheException {
//         log.debug("Cache evictAll [{}].", getCacheNamespace());
//         try {
//             getMemcachedAdapter().evictAll(getCacheNamespace());
//         } catch (Exception ex) {
//             log.warn("Failed to evictAll.", ex);
//         }
//     }
// 
//     /**
//      * Read expiry seconds from configuration properties
//      */
//     protected int getExpiryInSeconds() {
//         return expirySeconds;
//     }
// 
//     /**
//      * Memcached has limitation of key size. Shorten the key to avoid the limitation if needed.
//      */
//     protected String refineKey(Object key) {
//         return String.valueOf(key);
//     }
// }


// Path: hibernate4-memcached-core/src/main/java/kr/pe/kwonnam/hibernate4memcached/strategies/MemcachedRegionAccessStrategy.java
import kr.pe.kwonnam.hibernate4memcached.regions.GeneralDataMemcachedRegion;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.access.RegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

package kr.pe.kwonnam.hibernate4memcached.strategies;


/**
 * Basic Memcached Region Access Strategy.
 * <p/>
 * This strategy is for READ_ONLY and NONSTRICT_READ_WRITE.
 * This is not suitable for READ_WRITE and TRANSACTIONAL.
 * READ_WRITE, TRANSACTION strategy must override this class's methods.
 *
 * @author KwonNam Son (kwon37xi@gmail.com)
 */
public class MemcachedRegionAccessStrategy implements RegionAccessStrategy {
    private Logger log = LoggerFactory.getLogger(MemcachedRegionAccessStrategy.class);

    private GeneralDataMemcachedRegion internalRegion;