/**
 * 
 */
package com.ampiere.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.logging.Level;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.lang.StringUtils;
import org.apache.ecs.AlignType;
import org.apache.ecs.xhtml.a;
import org.apache.ecs.xhtml.body;
import org.apache.ecs.xhtml.br;
import org.apache.ecs.xhtml.button;
import org.apache.ecs.xhtml.hr;
import org.apache.ecs.xhtml.input;
import org.apache.ecs.xhtml.label;
import org.apache.ecs.xhtml.option;
import org.apache.ecs.xhtml.p;
import org.apache.ecs.xhtml.script;
import org.apache.ecs.xhtml.small;
import org.apache.ecs.xhtml.td;
import org.apache.ecs.xhtml.tr;
import org.compiere.model.GridField;
import org.compiere.model.MAttachment;
import org.compiere.model.MAttachmentEntry;
import org.compiere.util.CLogger;
import org.compiere.util.Ctx;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.HtmlCode;
import org.compiere.util.Language;
import org.compiere.util.MimeType;
import org.compiere.util.Msg;
import org.compiere.util.NamePair;
import org.compiere.util.Util;
import org.compiere.util.WebDoc;
import org.compiere.util.WebEnv;
import org.compiere.util.WebSessionCtx;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.ampiere.web.servlet.WWindowStatus;
import com.ampiere.web.servlet.WebField;
import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory;

/**
 *  Servlet Utilities
 *　 Ampiere Web Utils
 *  @author Jorg Janke
 *  @version  $Id: AWebUtil.java,v 1.1 2010/01/13 11:52:06 clmg Exp $
 */
public final class AWebUtil
{
	/**	Static Logger	*/
	private static CLogger		log	= CLogger.getCLogger (AWebUtil.class);

	/**
	 *  Create Timeout Message
	 *
	 *  @param request request
	 *  @param response response
	 *  @param servlet servlet
	 *  @param message - optional message
	 *  @throws ServletException
	 *  @throws IOException
	 */
	public static void createTimeoutPage (HttpServletRequest request, HttpServletResponse response,
			HttpServlet servlet, String message) throws ServletException, IOException
			{
		log.info(message);
		WebSessionCtx wsc = WebSessionCtx.get(request);
		String windowTitle = "Timeout";
		if (wsc != null)
			windowTitle = Msg.getMsg(wsc.ctx, "Timeout");

		WebDoc doc = WebDoc.create (windowTitle);

		//	Body
		body body = doc.getBody();
		//  optional message
		if (message != null && message.length() > 0)
			body.addElement(new p(message, AlignType.CENTER));

		//  login button
		body.addElement(getLoginButton(wsc == null ? null : wsc.ctx));

		//
		body.addElement(new hr());
		body.addElement(new small(servlet.getClass().getName()));
		//	fini
		createResponse (request, response, servlet, null, doc, false);
			}   //  createTimeoutPage

	/**
	 *  Create Error Message
	 *
	 *  @param request request
	 *  @param response response
	 *  @param servlet servlet
	 *  @param message message
	 *  @throws ServletException
	 *  @throws IOException
	 */
	public static void createErrorPage (HttpServletRequest request, HttpServletResponse response,
			HttpServlet servlet, String message) 
	throws ServletException, IOException
	{
		log.info( message);
		WebSessionCtx wsc = WebSessionCtx.get(request);
		String windowTitle = "Error";
		if (wsc != null)
			windowTitle = Msg.getMsg(wsc.ctx, "Error");
		if (message != null)
			windowTitle += ": " + message;

		WebDoc doc = WebDoc.create (windowTitle);

		//	Body
		body b = doc.getBody();

		b.addElement(new p(servlet.getServletName(), AlignType.CENTER));
		b.addElement(new br());

		//	fini
		createResponse (request, response, servlet, null, doc, true);
	}   //  createErrorPage

	/**
	 *  Create Exit Page "Log-off".
	 *  <p>
	 *  - End Session
	 *  - Go to start page (e.g. /compiere/index.html)
	 *
	 *  @param request request
	 *  @param response response
	 *  @param servlet servlet
	 *  @param ctx context
	 *  @param AD_Message messahe
	 *  @throws ServletException
	 *  @throws IOException
	 */
	public static void createLoginPage (HttpServletRequest request, HttpServletResponse response,
			HttpServlet servlet, Ctx ctx, String AD_Message) throws ServletException, IOException
			{
		request.getSession().invalidate();
		String url = WebEnv.getBaseDirectory("index.html");
		//
		WebDoc doc = null;
		if (ctx != null && AD_Message != null && !AD_Message.equals(""))
			doc = WebDoc.create (Msg.getMsg(ctx, AD_Message));
		else if (AD_Message != null)
			doc = WebDoc.create (AD_Message);
		else
			doc = WebDoc.create (false);
		script script = new script("window.top.location.replace('" + url + "');");
		doc.getBody().addElement(script);
		//
		createResponse (request, response, servlet, null, doc, false);
			}   //  createLoginPage

	/**
	 *  Create Login Button - replace Window
	 *
	 *  @param ctx context
	 *  @return Button
	 */
	public static button getLoginButton (Ctx ctx)
	{
		String text = "Login";
		if (ctx != null)
			text = Msg.getMsg (ctx, "Login");
		button button = new button();
		button.setType("button").setName("Login").addElement(text);
		StringBuffer cmd = new StringBuffer ("window.top.location.replace('");
		cmd.append(WebEnv.getBaseDirectory("index.html"));
		cmd.append("');");
		button.setOnClick(cmd.toString());
		return button;
	}   //  getLoginButton


	/**************************************************************************
	 *  Get Cookie Properties
	 *
	 *  @param request request
	 *  @return Properties
	 */
	public static Properties getCookieProprties(HttpServletRequest request)
	{
		//  Get Properties
		Cookie[] cookies = request.getCookies();
		if (cookies != null)
		{
			for (int i = 0; i < cookies.length; i++)
			{
				if (cookies[i].getName().equals(WebEnv.COOKIE_INFO))
					return propertiesDecode(cookies[i].getValue());
			}
		}
		return new Properties();
	}   //  getProperties


	/**
	 *  Get String Parameter.
	 *
	 *  @param request request
	 *  @param parameter parameter
	 *  @return string or null
	 */
	public static String getParameter (HttpServletRequest request, String parameter)
	{
		if (request == null || parameter == null)
			return null;
		String enc = request.getCharacterEncoding();
		try
		{
			if (enc == null)
			{
				request.setCharacterEncoding(WebEnv.ENCODING);
				enc = request.getCharacterEncoding();
			}
		}
		catch (Exception e)
		{
			log.log(Level.SEVERE, "Set CharacterEncoding=" + WebEnv.ENCODING, e);
			enc = request.getCharacterEncoding();
		}
		String data = request.getParameter(parameter);
		if (data == null || data.length() == 0)
			return data;

		//	Convert
		if (enc != null && !WebEnv.ENCODING.equals(enc))
		{
			try
			{
				String dataEnc = new String(data.getBytes(enc), WebEnv.ENCODING);
				log.log(Level.FINER, "Convert " + data + " (" + enc + ")-> " 
						+ dataEnc + " (" + WebEnv.ENCODING + ")");
				data = dataEnc;
			}
			catch (Exception e)
			{
				log.log(Level.SEVERE, "Convert " + data + " (" + enc + ")->" + WebEnv.ENCODING);
			}
		}

		//	Convert &#000; to character (JSTL input)
		String inStr = data;
		StringBuffer outStr = new StringBuffer();
		int i = inStr.indexOf("&#");
		while (i != -1)
		{
			outStr.append(inStr.substring(0, i));			// up to &#
			inStr = inStr.substring(i+2, inStr.length());	// from &#

			int j = inStr.indexOf(";");						// next ;
			if (j < 0)										// no second tag
			{
				inStr = "&#" + inStr;
				break;
			}

			String token = inStr.substring(0, j);
			try
			{
				int intToken = Integer.parseInt(token);
				outStr.append((char)intToken);				// replace context
			}
			catch (Exception e)
			{
				log.log(Level.SEVERE, "Token=" + token, e);
				outStr.append("&#").append(token).append(";");
			}
			inStr = inStr.substring(j+1, inStr.length());	// from ;
			i = inStr.indexOf("&#");
		}

		outStr.append(inStr);           					//	add remainder
		String retValue = outStr.toString();
		/**
		StringBuffer debug = new StringBuffer();
		char[] cc = data.toCharArray();
		for (int j = 0; j < cc.length; j++)
		{
			debug.append(cc[j]);
			int iii = (int)cc[j];
			debug.append("[").append(iii).append("]");
		}
		log.finest(parameter + "=" + data + " -> " + retValue + " == " + debug);
		 **/
		log.finest(parameter + "=" + data + " -> " + retValue);
		return retValue;
	}   //  getParameter

	/**
	 *  Get integer Parameter - 0 if not defined.
	 *
	 *  @param request request
	 *  @param parameter parameter
	 *  @return int result or 0
	 */
	public static int getParameterAsInt (HttpServletRequest request, String parameter)
	{
		if (request == null || parameter == null)
			return 0;
		String data = getParameter(request, parameter);
		if (data == null || data.length() == 0)
			return 0;
		try
		{
			return Integer.parseInt(data);
		}
		catch (Exception e)
		{
			log.warning (parameter + "=" + data + " - " + e);
		}
		return 0;
	}   //  getParameterAsInt

	/**
	 *  Get numeric Parameter - 0 if not defined
	 *
	 *  @param request request
	 *  @param parameter parameter
	 *  @return big decimal result or 0
	 */
	public static BigDecimal getParameterAsBD (HttpServletRequest request, String parameter)
	{
		if (request == null || parameter == null)
			return Env.ZERO;
		String data = getParameter(request, parameter);
		if (data == null || data.length() == 0)
			return Env.ZERO;
		try
		{
			return new BigDecimal (data);
		}
		catch (Exception e)
		{
		}
		try
		{
			DecimalFormat format = DisplayType.getNumberFormat(DisplayType.Number);
			Object oo = format.parseObject(data);
			if (oo instanceof BigDecimal)
				return (BigDecimal)oo;
			else if (oo instanceof Number)
				return new BigDecimal (((Number)oo).doubleValue());
			return new BigDecimal (oo.toString());
		}
		catch (Exception e)
		{
			log.fine(parameter + "=" + data + " - " + e);
		}
		return Env.ZERO;
	}   //  getParameterAsBD

	/**
	 *  Get date Parameter - null if not defined.
	 *	Date portion only
	 *  @param request request
	 *  @param parameter parameter
	 *  @return timestamp result or null
	 */
	public static Timestamp getParameterAsDate (HttpServletRequest request, 
			String parameter)
	{
		return getParameterAsDate (request, parameter, null);
	}	//	getParameterAsDate

	/**
	 *  Get date Parameter - null if not defined.
	 *	Date portion only
	 *  @param request request
	 *  @param parameter parameter
	 *  @param language optional language
	 *  @return timestamp result or null
	 */
	public static Timestamp getParameterAsDate (HttpServletRequest request, 
			String parameter, Language language)
	{
		if (request == null || parameter == null)
			return null;
		String data = getParameter(request, parameter);
		if (data == null || data.length() == 0)
			return null;

		//	Language Date Format
		if (language != null)
		{
			try
			{
				DateFormat format = DisplayType.getDateFormat(DisplayType.Date, language);
				java.util.Date date = format.parse(data);
				if (date != null)
					return new Timestamp (date.getTime());
			}
			catch (Exception e)
			{
			}
		}

		//	Default Simple Date Format
		try
		{
			SimpleDateFormat format = DisplayType.getDateFormat(DisplayType.Date);
			java.util.Date date = format.parse(data);
			if (date != null)
				return new Timestamp (date.getTime());
		}
		catch (Exception e)
		{
		}

		//	JDBC Format
		try 
		{
			return Timestamp.valueOf(data);
		}
		catch (Exception e) 
		{
		}

		log.warning(parameter + " - cannot parse: " + data);
		return null;
	}   //  getParameterAsDate

	/**
	 *  Get boolean Parameter.
	 *  @param request request
	 *  @param parameter parameter
	 *  @return true if found
	 */
	public static boolean getParameterAsBoolean (HttpServletRequest request, 
			String parameter)
	{
		return getParameterAsBoolean(request, parameter, null);
	}	//	getParameterAsBoolean

	/**
	 *  Get boolean Parameter.
	 *  @param request request
	 *  @param parameter parameter
	 *  @param expected optional expected value
	 *  @return true if found and if optional value matches
	 */
	public static boolean getParameterAsBoolean (HttpServletRequest request, 
			String parameter, String expected)
	{
		if (request == null || parameter == null)
			return false;
		String data = getParameter(request, parameter);
		if (data == null || data.length() == 0)
			return false;
		//	Ignore actual value
		if (expected == null)
			return true;
		//
		return expected.equalsIgnoreCase(data);
	}   //  getParameterAsBoolean


	/**************************************************************************
	 *  Create Standard Response Header with optional Cookie and print document.
	 *  D:\j2sdk1.4.0\docs\guide\intl\encoding.doc.html
	 *
	 *  @param request request
	 *  @param response response
	 *  @param servlet servlet
	 *  @param cookieProperties cookie properties
	 *  @param doc doc
	 *  @param debug debug
	 *  @throws IOException
	 */
	public static void createResponse (HttpServletRequest request, HttpServletResponse response,
			HttpServlet servlet, Properties cookieProperties, WebDoc doc, boolean debug) throws IOException
			{
		response.setHeader("Cache-Control", "no-cache");
		response.setContentType("text/html; charset=UTF-8");

		//
		//  Update Cookie - overwrite
		if (cookieProperties != null)
		{
			Cookie cookie = new Cookie (WebEnv.COOKIE_INFO, propertiesEncode(cookieProperties));
			cookie.setComment("(c) ComPiere, Inc - Jorg Janke");
			cookie.setSecure(false);
			cookie.setPath("/");
			if (cookieProperties.size() == 0)
				cookie.setMaxAge(0);            //  delete cookie
			else
				cookie.setMaxAge(2592000);      //  30 days in seconds   60*60*24*30
			response.addCookie(cookie);
		}
		//  add diagnostics
		if (debug && WebEnv.DEBUG)
		{
			//	doc.output(System.out);
			WebEnv.addFooter(request, response, servlet, doc.getBody());
			//	doc.output(System.out);
		}
		//	String content = doc.toString();
		//  response.setContentLength(content.length());    //  causes problems at the end of the output

		//  print document
		PrintWriter out = response.getWriter();     //  with character encoding support
		doc.output(out);
		out.flush();
		if (out.checkError())
			log.log(Level.SEVERE, "error writing");
		//  binary output (is faster but does not do character set conversion)
		//	OutputStream out = response.getOutputStream();
		//	byte[] data = doc.toString().getBytes();
		//	response.setContentLength(data.length);
		//	out.write(doc.toString().getBytes());
		//
		out.close();
			}   //  createResponse


	/**************************************************************************
	 *  Create Java Script to clear Target frame
	 *
	 *  @param targetFrame target frame
	 *  @return Clear Frame Script
	 */
	public static script getClearFrame (String targetFrame)
	{
		StringBuffer cmd = new StringBuffer();
		cmd.append("<!-- clear frame\n")
		.append("var d = parent.").append(targetFrame).append(".document;\n")
		.append("d.open();\n")
//		.append("d.write('<link href=\"").append(WebEnv.getStylesheetURL()).append("\" rel=\"stylesheet\">');\n") //clmg 2009/02/10
		.append("d.close();\n")
		.append("// -- clear frame -->");
		//
		return new script(cmd.toString());
	}   //  getClearFrame


	/**
	 * 	Return a link and script with new location.
	 * 	@param url forward url
	 * 	@param delaySec delay in seconds (default 3)
	 * 	@return html
	 */
	public static HtmlCode getForward (String url, int delaySec)
	{
		if (delaySec <= 0)
			delaySec = 3;
		HtmlCode retValue = new HtmlCode();
		//	Link
		a a = new a(url);
		a.addElement(url);
		retValue.addElement(a);
		//	Java Script	- document.location - 
		script script = new script("setTimeout(\"window.top.location.replace('" + url 
				+ "')\"," + (delaySec+1000) + ");");
		retValue.addElement(script);
		//
		return retValue;
	}	//	getForward

	/**
	 * 	Create Forward Page
	 * 	@param response response
	 * 	@param title page title
	 * 	@param forwardURL url
	 * 	@param delaySec delay in seconds (default 3)
	 * 	@throws ServletException
	 * 	@throws IOException
	 */
	public static void createForwardPage (HttpServletResponse response,
			String title, String forwardURL, int delaySec) throws ServletException, IOException
			{
		response.setContentType("text/html; charset=UTF-8");
		WebDoc doc = WebDoc.create(title);
		body b = doc.getBody();
		b.addElement(getForward(forwardURL, delaySec));
		PrintWriter out = response.getWriter();
		doc.output(out);
		out.flush();
		if (out.checkError())
			log.log(Level.SEVERE, "Error writing");
		out.close();
		log.fine(forwardURL + " - " + title);
			}	//	createForwardPage


	/**
	 * 	Does Test exist
	 *	@param test string
	 *	@return true if String with data
	 */
	public static boolean exists (String test)
	{
		if (test == null)
			return false;
		return test.length() > 0;
	}	//	exists

	/**
	 * 	Does Parameter exist
	 * 	@param request request
	 *	@param parameter string
	 *	@return true if String with data
	 */
	public static boolean exists (HttpServletRequest request, String parameter)
	{
		if (request == null || parameter == null)
			return false;
		try
		{
			String enc = request.getCharacterEncoding();
			if (enc == null)
				request.setCharacterEncoding(WebEnv.ENCODING);
		}
		catch (Exception e)
		{
			log.log(Level.SEVERE, "Set CharacterEncoding=" + WebEnv.ENCODING, e);
		}
		return exists (request.getParameter(parameter));
	}	//	exists


	/**
	 *	Is EMail address valid
	 * 	@param email mail address
	 * 	@return true if valid
	 */
	public static boolean isEmailValid (String email)
	{
		if (email == null || email.length () == 0)
			return false;
		try
		{
			InternetAddress ia = new InternetAddress (email, true);

			ia.getType();

			return true;
		}
		catch (AddressException ex)
		{
			log.warning (email + " - "
					+ ex.getLocalizedMessage ());
		}
		return false;
	}	//	isEmailValid


	/**************************************************************************
	 *  Decode Properties into String (URL encoded)
	 *
	 *  @param pp properties
	 *  @return Encoded String
	 */
	public static String propertiesEncode (Properties pp)
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try
		{
			pp.store(bos, "Compiere");   //  Header
		}
		catch (IOException e)
		{
			log.log(Level.SEVERE, "store", e);
		}
		String result = new String (bos.toByteArray());
		//	System.out.println("String=" + result);
		try
		{
			result = URLEncoder.encode(result, WebEnv.ENCODING);
		}
		catch (UnsupportedEncodingException e)
		{
			log.log(Level.SEVERE, "encode" + WebEnv.ENCODING, e);
			String enc = System.getProperty("file.encoding");      //  Windows default is Cp1252
			try
			{
				result = URLEncoder.encode(result, enc);
				log.info("encode: " + enc);
			}
			catch (Exception ex)
			{
				log.log(Level.SEVERE, "encode", ex);
			}
		}
		//	System.out.println("String-Encoded=" + result);
		return result;
	}   //  propertiesEncode

	/**
	 *  Decode data String (URL encoded) into Properties
	 *
	 *  @param data data
	 *  @return Properties
	 */
	public static Properties propertiesDecode (String data)
	{
		String result = null;
		//	System.out.println("String=" + data);
		try
		{
			result = URLDecoder.decode(data, WebEnv.ENCODING);
		}
		catch (UnsupportedEncodingException e)
		{
			log.log(Level.SEVERE, "decode" + WebEnv.ENCODING, e);
			String enc = System.getProperty("file.encoding");      //  Windows default is Cp1252
			try
			{
				result = URLEncoder.encode(data, enc);
				log.log(Level.SEVERE, "decode: " + enc);
			}
			catch (Exception ex)
			{
				log.log(Level.SEVERE, "decode", ex);
			}
		}
		//	System.out.println("String-Decoded=" + result);

		ByteArrayInputStream bis = new ByteArrayInputStream(result.getBytes());
		Properties pp = new Properties();
		try
		{
			pp.load(bis);
		}
		catch (IOException e)
		{
			log.log(Level.SEVERE, "load", e);
		}
		return pp;
	}   //  propertiesDecode


	/**************************************************************************
	 *  Convert Array of NamePair to HTTP Option Array.
	 *  <p>
	 *  If the ArrayList does not contain NamePairs, the String value is used
	 *  @see org.compiere.util.NamePair
	 *  @param  list    ArrayList containing NamePair values
	 *  @param  default_ID  Sets the default if the key/ID value is found.
	 *      If the value is null or empty, the first value is selected
	 *  @return Option Array
	 */
	public static option[] convertToOption (NamePair[] list, String default_ID)
	{
		int size = list.length;
		option[] retValue = new option[size];
		for (int i = 0; i < size; i++)
		{
			boolean selected = false;
			//  select first entry
			if (i == 0 && (default_ID == null || default_ID.length() == 0))
				selected = true;

			//  Create option
			String name = Util.maskHTML(list[i].getName());
			retValue[i] = new option(list[i].getID()).addElement(name);

			//  Select if ID/Key is same as default ID
			if (default_ID != null && default_ID.equals(list[i].getID()))
				selected = true;
			retValue[i].setSelected(selected);
		}
		return retValue;
	}   //  convertToOption


	/**
	 *  Create label/field table row
	 *
	 *  @param line - null for new line (table row)
	 *  @param FORMNAME form name
	 *  @param PARAMETER parameter name
	 *  @param labelText label
	 *  @param inputType HTML input type
	 *  @param value data value
	 *  @param sizeDisplay display size
	 *  @param size data size
	 *  @param longField field spanning two columns
	 *  @param mandatory mark as mandatory
	 *  @param onChange onChange call
	 *  @param script script
	 *  @return tr table row
	 */
	static public tr createField (tr line, String FORMNAME, String PARAMETER,
			String labelText, String inputType, Object value,
			int sizeDisplay, int size, boolean longField, 
			boolean mandatory, String onChange, StringBuffer script)
	{
		if (line == null)
			line = new tr();
		String labelInfo = labelText;
		if (mandatory)
		{
			labelInfo += "&nbsp;<font color=\"red\">*</font>";
			String fName = "document." + FORMNAME + "." + PARAMETER;
			script.append(fName).append(".required=true; ");
		}

		label llabel = new label().setFor(PARAMETER).addElement(labelInfo);
		llabel.setID("ID_" + PARAMETER + "_Label");
		//	label.setTitle(description);
		line.addElement(new td().addElement(llabel).setAlign(AlignType.RIGHT));
		input iinput = new input(inputType, PARAMETER, value == null ? "" : value.toString());
		iinput.setSize(sizeDisplay).setMaxlength(size);
		iinput.setID("ID_" + PARAMETER);
		if (onChange != null && onChange.length() > 0)
			iinput.setOnChange(onChange);
		iinput.setTitle(labelText);
		td field = new td().addElement(iinput).setAlign(AlignType.LEFT);
		if (longField)
			field.setColSpan(3);
		line.addElement(field);
		return line;
	}   //  addField

	/**
	 * 	Get Close PopUp Buton
	 *	@return button
	 */
	public static input createClosePopupButton()
	{
		input close = new input (input.TYPE_BUTTON, "closePopup", "Close");
		close.setTitle ("Close PopUp");	//	Help
		close.setOnClick ("closePopup();return false;");
		return close;
	}	//	getClosePopupButton


	/**
	 * 	Stream Attachment Entry
	 *	@param response response
	 *	@param attachment attachment
	 *	@param attachmentIndex logical index
	 *	@return error message or null
	 */
	public static String streamAttachment (HttpServletResponse response, 
			MAttachment attachment, int attachmentIndex)
	{
		if (attachment == null)
			return "No Attachment";

		int realIndex = -1;
		MAttachmentEntry[] entries = attachment.getEntries();
		for (int i = 0; i < entries.length; i++)
		{
			MAttachmentEntry entry = entries[i];
			if (entry.getIndex() == attachmentIndex)
			{
				realIndex = i;
				break;
			}
		}
		if (realIndex < 0)
		{
			log.fine("No Attachment Entry for Index=" 
					+ attachmentIndex + " - " + attachment);
			return "Attachment Entry not found";
		}

		MAttachmentEntry entry = entries[realIndex];
		if (entry.getData() == null)
		{
			log.fine("Empty Attachment Entry for Index=" 
					+ attachmentIndex + " - " + attachment);
			return "Attachment Entry empty";
		}

		//	Stream Attachment Entry
		try
		{
			int bufferSize = 2048; //	2k Buffer
			int fileLength = entry.getData().length;
			//
			response.setContentType(entry.getContentType());
			response.setBufferSize(bufferSize);
			response.setContentLength(fileLength);
			//
			log.fine(entry.toString());
			long time = System.currentTimeMillis();		//	timer start
			//
			ServletOutputStream out = response.getOutputStream ();
			out.write (entry.getData());
			out.flush();
			out.close();
			//
			time = System.currentTimeMillis() - time;
			double speed = (fileLength/1024) / ((double)time/1000);
			log.info("Length=" 
					+ fileLength + " - " 
					+ time + " ms - " 
					+ speed + " kB/sec - " + entry.getContentType());
		}
		catch (IOException ex)
		{
			log.log(Level.SEVERE, ex.toString());
			return "Streaming error - " + ex;
		}
		return null;
	}	//	streamAttachment


	/**
	 * 	Stream File
	 *	@param response response
	 *	@param file file to stream
	 *	@return error message or null
	 */
	public static String streamFile (HttpServletResponse response, File file)
	{
		if (file == null)
			return "No File";
		if (!file.exists())
			return "File not found: " + file.getAbsolutePath();

		MimeType mimeType = MimeType.get(file.getAbsolutePath());
		//	Stream File
		try
		{
			int bufferSize = 2048; //	2k Buffer
			int fileLength = (int)file.length();
			//
			response.setContentType(mimeType.getMimeType());
			response.setBufferSize(bufferSize);
			response.setContentLength(fileLength);
			//
			log.fine(file.toString());
			long time = System.currentTimeMillis();		//	timer start
			//	Get Data
			FileInputStream in = new FileInputStream(file);
			ServletOutputStream out = response.getOutputStream ();
			int c = 0;
			while ((c = in.read()) != -1)
				out.write(c);
			//
			out.flush();
			out.close();
			in.close();
			//
			time = System.currentTimeMillis() - time;
			double speed = (fileLength/1024) / ((double)time/1000);
			log.info("Length=" 
					+ fileLength + " - " 
					+ time + " ms - " 
					+ speed + " kB/sec - " + mimeType);
		}
		catch (IOException ex)
		{
			log.log(Level.SEVERE, ex.toString());
			return "Streaming error - " + ex;
		}
		return null;
	}	//	streamFile

	/**
	 * Response to callout , using Ajax
	 * @param response
	 * @throws IOException
	 */
	public static void createCalloutAjaxResponse (HttpServletResponse response, Document document) throws IOException
	{

		response.setContentType("text/xml; charset=UTF-8");
		response.addHeader("pragma", "no-store,no-cache");//HTTP 1.0
		response.addHeader("cache-control", "no-cache, no-store,must-revalidate, max-age=-1"); // HTTP 1.1
		response.addHeader("expires", "-1");

		PrintWriter out = null;
		out = response.getWriter();
		try {
			
//			System.out.println(System.getProperty("javax.xml.transform.TransformerFactory")); 
//			System.out.println(System.getProperty("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"));
//			System.out.println(System.setProperty(
//					"javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl")); 
			
			System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
			TransformerFactory tfactory = TransformerFactory.newInstance();
			Transformer transformer = tfactory.newTransformer();

			// インデントを行う
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			// インデントの文字数
			transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT,
			"2");

			transformer.transform(new DOMSource(document), new StreamResult(out));

			//for test, to insure the output xml is right
			    		File outfile = new File("H:/test.xml");
			    		transformer.transform(new DOMSource(document), new StreamResult(outfile)); 

		} catch(Exception e)
		{
			System.out.println("error---- createCalloutAjaxResponse");;
		}

	}   //  createResponse	

	/**
	 * displayTypeによって、objのhtmlで表示するためのstring型を獲得
	 * 例えば、date型の場合は、htmlで表示するとき今のルールを守らないといけません。
	 * @param obj
	 * @param m_wsc
	 * @param displayType
	 * @return
	 */
	public static String toString(Object obj, WebSessionCtx	m_wsc, int displayType, String columnName, GridField field){
		String ret_str = "";
		if(obj!=null){
			if(DisplayType.Date == displayType){
				ret_str = m_wsc.dateFormat.format(obj);
			}else if(DisplayType.DateTime == displayType){
				ret_str = m_wsc.dateTimeFormat.format(obj);
			}else if(DisplayType.Button == displayType){
				ret_str = getButtonValue(m_wsc, columnName, (String)obj, field);
			}
			else{
				ret_str = obj.toString();
			}
		}
		
		return ret_str;

	}
	
	public static String getButtonValue (WebSessionCtx	m_wsc, String columnName, String data, GridField field)
	{
        String header = "";         
        //  Special Buttons
        if (columnName.equals("PaymentRule")) {
            // readReference(195);
            header = readReferenceName(m_wsc, 195, data);
        } else if (columnName.equals("DocAction")) {
            // readReference(135);
            header = readReferenceName(m_wsc, 135, data);
        } else if (columnName.equals("Posted")) {
            // readReference(234);
            header = readReferenceName(m_wsc, 234, data);
        } else{
        	header = field.getHeader();
        }
        
        return header;
	}
	public static String readReferenceName(WebSessionCtx m_wsc, int AD_Reference_ID, String value)
    {
        String name = value;
        String SQL;
        if (Env.isBaseLanguage(m_wsc.ctx, "AD_Ref_List"))
            SQL = "SELECT Name FROM AD_Ref_List WHERE AD_Reference_ID=? AND VALUE=?";
        else
            SQL = "SELECT t.Name FROM AD_Ref_List l, AD_Ref_List_Trl t "
                + "WHERE l.AD_Ref_List_ID=t.AD_Ref_List_ID"
                + " AND t.AD_Language='" + Env.getAD_Language(m_wsc.ctx) + "'"
                + " AND l.AD_Reference_ID=?"
                + " AND l.VALUE=?";
        try
        {
            PreparedStatement pstmt = DB.prepareStatement(SQL, null);
            pstmt.setInt(1, AD_Reference_ID);
            pstmt.setString(2, value);
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                name = rs.getString(1);
            }
            rs.close();
            pstmt.close();
        }
        catch (SQLException e) {
        }
        
        return name;
    }   //  readReference
	
	public static void writeDebugLog(String FileName, String source){
		try{
			FileWriter fw = new FileWriter("H:/compiereWebLog/"+FileName);
			//File outfile = new File("H:/test.xml");
			char buffer[] = new char[source.length()];
			source.getChars(0, source.length(), buffer, 0);
			for (int i=0; i < buffer.length; i += 1) {
			fw.write(buffer[i]);
			}
			fw.close(); 
		}catch(Exception e ){
			;
		}
	}
	
	/**
	 * 
	 */
	
	public static void createDisplayElement(Document document, Element elements, String objId, GridField field, 
			String realOnlyFlag, boolean enabled){
		Element element = document.createElement(Constants.ELEMENT);
		elements.appendChild(element);

		/**
		 *  data elment below
		 */

		Element elm_id=document.createElement(Constants.ID);
		element.appendChild(elm_id);
		elm_id.appendChild(document.createTextNode(objId));

		Element elm_lookup=document.createElement(Constants.LOOKUP);
		element.appendChild(elm_lookup);
		elm_lookup.appendChild(document.createTextNode(Constants.DISABLED));

		Element elm_visibility=document.createElement(Constants.VISIBILITY);
		element.appendChild(elm_visibility);
		
		if(enabled){
			elm_visibility.appendChild(document.createTextNode(Constants.ENABLED));
		}else{
			elm_visibility.appendChild(document.createTextNode(Constants.DISABLED));
		}
		

		Element elm_newValue=document.createElement(Constants.NEW_VALUE);
		element.appendChild(elm_newValue);
		elm_newValue.appendChild(document.createTextNode(Constants.ENABLED));//dummy value due to disabled elem type

		Element elm_readonly=document.createElement(Constants.READONLY);
		element.appendChild(elm_readonly);					
		elm_readonly.appendChild(document.createTextNode(realOnlyFlag));


		Element elm_type=document.createElement(Constants.TYPE);
		element.appendChild(elm_type);
		elm_type.appendChild(document.createTextNode(Constants.DISABLED));
	}
	
	/**
	 * Response to check save error action , using Ajax
	 * @param response
	 * @throws IOException
	 */
	public static void createSaveErrorResponse (HttpServletResponse response, String status) throws IOException
	{

		//response.setContentType("text/xml; charset=UTF-8");
		response.addHeader("pragma", "no-store,no-cache");//HTTP 1.0
		response.addHeader("cache-control", "no-cache, no-store,must-revalidate, max-age=-1"); // HTTP 1.1
		response.addHeader("expires", "-1");

		response.getOutputStream().print(status);
		
		System.out.println("-------------createSaveErrorResponse " + "status:" + status);

	}   //  createResponse	
	
}   //  WebUtil
