/*
 * $Id: XMLPersister.java,v 1.3 2006/01/28 03:37:07 rampil Exp $
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.rss.lcmgr.persister;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.logical_paradox.rss.http.WebContents;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * XMLPersister
 * webコンテンツの表現するメタデータをXMLに変換して，永続化するツール．
 * XMLからwebコンテンツメタデータを復元することも可能とする．
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.3 $
 */
public class XMLPersister {
	/**
	 * コンストラクタ．
	 */
	private XMLPersister() {
	}
	/**
	 * webコンテンツメタデータをXMLドキュメントに変換する．
	 * @param webContents webコンテンツメタデータ
	 * @return XMLドキュメント
	 */
	public static final String marshall(WebContents webContents) throws ParserConfigurationException, FactoryConfigurationError, TransformerException {
		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document document = builder.newDocument();

		// ルート要素
		Element rootElement = document.createElement("Contents");
		// ドキュメント
		Element documentElement = document.createElement("Document");
		documentElement.appendChild(document.createTextNode(webContents.getDocument()));
		// ドキュメントロケーション
		Element locationElement = document.createElement("Location");
		locationElement.appendChild(document.createTextNode(webContents.getLocation()));
		// ドキュメントタイトル
		Element documentTitleElement = document.createElement("Title");
		documentTitleElement.appendChild(document.createTextNode(webContents.getTitle()));
		// サイト名
		Element sitenameElement = document.createElement("SiteName");
		sitenameElement.appendChild(document.createTextNode(webContents.getSitename()));
		// mimeタイプ
		Element contentTypeElement = document.createElement("MimeType");
		contentTypeElement.appendChild(document.createTextNode(webContents.getContentType()));

		// XMLドキュメントツリーの生成
		rootElement.appendChild(documentElement);
		rootElement.appendChild(locationElement);
		rootElement.appendChild(documentTitleElement);
		rootElement.appendChild(sitenameElement);
		rootElement.appendChild(contentTypeElement);

		document.appendChild(rootElement);

		// XMLを文字列に変換して出力する
		StringWriter xmlWriter = new StringWriter();

		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer transformer = tffactory.newTransformer();
		transformer.setOutputProperty("encoding", "Windows-31J");
		DOMSource src = new DOMSource();
		src.setNode(document);
		StreamResult target = new StreamResult();
		target.setWriter(xmlWriter);
		transformer.transform(src, target);

		return xmlWriter.getBuffer().toString();
	}
	/**
	 * XMLドキュメント形式のwebコンテンツメタデータを復元する．
	 * @param document XMLドキュメント
	 * @return 復元されたwebコンテンツメタデータ
	 */
	public static final WebContents unmarshall(String document) throws ParserConfigurationException, FactoryConfigurationError, SAXException, IOException {
		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		ByteArrayInputStream in = new ByteArrayInputStream(document.getBytes());
		Document doc = builder.parse(in);

		WebContents contents = new WebContents();

		Node root = doc.getFirstChild();
		NodeList webContentsElements = root.getChildNodes();

		for(int i = 0; i < webContentsElements.getLength(); i++) {
			Node node = webContentsElements.item(i);
			String nodename = node.getNodeName();
			String nodevalue = node.getFirstChild().getNodeValue();

			if("Document".equals(nodename)) {
				contents.setDocument(nodevalue);
			} else if("Location".equals(nodename)) {
				contents.setLocation(nodevalue);
			} else if("Title".equals(nodename)) {
				contents.setTitle(nodevalue);
			} else if("SiteName".equals(nodename)) {
				contents.setSitename(nodevalue);
			} else if("MimeType".equals(nodename)) {
				contents.setContentType(nodevalue);
			}
			// それ以外の場合は無視する
		}

		return contents;
	}
}
