package org.jactr.tools.experiment.impl; /* * default logging */ import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.model.IModel; import org.jactr.core.runtime.ACTRRuntime; public class VariableResolver { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(VariableResolver.class); private Collection<IResolver> _resolvers; private Map<String, String> _aliases; static final public String PREFIX = "${"; static final public String SUFFIX = "}"; static final private String ESCAPED_PREFIX = "\\$\\{"; static final private String ESCAPED_SUFFIX = "\\}"; /** * will return all models with matching names in the current runtime * * @param modelNames * @param resolver * @param context * @return */ static public Collection<IModel> getModels(String modelNames, VariableResolver resolver, IVariableContext context) { modelNames = resolver.resolve(modelNames, context).toString(); Collection<IModel> allModels = ACTRRuntime.getRuntime().getModels(); Collection<IModel> models = new ArrayList<IModel>(); for (String modelName : modelNames.split(",")) { modelName = modelName.trim(); for (IModel model : allModels) if (modelName.equalsIgnoreCase(model.getName())) models.add(model); } return models; } public VariableResolver() { _resolvers = new ArrayList<IResolver>(); _aliases = new TreeMap<String, String>(); initialize(); } public void addAlias(String alias, String value) { _aliases.put(alias, value); } protected void initialize() { /** * ${SystemProperty} */ add(new IResolver() { public boolean isRelevant(String key) { return System.getProperty(key) != null; } public Object resolve(String key, IVariableContext context) { return System.getProperty(key); } }); /** * ${context} */ add(new IResolver() { public boolean isRelevant(String key) { return true; } public Object resolve(String key, IVariableContext context) { Object value = context.get(key); return value; } }); /** * alias resolver */ add(new IResolver() { public boolean isRelevant(String key) { return _aliases.containsKey(key); } public Object resolve(String key, IVariableContext context) { return _aliases.get(key); } }); } public void add(IResolver resolver) { _resolvers.add(resolver); } public String getPrefix() { return PREFIX; } public String getSuffix() { return SUFFIX; } public boolean isVariable(String key) { return key.startsWith(PREFIX) && key.endsWith(SUFFIX); } public boolean isResolvable(String key, IVariableContext context) { if (!isVariable(key)) return false; key = key.substring(key.indexOf(PREFIX) + 2, key.lastIndexOf(SUFFIX)); Object rtn = null; for (IResolver resolver : _resolvers) if (resolver.isRelevant(key)) { rtn = resolver.resolve(key, context); if (rtn != null) break; } return rtn != null; } /** * find and attempt to resolve all variables in this string, returning the * resolved string. resolution follows * {@link #resolve(String, IVariableContext)} * * @param variablizedTemplate * @param context * @return */ public String resolveValues(String variablizedTemplate, IVariableContext context) { // four group pattern. 0-all, 1-prefix, 2-variableName, 3-suffix Pattern p = Pattern.compile(String.format("(%s)(.*)(%s)", ESCAPED_PREFIX, ESCAPED_SUFFIX)); Matcher m = p.matcher(variablizedTemplate); StringBuffer sb = new StringBuffer(); while (m.find()) { String fullName = m.group(0); String resolved = resolve(fullName, context).toString(); m.appendReplacement(sb, resolved); } m.appendTail(sb); return sb.toString(); } /** * attempts to resolve the variable key. It will resolve to the actual object, * not necessarily a string. If it cannot be resolved, the key is returned. In * this way, you can differentiate between a null value ( * resolve(key,context)==null ), and undefined ( resolve(key,context)==key) * * @param key * @param context * @return */ public Object resolve(String key, IVariableContext context) { if (!isVariable(key)) return key; String oKey = key; int start = key.indexOf(PREFIX) + 2; int end = key.indexOf(SUFFIX, start); key = key.substring(start, end); Object rtn = null; for (IResolver resolver : _resolvers) if (resolver.isRelevant(key)) { rtn = resolver.resolve(key, context); if (rtn != null) break; } if (rtn == null) { if (LOGGER.isWarnEnabled()) LOGGER.warn(String.format("Could not resolve %s, returing %s", key, oKey)); rtn = oKey; } return rtn; } public interface IResolver { public boolean isRelevant(String key); public Object resolve(String key, IVariableContext context); } }