<commit_before>package org.ovirt.engine.core.utils.branding;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.ovirt.engine.core.utils.EngineLocalConfig;
import org.ovirt.engine.core.utils.servlet.LocaleFilter;

/**
 * This class manages the available branding themes and changeable localized messages.
 */
public class BrandingManager {
    /**
     * The prefix of the keys in the properties.
     */
    public static final String WELCOME = "welcome";

    /**
     * The default branding path.
     */
    private static final String BRANDING_PATH = "branding"; //$NON-NLS-1$

    /**
     * The prefix denoting this is part of the branding.
     */
    private static final String BRAND_PREFIX = "obrand"; //$NON-NLS-1$

    /**
     * The place holder for the userLocale in the welcome page templates.
     */
    private static final String USER_LOCALE_HOLDER = "\\{userLocale\\}"; //$NON-NLS-1$
    /**
     * The prefix used for common messages.
     */
    private static final String COMMON_PREFIX = BRAND_PREFIX + ".common"; //$NON-NLS-1$

    /**
     * The regular expression {@code Pattern} to use to determine if a directory should be used
     * as a branding directory. The pattern is '.+\.brand' So anything ending in '.brand' will do.
     */
    private static final Pattern DIRECTORY_PATTERN = Pattern.compile(".+\\.brand"); //$NON-NLS-1$

    /**
     * The regular expression {@code Pattern} to use to find the replacement keys.
     */
    private static final Pattern TEMPLATE_PATTERN = Pattern.compile("\\{(\\D[\\w|\\.]*)\\}"); //$NON-NLS-1$

    /**
     * Only load branding themes for the current branding version. This allows for multiple version of a particular
     * branding theme to exist on the file system without interfering with each other. There is no backwards
     * compatibility, only ONE version will be valid at a time.
     */
    private static final int CURRENT_BRANDING_VERSION = 1;

    /**
     * A list of available {@code BrandingTheme}s.
     */
    private List<BrandingTheme> themes;

    /**
     * The root path of the branding themes.
     */
    private final File brandingRootPath;

    /**
     * Instance of the holder pattern, instance doesn't get initialized until needed. This removes
     * the need for synchronization and double locking pattern.
     */
    private static class Holder {
        /**
         * Instance of the BrandingManager.
         */
        static final BrandingManager instance;

        static {
            File etcDir;
            try {
                etcDir = EngineLocalConfig.getInstance().getEtcDir();
            } catch (IllegalArgumentException iae) {
                etcDir = new File(""); // Can't find etcDir, most likely unit tests, pretend there is no branding.
            }
            instance = new BrandingManager(etcDir);
        }
    }

    /**
     * ObjectMapper to translate map into Javascript.
     */
    private ObjectMapper objectMapper;

    /**
     * Constructor that takes a {@code File} object to configure the brandingRootPath.
     * @param etcDir A {@code File} pointing to the branding root path.
     */
    BrandingManager(final File etcDir) {
        brandingRootPath = new File(etcDir, BRANDING_PATH);
        objectMapper = new ObjectMapper();
    }

    /**
     * Get an instance of the {@code BrandingManager} with the default ETC_DIR.
     * @return A {@code BrandingManager}
     */
    public static BrandingManager getInstance() {
        return Holder.instance;
    }

    /**
     * Get a list of available {@code BrandingTheme}s.
     * @return A {@code List} of {@code BrandingTheme}s.
     */
    public synchronized List<BrandingTheme> getBrandingThemes() {
        if (themes == null && brandingRootPath.exists() && brandingRootPath.isDirectory()
                && brandingRootPath.canRead()) {
            themes = new ArrayList<BrandingTheme>();
            List<File> directories = Arrays.asList(
                    brandingRootPath.listFiles(new FileFilter() {
                        @Override
                        public boolean accept(final File file) {
                            return file.isDirectory() && DIRECTORY_PATTERN.matcher(file.getName()).matches();
                        }
                    }));
            Collections.sort(directories);
            for (File directory : directories) {
                BrandingTheme theme = new BrandingTheme(directory.getAbsolutePath(), brandingRootPath,
                        CURRENT_BRANDING_VERSION);
                if (theme.load()) {
                    themes.add(theme);
                }
            }
        }
        return themes;
    }

    /**
     * Get the message associated with the passed in key.
     * @param key The key to get the message for. For instance obrand.common.copy_right_notice.
     * @return The associated message in the default locale.
     */
    public String getMessage(final String key) {
        return getMessage(key, LocaleFilter.DEFAULT_LOCALE);
    }

    /**
     * Get the message associated with the passed in key.
     * @param key The key to get the message for. For instance obrand.common.copy_right_notice.
     * @param locale The locale to use to look up the message.
     * @return The associated message in the passed in locale.
     */
    public String getMessage(final String key, final Locale locale) {
        String result = "";
        // key needs to start with obrand.
        if (key != null && key.startsWith(BRAND_PREFIX + ".")) {
            String[] splitString = key.split("\\.");
            String prefix = (splitString.length >= 2) ? splitString[1] : "";
            if (prefix.length() > 0) {
                result = getMessageMap(prefix, locale).get(key.substring(key.indexOf(prefix) + prefix.length() + 1));
            }
        }<commit_msg>userportal,webadmin: fix WelcomePage unit test<commit_after>package org.ovirt.engine.core.utils.branding;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.ovirt.engine.core.utils.EngineLocalConfig;
import org.ovirt.engine.core.utils.servlet.LocaleFilter;

/**
 * This class manages the available branding themes and changeable localized messages.
 */
public class BrandingManager {
    /**
     * The prefix of the keys in the properties.
     */
    public static final String WELCOME = "welcome";

    /**
     * The default branding path.
     */
    private static final String BRANDING_PATH = "branding"; //$NON-NLS-1$

    /**
     * The prefix denoting this is part of the branding.
     */
    private static final String BRAND_PREFIX = "obrand"; //$NON-NLS-1$

    /**
     * The place holder for the userLocale in the welcome page templates.
     */
    private static final String USER_LOCALE_HOLDER = "\\{userLocale\\}"; //$NON-NLS-1$
    /**
     * The prefix used for common messages.
     */
    private static final String COMMON_PREFIX = BRAND_PREFIX + ".common"; //$NON-NLS-1$

    /**
     * The regular expression {@code Pattern} to use to determine if a directory should be used
     * as a branding directory. The pattern is '.+\.brand' So anything ending in '.brand' will do.
     */
    private static final Pattern DIRECTORY_PATTERN = Pattern.compile(".+\\.brand"); //$NON-NLS-1$

    /**
     * The regular expression {@code Pattern} to use to find the replacement keys.
     */
    private static final Pattern TEMPLATE_PATTERN = Pattern.compile("\\{(\\D[\\w|\\.]*)\\}"); //$NON-NLS-1$

    /**
     * Only load branding themes for the current branding version. This allows for multiple version of a particular
     * branding theme to exist on the file system without interfering with each other. There is no backwards
     * compatibility, only ONE version will be valid at a time.
     */
    private static final int CURRENT_BRANDING_VERSION = 1;

    /**
     * A list of available {@code BrandingTheme}s.
     */
    private List<BrandingTheme> themes;

    /**
     * The root path of the branding themes.
     */
    private final File brandingRootPath;

    /**
     * Instance of the holder pattern, instance doesn't get initialized until needed. This removes
     * the need for synchronization and double locking pattern.
     */
    private static class Holder {
        /**
         * Instance of the BrandingManager.
         */
        static final BrandingManager instance;

        static {
            File etcDir;
            try {
                etcDir = EngineLocalConfig.getInstance().getEtcDir();
            } catch (IllegalArgumentException iae) {
                etcDir = new File(""); // Can't find etcDir, most likely unit tests, pretend there is no branding.
            }
            instance = new BrandingManager(etcDir);
        }
    }

    /**
     * ObjectMapper to translate map into Javascript.
     */
    private ObjectMapper objectMapper;

    /**
     * Constructor that takes a {@code File} object to configure the brandingRootPath.
     * @param etcDir A {@code File} pointing to the branding root path.
     */
    BrandingManager(final File etcDir) {
        brandingRootPath = new File(etcDir, BRANDING_PATH);
        objectMapper = new ObjectMapper();
    }

    /**
     * Get an instance of the {@code BrandingManager} with the default ETC_DIR.
     * @return A {@code BrandingManager}
     */
    public static BrandingManager getInstance() {
        return Holder.instance;
    }

    /**
     * Get a list of available {@code BrandingTheme}s.
     * @return A {@code List} of {@code BrandingTheme}s.
     */
    public synchronized List<BrandingTheme> getBrandingThemes() {
        if (themes == null && brandingRootPath.exists() && brandingRootPath.isDirectory()
                && brandingRootPath.canRead()) {
            themes = new ArrayList<BrandingTheme>();
            List<File> directories = Arrays.asList(
                    brandingRootPath.listFiles(new FileFilter() {
                        @Override
                        public boolean accept(final File file) {
                            return file.isDirectory() && DIRECTORY_PATTERN.matcher(file.getName()).matches();
                        }
                    }));
            Collections.sort(directories);
            for (File directory : directories) {
                BrandingTheme theme = new BrandingTheme(directory.getAbsolutePath(), brandingRootPath,
                        CURRENT_BRANDING_VERSION);
                if (theme.load()) {
                    themes.add(theme);
                }
            }
        }
        return themes != null ? themes : new ArrayList<BrandingTheme>();
    }

    /**
     * Get the message associated with the passed in key.
     * @param key The key to get the message for. For instance obrand.common.copy_right_notice.
     * @return The associated message in the default locale.
     */
    public String getMessage(final String key) {
        return getMessage(key, LocaleFilter.DEFAULT_LOCALE);
    }

    /**
     * Get the message associated with the passed in key.
     * @param key The key to get the message for. For instance obrand.common.copy_right_notice.
     * @param locale The locale to use to look up the message.
     * @return The associated message in the passed in locale.
     */
    public String getMessage(final String key, final Locale locale) {
        String result = "";
        // key needs to start with obrand.
        if (key != null && key.startsWith(BRAND_PREFIX + ".")) {
            String[] splitString = key.split("\\.");
            String prefix = (splitString.length >= 2) ? splitString[1] : "";
            if (prefix.length() > 0) {
                result = getMessageMap(prefix, locale).get(key.substring(key.indexOf(prefix) + prefix.length() + 1));
            }
        }
{'fraction_non_alphanumeric': 0.10149206095906806, 'fraction_numerical': 0.0017553658341977181, 'mean_word_length': 2.289763779527559, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 16, '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': '1924607', 'n_tokens_mistral': 3439, 'n_tokens_neox': 3263, 'n_words': 1088}