<commit_before>/*
 * Copyright (C) 2004-2016 Polarion Software
 *
 * Licensed 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 com.polarion.alm.extensions.codereview;

import java.io.IOException;
import java.io.InputStream;
import java.security.PrivilegedExceptionAction;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Function;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.polarion.alm.shared.api.utils.links.HtmlLink;
import com.polarion.alm.shared.api.utils.links.HtmlLinkFactory;
import com.polarion.alm.tracker.ITrackerService;
import com.polarion.alm.tracker.model.IStatusOpt;
import com.polarion.alm.tracker.model.ITrackerUser;
import com.polarion.alm.tracker.model.IWorkItem;
import com.polarion.alm.tracker.model.IWorkflowAction;
import com.polarion.core.util.RunnableWEx;
import com.polarion.platform.TransactionExecuter;
import com.polarion.platform.context.IContextService;
import com.polarion.platform.core.PlatformContext;
import com.polarion.platform.persistence.IEnumOption;
import com.polarion.platform.persistence.model.IPObjectList;
import com.polarion.platform.security.ISecurityService;
import com.polarion.platform.service.repository.IRepositoryService;
import com.polarion.subterra.base.data.identification.IContextId;
import com.polarion.subterra.base.location.ILocation;

@SuppressWarnings("nls")
public class Parameters {

    private static @NotNull IContextService contextService = PlatformContext.getPlatform().lookupService(IContextService.class);
    private static @NotNull IRepositoryService repositoryService = PlatformContext.getPlatform().lookupService(IRepositoryService.class);
    private static @NotNull ISecurityService securityService = PlatformContext.getPlatform().lookupService(ISecurityService.class);
    private static @NotNull ITrackerService trackerService = PlatformContext.getPlatform().lookupService(ITrackerService.class);

    // URL parameters
    private static final String PARAM_WORK_ITEM_ID = CodeReviewServlet.PARAM_ID;
    private static final String PARAM_PROJECT_ID = "projectId";
    private static final String PARAM_AGGREGATED_COMPARE = "aggregated";
    private static final String PARAM_COMPARE_ALL = "compareAll";
    private static final String PARAM_WORKFLOW_ACTION = "workflowAction";

    // configuration parameters
    private static final String CONFIG_LAST_REVIEWED_REVISION_FIELD = "lastReviewedRevisionField";
    private static final String CONFIG_REVIEWED_REVISIONS_FIELD = "reviewedRevisionsField";
    private static final String CONFIG_REVIEWER_FIELD = "reviewerField";
    private static final String CONFIG_IN_REVIEW_STATUS = "inReviewStatus";
    private static final String CONFIG_SUCCESSFUL_REVIEW_WF_ACTION = "successfulReviewWorkflowAction";
    private static final String CONFIG_SUCCESSFUL_REVIEW_RESOLUTION = "successfulReviewResolution";
    private static final String CONFIG_FAST_TRACK_PERMITTED_LOCATION_PATTERN = "fastTrackPermittedLocationPattern";
    private static final String CONFIG_FAST_TRACK_REVIEWER = "fastTrackReviewer";
    private static final String CONFIG_UNRESOLVED_WORK_ITEM_WITH_REVISIONS_NEEDS_TIMEPOINT = "unresolvedWorkItemWithRevisionsNeedsTimePoint";
    private static final String CONFIG_REVIEWER_ROLE = "reviewerRole";
    private static final String CONFIG_PAST_REVIEWERS = "pastReviewers";
    private static final String CONFIG_PREVENT_REVIEW_CONFLICTS = "preventReviewConflicts";

    public static enum WorkflowAction {
        successfulReview;
    }

    private final @NotNull IWorkItem workItem;
    private final boolean aggregatedCompare;
    private final boolean compareAll;
    private final @Nullable WorkflowAction workflowAction;

    private final @Nullable String lastReviewedRevisionField;
    private final @Nullable String reviewedRevisionsField;
    private final @Nullable String reviewerField;
    private final @Nullable String inReviewStatus;
    private final @Nullable String successfulReviewWorkflowAction;
    private final @Nullable String successfulReviewResolution;
    private final @Nullable Pattern fastTrackPermittedLocationPattern;
    private final @Nullable String fastTrackReviewer;
    private final boolean unresolvedWorkItemWithRevisionsNeedsTimePoint;
    private final @Nullable String reviewerRole;
    private final @NotNull Collection<String> pastReviewers;
    private final boolean preventReviewConflicts;

    private Parameters(@NotNull IWorkItem workItem, boolean aggregatedCompare, boolean compareAll, @Nullable WorkflowAction workflowAction, @NotNull Function<IWorkItem, Properties> configurationLoader) {
        super();
        this.workItem = workItem;
        this.aggregatedCompare = aggregatedCompare;
        this.compareAll = compareAll;
        this.workflowAction = workflowAction;
        Properties configuration = configurationLoader.apply(workItem);
        lastReviewedRevisionField = configuration.getProperty(CONFIG_LAST_REVIEWED_REVISION_FIELD);
        reviewedRevisionsField = configuration.getProperty(CONFIG_REVIEWED_REVISIONS_FIELD);
        reviewerField = configuration.getProperty(CONFIG_REVIEWER_FIELD);
        inReviewStatus = configuration.getProperty(CONFIG_IN_REVIEW_STATUS);
        successfulReviewWorkflowAction = configuration.getProperty(CONFIG_SUCCESSFUL_REVIEW_WF_ACTION);
        successfulReviewResolution = configuration.getProperty(CONFIG_SUCCESSFUL_REVIEW_RESOLUTION);
        String fastTrackPermittedLocationPatternStr = configuration.getProperty(CONFIG_FAST_TRACK_PERMITTED_LOCATION_PATTERN);
        fastTrackPermittedLocationPattern = Pattern.compile(fastTrackPermittedLocationPatternStr);
        fastTrackReviewer = configuration.getProperty(CONFIG_FAST_TRACK_REVIEWER);
        unresolvedWorkItemWithRevisionsNeedsTimePoint = Boolean.parseBoolean(configuration.getProperty(CONFIG_UNRESOLVED_WORK_ITEM_WITH_REVISIONS_NEEDS_TIMEPOINT));
        reviewerRole = configuration.getProperty(CONFIG_REVIEWER_ROLE);
        String pastReviewersString = configuration.getProperty(CONFIG_PAST_REVIEWERS);
        if (pastReviewersString != null) {
            pastReviewers = new HashSet(Arrays.asList(pastReviewersString.split("\\s+")));
        } else {
            pastReviewers = Collections.EMPTY_SET;
        }
        preventReviewConflicts = Boolean.parseBoolean(configuration.getProperty(CONFIG_PREVENT_REVIEW_CONFLICTS));
    }

    public static @NotNull Function<IWorkItem, Properties> repositoryConfigurationLoader() {
        return wi -> loadConfiguration(wi);
    }

    public static @NotNull Function<IWorkItem, Properties> perContextCachingConfigurationLoader(@NotNull Function<IWorkItem, Properties> loader) {
        Map<IContextId, Properties> cache = new HashMap<>();
        return wi -> {
            IContextId contextId = wi.getContextId();
            Properties properties = cache.get(contextId);
            if (properties == null) {
                properties = loader.apply(wi);<commit_msg>DPP-105279 - fastTrackPermittedLocationPattern is optional<commit_after>/*
 * Copyright (C) 2004-2016 Polarion Software
 *
 * Licensed 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 com.polarion.alm.extensions.codereview;

import java.io.IOException;
import java.io.InputStream;
import java.security.PrivilegedExceptionAction;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Function;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.polarion.alm.shared.api.utils.links.HtmlLink;
import com.polarion.alm.shared.api.utils.links.HtmlLinkFactory;
import com.polarion.alm.tracker.ITrackerService;
import com.polarion.alm.tracker.model.IStatusOpt;
import com.polarion.alm.tracker.model.ITrackerUser;
import com.polarion.alm.tracker.model.IWorkItem;
import com.polarion.alm.tracker.model.IWorkflowAction;
import com.polarion.core.util.RunnableWEx;
import com.polarion.platform.TransactionExecuter;
import com.polarion.platform.context.IContextService;
import com.polarion.platform.core.PlatformContext;
import com.polarion.platform.persistence.IEnumOption;
import com.polarion.platform.persistence.model.IPObjectList;
import com.polarion.platform.security.ISecurityService;
import com.polarion.platform.service.repository.IRepositoryService;
import com.polarion.subterra.base.data.identification.IContextId;
import com.polarion.subterra.base.location.ILocation;

@SuppressWarnings("nls")
public class Parameters {

    private static @NotNull IContextService contextService = PlatformContext.getPlatform().lookupService(IContextService.class);
    private static @NotNull IRepositoryService repositoryService = PlatformContext.getPlatform().lookupService(IRepositoryService.class);
    private static @NotNull ISecurityService securityService = PlatformContext.getPlatform().lookupService(ISecurityService.class);
    private static @NotNull ITrackerService trackerService = PlatformContext.getPlatform().lookupService(ITrackerService.class);

    // URL parameters
    private static final String PARAM_WORK_ITEM_ID = CodeReviewServlet.PARAM_ID;
    private static final String PARAM_PROJECT_ID = "projectId";
    private static final String PARAM_AGGREGATED_COMPARE = "aggregated";
    private static final String PARAM_COMPARE_ALL = "compareAll";
    private static final String PARAM_WORKFLOW_ACTION = "workflowAction";

    // configuration parameters
    private static final String CONFIG_LAST_REVIEWED_REVISION_FIELD = "lastReviewedRevisionField";
    private static final String CONFIG_REVIEWED_REVISIONS_FIELD = "reviewedRevisionsField";
    private static final String CONFIG_REVIEWER_FIELD = "reviewerField";
    private static final String CONFIG_IN_REVIEW_STATUS = "inReviewStatus";
    private static final String CONFIG_SUCCESSFUL_REVIEW_WF_ACTION = "successfulReviewWorkflowAction";
    private static final String CONFIG_SUCCESSFUL_REVIEW_RESOLUTION = "successfulReviewResolution";
    private static final String CONFIG_FAST_TRACK_PERMITTED_LOCATION_PATTERN = "fastTrackPermittedLocationPattern";
    private static final String CONFIG_FAST_TRACK_REVIEWER = "fastTrackReviewer";
    private static final String CONFIG_UNRESOLVED_WORK_ITEM_WITH_REVISIONS_NEEDS_TIMEPOINT = "unresolvedWorkItemWithRevisionsNeedsTimePoint";
    private static final String CONFIG_REVIEWER_ROLE = "reviewerRole";
    private static final String CONFIG_PAST_REVIEWERS = "pastReviewers";
    private static final String CONFIG_PREVENT_REVIEW_CONFLICTS = "preventReviewConflicts";

    public static enum WorkflowAction {
        successfulReview;
    }

    private final @NotNull IWorkItem workItem;
    private final boolean aggregatedCompare;
    private final boolean compareAll;
    private final @Nullable WorkflowAction workflowAction;

    private final @Nullable String lastReviewedRevisionField;
    private final @Nullable String reviewedRevisionsField;
    private final @Nullable String reviewerField;
    private final @Nullable String inReviewStatus;
    private final @Nullable String successfulReviewWorkflowAction;
    private final @Nullable String successfulReviewResolution;
    private final @Nullable Pattern fastTrackPermittedLocationPattern;
    private final @Nullable String fastTrackReviewer;
    private final boolean unresolvedWorkItemWithRevisionsNeedsTimePoint;
    private final @Nullable String reviewerRole;
    private final @NotNull Collection<String> pastReviewers;
    private final boolean preventReviewConflicts;

    private Parameters(@NotNull IWorkItem workItem, boolean aggregatedCompare, boolean compareAll, @Nullable WorkflowAction workflowAction, @NotNull Function<IWorkItem, Properties> configurationLoader) {
        super();
        this.workItem = workItem;
        this.aggregatedCompare = aggregatedCompare;
        this.compareAll = compareAll;
        this.workflowAction = workflowAction;
        Properties configuration = configurationLoader.apply(workItem);
        lastReviewedRevisionField = configuration.getProperty(CONFIG_LAST_REVIEWED_REVISION_FIELD);
        reviewedRevisionsField = configuration.getProperty(CONFIG_REVIEWED_REVISIONS_FIELD);
        reviewerField = configuration.getProperty(CONFIG_REVIEWER_FIELD);
        inReviewStatus = configuration.getProperty(CONFIG_IN_REVIEW_STATUS);
        successfulReviewWorkflowAction = configuration.getProperty(CONFIG_SUCCESSFUL_REVIEW_WF_ACTION);
        successfulReviewResolution = configuration.getProperty(CONFIG_SUCCESSFUL_REVIEW_RESOLUTION);
        String fastTrackPermittedLocationPatternStr = configuration.getProperty(CONFIG_FAST_TRACK_PERMITTED_LOCATION_PATTERN);
        if (fastTrackPermittedLocationPatternStr != null) {
            fastTrackPermittedLocationPattern = Pattern.compile(fastTrackPermittedLocationPatternStr);
        } else {
            fastTrackPermittedLocationPattern = null;
        }
        fastTrackReviewer = configuration.getProperty(CONFIG_FAST_TRACK_REVIEWER);
        unresolvedWorkItemWithRevisionsNeedsTimePoint = Boolean.parseBoolean(configuration.getProperty(CONFIG_UNRESOLVED_WORK_ITEM_WITH_REVISIONS_NEEDS_TIMEPOINT));
        reviewerRole = configuration.getProperty(CONFIG_REVIEWER_ROLE);
        String pastReviewersString = configuration.getProperty(CONFIG_PAST_REVIEWERS);
        if (pastReviewersString != null) {
            pastReviewers = new HashSet(Arrays.asList(pastReviewersString.split("\\s+")));
        } else {
            pastReviewers = Collections.EMPTY_SET;
        }
        preventReviewConflicts = Boolean.parseBoolean(configuration.getProperty(CONFIG_PREVENT_REVIEW_CONFLICTS));
    }

    public static @NotNull Function<IWorkItem, Properties> repositoryConfigurationLoader() {
        return wi -> loadConfiguration(wi);
    }

    public static @NotNull Function<IWorkItem, Properties> perContextCachingConfigurationLoader(@NotNull Function<IWorkItem, Properties> loader) {
        Map<IContextId, Properties> cache = new HashMap<>();
        return wi -> {
            IContextId contextId = wi.getContextId();
            Properties properties = cache.get(contextId);
            if (properties == null) {
                properties = loader.apply(wi);
{'fraction_non_alphanumeric': 0.0699309478970496, 'fraction_numerical': 0.0018832391713747645, 'mean_word_length': 5.259724950884086, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '7057069', 'n_tokens_mistral': 4246, 'n_tokens_neox': 4119, 'n_words': 954}