001package org.unix4j.util;
002
003import java.util.Map;
004
005import org.unix4j.command.Command;
006
007/**
008 * Variables contains static utility methods related to variables or place
009 * holders used as {@link Command} arguments. Variables are represented as
010 * string of the form <tt>"{varname}"</tt>, where {@code varname} refers to the
011 * name of the variable.
012 */
013public class Variables {
014
015        /**
016         * Returns the string encoding for a variable with the given {@code name}.
017         * The returned string has the form <tt>"{varname}"</tt>. For instance, a
018         * variable named <tt>"hostname"</tt> would result in a string
019         * <tt>"{hostname}"</tt>.
020         * 
021         * @param varname
022         *            the name of the variable
023         * @return the encoded variable, a string of the form <tt>"{varname}"</tt>
024         */
025        public static String encode(String varname) {
026                return "{" + varname + "}";
027        }
028
029        /**
030         * Returns the string encoding for an indexed variable with the given
031         * {@code name} and {@code index}. The returned string has the form
032         * <tt>"{varname[index]}"</tt>. For instance, the second element of a
033         * variable named <tt>"args"</tt> would result in a string
034         * <tt>"{args[1]}"</tt>.
035         * 
036         * @param varname
037         *            the name of the variable
038         * @param index
039         *            the zero-based variable index
040         * @return the encoded variable, a string of the form
041         *         <tt>"{varname[index]}"</tt>
042         */
043        public static String encode(String varname, int index) {
044                if (index < 0) {
045                        throw new IndexOutOfBoundsException("index must be >= 0, but was " + index);
046                }
047                return "{" + varname + "[" + index + "]}";
048        }
049
050        /**
051         * Returns true if the given {@code expression} represents an encoded
052         * variable. A variable expression starts with <tt>"{"</tt> and ends with
053         * <tt>"}"</tt> as described for {@link #encode(String)} and
054         * {@link #encode(String, int)}.
055         * 
056         * @param expression
057         *            the expression to be checked
058         * @return true if the expression represents a variable, that is, if it has
059         *         the form <tt>"{varname}"</tt>
060         */
061        public static boolean isVariable(String expression) {
062                final int len = expression == null ? 0 : expression.length();
063                return len > 2 && expression.charAt(0) == '{' && expression.charAt(len - 1) == '}';
064        }
065
066        /**
067         * If {@code expression} represents an encoded variable, it is resolved
068         * using the values in the given {@code map}. The key in the map must
069         * exactly match the encoded expression to be successfully resolved. If no
070         * value is found for the variable expression, an expression is thrown.
071         * <p>
072         * If the given expression does not represent a variable, it is returned
073         * unchanged.
074         * 
075         * @param expression
076         *            the expression to resolve
077         * @param variables
078         *            the variable values with the encoded variable name as key
079         * @return the resolved variable if {@code expression} represents a
080         *         variable, and the unchanged expression otherwise
081         * @throws IllegalArgumentException
082         *             if {@code expression} represents a variable but no value for
083         *             this variable is found in the given {@code variables} map
084         */
085        public static String resolve(String expression, Map<String, String> variables) {
086                if (isVariable(expression)) {
087                        if (variables.containsKey(expression)) {
088                                return variables.get(expression);
089                        }
090                        throw new IllegalArgumentException("unresolved variable: " + expression);
091                }
092                return expression;
093        }
094
095        // no instances
096        private Variables() {
097                super();
098        }
099}