// Path: props-common/src/main/java/base/props4j/impl/ElOps.java
// public class ElOps {
// 	
// 	private static ThreadLocal<Boolean> threadLocalSkipEl = new ThreadLocal<Boolean>();
// 	
// 	public static void setSkipEl(boolean val){
// 		if(val) threadLocalSkipEl.set(true);
// 		else threadLocalSkipEl.remove();
// 	}
// 	
// 	public static String processEl(String val, ValsHolder vals){
// 		Pair<String, Boolean> out = processElIfNeed(val, vals);
// 		return out.first;
// 	}
// 
// 	public static Pair<String, Boolean> processElIfNeed(String val, ValsHolder vals){
// 		
// 		if(TRUE.equals(threadLocalSkipEl.get()))
// 			return new Pair<>(val, false);
// 		
// 		if( ! hasText(val))
// 			return new Pair<>(val, false);
// 		
// 		String elBegin = "${";
// 		
// 		int maxTries = 10;
// 		int curTry = 0;
// 		int fromIndex = 0;
// 		boolean updated = false;
// 		while(true){
// 			
// 			curTry++;
// 			if(curTry > maxTries)
// 				return new Pair<>(val, updated);
// 			
// 			if(fromIndex >= val.length())
// 				return new Pair<>(val, updated);
// 			
// 			int beginIndex = val.indexOf(elBegin, fromIndex);
// 			if(beginIndex < 0)
// 				return new Pair<>(val, updated);
// 			
// 			int keyBeginIndex = beginIndex+elBegin.length();
// 			int endIndex = val.indexOf('}', keyBeginIndex);
// 			if(endIndex < 1)
// 				return new Pair<>(val, updated);
// 			
// 			
// 			String elKey = val.substring(keyBeginIndex, endIndex);
// 			String elVal = vals.strVal(elKey, (String)null);
// 			
// 			if(isEmpty(elVal)){
// 				fromIndex = endIndex+1;
// 				continue;
// 			} else {
// 				updated = true;
// 				fromIndex = 0;
// 				val = val.substring(0, beginIndex) + elVal + val.substring(endIndex+1);
// 			}
// 		}
// 
// 		
// 	}
// 
// }
// 
// Path: props-common/src/main/java/base/props4j/ValsHolder.java
// public interface ValsHolder {
// 	
// 	String strVal(String key, String defaultVal);
// 
// }
// 
// Path: props-common/src/main/java/base/props4j/api/model/Pair.java
// public class Pair<A, B>{
// 	
// 	public A first;
// 	public B second;
// 	
// 	public Pair(A first, B second) {
// 		super();
// 		this.first = first;
// 		this.second = second;
// 	}
// 
// 	public Pair() {
// 		super();
// 	}
// 
// 	public void setFirst(A first) {
// 		this.first = first;
// 	}
// 
// 	public void setSecond(B second) {
// 		this.second = second;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "Pair [" + first + ", " + second + "]";
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + ((first == null) ? 0 : first.hashCode());
// 		result = prime * result + ((second == null) ? 0 : second.hashCode());
// 		return result;
// 	}
// 
// 	@SuppressWarnings("rawtypes")
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		Pair other = (Pair) obj;
// 		if (first == null) {
// 			if (other.first != null)
// 				return false;
// 		} else if (!first.equals(other.first))
// 			return false;
// 		if (second == null) {
// 			if (other.second != null)
// 				return false;
// 		} else if (!second.equals(other.second))
// 			return false;
// 		return true;
// 	}
// 	
// 	
// 	
// 	
// 
// }


import static base.props4j.impl.ElOps.*;
import base.props4j.ValsHolder;
import base.props4j.api.model.Pair;
import java.util.concurrent.ConcurrentHashMap;
package base.props4j.impl;



public class ElHolder {
	
	private ValsHolder valsHolder;
	private ConcurrentHashMap<String, CacheData> cache;

// Path: props-common/src/main/java/base/props4j/impl/ElOps.java
// public class ElOps {
// 	
// 	private static ThreadLocal<Boolean> threadLocalSkipEl = new ThreadLocal<Boolean>();
// 	
// 	public static void setSkipEl(boolean val){
// 		if(val) threadLocalSkipEl.set(true);
// 		else threadLocalSkipEl.remove();
// 	}
// 	
// 	public static String processEl(String val, ValsHolder vals){
// 		Pair<String, Boolean> out = processElIfNeed(val, vals);
// 		return out.first;
// 	}
// 
// 	public static Pair<String, Boolean> processElIfNeed(String val, ValsHolder vals){
// 		
// 		if(TRUE.equals(threadLocalSkipEl.get()))
// 			return new Pair<>(val, false);
// 		
// 		if( ! hasText(val))
// 			return new Pair<>(val, false);
// 		
// 		String elBegin = "${";
// 		
// 		int maxTries = 10;
// 		int curTry = 0;
// 		int fromIndex = 0;
// 		boolean updated = false;
// 		while(true){
// 			
// 			curTry++;
// 			if(curTry > maxTries)
// 				return new Pair<>(val, updated);
// 			
// 			if(fromIndex >= val.length())
// 				return new Pair<>(val, updated);
// 			
// 			int beginIndex = val.indexOf(elBegin, fromIndex);
// 			if(beginIndex < 0)
// 				return new Pair<>(val, updated);
// 			
// 			int keyBeginIndex = beginIndex+elBegin.length();
// 			int endIndex = val.indexOf('}', keyBeginIndex);
// 			if(endIndex < 1)
// 				return new Pair<>(val, updated);
// 			
// 			
// 			String elKey = val.substring(keyBeginIndex, endIndex);
// 			String elVal = vals.strVal(elKey, (String)null);
// 			
// 			if(isEmpty(elVal)){
// 				fromIndex = endIndex+1;
// 				continue;
// 			} else {
// 				updated = true;
// 				fromIndex = 0;
// 				val = val.substring(0, beginIndex) + elVal + val.substring(endIndex+1);
// 			}
// 		}
// 
// 		
// 	}
// 
// }
// 
// Path: props-common/src/main/java/base/props4j/ValsHolder.java
// public interface ValsHolder {
// 	
// 	String strVal(String key, String defaultVal);
// 
// }
// 
// Path: props-common/src/main/java/base/props4j/api/model/Pair.java
// public class Pair<A, B>{
// 	
// 	public A first;
// 	public B second;
// 	
// 	public Pair(A first, B second) {
// 		super();
// 		this.first = first;
// 		this.second = second;
// 	}
// 
// 	public Pair() {
// 		super();
// 	}
// 
// 	public void setFirst(A first) {
// 		this.first = first;
// 	}
// 
// 	public void setSecond(B second) {
// 		this.second = second;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "Pair [" + first + ", " + second + "]";
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + ((first == null) ? 0 : first.hashCode());
// 		result = prime * result + ((second == null) ? 0 : second.hashCode());
// 		return result;
// 	}
// 
// 	@SuppressWarnings("rawtypes")
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		Pair other = (Pair) obj;
// 		if (first == null) {
// 			if (other.first != null)
// 				return false;
// 		} else if (!first.equals(other.first))
// 			return false;
// 		if (second == null) {
// 			if (other.second != null)
// 				return false;
// 		} else if (!second.equals(other.second))
// 			return false;
// 		return true;
// 	}
// 	
// 	
// 	
// 	
// 
// }


// Path: props-common/src/main/java/base/props4j/impl/ElHolder.java
import static base.props4j.impl.ElOps.*;
import base.props4j.ValsHolder;
import base.props4j.api.model.Pair;
import java.util.concurrent.ConcurrentHashMap;

package base.props4j.impl;



public class ElHolder {
	
	private ValsHolder valsHolder;
	private ConcurrentHashMap<String, CacheData> cache;

	public ElHolder(ValsHolder props) {