//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.layout.util;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.epf.common.utils.FileUtil;


/**
 * Implements a XML element.
 * 
 * @author Jinhua Xi
 * @author Kelvin Low
 * @since 1.0
 */
public class XmlElement implements IXmlElement {

	public static final String BR = FileUtil.LINE_SEP;

	private static String NODE_ID = "nodeId"; //$NON-NLS-1$

	// private static String PARENT_NODE_ID = "parentNodeId";

	private String element_name = null;

	private String element_value = null;

	private Map attributes = new HashMap();

	private Map contents = new HashMap();

	private List children = new ArrayList();

	private String id = null;

	public XmlElement(String name) {
		this(name, null);
	}

	public XmlElement(String name, String id) {
		this.element_name = name;
		
		if (id == null ) {
			id = Integer.toHexString(this.toString().hashCode());
		}
		
		this.id = id;
		setAttribute(NODE_ID, this.id);
	}
	
	public XmlElement setAttribute(String name, String value) {
		attributes.put(name, value);
		return this;
	}

	public XmlElement setValue(String value) {
		this.element_value = value;
		return this;
	}

	public XmlElement setContent(String name, Object value) {
		contents.put(name, value);
		return this;
	}

	public XmlElement addChild(XmlElement child) {
		children.add(child);
		return this;
	}

	public XmlElement newChild(String name) {
		return newChild(name, null);
	}
	
	public XmlElement newChild(String name, String id) {
		XmlElement child = new XmlElement(name, id);
		children.add(child);
		return child;
	}

	public String getId() {
		return this.id;
	}
	
	public StringBuffer toXml() {
		StringBuffer buffer = new StringBuffer();
		if (contents.size() == 0 && children.size() == 0) {
			buffer.append(
					XmlHelper.getElement(element_name, element_value,
							attributes)).append(BR);
		} else {
			buffer.append(XmlHelper.beginElement(element_name, attributes))
					.append(BR);

			// process the contents
			for (Iterator it = contents.entrySet().iterator(); it.hasNext();) {
				Map.Entry entry = (Map.Entry) it.next();
				String key = (String) entry.getKey();
				Object value = entry.getValue();
				if (value instanceof List) {
					for (Iterator itList = ((List) value).iterator(); itList
							.hasNext();) {
						buffer.append(
								XmlHelper.getElement(key, itList.next()
										.toString(), null)).append(BR);
					}
				} else {
					buffer
							.append(
									XmlHelper
											.getElement(
													key,
													(value == null) ? "" : value.toString(), null)).append(BR); //$NON-NLS-1$
				}
			}

			// process the children
			for (Iterator it = children.iterator(); it.hasNext();) {
				IXmlElement child = (IXmlElement) it.next();
				buffer.append(child.toXml());
			}

			buffer.append(XmlHelper.endElement(element_name)).append(BR);
		}

		return buffer;
	}

	public void saveTo(String filePathName) {
		StringBuffer xml = new StringBuffer();
		xml.append(XmlHelper.XML_HEADER).append(this.toXml());

		try {
			// may need to create the folders, TODO
			/*
			 * File xf = new File( filePath); if ( !xf.exists() ) { xf.mkdirs(); }
			 */

			// need to enfore utf-8 encoding, can't use FileWriter, jxi
			// FileWriter xw = new FileWriter(filePathName);
			OutputStreamWriter xw = new OutputStreamWriter(
					new FileOutputStream(filePathName), "utf-8"); //$NON-NLS-1$

			xw.write(xml.toString());
			xw.flush();
			xw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
