<commit_before>/*
 * Copyright 2016 EPAM Systems
 * 
 * 
 * This file is part of EPAM Report Portal.
 * https://github.com/reportportal/commons-dao
 * 
 * Report Portal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Report Portal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Report Portal.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.epam.ta.reportportal.database.dao;

import com.epam.ta.reportportal.config.CacheConfiguration;
import com.epam.ta.reportportal.database.entity.Launch;
import com.epam.ta.reportportal.database.entity.Project;
import com.epam.ta.reportportal.database.entity.Status;
import com.epam.ta.reportportal.database.entity.item.TestItem;
import com.epam.ta.reportportal.database.entity.item.issue.TestItemIssueType;
import com.epam.ta.reportportal.database.entity.statistics.StatisticSubType;
import com.epam.ta.reportportal.database.search.Filter;
import com.epam.ta.reportportal.database.search.QueryBuilder;
import com.epam.ta.reportportal.database.search.Queryable;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.DocumentCallbackHandler;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.time.Duration;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.epam.ta.reportportal.database.dao.aggregation.AddFieldsOperation.addFields;
import static com.epam.ta.reportportal.database.dao.aggregation.AggregationUtils.matchOperationFromFilter;
import static com.epam.ta.reportportal.database.dao.aggregation.SortingOperation.sorting;
import static com.epam.ta.reportportal.database.entity.Status.IN_PROGRESS;
import static com.epam.ta.reportportal.database.search.ModifiableQueryBuilder.findModifiedLaterThanPeriod;
import static com.epam.ta.reportportal.database.search.UpdateStatisticsQueryBuilder.*;
import static java.util.stream.Collectors.toList;
import static org.bson.types.ObjectId.isValid;
import static org.springframework.data.domain.Sort.Direction.DESC;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

/**
 * Implementations of custom methods which are cannot be generated via default Spring's repositories mechanism
 *
 * @author <NAME>
 * @author Andrei_Ramanchuk
 */
public class LaunchRepositoryCustomImpl implements LaunchRepositoryCustom {

	public static final String PROJECT_ID_REFERENCE = "projectRef";
	public static final String LAUNCH_ID_REFERENCE = "launchRef";
	public static final String USER_ID_REFERENCE = "userRef";
	public static final String ID_REFERENCE = "id";
	public static final String NUMBER = "number";
	public static final String MODE = "mode";
	public static final String STATISTICS = "statistics";
	public static final String START_TIME = "start_time";
	public static final String STATUS = "status";
	public static final String NAME = "name";
	public static final int AUTOCOMPLETE_LIMITATION = 50;

	//useful constants for latest launches
	private static final String ORIGINAL = "original";
	private static final String RESULT = "result";

	//useful constants for cumulative
	private static final String TAGS = "tags";
	private static final String REGEX = "^\\Q%s\\E:.+";

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public List<Launch> findLaunchIdsByProject(Project project) {
		Query query = query(where(PROJECT_ID_REFERENCE).is(isValid(project.getId()) ? new ObjectId(project.getId()) : project.getId()));
		query.fields().include(ID_REFERENCE);
		return mongoTemplate.find(query, Launch.class);
	}

	@Override
	public void updateExecutionStatistics(TestItem item) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()), fromItemStatusAware(item.getStatus(), 1, 1), Launch.class);
	}

	@Override
	public void updateIssueStatistics(TestItem item, Project.Configuration settings) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()),
				fromIssueTypeAware(settings.getByLocator(item.getIssue().getIssueType()), 1),
				Launch.class
		);
	}

	@Override
	public void dropIssueStatisticsType(String id, StatisticSubType type) {
		mongoTemplate.updateMulti(getLaunchQuery(id), dropIssueTypeAware(type), Launch.class);
	}

	@Override
	public List<String> findLaunchIdsByProjectIds(List<String> ids) {
		Aggregation aggregation = newAggregation(match(where(PROJECT_ID_REFERENCE).in(ids)), group(ID_REFERENCE));
		AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, Launch.class, Map.class);
		return results.getMappedResults().stream().map(it -> it.get("_id").toString()).collect(toList());
	}

	@Override
	public void updateHasRetries(String id, boolean hasRetries) {
		mongoTemplate.updateFirst(
				new Query().addCriteria(where(LAUNCH_ID_REFERENCE).is(id)),
				Update.update("hasRetries", hasRetries),
				Launch.class
		);

	}

	@Override
	public void resetIssueStatistics(TestItem item, Project.Configuration settings) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()),
				fromIssueTypeAware(settings.getByLocator(item.getIssue().getIssueType()), -1),
				Launch.class
		);
	}

	@Override
	public void resetExecutionStatistics(TestItem item) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()), fromItemStatusAware(item.getStatus(), -1, -1), Launch.class);
	}

	@Override<commit_msg>fix issue with update retries<commit_after>/*
 * Copyright 2016 EPAM Systems
 * 
 * 
 * This file is part of EPAM Report Portal.
 * https://github.com/reportportal/commons-dao
 * 
 * Report Portal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Report Portal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Report Portal.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.epam.ta.reportportal.database.dao;

import com.epam.ta.reportportal.config.CacheConfiguration;
import com.epam.ta.reportportal.database.entity.Launch;
import com.epam.ta.reportportal.database.entity.Project;
import com.epam.ta.reportportal.database.entity.Status;
import com.epam.ta.reportportal.database.entity.item.TestItem;
import com.epam.ta.reportportal.database.entity.item.issue.TestItemIssueType;
import com.epam.ta.reportportal.database.entity.statistics.StatisticSubType;
import com.epam.ta.reportportal.database.search.Filter;
import com.epam.ta.reportportal.database.search.QueryBuilder;
import com.epam.ta.reportportal.database.search.Queryable;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.DocumentCallbackHandler;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.time.Duration;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.epam.ta.reportportal.database.dao.aggregation.AddFieldsOperation.addFields;
import static com.epam.ta.reportportal.database.dao.aggregation.AggregationUtils.matchOperationFromFilter;
import static com.epam.ta.reportportal.database.dao.aggregation.SortingOperation.sorting;
import static com.epam.ta.reportportal.database.entity.Status.IN_PROGRESS;
import static com.epam.ta.reportportal.database.search.ModifiableQueryBuilder.findModifiedLaterThanPeriod;
import static com.epam.ta.reportportal.database.search.UpdateStatisticsQueryBuilder.*;
import static java.util.stream.Collectors.toList;
import static org.bson.types.ObjectId.isValid;
import static org.springframework.data.domain.Sort.Direction.DESC;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

/**
 * Implementations of custom methods which are cannot be generated via default Spring's repositories mechanism
 *
 * @author <NAME>
 * @author Andrei_Ramanchuk
 */
public class LaunchRepositoryCustomImpl implements LaunchRepositoryCustom {

	public static final String PROJECT_ID_REFERENCE = "projectRef";
	public static final String LAUNCH_ID_REFERENCE = "launchRef";
	public static final String USER_ID_REFERENCE = "userRef";
	public static final String ID_REFERENCE = "id";
	public static final String NUMBER = "number";
	public static final String MODE = "mode";
	public static final String STATISTICS = "statistics";
	public static final String START_TIME = "start_time";
	public static final String STATUS = "status";
	public static final String NAME = "name";
	public static final int AUTOCOMPLETE_LIMITATION = 50;

	//useful constants for latest launches
	private static final String ORIGINAL = "original";
	private static final String RESULT = "result";

	//useful constants for cumulative
	private static final String TAGS = "tags";
	private static final String REGEX = "^\\Q%s\\E:.+";

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public List<Launch> findLaunchIdsByProject(Project project) {
		Query query = query(where(PROJECT_ID_REFERENCE).is(isValid(project.getId()) ? new ObjectId(project.getId()) : project.getId()));
		query.fields().include(ID_REFERENCE);
		return mongoTemplate.find(query, Launch.class);
	}

	@Override
	public void updateExecutionStatistics(TestItem item) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()), fromItemStatusAware(item.getStatus(), 1, 1), Launch.class);
	}

	@Override
	public void updateIssueStatistics(TestItem item, Project.Configuration settings) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()),
				fromIssueTypeAware(settings.getByLocator(item.getIssue().getIssueType()), 1),
				Launch.class
		);
	}

	@Override
	public void dropIssueStatisticsType(String id, StatisticSubType type) {
		mongoTemplate.updateMulti(getLaunchQuery(id), dropIssueTypeAware(type), Launch.class);
	}

	@Override
	public List<String> findLaunchIdsByProjectIds(List<String> ids) {
		Aggregation aggregation = newAggregation(match(where(PROJECT_ID_REFERENCE).in(ids)), group(ID_REFERENCE));
		AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, Launch.class, Map.class);
		return results.getMappedResults().stream().map(it -> it.get("_id").toString()).collect(toList());
	}

	@Override
	public void updateHasRetries(String id, boolean hasRetries) {
		mongoTemplate.updateFirst(
				new Query().addCriteria(where(ID_REFERENCE).is(id)),
				Update.update("hasRetries", hasRetries),
				Launch.class
		);

	}

	@Override
	public void resetIssueStatistics(TestItem item, Project.Configuration settings) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()),
				fromIssueTypeAware(settings.getByLocator(item.getIssue().getIssueType()), -1),
				Launch.class
		);
	}

	@Override
	public void resetExecutionStatistics(TestItem item) {
		mongoTemplate.updateMulti(getLaunchQuery(item.getLaunchRef()), fromItemStatusAware(item.getStatus(), -1, -1), Launch.class);
	}

	@Override
{'fraction_non_alphanumeric': 0.10318218563974425, 'fraction_numerical': 0.0019107812155508194, 'mean_word_length': 5.876200101061142, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 2, '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': '683345', 'n_tokens_mistral': 4100, 'n_tokens_neox': 3939, 'n_words': 887}