package aQute.bnd.osgi;

import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.regex.*;

import aQute.lib.collections.*;
import aQute.lib.io.*;

/**
 * Provide a macro processor. This processor can replace variables in strings
 * based on a properties and a domain. The domain can implement functions that
 * start with a "_" and take args[], the names of these functions are available
 * as functions in the macro processor (without the _). Macros can nest to any
 * depth but may not contain loops. Add POSIX macros: ${#parameter} String
 * length. ${parameter%word} Remove smallest suffix pattern. ${parameter%%word}
 * Remove largest suffix pattern. ${parameter#word} Remove smallest prefix
 * pattern. ${parameter##word} Remove largest prefix pattern.
 */
public class Macro {
	Processor	domain;
	Object		targets[];
	boolean		flattening;

	public Macro(Processor domain, Object... targets) {
		this.domain = domain;
		this.targets = targets;
		if (targets != null) {
			for (Object o : targets) {
				assert o != null;
			}
		}
	}

	public String process(String line, Processor source) {
		return process(line, new Link(source, null, line));
	}

	String process(String line, Link link) {
		StringBuilder sb = new StringBuilder();
		process(line, 0, '\u0000', '\u0000', sb, link);
		return sb.toString();
	}

	int process(CharSequence org, int index, char begin, char end, StringBuilder result, Link link) {
		StringBuilder line = new StringBuilder(org);
		int nesting = 1;

		StringBuilder variable = new StringBuilder();
		outer: while (index < line.length()) {
			char c1 = line.charAt(index++);
			if (c1 == end) {
				if (--nesting == 0) {
					result.append(replace(variable.toString(), link));
					return index;
				}
			} else if (c1 == begin)
				nesting++;
			else if (c1 == '\\' && index < line.length() - 1 && line.charAt(index) == '$') {
				// remove the escape backslash and interpret the dollar
				// as a
				// literal
				index++;
				variable.append('$');
				continue outer;
			} else if (c1 == '$' && index < line.length() - 2) {
				char c2 = line.charAt(index);
				char terminator = getTerminator(c2);
				if (terminator != 0) {
					index = process(line, index + 1, c2, terminator, variable, link);
					continue outer;
				}
			} else if (c1 == '.' && index < line.length() && line.charAt(index) == '/') {
				// Found the sequence ./
				if (index == 1 || Character.isWhitespace(line.charAt(index - 2))) {
					// make sure it is preceded by whitespace or starts at begin
					index++;
					variable.append(domain.getBase().getAbsolutePath());
					variable.append('/');
					continue outer;
				}
			}
			variable.append(c1);
		}
		result.append(variable);
		return index;
	}

	public static char getTerminator(char c) {
		switch (c) {
			case '(' :
				return ')';
			case '[' :
				return ']';
			case '{' :
				return '}';
			case '<' :
				return '>';
			case '\u00ab' : // Guillemet double << >>
				return '\u00bb';
			case '\u2039' : // Guillemet single
				return '\u203a';
		}
		return 0;
	}

	protected String replace(String key, Link link) {
		if (link != null && link.contains(key))
			return "${infinite:" + link.toString() + "}";

		if (key != null) {
			key = key.trim();
			if (key.length() > 0) {
				Processor source = domain;
				String value = null;

				if (key.indexOf(';') < 0) {
					Instruction ins = new Instruction(key);
					if (!ins.isLiteral()) {
						SortedList<String> sortedList = SortedList.fromIterator(domain.iterator());
						StringBuilder sb = new StringBuilder();
						String del = "";
						for (String k : sortedList) {
							if (ins.matches(k)) {
								String v = replace(k, new Link(source, link, key));
								if (v != null) {
									sb.append(del);
									del = ",";
									sb.append(v);
								}
							}
						}
						return sb.toString();
					}
				}
				while (value == null && source != null) {
					value = source.getProperties().getProperty(key);
					source = source.getParent();
				}

				if (value != null)
					return process(value, new Link(source, link, key));

				value = doCommands(key, link);
				if (value != null)
					return process(value, new Link(source, link, key));

				if (key != null && key.trim().length() > 0) {
					value = System.getProperty(key);
					if (value != null)
						return value;
				}
				if (!flattening && !key.equals("@"))
					domain.warning("No translation found for macro: " + key);
			} else {
				domain.warning("Found empty macro key");
			}
		} else {
			domain.warning("Found null macro key");
		}
		return "${" + key + "}";
	}

	/**
	 * Parse the key as a command. A command consist of parameters separated by
	 * ':'.
	 * 
	 * @param key
	 * @return
	 */
	static Pattern	commands	= Pattern.compile("(?<!\\\\);");

	private String doCommands(String key, Link source) {
		String[] args = commands.split(key);
		if (args == null || args.length == 0)
			return null;

		for (int i = 0; i < args.length; i++)
			if (args[i].indexOf('\\') >= 0)
				args[i] = args[i].replaceAll("\\\\;", ";");

		if (args[0].startsWith("^")) {
			String varname = args[0].substring(1).trim();

			Processor parent = source.start.getParent();
			if (parent != null)
				return parent.getProperty(varname);
			return null;
		}

		Processor rover = domain;
		while (rover != null) {
			String result = doCommand(rover, args[0], args);
			if (result != null)
				return result;

			rover = rover.getParent();
		}

		for (int i = 0; targets != null && i < targets.length; i++) {
			String result = doCommand(targets[i], args[0], args);
			if (result != null)
				return result;
		}

		return doCommand(this, args[0], args);
	}

	private String doCommand(Object target, String method, String[] args) {
		if (target == null)
			; // System.err.println("Huh? Target should never be null " +
		// domain);
		else {
			String cname = "_" + method.replaceAll("-", "_");
			try {
				Method m = target.getClass().getMethod(cname, new Class[] {
					String[].class
				});
				return (String) m.invoke(target, new Object[] {
					args
				});
			}
			catch (NoSuchMethodException e) {
				// Ignore
			}
			catch (InvocationTargetException e) {
				if (e.getCause() instanceof IllegalArgumentException) {
					domain.error("%s, for cmd: %s, arguments; %s", e.getMessage(), method, Arrays.toString(args));
				} else {
					domain.warning("Exception in replace: " + e.getCause());
					e.getCause().printStackTrace();
				}
			}
			catch (Exception e) {
				domain.warning("Exception in replace: " + e + " method=" + method);
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * Return a unique list where the duplicates are removed.
	 * 
	 * @param args
	 * @return
	 */
	static String	_uniqHelp	= "${uniq;<list> ...}";

	public String _uniq(String args[]) {
		verifyCommand(args, _uniqHelp, null, 1, Integer.MAX_VALUE);
		Set<String> set = new LinkedHashSet<String>();
		for (int i = 1; i < args.length; i++) {
			Processor.split(args[i], set);
		}
		return Processor.join(set, ",");
	}

	public String _pathseparator(@SuppressWarnings("unused") String args[]) {
		return File.pathSeparator;
	}

	public String _separator(@SuppressWarnings("unused") String args[]) {
		return File.separator;
	}

	public String _filter(String args[]) {
		return filter(args, false);
	}

	public String _filterout(String args[]) {
		return filter(args, true);

	}

	static String	_filterHelp	= "${%s;<list>;<regex>}";

	String filter(String[] args, boolean include) {
		verifyCommand(args, String.format(_filterHelp, args[0]), null, 3, 3);

		Collection<String> list = new ArrayList<String>(Processor.split(args[1]));
		Pattern pattern = Pattern.compile(args[2]);

		for (Iterator<String> i = list.iterator(); i.hasNext();) {
			if (pattern.matcher(i.next()).matches() == include)
				i.remove();
		}
		return Processor.join(list);
	}

	static String	_sortHelp	= "${sort;<list>...}";

	public String _sort(String args[]) {
		verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);

		List<String> result = new ArrayList<String>();
		for (int i = 1; i < args.length; i++) {
			Processor.split(args[i], result);
		}
		Collections.sort(result);
		return Processor.join(result);
	}

	static String	_joinHelp	= "${join;<list>...}";

	public String _join(String args[]) {

		verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);

		List<String> result = new ArrayList<String>();
		for (int i = 1; i < args.length; i++) {
			Processor.split(args[i], result);
		}
		return Processor.join(result);
	}

	static String	_ifHelp	= "${if;<condition>;<iftrue> [;<iffalse>] }";

	public String _if(String args[]) {
		verifyCommand(args, _ifHelp, null, 3, 4);
		String condition = args[1].trim();
		if (!condition.equalsIgnoreCase("false"))
			if (condition.length() != 0)
				return args[2];

		if (args.length > 3)
			return args[3];
		return "";
	}

	public String _now(@SuppressWarnings("unused") String args[]) {
		return new Date().toString();
	}

	public final static String	_fmodifiedHelp	= "${fmodified;<list of filenames>...}, return latest modification date";

	public String _fmodified(String args[]) throws Exception {
		verifyCommand(args, _fmodifiedHelp, null, 2, Integer.MAX_VALUE);

		long time = 0;
		Collection<String> names = new ArrayList<String>();
		for (int i = 1; i < args.length; i++) {
			Processor.split(args[i], names);
		}
		for (String name : names) {
			File f = new File(name);
			if (f.exists() && f.lastModified() > time)
				time = f.lastModified();
		}
		return "" + time;
	}

	public String _long2date(String args[]) {
		try {
			return new Date(Long.parseLong(args[1])).toString();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return "not a valid long";
	}

	public String _literal(String args[]) {
		if (args.length != 2)
			throw new RuntimeException("Need a value for the ${literal;<value>} macro");
		return "${" + args[1] + "}";
	}

	public String _def(String args[]) {
		if (args.length != 2)
			throw new RuntimeException("Need a value for the ${def;<value>} macro");

		return domain.getProperty(args[1], "");
	}

	/**
	 * replace ; <list> ; regex ; replace
	 * 
	 * @param args
	 * @return
	 */
	public String _replace(String args[]) {
		if (args.length != 4) {
			domain.warning("Invalid nr of arguments to replace " + Arrays.asList(args));
			return null;
		}

		String list[] = args[1].split("\\s*,\\s*");
		StringBuilder sb = new StringBuilder();
		String del = "";
		for (int i = 0; i < list.length; i++) {
			String element = list[i].trim();
			if (!element.equals("")) {
				sb.append(del);
				sb.append(element.replaceAll(args[2], args[3]));
				del = ", ";
			}
		}

		return sb.toString();
	}

	public String _warning(String args[]) {
		for (int i = 1; i < args.length; i++) {
			domain.warning(process(args[i]));
		}
		return "";
	}

	public String _error(String args[]) {
		for (int i = 1; i < args.length; i++) {
			domain.error(process(args[i]));
		}
		return "";
	}

	/**
	 * toclassname ; <path>.class ( , <path>.class ) *
	 * 
	 * @param args
	 * @return
	 */
	static String	_toclassnameHelp	= "${classname;<list of class names>}, convert class paths to FQN class names ";

	public String _toclassname(String args[]) {
		verifyCommand(args, _toclassnameHelp, null, 2, 2);
		Collection<String> paths = Processor.split(args[1]);

		List<String> names = new ArrayList<String>(paths.size());
		for (String path : paths) {
			if (path.endsWith(".class")) {
				String name = path.substring(0, path.length() - 6).replace('/', '.');
				names.add(name);
			} else if (path.endsWith(".java")) {
				String name = path.substring(0, path.length() - 5).replace('/', '.');
				names.add(name);
			} else {
				domain.warning("in toclassname, " + args[1] + " is not a class path because it does not end in .class");
			}
		}
		return Processor.join(names, ",");
	}

	/**
	 * toclassname ; <path>.class ( , <path>.class ) *
	 * 
	 * @param args
	 * @return
	 */

	static String	_toclasspathHelp	= "${toclasspath;<list>[;boolean]}, convert a list of class names to paths";

	public String _toclasspath(String args[]) {
		verifyCommand(args, _toclasspathHelp, null, 2, 3);
		boolean cl = true;
		if (args.length > 2)
			cl = Boolean.valueOf(args[2]);

		Collection<String> names = Processor.split(args[1]);
		Collection<String> paths = new ArrayList<String>(names.size());
		for (String name : names) {
			String path = name.replace('.', '/') + (cl ? ".class" : "");
			paths.add(path);
		}
		return Processor.join(paths, ",");
	}

	public String _dir(String args[]) {
		if (args.length < 2) {
			domain.warning("Need at least one file name for ${dir;...}");
			return null;
		}
		String del = "";
		StringBuilder sb = new StringBuilder();
		for (int i = 1; i < args.length; i++) {
			File f = domain.getFile(args[i]);
			if (f.exists() && f.getParentFile().exists()) {
				sb.append(del);
				sb.append(f.getParentFile().getAbsolutePath());
				del = ",";
			}
		}
		return sb.toString();

	}

	public String _basename(String args[]) {
		if (args.length < 2) {
			domain.warning("Need at least one file name for ${basename;...}");
			return null;
		}
		String del = "";
		StringBuilder sb = new StringBuilder();
		for (int i = 1; i < args.length; i++) {
			File f = domain.getFile(args[i]);
			if (f.exists() && f.getParentFile().exists()) {
				sb.append(del);
				sb.append(f.getName());
				del = ",";
			}
		}
		return sb.toString();

	}

	public String _isfile(String args[]) {
		if (args.length < 2) {
			domain.warning("Need at least one file name for ${isfile;...}");
			return null;
		}
		boolean isfile = true;
		for (int i = 1; i < args.length; i++) {
			File f = new File(args[i]).getAbsoluteFile();
			isfile &= f.isFile();
		}
		return isfile ? "true" : "false";

	}

	public String _isdir(String args[]) {
		if (args.length < 2) {
			domain.warning("Need at least one file name for ${isdir;...}");
			return null;
		}
		boolean isdir = true;
		for (int i = 1; i < args.length; i++) {
			File f = new File(args[i]).getAbsoluteFile();
			isdir &= f.isDirectory();
		}
		return isdir ? "true" : "false";

	}

	public String _tstamp(String args[]) {
		String format = "yyyyMMddHHmm";
		long now = System.currentTimeMillis();
		TimeZone tz = TimeZone.getTimeZone("UTC");

		if (args.length > 1) {
			format = args[1];
		}
		if (args.length > 2) {
			tz = TimeZone.getTimeZone(args[2]);
		}
		if (args.length > 3) {
			now = Long.parseLong(args[3]);
		}
		if (args.length > 4) {
			domain.warning("Too many arguments for tstamp: " + Arrays.toString(args));
		}

		SimpleDateFormat sdf = new SimpleDateFormat(format);
		sdf.setTimeZone(tz);

		return sdf.format(new Date(now));
	}

	/**
	 * Wildcard a directory. The lists can contain Instruction that are matched
	 * against the given directory ${lsr;<dir>;<list>(;<list>)*}
	 * ${lsa;<dir>;<list>(;<list>)*}
	 * 
	 * @author aqute
	 */

	public String _lsr(String args[]) {
		return ls(args, true);
	}

	public String _lsa(String args[]) {
		return ls(args, false);
	}

	String ls(String args[], boolean relative) {
		if (args.length < 2)
			throw new IllegalArgumentException("the ${ls} macro must at least have a directory as parameter");

		File dir = domain.getFile(args[1]);
		if (!dir.isAbsolute())
			throw new IllegalArgumentException("the ${ls} macro directory parameter is not absolute: " + dir);

		if (!dir.exists())
			throw new IllegalArgumentException("the ${ls} macro directory parameter does not exist: " + dir);

		if (!dir.isDirectory())
			throw new IllegalArgumentException(
					"the ${ls} macro directory parameter points to a file instead of a directory: " + dir);

		List<File> files = new ArrayList<File>(new SortedList<File>(dir.listFiles()));

		for (int i = 2; i < args.length; i++) {
			Instructions filters = new Instructions(args[i]);
			filters.select(files, true);
		}

		List<String> result = new ArrayList<String>();
		for (File file : files)
			result.add(relative ? file.getName() : file.getAbsolutePath());

		return Processor.join(result, ",");
	}

	public String _currenttime(@SuppressWarnings("unused") String args[]) {
		return Long.toString(System.currentTimeMillis());
	}

	/**
	 * Modify a version to set a version policy. Thed policy is a mask that is
	 * mapped to a version.
	 * 
	 * <pre>
	 * +           increment
	 * -           decrement
	 * =           maintain
	 * &tilde;           discard
	 * 
	 * ==+      = maintain major, minor, increment micro, discard qualifier
	 * &tilde;&tilde;&tilde;=     = just get the qualifier
	 * version=&quot;[${version;==;${@}},${version;=+;${@}})&quot;
	 * </pre>
	 * 
	 * @param args
	 * @return
	 */
	final static String		MASK_STRING			= "[\\-+=~0123456789]{0,3}[=~]?";
	final static Pattern	MASK				= Pattern.compile(MASK_STRING);
	final static String		_versionHelp		= "${version;<mask>;<version>}, modify a version\n"
														+ "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
														+ "M ::= '+' | '-' | MQ\n" + "MQ ::= '~' | '='";
	final static Pattern	_versionPattern[]	= new Pattern[] {
			null, null, MASK, Verifier.VERSION
												};

	public String _version(String args[]) {
		verifyCommand(args, _versionHelp, null, 2, 3);

		String mask = args[1];

		Version version = null;
		if (args.length >= 3)
			version = new Version(args[2]);

		return version(version, mask);
	}

	String version(Version version, String mask) {
		if (version == null) {
			String v = domain.getProperty("@");
			if (v == null) {
				domain.error(
						"No version specified for ${version} or ${range} and no implicit version ${@} either, mask=%s",
						mask);
				v = "0";
			}
			version = new Version(v);
		}

		StringBuilder sb = new StringBuilder();
		String del = "";

		for (int i = 0; i < mask.length(); i++) {
			char c = mask.charAt(i);
			String result = null;
			if (c != '~') {
				if (i == 3) {
					result = version.getQualifier();
				} else if (Character.isDigit(c)) {
					// Handle masks like +00, =+0
					result = String.valueOf(c);
				} else {
					int x = version.get(i);
					switch (c) {
						case '+' :
							x++;
							break;
						case '-' :
							x--;
							break;
						case '=' :
							break;
					}
					result = Integer.toString(x);
				}
				if (result != null) {
					sb.append(del);
					del = ".";
					sb.append(result);
				}
			}
		}
		return sb.toString();
	}

	/**
	 * Schortcut for version policy
	 * 
	 * <pre>
	 * -provide-policy : ${policy;[==,=+)}
	 * -consume-policy : ${policy;[==,+)}
	 * </pre>
	 * 
	 * @param args
	 * @return
	 */

	static Pattern	RANGE_MASK		= Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING + ")(\\]|\\))");
	static String	_rangeHelp		= "${range;<mask>[;<version>]}, range for version, if version not specified lookyp ${@}\n"
											+ "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
											+ "M ::= '+' | '-' | MQ\n"
											+ "MQ ::= '~' | '='";
	static Pattern	_rangePattern[]	= new Pattern[] {
			null, RANGE_MASK
									};

	public String _range(String args[]) {
		verifyCommand(args, _rangeHelp, _rangePattern, 2, 3);
		Version version = null;
		if (args.length >= 3)
			version = new Version(args[2]);
		else {
			String v = domain.getProperty("@");
			if (v == null)
				return null;
			version = new Version(v);
		}
		String spec = args[1];

		Matcher m = RANGE_MASK.matcher(spec);
		m.matches();
		String floor = m.group(1);
		String floorMask = m.group(2);
		String ceilingMask = m.group(3);
		String ceiling = m.group(4);

		String left = version(version, floorMask);
		String right = version(version, ceilingMask);
		StringBuilder sb = new StringBuilder();
		sb.append(floor);
		sb.append(left);
		sb.append(",");
		sb.append(right);
		sb.append(ceiling);

		String s = sb.toString();
		VersionRange vr = new VersionRange(s);
		if (!(vr.includes(vr.getHigh()) || vr.includes(vr.getLow()))) {
			domain.error("${range} macro created an invalid range %s from %s and mask %s", s, version, spec);
		}
		return sb.toString();
	}

	/**
	 * System command. Execute a command and insert the result.
	 * 
	 * @param args
	 * @param help
	 * @param patterns
	 * @param low
	 * @param high
	 */
	public String system_internal(boolean allowFail, String args[]) throws Exception {
		verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "system")
				+ ";<command>[;<in>]}, execute a system command", null, 2, 3);
		String command = args[1];
		String input = null;

		if (args.length > 2) {
			input = args[2];
		}

		Process process = Runtime.getRuntime().exec(command, null, domain.getBase());
		if (input != null) {
			process.getOutputStream().write(input.getBytes("UTF-8"));
		}
		process.getOutputStream().close();

		String s = IO.collect(process.getInputStream(), "UTF-8");
		int exitValue = process.waitFor();
		if (exitValue != 0)
			return exitValue + "";

		if (!allowFail && (exitValue != 0)) {
			domain.error("System command " + command + " failed with " + exitValue);
		}
		return s.trim();
	}

	public String _system(String args[]) throws Exception {
		return system_internal(false, args);
	}

	public String _system_allow_fail(String args[]) throws Exception {
		String result = "";
		try {
			result = system_internal(true, args);
		}
		catch (Throwable t) {
			/* ignore */
		}
		return result;
	}

	public String _env(String args[]) {
		verifyCommand(args, "${env;<name>}, get the environmet variable", null, 2, 2);

		try {
			return System.getenv(args[1]);
		}
		catch (Throwable t) {
			return null;
		}
	}

	/**
	 * Get the contents of a file.
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */

	public String _cat(String args[]) throws IOException {
		verifyCommand(args, "${cat;<in>}, get the content of a file", null, 2, 2);
		File f = domain.getFile(args[1]);
		if (f.isFile()) {
			return IO.collect(f);
		} else if (f.isDirectory()) {
			return Arrays.toString(f.list());
		} else {
			try {
				URL url = new URL(args[1]);
				return IO.collect(url, "UTF-8");
			}
			catch (MalformedURLException mfue) {
				// Ignore here
			}
			return null;
		}
	}

	public static void verifyCommand(String args[], @SuppressWarnings("unused") String help, Pattern[] patterns, int low, int high) {
		String message = "";
		if (args.length > high) {
			message = "too many arguments";
		} else if (args.length < low) {
			message = "too few arguments";
		} else {
			for (int i = 0; patterns != null && i < patterns.length && i < args.length; i++) {
				if (patterns[i] != null) {
					Matcher m = patterns[i].matcher(args[i]);
					if (!m.matches())
						message += String.format("Argument %s (%s) does not match %s%n", i, args[i],
								patterns[i].pattern());
				}
			}
		}
		if (message.length() != 0) {
			StringBuilder sb = new StringBuilder();
			String del = "${";
			for (String arg : args) {
				sb.append(del);
				sb.append(arg);
				del = ";";
			}
			sb.append("}, is not understood. ");
			sb.append(message);
			throw new IllegalArgumentException(sb.toString());
		}
	}

	// Helper class to track expansion of variables
	// on the stack.
	static class Link {
		Link		previous;
		String		key;
		Processor	start;

		public Link(Processor start, Link previous, String key) {
			this.previous = previous;
			this.key = key;
			this.start = start;
		}

		public boolean contains(String key) {
			if (this.key.equals(key))
				return true;

			if (previous == null)
				return false;

			return previous.contains(key);
		}

		public String toString() {
			StringBuilder sb = new StringBuilder();
			String del = "[";
			for (Link r = this; r != null; r = r.previous) {
				sb.append(del);
				sb.append(r.key);
				del = ",";
			}
			sb.append("]");
			return sb.toString();
		}
	}

	/**
	 * Take all the properties and translate them to actual values. This method
	 * takes the set properties and traverse them over all entries, including
	 * the default properties for that properties. The values no longer contain
	 * macros.
	 * 
	 * @return A new Properties with the flattened values
	 */
	public Properties getFlattenedProperties() {
		// Some macros only work in a lower processor, so we
		// do not report unknown macros while flattening
		flattening = true;
		try {
			Properties flattened = new Properties();
			Properties source = domain.getProperties();
			for (Enumeration< ? > e = source.propertyNames(); e.hasMoreElements();) {
				String key = (String) e.nextElement();
				if (!key.startsWith("_"))
					if (key.startsWith("-"))
						flattened.put(key, source.getProperty(key));
					else
						flattened.put(key, process(source.getProperty(key)));
			}
			return flattened;
		}
		finally {
			flattening = false;
		}
	}

	public final static String	_fileHelp	= "${file;<base>;<paths>...}, create correct OS dependent path";

	public String _osfile(String args[]) {
		verifyCommand(args, _fileHelp, null, 3, 3);
		File base = new File(args[1]);
		File f = Processor.getFile(base, args[2]);
		return f.getAbsolutePath();
	}

	public String _path(String args[]) {
		List<String> list = new ArrayList<String>();
		for (int i = 1; i < args.length; i++) {
			list.addAll(Processor.split(args[i]));
		}
		return Processor.join(list, File.pathSeparator);
	}

	public static Properties getParent(Properties p) {
		try {
			Field f = Properties.class.getDeclaredField("defaults");
			f.setAccessible(true);
			return (Properties) f.get(p);
		}
		catch (Exception e) {
			Field[] fields = Properties.class.getFields();
			System.err.println(Arrays.toString(fields));
			return null;
		}
	}

	public String process(String line) {
		return process(line, domain);
	}

}
