/**
 * Get more info at : www.jrebirth.org .
 * Copyright JRebirth.org © 2011-2013
 * Contact : sebastien.bordes@jrebirth.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jrebirth.af.core.resource.builder;

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;

import org.jrebirth.af.api.resource.ResourceItem;
import org.jrebirth.af.api.resource.ResourceParams;
import org.jrebirth.af.api.resource.builder.ResourceBuilder;
import org.jrebirth.af.core.resource.Resources;
import org.jrebirth.af.core.resource.provided.JRebirthParameters;

/**
 * The abstract class <strong>AbstractResourceBuilder</strong>.
 *
 * The base abstract class used to manage resource weakly.
 *
 * @author Sébastien Bordes
 *
 * @param <I> The item used to wrap the resource
 * @param <P> The resource params type
 * @param <R> The real resource managed
 */
public abstract class AbstractResourceBuilder<I extends ResourceItem<?, ?, ?>, P extends ResourceParams, R> implements ResourceBuilder<I, P, R> {

    /** The resource weak Map. */
    private final Map<I, P> paramsMap = new WeakHashMap<I, P>();

    /** The resource weak Map. */
    private final Map<String, WeakReference<R>> resourceMap = new WeakHashMap<>();

    /**
     * {@inheritDoc}
     */
    @Override
    public void storeParams(final I key, final P params) {
        // Store the resource into the map
        this.paramsMap.put(key, params);

        // Activate the AutoRefresh feature only for other parameters
        if (Resources.isNotAutoRefreshParam(params) && JRebirthParameters.AUTO_REFRESH_RESOURCE.get()) {
            params.activateAutoRefresh();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public P getParam(final I key) {
        // Retrieve the resource from the map
        return this.paramsMap.get(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getParamKey(final I key) {
        return getParam(key).getKey();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public R get(final I key) {

        final P params = getParam(key);

        final String paramsKey = params.getKey();

        // Retrieve the resource weak reference from the map
        WeakReference<R> resourceWeakRef = this.resourceMap.get(paramsKey);

        // The resourceWeakRef may be null if nobody use it
        R resource = resourceWeakRef == null ? null : resourceWeakRef.get();
        if (resourceWeakRef == null || resource == null) {
            // So we must rebuild an instance and then store it weakly
            resource = buildResource(key, params);
            set(paramsKey, resource);
            params.hasChanged(false);
        }
        return resource;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void set(final String key, final R resource) {
        this.resourceMap.put(key, new WeakReference<R>(resource));
    }

    /**
     * Build the resource requested.
     *
     * @param item the parameter item used to identify the resource element
     * @param params the primitive parameters used to build the resource
     *
     * @return the resource built and weakly stored with a WeakReference
     */
    protected abstract R buildResource(final I item, final P params);

}

@@ -769,20 +769,20 @@
 ang.ref.
-Weak
+Soft
 Referenc
@@ -1683,32 +1683,40 @@
 P%3E();%0D%0A%0D%0A    /**
+%0D%0A     *
  The resource we
@@ -1714,32 +1714,171 @@
 source weak Map.
+%3Cbr /%3E%0D%0A     * SoftReference can be kept longer in memory depending on the -client or -server jvm argument and on Xms and Xms values.%0D%0A    
  */%0D%0A    private
@@ -1896,20 +1896,20 @@
 String, 
-Weak
+Soft
 Referenc
@@ -2991,20 +2991,26 @@
         
-Weak
+final Soft
 Referenc
@@ -3018,28 +3018,28 @@
 %3CR%3E resource
-Weak
+Soft
 Ref = this.r
@@ -3083,56 +3083,326 @@
  // 
-The resourceWeakRef may be null if nobody use it
+Warning the gc can collect gthe resource between the test and the getter call so we have to get the resource immediately%0D%0A        // and test it instead of testing the reference value%0D%0A%0D%0A        // The resourceSoftRef may be null if nobody use it%0D%0A        // If the resource reference is not null try to grab its value
 %0D%0A  
@@ -3420,36 +3420,36 @@
 ource = resource
-Weak
+Soft
 Ref == null ? nu
@@ -3461,20 +3461,20 @@
 resource
-Weak
+Soft
 Ref.get(
@@ -3477,24 +3477,26 @@
 get();%0D%0A
+%0D%0A
         
 if (reso
@@ -3491,24 +3491,146 @@
     
-if (resourceWeak
+// When the reference is null (first access time) or the resource is null (the resource has been collected y gc)%0D%0A        if (resourceSoft
 Ref 
@@ -3680,21 +3680,20 @@
  // 
-So w
+W
 e must 
+(
 re
+)
 buil
@@ -4060,20 +4060,20 @@
 ey, new 
-Weak
+Soft
 Referenc

Use soft references for Resource to try to hold resources a bit longer in memory (depend on jvm argument ans heap min size)