/*
 * 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.ace.deployment.provider.repositorybased;

import java.io.StringWriter;
import java.util.Collection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.ace.deployment.provider.ArtifactData;
import org.apache.ace.repository.Repository;
import org.apache.ace.test.utils.TestUtils;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.service.log.LogService;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class RepositoryBasedProviderPerformanceTest {

    private static final String TAGS_TAG = "tags";
    private static final String VERSION_TAG = "version";
    private static final String TARGETID_TAG = "targetID";
    private static final String ARTIFACTS_TAG = "artifacts";
    private static final String ARTIFACT_TAG = "deploymentArtifact";
    private static final String URL_TAG = "url";
    private static final String DIRECTIVES_TAG = "directives";
    private static final String ATTRIBUTES_TAG = "attributes";
    private static final String DEPLOYMENTVERSION_TAG = "deploymentversion";

    private static final String TARGET = "target";
    private static final String RESOURCETARGET = "resource-target";
    public static final String KEY_SYMBOLICNAME = Constants.BUNDLE_SYMBOLICNAME;
    public static final String KEY_NAME = Constants.BUNDLE_NAME;
    public static final String KEY_VERSION = Constants.BUNDLE_VERSION;
    public static final String KEY_VENDOR = Constants.BUNDLE_VENDOR;
    public static final String KEY_RESOURCE_PROCESSOR_PID = "Deployment-ProvidesResourceProcessor";
    /**
     * Key, intended to be used for artifacts which are bundles and will publish
     * a resource processor (see OSGi compendium section 114.10).
     */
    public static final String DIRECTIVE_ISCUSTOMIZER = "DeploymentPackage-Customizer";

    /**
     * Key, intended to be used for resources which require a resource processor
     * (see OSGi compendium section 114.10).
     */
    public static final String DIRECTIVE_KEY_PROCESSORID = "Resource-Processor";

    /**
     * Key, intended to be used for artifacts which have a resourceID that's different
     * from their generated name (based on URL).
     */
    public static final String DIRECTIVE_KEY_RESOURCE_ID = "Resource-ID";

    /**
     * Key, intended to be used for matching processed (see ArtifactPreprocessor) to their
     * 'original' one.
     */
    public static final String DIRECTIVE_KEY_BASEURL = "Base-Url";

	public static final String REPOSITORY_PATH = "ACE-RepositoryPath";

    public static final String MIMETYPE = "application/vnd.osgi.bundle";

    private RepositoryBasedProvider m_backend;

    /**
     * Sets up for the test cases.
     */
    @BeforeMethod(alwaysRun = true)
    public void setUp() throws Exception {
        // setup mock repository
        String range = "1-100000";
        Repository mock = new MockDeploymentRepository(range, generateHugeTestXml(), null);
        m_backend = new RepositoryBasedProvider();
        TestUtils.configureObject(m_backend, Repository.class, mock);
        TestUtils.configureObject(m_backend, LogService.class);
    }
    
    /**
     * Test the getBundleData for a single version, returning a single bundle, for a huge XML.
     */
    @Test(timeOut = 2000 /* millis */)
    public void testSingleBundleSingleVersionBundleDataFromHugeXml() throws Exception {
        // will parse the entire XML structure;
        // with XPath queries, it takes about 115 seconds of time;
        // with a SAX parser, it takes about 0.9(!) seconds of time.
        Collection<ArtifactData> bundleData = m_backend.getBundleData(TARGET, "44.0.0");
        assert bundleData.size() == 1 : "Expected one bundle to be found, but found " + bundleData.size();
    }

    /**
     * Test the getBundleData for a single version, returning a single bundle, for a huge XML.
     */
    @Test(timeOut = 3000 /* millis */)
    public void testSingleBundleMultipleVersionBundleDataFromHugeXml() throws Exception {
        // will parse the entire XML structure;
        // with XPath queries, it takes about 115 seconds of time;
        // with a SAX parser, it takes about 0.9(!) seconds of time.
        Collection<ArtifactData> bundleData = m_backend.getBundleData(TARGET, "40.0.0", "44.6.0");
        assert bundleData.size() == 1 : "Expected one bundle to be found, but found " + bundleData.size();
    }

    /**
     * @return a "huge" XML repository, with lots of deployment versions (approx. 10000) for a single target.
     */
    private String generateHugeTestXml() throws Exception {
        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
        Document doc = docBuilder.newDocument();

        // create the root element
        Element root = doc.createElement("repository");
        doc.appendChild(root);

        // create the versions element
        Element versions = doc.createElement("deploymentversions");
        root.appendChild(versions);

        String bundleUrl = "file:///path/to/bundle1";
        String symName = "my-test-bundle1";

        // create deployment versions
        for (int i = 0; i < 10000; i++) {
            Version dpVersion = new Version(i / 100, i % 100, 0);
            Version bundleVersion = new Version(i / 100, i % 100, 1);
            versions.appendChild(generateDeploymentVersion(doc, TARGET, dpVersion.toString(),
                new String[] { bundleUrl, KEY_SYMBOLICNAME, symName, KEY_VERSION,
                    bundleVersion.toString() }));
        }

        String rpUrl = "file:///path/to/rp";
        String artUrl = "file:///path/to/artifact";
        String rpSymName = "my-test-rp1";

        versions.appendChild(generateDeploymentVersion(doc, RESOURCETARGET, "1.0.0",
            new String[] { bundleUrl, KEY_SYMBOLICNAME, symName, KEY_VERSION, "1.0.1" },
            new String[] { rpUrl, DIRECTIVE_ISCUSTOMIZER, "true", KEY_SYMBOLICNAME, rpSymName, KEY_VERSION, "1.0.2" },
            new String[] { artUrl, DIRECTIVE_KEY_PROCESSORID, "my.processor.pid" },
            new String[] { artUrl, DIRECTIVE_KEY_RESOURCE_ID, "Artifact2", DIRECTIVE_KEY_PROCESSORID, "my.processor.pid" }));

        // transform the document to string
        TransformerFactory tFactory = TransformerFactory.newInstance();
        Transformer transformer = tFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        DOMSource source = new DOMSource(doc);

        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        transformer.transform(source, result);

        return sw.toString();
    }

    /**
     * Helper method to create the description of a deploymentpacakge with given data.
     * 
     * @param doc The document to add the version to.
     * @param targetText The targetId in the deploymentversion.
     * @param versionText The version in the deploymentversion.
     * @param data An array of data for the deployment artifact. [0] is the url, and each following item is
     *        first a directive key, and a directive value. For example,<br>
     *        <code>new String[] { "http://mybundle", "somedirective", "somevalue" }</code>
     * @return
     */
    private Node generateDeploymentVersion(Document doc, String targetText, String versionText, String[]... data) {
        Element deploymentversion = doc.createElement(DEPLOYMENTVERSION_TAG);
        Element attr = doc.createElement(ATTRIBUTES_TAG);
        deploymentversion.appendChild(attr);

        // Create and add targetId Tag
        Element elem = null;
        elem = doc.createElement(TARGETID_TAG);
        elem.setTextContent(targetText);
        attr.appendChild(elem);

        // Create and add versionTag
        elem = doc.createElement(VERSION_TAG);
        elem.setTextContent(versionText);
        attr.appendChild(elem);

        // Create and add empty tagsTag to deploymentversion
        elem = doc.createElement(TAGS_TAG);
        deploymentversion.appendChild(elem);

        // create and add bundlesTag
        elem = doc.createElement(ARTIFACTS_TAG);
        for (String[] s : data) {
            Element artifact = doc.createElement(ARTIFACT_TAG);
            Element url = doc.createElement(URL_TAG);
            url.setTextContent(s[0]);
            artifact.appendChild(url);
            Element directives = doc.createElement(DIRECTIVES_TAG);
            for (int i = 1; i < s.length; i += 2) {
                Element directive = doc.createElement(s[i]);
                directive.setTextContent(s[i + 1]);
                directives.appendChild(directive);
            }
            artifact.appendChild(directives);
            elem.appendChild(artifact);
        }

        deploymentversion.appendChild(elem);

        return deploymentversion;
    }
}
