/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 * #L%
 */
package org.alfresco.repo.rendition.executer;
import java.util.Arrays;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.rendition.RenditionDefinition;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateProcessor;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.namespace.QName;
import org.alfresco.test_category.BaseSpringTestsCategory;
import org.alfresco.util.BaseAlfrescoSpringTest;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.custommonkey.xmlunit.Diff;
import org.junit.experimental.categories.Category;
/**
 * @author Brian
 * 
 */
@Category(BaseSpringTestsCategory.class)
public class XSLTRenderingEngineTest extends BaseAlfrescoSpringTest
{
    private final static Log log = LogFactory.getLog(XSLTRenderingEngineTest.class);
    private NodeRef companyHome;
    private FileFolderService fileFolderService;
    private TemplateProcessor xsltProcessor;
    private TemplateService templateService;
    private RenditionService renditionService;
    /*
     * (non-Javadoc)
     * 
     * @see org.alfresco.util.BaseAlfrescoSpringTest#onSetUpInTransaction()
     */
    @SuppressWarnings("deprecation")
    @Override
    protected void onSetUpInTransaction() throws Exception
    {
        super.onSetUpInTransaction();
        this.nodeService = (NodeService) this.applicationContext.getBean("NodeService");
        this.contentService = (ContentService) this.applicationContext.getBean("ContentService");
        this.fileFolderService = (FileFolderService) this.applicationContext.getBean("FileFolderService");
        this.xsltProcessor = (TemplateProcessor) this.applicationContext.getBean("xsltProcessor");
        this.templateService = (TemplateService) this.applicationContext.getBean("TemplateService");
        this.renditionService = (RenditionService) this.applicationContext.getBean("RenditionService");
        
        this.companyHome = this.applicationContext.getBean("repositoryHelper", Repository.class).getCompanyHome();
    }
    public void testSimplestStringTemplate() throws Exception
    {
        try
        {
            FileInfo file = createXmlFile(companyHome);
            FileInfo xslFile = createXmlFile(companyHome, verySimpleXSLT);
            RenditionDefinition def = renditionService.createRenditionDefinition(QName.createQName("Test"), XSLTRenderingEngine.NAME);
            def.setParameterValue(XSLTRenderingEngine.PARAM_TEMPLATE_NODE, xslFile.getNodeRef());
            ChildAssociationRef rendition = renditionService.render(file.getNodeRef(), def);
            
            assertNotNull(rendition);
            
            ContentReader reader = contentService.getReader(rendition.getChildRef(), ContentModel.PROP_CONTENT);
            assertNotNull(reader);
            String output = reader.getContentString();
            
            log.debug("XSLT Processor output: " + output);
            assertEquals("Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate", output);
        }
        catch (Exception ex)
        {
            log.error("Error!", ex);
            fail();
        }
    }
    public void testSimplestTemplateWithTargetPath() throws Exception
    {
        try
        {
            FileInfo file = createXmlFile(companyHome);
            FileInfo xslFile = createXmlFile(companyHome, verySimpleXSLT);
            RenditionDefinition def = renditionService.createRenditionDefinition(QName.createQName("Test"), XSLTRenderingEngine.NAME);
            def.setParameterValue(XSLTRenderingEngine.PARAM_TEMPLATE_NODE, xslFile.getNodeRef());
            def.setParameterValue(RenditionService.PARAM_DESTINATION_PATH_TEMPLATE, "output/path/for/rendition/output.txt");
            
            ChildAssociationRef rendition = renditionService.render(file.getNodeRef(), def);
            
            assertNotNull(rendition);
            assertEquals(2, nodeService.getParentAssocs(rendition.getChildRef()).size());
            
            ContentReader reader = contentService.getReader(rendition.getChildRef(), ContentModel.PROP_CONTENT);
            assertNotNull(reader);
            String output = reader.getContentString();
            
            log.debug("XSLT Processor output: " + output);
            assertEquals("Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate", output);
        }
        catch (Exception ex)
        {
            log.error("Error!", ex);
            fail();
        }
    }
    public void testParseXMLDocument() throws Exception
    {
        try
        {
            FileInfo file = createXmlFile(companyHome);
            createXmlFile(companyHome, "TestXML.xml", sampleXML);
            FileInfo xslFile = createXmlFile(companyHome, callParseXmlDocument);
            RenditionDefinition def = renditionService.createRenditionDefinition(QName.createQName("Test"), XSLTRenderingEngine.NAME);
            def.setParameterValue(XSLTRenderingEngine.PARAM_TEMPLATE_NODE, xslFile.getNodeRef());
            ChildAssociationRef rendition = renditionService.render(file.getNodeRef(), def);
            
            assertNotNull(rendition);
            
            ContentReader reader = contentService.getReader(rendition.getChildRef(), ContentModel.PROP_CONTENT);
            assertNotNull(reader);
            String output = reader.getContentString();
            
            log.debug("XSLT Processor output: " + output);
            assertEquals("Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate", output);
        }
        catch (Exception ex)
        {
            log.error("Error!", ex);
            fail();
        }
    }
    public void testParseXMLDocuments() throws Exception
    {
        try
        {
            FileInfo file = createXmlFile(companyHome);
            String path = "path/to/xml/files";
            List pathElements = Arrays.asList(path.split("/"));
            FileInfo folder = FileFolderServiceImpl.makeFolders(fileFolderService, companyHome, pathElements, ContentModel.TYPE_FOLDER);
            createXmlFile(folder.getNodeRef());
            createXmlFile(folder.getNodeRef());
            createXmlFile(folder.getNodeRef());
            createXmlFile(folder.getNodeRef());
            createXmlFile(folder.getNodeRef());
            FileInfo xslFile = createXmlFile(companyHome, callParseXmlDocuments);
            RenditionDefinition def = renditionService.createRenditionDefinition(QName.createQName("Test"), XSLTRenderingEngine.NAME);
            def.setParameterValue(XSLTRenderingEngine.PARAM_TEMPLATE_NODE, xslFile.getNodeRef());
            ChildAssociationRef rendition = renditionService.render(file.getNodeRef(), def);
            
            assertNotNull(rendition);
            
            ContentReader reader = contentService.getReader(rendition.getChildRef(), ContentModel.PROP_CONTENT);
            assertNotNull(reader);
            String output = reader.getContentString();
            
            log.debug("XSLT Processor output: " + output);
            assertEquals(
                    "Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate"+
                    "Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate"+
                    "Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate"+
                    "Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate"+
                    "Avocado DipBagels, New York StyleBeef Frankfurter, Quarter PoundChicken Pot PieCole SlawEggsHazelnut SpreadPotato ChipsSoy Patties, GrilledTruffles, Dark Chocolate"
                    , output);
        }
        catch (Exception ex)
        {
            log.error("Error!", ex);
            fail();
        }
    }
    public void testImportXMLDocument() throws Exception
    {
        try
        {
            FileInfo file = createXmlFile(companyHome);
            createXmlFile(companyHome, "TestTableXML.xml", testTableXml);
            FileInfo testImportTable = createXmlFile(companyHome, "TestImportTableXML.xml", testImportTableXml);
            RenditionDefinition def = renditionService.createRenditionDefinition(QName.createQName("Test"), XSLTRenderingEngine.NAME);
            def.setParameterValue(XSLTRenderingEngine.PARAM_TEMPLATE_NODE, testImportTable.getNodeRef());
            ChildAssociationRef rendition = renditionService.render(file.getNodeRef(), def);
            
            assertNotNull(rendition);
            
            ContentReader reader = contentService.getReader(rendition.getChildRef(), ContentModel.PROP_CONTENT);
            assertNotNull(reader);
            String output = reader.getContentString();
            
            log.debug("XSLT Processor output: " + output);
            Diff myDiff = new Diff("\n\nMy CD Collection
\n\n\n| Title | Artist\n | 
\n\n|  | \n | 
\n
\n\n\n", output);
            assertTrue("Pieces of XML are similar " + myDiff, myDiff.similar());
        }
        catch (Exception ex)
        {
            log.error("Error!", ex);
            fail();
        }
    }
    
    private FileInfo createXmlFile(NodeRef folder)
    {
        return createXmlFile(folder, sampleXML);
    }
    private FileInfo createXmlFile(NodeRef folder, String content)
    {
        String name = GUID.generate() + ".xml";
        return createXmlFile(folder, name, content);
    }
    private FileInfo createXmlFile(NodeRef folder, String filename, String content)
    {
        FileInfo testXmlFile = fileFolderService.create(folder, filename, ContentModel.TYPE_CONTENT);
        ContentWriter writer = contentService.getWriter(testXmlFile.getNodeRef(), ContentModel.PROP_CONTENT, true);
        writer.setMimetype("text/xml");
        writer.setEncoding("UTF-8");
        writer.putContent(content);
        return testXmlFile;
    }
    private String sampleXML = "" + "" +
    "" + "65" + "20"
            + "300" + "2400"
            + "300" + "25" + "50"
            + "" +
            "" + "Avocado Dip" + "Sunnydale" + "29"
            + "" + "11"
            + "3" + "5" + "210"
            + "2" + "0" + "1" + "" + "0" + "0"
            + "" + "" + "0" + "0" + "" + "" +
            "" + "Bagels, New York Style" + "Thompson"
            + "104" + ""
            + "4" + "1" + "0"
            + "510" + "54" + "3" + "11" + ""
            + "0" + "0" + "" + "" + "8" + "20" + ""
            + "" +
            "" + "Beef Frankfurter, Quarter Pound" + "Armitage"
            + "115" + ""
            + "32" + "15" + "65"
            + "1100" + "8" + "0" + "13" + ""
            + "0" + "2" + "" + "" + "1" + "6" + ""
            + "" +
            "" + "Chicken Pot Pie" + "Lakeson" + "198"
            + "" + "22"
            + "9" + "25" + "810"
            + "42" + "2" + "10" + "" + "20"
            + "2" + "" + "" + "2" + "10" + "" + "" +
            "" + "Cole Slaw" + "Fresh Quick" + "1.5"
            + "" + "0" + "0"
            + "0" + "15" + "5" + "2"
            + "1" + "" + "30" + "45" + "" + ""
            + "4" + "2" + "" + "" +
            "" + "Eggs" + "Goodpath" + "50"
            + "" + "4.5"
            + "1.5" + "215" + "65"
            + "1" + "0" + "6" + "" + "6" + "0"
            + "" + "" + "2" + "4" + "" + "" +
            "" + "Hazelnut Spread" + "Ferreira" + "2"
            + "" + "10" + "2"
            + "0" + "20" + "23" + "2"
            + "3" + "" + "0" + "0" + "" + ""
            + "6" + "4" + "" + "" +
            "" + "Potato Chips" + "Lees" + "28"
            + "" + "10" + "3"
            + "0" + "180" + "15" + "1"
            + "2" + "" + "0" + "10" + "" + ""
            + "0" + "0" + "" + "" +
            "" + "Soy Patties, Grilled" + "Gardenproducts"
            + "96" + "" + "5"
            + "0" + "0" + "420"
            + "10" + "4" + "9" + "" + "0" + "0"
            + "" + "" + "0" + "0" + "" + "" +
            "" + "Truffles, Dark Chocolate" + "Lyndon's"
            + "39" + ""
            + "19" + "14" + "25"
            + "10" + "16" + "1" + "1" + ""
            + "0" + "0" + "" + "" + "0" + "0" + ""
            + "" +
            "";
    
    private String verySimpleXSLT = "" + " " + "" +
    "" +
    "" + ""
    + "" + "" + "" + "";
    private String callParseXmlDocument = "" + " " + "" +
    "" +
    "" +
    "" + ""
    + "" + "" + "" + "";
    private String callParseXmlDocuments = "" + " " + "" +
    "" +
    "" +
    "" + ""
    + "" + "" + "" + "";
    private String testTableXml = "" + ""
    + ""
    + ""
    + ""
    + "My CD Collection
"
    + ""
    + ""
    + "| Title"
    + " | Artist"
    + " | 
"
    + ""
    + "| "
    + " | "
    + " | 
"
    + "
"
    + ""
    + ""
    + ""
    + "";
    private String testImportTableXml = "" + ""
    + ""
    + ""
    + ""
    + ""
    + "";
}