/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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
 *
 * 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.apache.cocoon.sax.component;

import static junit.framework.Assert.*;

import java.io.ByteArrayOutputStream;
import java.net.URL;

import org.apache.cocoon.pipeline.NonCachingPipeline;
import org.apache.cocoon.pipeline.Pipeline;
import org.apache.cocoon.sax.SAXPipelineComponent;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * $Id: XIncludeTransformerTest.java 892822 2009-12-21 13:53:55Z reinhard $
 */
public final class XIncludeTransformerTest {

    @BeforeClass
    public static void setUp() {
        XMLUnit.setIgnoreWhitespace(true);
    }

    /**
     * A pipeline that reads from a file and perform a simple XInclude operation.
     */
     @Test
     public void testPipelineWithXInclude() throws Exception {
         this.internalXIncludeTest("xinclude-xml.xml",
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?><x><test/></x>");
     }

    /**
     * A pipeline that performs an XInclude operation, including just text.
     **/
     @Test
     public void testPipelineWithXIncludeText() throws Exception {
         this.internalXIncludeTest("xinclude-text-only.xml",
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                 + "<x>in girum imus nocte et cosumimur igni</x>");
     }

    /**
     * A pipeline that performs an XInclude operation, forced to use the fallback.
     **/
     @Test
     public void testPipelineWithXIncludeFallback() throws Exception {
         this.internalXIncludeTest("xinclude-fallback.xml",
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><x>"
                 + "<error>the linked document has not found</error></x>");
     }

    /**
     * A pipeline that performs an XInclude operation and use XPointer to extract
     * a fragment from the included document.
     **/
    @Test
    public void testPipelineWithXIncludeAndXPointer() throws Exception {
        this.internalXIncludeTest("xinclude-xpointer.xml",
               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                + "<x xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><p>"
                + "<xsl:value-of select=\"$myParam\"/></p></x>");
    }

    /**
     * A pipeline that performs an XInclude operation and use the deprecated
     * XPointer to extract a fragment from the included document.
     **/
    @Test
    public void testPipelineWithXIncludeAndDeprecatedXPointer() throws Exception {
         this.internalXIncludeTest("xinclude-deprecated_xpointer.xml",
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                 + "<x xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><p>"
                 + "<xsl:value-of select=\"$myParam\"/></p></x>");
    }

    /**
     * A pipeline that performs an XInclude operation and use the shorthand
     * XPointer to extract a fragment from the included document.
     **/
    @Test
    public void testPipelineWithShorthandXPointerPart() throws Exception {
        this.internalXIncludeTest("xinclude-shorthand.xml",
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><x>"
                + "<url id=\"url\">http://www.opensource.org/licenses/apache2.0.php</url>"
                + "<url id=\"url\">http://www.opensource.org/licenses/lgpl-3.0.html</url>"
                + "<url id=\"url\">http://www.opensource.org/licenses/mit-license.php</url>"
                + "<url id=\"url\">http://www.opensource.org/licenses/W3C.php</url></x>");
    }

   /**
    *
    */
   private void internalXIncludeTest(final String testResource, final String expectedDocument) throws Exception {
       URL base = this.getClass().getResource("/");
       URL source = new URL(base, testResource);

       Pipeline<SAXPipelineComponent> pipeline = new NonCachingPipeline<SAXPipelineComponent>();
       pipeline.addComponent(new XMLGenerator(source));
       pipeline.addComponent(new XIncludeTransformer(base));
       pipeline.addComponent(new XMLSerializer());

       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       pipeline.setup(baos);
       pipeline.execute();

       String actualDocument = new String(baos.toByteArray());

       Diff diff = new Diff(expectedDocument, actualDocument);
       assertTrue("XInclude transformation didn't work as expected " + diff,
               diff.identical());
   }

}
