/*
 * Dumbster - a dummy SMTP server
 * Copyright 2004 Jason Paul Kitchen
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.dumbster.smtp;

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

/**
 * Container for a complete SMTP message - headers and message body.
 */
public class SmtpMessage {
	/**
	 * Headers: Map of List of String hashed on header name.
	 */
	private Map headers;
	/**
	 * Message body.
	 */
	private StringBuffer body;

	/**
	 * Constructor. Initializes headers Map and body buffer.
	 */
	public SmtpMessage() {
		headers = new HashMap(10);
		body = new StringBuffer();
	}

	/**
	 * Update the headers or body depending on the SmtpResponse object and line
	 * of input.
	 * 
	 * @param response
	 *            SmtpResponse object
	 * @param params
	 *            remainder of input line after SMTP command has been removed
	 */
	public void store(SmtpResponse response, String params) {
		if (params != null) {
			if (SmtpState.DATA_HDR.equals(response.getNextState())) {
				int headerNameEnd = params.indexOf(':');
				if (headerNameEnd >= 0) {
					String name = params.substring(0, headerNameEnd).trim();
					String value = params.substring(headerNameEnd + 1).trim();
					addHeader(name, value);
				}
			} else if (SmtpState.DATA_BODY == response.getNextState()) {
				body.append(params);
			}
		}
	}

	/**
	 * Get an Iterator over the header names.
	 * 
	 * @return an Iterator over the set of header names (String)
	 */
	public Iterator getHeaderNames() {
		Set nameSet = headers.keySet();
		return nameSet.iterator();
	}

	/**
	 * Get the value(s) associated with the given header name.
	 * 
	 * @param name
	 *            header name
	 * @return value(s) associated with the header name
	 */
	public String[] getHeaderValues(String name) {
		List values = (List) headers.get(name);
		if (values == null) {
			return new String[0];
		} else {
			return (String[]) values.toArray(new String[0]);
		}
	}

	/**
	 * Get the first values associated with a given header name.
	 * 
	 * @param name
	 *            header name
	 * @return first value associated with the header name
	 */
	public String getHeaderValue(String name) {
		List values = (List) headers.get(name);
		if (values == null) {
			return null;
		} else {
			Iterator iterator = values.iterator();
			return (String) iterator.next();
		}
	}

	/**
	 * Get the message body.
	 * 
	 * @return message body
	 */
	public String getBody() {
		return body.toString();
	}

	/**
	 * Adds a header to the Map.
	 * 
	 * @param name
	 *            header name
	 * @param value
	 *            header value
	 */
	private void addHeader(String name, String value) {
		List valueList = (List) headers.get(name);
		if (valueList == null) {
			valueList = new ArrayList(1);
			headers.put(name, valueList);
		}
		valueList.add(value);
	}

	/**
	 * String representation of the SmtpMessage.
	 * 
	 * @return a String
	 */
	public String toString() {
		StringBuffer msg = new StringBuffer();
		for (Iterator i = headers.keySet().iterator(); i.hasNext();) {
			String name = (String) i.next();
			List values = (List) headers.get(name);
			for (Iterator j = values.iterator(); j.hasNext();) {
				String value = (String) j.next();
				msg.append(name);
				msg.append(": ");
				msg.append(value);
				msg.append('\n');
			}
		}
		msg.append('\n');
		msg.append(body);
		msg.append('\n');
		return msg.toString();
	}
}

@@ -1019,16 +1019,38 @@
 vate Map
+%3CString, List%3CString%3E%3E
  headers
@@ -1233,16 +1233,38 @@
  HashMap
+%3CString, List%3CString%3E%3E
 (10);%0D%0A%09
@@ -2199,16 +2199,24 @@
 Iterator
+%3CString%3E
  getHead
@@ -2233,16 +2233,24 @@
 %7B%0D%0A%09%09Set
+%3CString%3E
  nameSet
@@ -2532,32 +2532,40 @@
  name) %7B%0D%0A%09%09List
+%3CString%3E
  values = (List)
@@ -2555,32 +2555,40 @@
 %3E values = (List
+%3CString%3E
 ) headers.get(na
@@ -2951,24 +2951,32 @@
 e) %7B%0D%0A%09%09List
+%3CString%3E
  values = (L
@@ -2970,32 +2970,40 @@
 %3E values = (List
+%3CString%3E
 ) headers.get(na
@@ -3073,16 +3073,24 @@
 Iterator
+%3CString%3E
  iterato
@@ -3490,24 +3490,32 @@
 e) %7B%0D%0A%09%09List
+%3CString%3E
  valueList =
@@ -3512,32 +3512,40 @@
 alueList = (List
+%3CString%3E
 ) headers.get(na
@@ -3606,16 +3606,24 @@
 rrayList
+%3CString%3E
 (1);%0D%0A%09%09
@@ -3863,16 +3863,24 @@
 Iterator
+%3CString%3E
  i = hea
@@ -3966,16 +3966,24 @@
 %0A%09%09%09List
+%3CString%3E
  values 
@@ -3989,16 +3989,24 @@
  = (List
+%3CString%3E
 ) header
@@ -4035,16 +4035,24 @@
 Iterator
+%3CString%3E
  j = val

put the types into the collections in SmtpMessage