// java.util.Properties -- an implementation of the Java Language Spec sec 21.6
// Written by Charles Briscoe-Smith; refer to the file LEGAL for details.

package java.util;

import java.io.PrintStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

class PropertiesEnumeration implements Enumeration {

	private Properties defs;
	private Enumeration defsenum;
	private Enumeration subenum;

	PropertiesEnumeration(Properties defaults, Enumeration enum)
	{
		defs=defaults;
		if (defaults!=null)
			defsenum=defaults.propertyNames();
		subenum=enum;
	}

	public boolean hasMoreElements()
	{
		return subenum.hasMoreElements()
		       || (defsenum!=null && defsenum.hasMoreElements());
	}

	public Object nextElement() throws NoSuchElementException
	{
		if (! subenum.hasMoreElements())
			if (defsenum!=null)
				return defsenum.nextElement();
			else
				throw new NoSuchElementException();
		String candidate=(String) subenum.nextElement();
		if (defs==null || defs.getProperty(candidate)==null)
			return candidate;
		return nextElement();
	}

}

public class Properties extends Hashtable {

	protected Properties defaults;

	public Properties()
	{
	}

	public Properties(Properties def)
	{
		defaults=def;
	}

	public String getProperty(String k)
	{
		getProperty(k, null);
	}

	public String getProperty(String k, String def)
	{
		String rv=(String) get(k);
		if (rv==null && defaults!=null)
			rv=defaults.getProperty(k, def);
		if (rv==null)
			rv=def;
		return rv;
	}

	public Enumeration propertyNames()
	{
		return new PropertiesEnumeration(defaults, keys());
	}

	public void load(InputStream in) throws IOException
	{
		throw new IOException("load() not yet implemented");
	}

	public void save(OutputStream baseout, String header)
	{
		PrintStream out=new PrintStream(
		                        Runtime.getRuntime()
		                        .getLocalizedOutputStream(baseout));
		if (header!=null)
			out.println("#"+header);
		out.println("#"+new Date());
		for (Enumeration e=keys(); e.hasMoreElements(); ) {
			String key=(String) e.nextElement();
			out.print(key);
			out.print('=');
			String val=(String) get(key);
			if (val.length()>0 && val.charAt(0)==' ')
				out.print('\\');
			for (int i=0; i<val.length(); i++) {
				char c=val.charAt(i);
				if (c=='\\') out.print("\\\\");
				else if (c=='\t') out.print("\\t");
				else if (c=='\n') out.print("\\n");
				else if (c=='\r') out.print("\\r");
				else if (c<0x20 || c>0x7e) {
					String digits="0123456789abcdef";
					out.print("\\u");
					out.print(digits.charAt((c>>12)&0xf));
					out.print(digits.charAt((c>>8)&0xf));
					out.print(digits.charAt((c>>4)&0xf));
					out.print(digits.charAt((c)&0xf));
				} else
					out.print(c);
			}
			out.println();
		}
	}

	public void list(PrintStream out)
	{
		out.println("#"+new Date());
		for (Enumeration e=keys(); e.hasMoreElements(); ) {
			String key=(String) e.nextElement();
			out.print(key);
			out.print('=');
			String val=(String) get(key);
			if (val.length()>40) {
				out.print(val.substring(0, 37));
				out.println("...");
			} else {
				out.println(val);
			}
		}
	}

}
