/************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 *
 * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * 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. You can also
 * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
 *
 * 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 org.odftoolkit.odfdom.pkg;

import java.util.logging.Logger;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;

import junit.framework.TestCase;

import org.junit.Test;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.doc.OdfTextDocument;
import org.odftoolkit.odfdom.dom.OdfContentDom;
import org.odftoolkit.odfdom.dom.element.table.TableCoveredTableCellElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableCellElement;
import org.odftoolkit.odfdom.dom.element.text.TextBookmarkStartElement;
import org.odftoolkit.odfdom.dom.element.text.TextHElement;
import org.odftoolkit.odfdom.dom.element.text.TextMetaElement;
import org.odftoolkit.odfdom.dom.element.text.TextPElement;
import org.odftoolkit.odfdom.dom.rdfa.BookmarkRDFMetadataExtractor;
import org.odftoolkit.odfdom.utils.ResourceUtilities;
import org.w3c.dom.Node;

import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.rdf.model.StmtIterator;
import org.apache.jena.rdf.model.test.ModelTestBase;
import org.apache.jena.util.PrintUtil;

public class RDFMetadataTest extends ModelTestBase {

	private static final Logger LOG = Logger.getLogger(RDFMetadataTest.class
			.getName());
	private static final String SIMPLE_ODT = "test_rdfmeta.odt";

	public RDFMetadataTest(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Test
	public void testGetRDFMetaFromGRDDLXSLT() throws Exception {
		OdfTextDocument odt = (OdfTextDocument) OdfDocument
				.loadDocument(ResourceUtilities.getAbsolutePath(SIMPLE_ODT));
		Model m1 = odt.getManifestRDFMetadata();
		LOG.info("RDF Model - manifest:\n" + m1.toString());
		long size1 = m1.size();
		TestCase.assertEquals(25, size1);

		Model m2 = odt.getInContentMetadata();
		LOG.info("RDF Model - rood document in-content:\n" + m1.toString());
		long size2 = m2.size();
		TestCase.assertEquals(20, size2);

		Model m = odt.getRDFMetadata();

		// This triples are duplicated in m1 and m2:
		// (test_rdfmeta.odt rdf:type
		// http://docs.oasis-open.org/ns/office/1.2/meta/pkg#Document)
		// (test_rdfmeta.odt/embeded.odt rdf:type
		// http://docs.oasis-open.org/ns/office/1.2/meta/pkg#Document)
//		int duplicated = 2;
		Model m3 = m1.intersection(m2);
		LOG.info("RDF Model - duplicated (manifest & in-content of root doc):\n" + m3.toString());
// Uncertain about the previuos statement, as the duplicated RDF triple do not have an identical subject..
//		TestCase.assertEquals(duplicated, m3.size());
//		TestCase.assertEquals(size1 + size2 - duplicated, m.size());

		// test the embeded document
		OdfDocument subDoc = odt.loadSubDocument("embeded.odt");
		m1 = subDoc.getManifestRDFMetadata();
		size1 = m1.size();
		TestCase.assertEquals(5, size1);

		m2 = subDoc.getInContentMetadata();
		size2 = m2.size();
		LOG.info("RDF Model - embedded document in content:\n" + m2.toString());
		TestCase.assertEquals(6, size2);

		m = subDoc.getRDFMetadata();

		// This triple is duplicated in m1 and m2:
		// (test_rdfmeta.odt/embeded.odt rdf:type
		// http://docs.oasis-open.org/ns/office/1.2/meta/pkg#Document)
//		duplicated = 1;
		m3 = m1.intersection(m2);
		LOG.info("RDF Model - intersection of in-content metadata of root & embedded document:\n" + m2.toString());
		//TestCase.assertEquals(duplicated, m3.size());
		//TestCase.assertEquals(size1 + size2 - duplicated, m.size());

	}

	@Test
	public void testGetInContentMetaFromCache() throws Exception {
		OdfTextDocument odt = (OdfTextDocument) OdfDocument
				.loadDocument(ResourceUtilities.getAbsolutePath(SIMPLE_ODT));
		Model m1 = odt.getInContentMetadataFromCache();

		// We have the following 1 triple in cache:
		// (http://dbpedia.org/page/J._R._R._Tolkien
		// http://www.w3.org/2006/vcard/ns#fn 'John Ronald Reuel Tolkien')
		TestCase.assertEquals(1, m1.size());

		OdfContentDom contentDom = odt.getContentDom();
		XPath xpath = contentDom.getXPath();
		TextMetaElement tm = (TextMetaElement) xpath.evaluate(
				"//text:p/text:meta[last()]", contentDom, XPathConstants.NODE);

		tm.setXhtmlAboutAttribute("http://dbpedia.org/page/J._K._Rowling");
		m1 = odt.getInContentMetadataFromCache();
		PrintUtil.printOut(m1.listStatements());
		TestCase.assertEquals("http://dbpedia.org/page/J._K._Rowling", m1
				.listStatements().nextStatement().getSubject().getURI());

		tm.setTextContent("Joanne Kathleen Rowling");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals("Joanne Kathleen Rowling", m1.listStatements()
				.nextStatement().getObject().toString());

		tm.setXhtmlPropertyAttribute("dc:name");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals("http://purl.org/dc/elements/1.1/name", m1
				.listStatements().nextStatement().getPredicate().getURI());

		Node parent = tm.getParentNode();
		parent.removeChild(tm);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(0, m1.size());
		parent.appendChild(tm);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		parent.removeChild(tm);

		TextPElement pEle = contentDom.newOdfElement(TextPElement.class);
		parent.appendChild(pEle);
		pEle.setXhtmlAboutAttribute("[dbpedia:J._K._Rowling]");
		pEle.setXhtmlPropertyAttribute("dbpprop:birthDate dbpprop:dateOfBirth");
		pEle.setXhtmlDatatypeAttribute("xsd:date");
		pEle.setXhtmlContentAttribute("1965-07-31");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(2, m1.size());
		StmtIterator iter = m1.listStatements();
		while (iter.hasNext()) {
			Statement stmt = iter.nextStatement();
			TestCase.assertEquals("http://dbpedia.org/page/J._K._Rowling", stmt
					.getSubject().getURI());
			TestCase.assertTrue(stmt.getObject().canAs(Literal.class));
			Literal literal = stmt.getObject().as(Literal.class);
			TestCase.assertEquals("http://www.w3.org/2001/XMLSchema#date",
					literal.getDatatypeURI());
			TestCase.assertEquals("1965-07-31", literal.getLexicalForm());
		}
		pEle.setXhtmlPropertyAttribute("dc:date");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		TestCase.assertEquals("http://purl.org/dc/elements/1.1/date", m1
				.listStatements().nextStatement().getPredicate().getURI());

		parent.removeChild(pEle);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(0, m1.size());
		parent.appendChild(pEle);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		parent.removeChild(pEle);

		TextHElement hEle = contentDom.newOdfElement(TextHElement.class);
		parent.appendChild(hEle);
		hEle.setXhtmlAboutAttribute("[dbpedia:J._K._Rowling]");
		hEle.setXhtmlPropertyAttribute("dbpprop:children");
		hEle.setXhtmlDatatypeAttribute("xsd:integer");
		hEle.setTextContent("2");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		TestCase.assertEquals("http://dbpedia.org/page/J._K._Rowling", m1
				.listStatements().nextStatement().getSubject().getURI());
		TestCase.assertEquals("http://dbpedia.org/property/children", m1
				.listStatements().nextStatement().getPredicate().getURI());
		TestCase.assertTrue(m1.listStatements().nextStatement().getObject()
				.canAs(Literal.class));
		TestCase.assertEquals("2^^http://www.w3.org/2001/XMLSchema#integer", m1
				.listStatements().nextStatement().getObject().toString());
		hEle.setTextContent("3");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals("3^^http://www.w3.org/2001/XMLSchema#integer", m1
				.listStatements().nextStatement().getObject().toString());

		parent.removeChild(hEle);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(0, m1.size());
		parent.appendChild(hEle);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		parent.removeChild(hEle);

		TableTableCellElement ttce = contentDom
				.newOdfElement(TableTableCellElement.class);
		parent.appendChild(ttce);
		ttce.setXhtmlAboutAttribute("[dbpedia:J._K._Rowling]");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(0, m1.size());
		ttce.setXhtmlPropertyAttribute("dbpprop:nationality");
		ttce.setTextContent("British");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		ttce.setXhtmlAboutAttribute("http://dbpedia.org/page/J._R._R._Tolkien");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		TestCase.assertEquals("http://dbpedia.org/page/J._R._R._Tolkien", m1
				.listStatements().nextStatement().getSubject().getURI());

		TableCoveredTableCellElement tctce = contentDom
				.newOdfElement(TableCoveredTableCellElement.class);
		parent.appendChild(tctce);
		tctce.setXhtmlAboutAttribute("[dbpedia:J._R._R._Tolkien]");
		tctce.setXhtmlPropertyAttribute("dbpprop:shortDescription");
		tctce.setXhtmlContentAttribute("British philologist and author");
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(2, m1.size());

		parent.removeChild(ttce);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		parent.appendChild(ttce);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(2, m1.size());
		parent.removeChild(ttce);

		parent.removeChild(tctce);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(0, m1.size());
		parent.appendChild(tctce);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(1, m1.size());
		parent.removeChild(tctce);
		m1 = odt.getInContentMetadataFromCache();
		TestCase.assertEquals(0, m1.size());

	}

	@Test
	public void testGetBookmarkRDFMetadata() throws Exception {
		OdfTextDocument odt = (OdfTextDocument) OdfDocument
				.loadDocument(ResourceUtilities.getAbsolutePath(SIMPLE_ODT));
		Model m = odt.getBookmarkRDFMetadata();
		TestCase.assertEquals(2, m.size());

		OdfContentDom contentDom = odt.getContentDom();
		XPath xpath = contentDom.getXPath();
		TextBookmarkStartElement tm = (TextBookmarkStartElement) xpath
				.evaluate("//text:bookmark-start[last()]", contentDom,
						XPathConstants.NODE);
		BookmarkRDFMetadataExtractor extractor = BookmarkRDFMetadataExtractor
				.newBookmarkTextExtractor();
		m = extractor.getBookmarkRDFMetadata(tm);
		TestCase.assertEquals(1, m.size());
	}
}
