package com.buabook.spring.properties;

import org.springframework.beans.factory.support.AbstractBeanFactory;

import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

/**
 * <h3>Spring Properties Programmatic Access</h3>
 * <p>Provides programmatic access to the Spring properties defined in the application.</p>
 * <p>NOTE: This class caches results <i>indefinitely</i> once queried from the property file.</p>
 * (c) 2015 Sport Trades Ltd
 * 
 * @author Jas Rajasansir
 * @version 1.0.0
 * @since 6 Oct 2015
 */
public class PropertyLoader {
	private final AbstractBeanFactory beanFactory;
	
	private final LoadingCache<String, String> cache;

	
	/** @see PropertyLoader */
	public PropertyLoader(AbstractBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		
		this.cache = CacheBuilder.newBuilder().build(getCacheLoader());
	}
	
	/** 
	 * <p>NOTE: It is recommended in most cases to use Spring's <code>@Value</code> annotation to load
	 * property configuration. This method is supplied in the rare cases that you need to programmatically 
	 * define the key.</p> 
	 * @return The specified property value
	 */
	public String getProperty(String property) {
		if(Strings.isNullOrEmpty(property))
			return null;
		
		return cache.getUnchecked(property);
	}
	
	
	private String getPropertyFromSpring(String property) {
		String propertyName = "${" + property + "}";
		String propertyValue = "";
		
		try {
			propertyValue = beanFactory.resolveEmbeddedValue(propertyName);
		} catch(IllegalArgumentException e) {
			// If the property doesn't exist, an IllegalArgumentException will be thrown. We'll catch it and just return empty string
		}
		
		return propertyValue;
	}
	
	
	private CacheLoader<String, String> getCacheLoader() {
		return new CacheLoader<String, String>() {
			@Override
			public String load(String key) throws Exception {
				return getPropertyFromSpring(key);
			}
		};
	}
}
@@ -33,16 +33,75 @@
 rties;%0A%0A
+import org.springframework.beans.factory.annotation.Value;%0A
 import o
@@ -162,16 +162,16 @@
 actory;%0A
-
 %0Aimport 
@@ -495,17 +495,29 @@
 p%3ENOTE: 
-T
+By default, t
 his clas
@@ -1095,27 +1095,21 @@
 g's 
-%3Ccode%3E@Value%3C/code%3E
+%7B@link Value%7D
  ann
@@ -1441,32 +1441,413 @@
 operty);%0A%09%7D%0A%09%0A%09%0A
+%09/** %0A%09 * %3Cp%3EProvides the cache to store properties loaded via the %7B@link AbstractBeanFactory%7D.%3C/p%3E%0A%09 * %3Cp%3EThis can be overridden if necessary to customise the cache. Use %7B@link #getCacheLoader()%7D as the %7B@link CacheLoader%7D.%3C/p%3E%0A%09 * @see CacheBuilder%0A%09 */%0A%09protected LoadingCache%3CString, String%3E buildNewCache() %7B%0A%09%09return CacheBuilder.newBuilder().build(getCacheLoader());%0A%09%7D%0A%09%0A%09%0A
 %09private String 
@@ -2237,23 +2237,21 @@
 yValue;%0A
+
 %09%7D%0A%09%0A
-%09%0A
 %09private

Enable overriding of cache builder