package relational.email;

import relational.*;
import java.lang.reflect.Field;
import java.rmi.RemoteException;

/**
 * Part of the email database schema. A Header is a single header from
 * a message. Headers with multi-line values are collapsed into a
 * single Header row, so that their value can be easily retrieved.
 * Headers have an order field that specify the order the headers
 * appeared in the received message.<p>
 * 
 * <em>Synthetic</em> headers are properties added to a message after
 * receipt.
 */
public class Header
	extends ClumpRelational {
	
	/**
	 * The name of the header; the part before the colon.
	 */
	public String name;

	/**
	 * Any whitespace that got removed between the colon and the value.
	 * Storing this junk lets us reconstruct the original message precisely.
	 */
	public String whitespace;

	/**
	 * The value of the header. When the header is a multi-line header,
	 * this field contains carriage return characters.
	 */
	public String value;

	/**
	 * This field is used to reassemble headers in the order they
	 * appeared in the message when it arrived. 
	 */
	public int order;

	/**
	 * indicates a synthetic header that didn't really appear in the
	 * message, but we're encoding some private (and immutable) data in
	 * it.
	 */
	public boolean synthetic;

	/**
	 * Reference to the {@link Message} of which this header is part.
	 * @todo has to be public for introspection. darn it.
	 */
	public Object msg_fk;

	transient protected Message msgCached;
	/**
	 * Retrieve the Message to which this header belongs.
	 */
	public Message getMsg() {
		if (msgCached==null) {
			msgCached = (Message) resolveForeignKey(Message.class, msg_fk);
		}
		return msgCached;
	}

	/**
	 * Attach this header to a given message.
	 */
	public void setMsg(Message m) {
		msg_fk = m.primaryKey;
		msgCached = m;
	}

//	public static Header newRow(Database d)
//		throws RemoteException {
//		return (Header) d.newRow(Header.class);
//	}
	/**
	 * Create a header in a given Database.
	 */
	public Header(Database db) { super(db); }
		// because I belong to ClumpRelational

	public static FieldDescriptor f_reference;
	public static FieldDescriptor f_primaryKey;
	public static FieldDescriptor f_name;
	public static FieldDescriptor f_whitespace;
	public static FieldDescriptor f_value;
	public static FieldDescriptor f_order;
	public static FieldDescriptor f_msg;
	public static FieldDescriptor f_synthetic;
	static {
		try {
			f_reference = FieldDescriptor.get(Header.class);
			f_primaryKey= FieldDescriptor.getPrimaryKey(Header.class);
			f_name		= FieldDescriptor.get(Header.class.getField("name"));
			f_whitespace= FieldDescriptor.get(Header.class.getField("whitespace"));
			f_value		= FieldDescriptor.get(Header.class.getField("value"));
			f_order		= FieldDescriptor.get(Header.class.getField("order"));
			f_msg		= FieldDescriptor.get(Header.class.getField("msg_fk"));
			f_synthetic	= FieldDescriptor.get(Header.class.getField("synthetic"));
		} catch (NoSuchFieldException ex) {
			// Boy would that be weird. It's really too bad
			// that there aren't static reflection constructs
			// (there is Classname.class, after all.)
		}
	}
}
