package mhfc.net.common.util.parsing;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import mhfc.net.common.util.parsing.proxies.ContextWrapper;
import mhfc.net.common.util.parsing.proxies.StaticAccess;
import mhfc.net.common.util.parsing.valueholders.ValueHolders;
public class Context {
public static String checkKeySyntax(String key) {
if (key.isEmpty()) {
throw new IllegalArgumentException("Key can't be the empty string");
}
return key;
}
private static <T> boolean put(Map<String, ? super T> map, String key, T item) {
Objects.requireNonNull(key);
Objects.requireNonNull(item);
key = checkKeySyntax(key);
if (key.startsWith("_") && map.containsKey(key)) {
return false;
}
map.put(key, item);
return true;
}
private Map<String, IValueHolder> map = new HashMap<>();
private ContextWrapper wrapper = new ContextWrapper(this);
private BoundExpressionTranslator translator;
private Object lock = new Object();
/**
*
* @param key
* @return
* @see Map#get(Object)
*/
public IValueHolder getVar(String key) {
if (!map.containsKey(key)) {
return ValueHolders
.throwing(() -> new IllegalArgumentException("No value named " + key + " in " + Context.this));
}
return map.get(key);
}
/**
*
* @param key
* @return
* @see Map#containsKey(Object)
*/
public boolean hasVar(String key) {
return map.containsKey(key);
}
/**
* Puts a variable into the context. The key must not be empty, also the any shall not be <code>null</code>.<br>
* Keys that begin with an <code>'_'(LOW LINE U+005F)</code> are "internal". Once they are set, they can not be
* replaced. Don't use this if you don't exactly know what you're doing.
*
* @param key
* @param any
* @return if the any was successfully placed into the context
*/
public boolean putVar(String key, IValueHolder any) {
return put(map, key, any);
}
/**
* Puts a class into the context, which static methods and members can be access.
*
* @param key
* @param clazz
* @return if it was successfully placed into the context
* @see #putVar(String, IValueHolder)
*/
public boolean putClass(String key, Class<?> clazz) {
return put(map, key, Holder.valueOf(new StaticAccess(clazz)));
}
public BoundExpressionTranslator getTranslator() {
if (translator == null) {
synchronized (lock) {
// Double-tap for performance
if (translator == null) {
translator = new BoundExpressionTranslator(this);
}
}
}
return translator;
}
/**
* The wrapper that is being accessed in the parsded expressions.
*
* @return
*/
public ContextWrapper getWrapper() {
return wrapper;
}
}