<commit_before>package ua.com.fielden.platform.web.ioc;

import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.google.common.base.Charsets;
import com.google.inject.Inject;

import ua.com.fielden.platform.serialisation.api.ISerialiser;
import ua.com.fielden.platform.serialisation.api.SerialiserEngines;
import ua.com.fielden.platform.serialisation.api.impl.TgJackson;
import ua.com.fielden.platform.utils.EntityUtils;
import ua.com.fielden.platform.utils.ResourceLoader;
import ua.com.fielden.platform.web.app.ISourceController;
import ua.com.fielden.platform.web.app.IWebUiConfig;
import ua.com.fielden.platform.web.factories.webui.ResourceFactoryUtils;
import ua.com.fielden.platform.web.resources.webui.FileResource;

/**
 * {@link ISourceController} implementation.
 *
 * @author TG Team
 *
 */
public class SourceControllerImpl implements ISourceController {
    private static final String COMMENT_END = "-->";
    private static final String COMMENT_START = "<!--";
    private static final String SGL_QUOTED_HREF = "href='";
    private static final String DBL_QUOTED_HREF = "href=\"";
    private final IWebUiConfig webUiConfig;
    private final ISerialiser serialiser;
    private final TgJackson tgJackson;
    private static final Logger logger = Logger.getLogger(SourceControllerImpl.class);
    /**
     * Root URIs, that will be preloaded ('/resources/application-startup-resources.html' defines them) during index.html loading.
     */
    private LinkedHashSet<String> preloadedResources;
    /**
     * All URIs (including derived ones), that will be preloaded ('/resources/application-startup-resources.html' defines them) during index.html loading.
     */
    private LinkedHashSet<String> allPreloadedResources;
    private Boolean deploymentMode;

    @Inject
    public SourceControllerImpl(final IWebUiConfig webUiConfig, final ISerialiser serialiser) {
        this.webUiConfig = webUiConfig;
        this.serialiser = serialiser;
        this.tgJackson = (TgJackson) serialiser.getEngine(SerialiserEngines.JACKSON);
    }

    /**
     * Returns <code>true</code> in case where the server is in deployment mode, <code>false</code> -- in development mode.
     * <p>
     * At this stage deployment mode is activated in the case, where /resources/startup-resources.html and /resources/startup-resources-origin.html are different (which means that potentially /resources/startup-resources.html is vulcanized
     * version of /resources/startup-resources-origin.html or just changed intentionally to activate the deployment mode for testing purposes).
     *
     * After the first heavy comparison has been performed -- the flag is cached.
     *
     * @return
     */
    @Override
    public boolean isDeploymentMode() {
        if (deploymentMode == null) {
            final String startupResources = getSource("/resources/startup-resources.html");
            final String startupResourcesOrigin = getSource("/resources/startup-resources-origin.html");
            deploymentMode = !EntityUtils.equalsEx(startupResources, startupResourcesOrigin);
        }
        return deploymentMode;
    }

    @Override
    public void setDeploymentMode(final boolean deploymentMode) {
        if (this.deploymentMode != null) {
            throw new IllegalStateException("The [deployment mode == " + this.deploymentMode + "] has been already automatically populated (it cannot be overriden now). Please, ensure that no resource loading occurs before this setting.");
        }
        this.deploymentMode = deploymentMode;
    }

    /**
     * Reads the source and extracts the list of top-level (root) dependency URIs.
     *
     * @param source
     * @return
     */
    private static LinkedHashSet<String> getRootDependencies(final String source, final LinkedHashSet<String> currentRootDependencies) {
        final int commentStart = source.indexOf(COMMENT_START);
        // TODO enhance the logic to support whitespaces etc.?
        final int doubleQuotedStart = source.indexOf(DBL_QUOTED_HREF);
        final int singleQuotedStart = source.indexOf(SGL_QUOTED_HREF);

        if (doubleQuotedStart >= 0 || singleQuotedStart >= 0) {
            final boolean doubleQuote = doubleQuotedStart >= 0;
            final int start = doubleQuote ? doubleQuotedStart : singleQuotedStart;
            if (commentStart >= 0) {
                if (commentStart < start) {
                    // remove comment and process the rest of source
                    final String temp = source.substring(commentStart + COMMENT_START.length());
                    final int indexOfUncommentedPart = temp.indexOf(COMMENT_END);
                    final String sourceWithoutComment = temp.substring(indexOfUncommentedPart + COMMENT_END.length());
                    return getRootDependencies(sourceWithoutComment, currentRootDependencies);
                } else {
                    return rootDependencies0(source, currentRootDependencies, start, doubleQuote);
                }
            } else {
                return rootDependencies0(source, currentRootDependencies, start, doubleQuote);
            }
        } else {
            return currentRootDependencies;
        }
//        old implementation:
//        final LinkedHashSet<String> set = new LinkedHashSet<String>(currentRootDependencies);
//        String curr = source;
//        // TODO enhance the logic to support whitespaces etc.?
//        while (curr.indexOf("href=\"") >= 0 || curr.indexOf("href='") >= 0) {
//            final boolean singleQuote = curr.indexOf("href='") >= 0;
//            final int startIndex = singleQuote ? curr.indexOf("href='") + 6 : curr.indexOf("href=\"") + 6;
//            final String nextCurr = curr.substring(startIndex);
//            final int endIndex = singleQuote ? nextCurr.indexOf("'") : nextCurr.indexOf("\"");
//            final String importURI = nextCurr.substring(0, endIndex);
//            set.add(importURI);
//            curr = nextCurr.substring(endIndex);
//        }
//<commit_msg>#214 Fixed the bug with determining of next import URI during source dependencies processing.<commit_after>package ua.com.fielden.platform.web.ioc;

import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.google.common.base.Charsets;
import com.google.inject.Inject;

import ua.com.fielden.platform.serialisation.api.ISerialiser;
import ua.com.fielden.platform.serialisation.api.SerialiserEngines;
import ua.com.fielden.platform.serialisation.api.impl.TgJackson;
import ua.com.fielden.platform.utils.EntityUtils;
import ua.com.fielden.platform.utils.ResourceLoader;
import ua.com.fielden.platform.web.app.ISourceController;
import ua.com.fielden.platform.web.app.IWebUiConfig;
import ua.com.fielden.platform.web.factories.webui.ResourceFactoryUtils;
import ua.com.fielden.platform.web.resources.webui.FileResource;

/**
 * {@link ISourceController} implementation.
 *
 * @author TG Team
 *
 */
public class SourceControllerImpl implements ISourceController {
    private static final String COMMENT_END = "-->";
    private static final String COMMENT_START = "<!--";
    private static final String SGL_QUOTED_HREF = "href='";
    private static final String DBL_QUOTED_HREF = "href=\"";
    private final IWebUiConfig webUiConfig;
    private final ISerialiser serialiser;
    private final TgJackson tgJackson;
    private static final Logger logger = Logger.getLogger(SourceControllerImpl.class);
    /**
     * Root URIs, that will be preloaded ('/resources/application-startup-resources.html' defines them) during index.html loading.
     */
    private LinkedHashSet<String> preloadedResources;
    /**
     * All URIs (including derived ones), that will be preloaded ('/resources/application-startup-resources.html' defines them) during index.html loading.
     */
    private LinkedHashSet<String> allPreloadedResources;
    private Boolean deploymentMode;

    @Inject
    public SourceControllerImpl(final IWebUiConfig webUiConfig, final ISerialiser serialiser) {
        this.webUiConfig = webUiConfig;
        this.serialiser = serialiser;
        this.tgJackson = (TgJackson) serialiser.getEngine(SerialiserEngines.JACKSON);
    }

    /**
     * Returns <code>true</code> in case where the server is in deployment mode, <code>false</code> -- in development mode.
     * <p>
     * At this stage deployment mode is activated in the case, where /resources/startup-resources.html and /resources/startup-resources-origin.html are different (which means that potentially /resources/startup-resources.html is vulcanized
     * version of /resources/startup-resources-origin.html or just changed intentionally to activate the deployment mode for testing purposes).
     *
     * After the first heavy comparison has been performed -- the flag is cached.
     *
     * @return
     */
    @Override
    public boolean isDeploymentMode() {
        if (deploymentMode == null) {
            final String startupResources = getSource("/resources/startup-resources.html");
            final String startupResourcesOrigin = getSource("/resources/startup-resources-origin.html");
            deploymentMode = !EntityUtils.equalsEx(startupResources, startupResourcesOrigin);
        }
        return deploymentMode;
    }

    @Override
    public void setDeploymentMode(final boolean deploymentMode) {
        if (this.deploymentMode != null) {
            throw new IllegalStateException("The [deployment mode == " + this.deploymentMode + "] has been already automatically populated (it cannot be overriden now). Please, ensure that no resource loading occurs before this setting.");
        }
        this.deploymentMode = deploymentMode;
    }

    /**
     * Reads the source and extracts the list of top-level (root) dependency URIs.
     *
     * @param source
     * @return
     */
    private static LinkedHashSet<String> getRootDependencies(final String source, final LinkedHashSet<String> currentRootDependencies) {
        final int commentStart = source.indexOf(COMMENT_START);
        // TODO enhance the logic to support whitespaces etc.?
        final int doubleQuotedStart = source.indexOf(DBL_QUOTED_HREF);
        final int singleQuotedStart = source.indexOf(SGL_QUOTED_HREF);

        if (doubleQuotedStart >= 0 || singleQuotedStart >= 0) {
            final boolean bothTypesPresent = doubleQuotedStart >= 0 && singleQuotedStart >= 0;
            final boolean doubleQuote = bothTypesPresent ? doubleQuotedStart < singleQuotedStart : (doubleQuotedStart >= 0);
            final int start = doubleQuote ? doubleQuotedStart : singleQuotedStart;
            if (commentStart >= 0) {
                if (commentStart < start) {
                    // remove comment and process the rest of source
                    final String temp = source.substring(commentStart + COMMENT_START.length());
                    final int indexOfUncommentedPart = temp.indexOf(COMMENT_END);
                    final String sourceWithoutComment = temp.substring(indexOfUncommentedPart + COMMENT_END.length());
                    return getRootDependencies(sourceWithoutComment, currentRootDependencies);
                } else {
                    return rootDependencies0(source, currentRootDependencies, start, doubleQuote);
                }
            } else {
                return rootDependencies0(source, currentRootDependencies, start, doubleQuote);
            }
        } else {
            return currentRootDependencies;
        }
//        old implementation:
//        final LinkedHashSet<String> set = new LinkedHashSet<String>(currentRootDependencies);
//        String curr = source;
//        // TODO enhance the logic to support whitespaces etc.?
//        while (curr.indexOf("href=\"") >= 0 || curr.indexOf("href='") >= 0) {
//            final boolean singleQuote = curr.indexOf("href='") >= 0;
//            final int startIndex = singleQuote ? curr.indexOf("href='") + 6 : curr.indexOf("href=\"") + 6;
//            final String nextCurr = curr.substring(startIndex);
//            final int endIndex = singleQuote ? nextCurr.indexOf("'") : nextCurr.indexOf("\"");
//            final String importURI = nextCurr.substring(0, endIndex);
//            set.add(importURI);
//            curr = nextCurr.substring(endIndex);
//        }
//
{'fraction_non_alphanumeric': 0.09748927379628158, 'fraction_numerical': 0.0024630541871921183, 'mean_word_length': 3.0603225806451615, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4560483', 'n_tokens_mistral': 3367, 'n_tokens_neox': 3269, 'n_words': 869}