class GuavaOffHeapCacheBuilder {

    @SuppressWarnings("rawtypes")
    public GuavaOffHeapCache<K, V> build(final Class<V> clazz) {
        if ( executorService == null )
            executorService = MoreExecutors.sameThreadExecutor();
        if ( kryo == null )
            kryo = new DecoratedKryo();
        if ( memoryManager == null )
            memoryManager = new UnsafeMemoryManager();
        kryo.register( clazz, new FieldsSerializer( kryo, new BasicBO( clazz ) ) );
        MatchingSerializer<?> serializer = new ExplicitCacheEntrySerializer( kryo );
        final MutableObject<SimpleStatsCounter> statsCounter = new MutableObject<AbstractCache.SimpleStatsCounter>();
        if ( recordStats )
            statsCounter.set( new SimpleStatsCounter() );
        OffHeapLinearProbingSet offheapSet = new OffHeapLinearProbingSet( memoryManager, capacityRestriction, null, serializer, executorService );
        SpaceExpirationListener<K, ByteBuffer> evictionListener = new SpaceExpirationListener<K, ByteBuffer>( false ) {
            @Override
            public void handleNotification(final ByteBuffer entity,
                                           final K id,
                                           final Class<ByteBuffer> persistentClass,
                                           final int originalTimeToLive) {
                if ( statsCounter.get() != null )
                    statsCounter.get().recordEviction();
            }
        };
        if ( expirationListener != null )
            offheapSet.setExpirationListeners( evictionListener, new SpaceExpirationListener<K, ExplicitCacheEntry<K, V>>() {
                @SuppressWarnings("unchecked")
                @Override
                public void handleNotification(final ExplicitCacheEntry<K, V> entity,
                                               final K id,
                                               final Class<ExplicitCacheEntry<K, V>> persistentClass,
                                               final int originalTimeToLive) {
                    expirationListener.handleNotification( entity.getBean(), id, (Class<V>) entity.getBean().getClass(), originalTimeToLive );
                }
            } );
        else
            offheapSet.setExpirationListeners( evictionListener );
        return new GuavaOffHeapCache<K, V>( memoryManager, offheapSet, kryo, ttl, statsCounter.get() );
    }

}