/*
 * $Id: XmlDocumentUtils.java,v 1.6 2005/03/21 20:30:06 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 */

package vkc.xml;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCKeyword;
import vkc.misc.VKCLogManager;
import vkc.util.StringUtils;
import vkc.view.WebShare;

public final class XmlDocumentUtils {
	private XmlDocumentUtils() {
	}
	
	/**
	 * Method inserts document meta information for the argument document
	 * into the "content"-Element of the XML document object
	 */
	public static final void addDocumentMetaData( Document xmlDoc, VKCDocument vkcDoc ) {
		if ( xmlDoc == null || vkcDoc == null ) {
			return;
		}
															  	
		Node contentNode = XmlUtils.getNodeByName( xmlDoc.getDocumentElement(), "content" );
		
		if ( contentNode == null ) {
			return;
		}

		Element root = XmlDocumentUtils.createDocumentElement( xmlDoc, vkcDoc );
		contentNode.appendChild( root );

		XmlDocumentUtils.populateDocumentMetaElement( root, vkcDoc );
	}

	/**
	 * Method inserts document version information for the argument document
	 * into the "content"-Element of the XML document object
	 */
	public static final void addDocumentVersionData( Document xmlDoc, VKCDocument vkcDoc ) {
		if ( xmlDoc == null || vkcDoc == null ) {
			return;
		}
															  	
		Node contentNode = XmlUtils.getNodeByName( xmlDoc.getDocumentElement(), "content" );
		
		if ( contentNode == null ) {
			return;
		}

		Element root = XmlDocumentUtils.createDocumentElement( xmlDoc, vkcDoc );
		contentNode.appendChild( root );

		XmlDocumentUtils.populateDocumentVersionElement( root, vkcDoc );
	}
	
	/**
	 * Methode konvertiert eine Collection von VKCDocument-Objekten
	 * in ein XML-Dokument
	 */
	public static final Document toXml( Collection c ) throws ParserConfigurationException {
		if ( c == null ) {
			return null;
		}

		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder = docFactory.newDocumentBuilder();

		Document xmlDoc = documentBuilder.newDocument();

		Element documentsRoot = xmlDoc.createElement( "documents" );
		xmlDoc.appendChild( documentsRoot );

		for ( Iterator iter = c.iterator() ; iter.hasNext() ; ) {
			VKCDocument vkcDoc = (VKCDocument)iter.next();

			Element docRoot = createDocumentElement( xmlDoc, vkcDoc );
			populateDocumentMetaElement( docRoot, vkcDoc );

			documentsRoot.appendChild( docRoot );
		}

		return xmlDoc;
	}
	
	/**
	 * Methode konvertiert ein VKCDocumet in ein XML-Dokument
	 */
	public static final Document toXml( VKCDocument vkcDocument ) throws ParserConfigurationException {
		if ( vkcDocument == null ) {
			return null;
		}
		
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder = docFactory.newDocumentBuilder();

		Document doc = documentBuilder.newDocument();
		
		Element root = createDocumentElement( doc, vkcDocument );
		doc.appendChild( root );

		populateDocumentMetaElement( root, vkcDocument );

		return doc;
	}
	
	// #########################################################################
	// # helper methods                                                        #
	// #########################################################################

	private final static Element createDocumentElement( Document xmlDoc, VKCDocument vkcDoc ) {
		// Wurzelknoten erzeugen
		Element elem = xmlDoc.createElement( "document" );
		elem.setAttribute( "id", "" + vkcDoc.getDocumentId() );
		
		return elem;
	}
	
	private final static void populateDocumentMetaElement( Element elem, VKCDocument vkcDoc ) {
		Document owner = elem.getOwnerDocument();
		
		// Dokumenttyp einfügen
		Element docType = owner.createElement( "docType" );
		docType.setAttribute( "id", "" + vkcDoc.getDocTypeId() );
		elem.appendChild( docType );

		// Dokumentklasse einfügen
		Element docClass = owner.createElement( "docClass" );
		docClass.setAttribute( "id", "" + vkcDoc.getDocClassId() );
		elem.appendChild( docClass );

		// Title einfügen
		Element title = owner.createElement( "docTitle" );
		title.appendChild( owner.createTextNode( StringUtils.normalize( vkcDoc.getTitle() ) ) );
		elem.appendChild( title );

		// Beschreibung einfügen
		Element description = owner.createElement( "docDescription" );
		description.appendChild( owner.createTextNode( StringUtils.normalize( vkcDoc.getDescription() ) ) );
		elem.appendChild( description );	

		// Keywords einfügen
		Set keywords = vkcDoc.getKeywords();
		if ( keywords != null && !keywords.isEmpty() ) {
			for( Iterator iter = keywords.iterator() ; iter.hasNext() ; ) {
				VKCKeyword keyword = (VKCKeyword)iter.next();

				if ( keyword.isInternal() || StringUtils.isEmpty( keyword.getTerm() ) ) {
					continue;
				}

				Element keywordElem = owner.createElement( "docKeyword" );
				keywordElem.setAttribute( "name", keyword.getTerm().trim() );
				elem.appendChild( keywordElem );	
			}
		}
		
		// Erstellungsdatum einfügen
		Element docPublished = owner.createElement( "published" );
		docPublished.setAttribute( "timestamp", "" + vkcDoc.getPublished().getTime() );
		elem.appendChild( docPublished );

		if ( vkcDoc.getExpires() != null ) {
			// Verfallsdatum einfügen
			Element docExpires = owner.createElement( "expires" );
			docExpires.setAttribute( "timestamp", "" + vkcDoc.getExpires().getTime() );
			elem.appendChild( docExpires );
		}

		if ( vkcDoc.getDocSize() != null && vkcDoc.getDocSize().longValue() > 0 ) {
			try {
				Element docSize = owner.createElement( "docSize" );
				docSize.setAttribute( "value", "" + vkcDoc.getDocSize() );
				elem.appendChild( docSize );	

				Element docURI = owner.createElement( "docUri" );
				docURI.setAttribute( "value", WebShare.getRootURL() + WebShare.getContextPath() + vkcDoc.getDisplayURI() );
				elem.appendChild( docURI );	

			} catch (Exception e) { // never happens ..
				VKCLogManager.errorLog(XmlDocumentUtils.class, "", e.getMessage(), e);
			}
		}
		
		populateDocumentVersionElement( elem, vkcDoc );
	}
	
	private final static void populateDocumentVersionElement( Element elem, VKCDocument vkcDoc ) {
		Document owner = elem.getOwnerDocument();
		
		// Dokumentversion einfügen
		Element docVersion = owner.createElement( "version" );
		docVersion.setAttribute( "number", "" + vkcDoc.getVersionNo() );

		if ( vkcDoc.getVersionHigh()!=null ) {
			docVersion.setAttribute( "versionHigh", "" + vkcDoc.getVersionHigh() );
		}

		if ( vkcDoc.getVersionLow()!=null ) {
			docVersion.setAttribute( "versionLow", "" + vkcDoc.getVersionLow() );
		}
		
		elem.appendChild( docVersion );

		if ( !StringUtils.isEmpty( vkcDoc.getVersionDescr() ) ) {
			// Versionsbeschreibung einfügen
			Element versionDescription = owner.createElement( "versionDescription" );
			versionDescription.appendChild( owner.createTextNode( StringUtils.normalize( vkcDoc.getVersionDescr() ) ) );
			elem.appendChild( versionDescription );
		}
	}
}