<commit_before>/*
 * Copyright 2011-2021 B2i Healthcare Pte Ltd, http://b2i.sg
 * 
 * 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.b2international.snowowl.core.codesystem;

import java.util.Map;
import java.util.Optional;

import org.hibernate.validator.constraints.NotEmpty;

import com.b2international.commons.StringUtils;
import com.b2international.commons.exceptions.AlreadyExistsException;
import com.b2international.commons.exceptions.BadRequestException;
import com.b2international.snowowl.core.RepositoryManager;
import com.b2international.snowowl.core.ResourceURI;
import com.b2international.snowowl.core.ServiceProvider;
import com.b2international.snowowl.core.branch.Branch;
import com.b2international.snowowl.core.branch.Branches;
import com.b2international.snowowl.core.domain.RepositoryContext;
import com.b2international.snowowl.core.domain.TransactionContext;
import com.b2international.snowowl.core.internal.ResourceDocument.Builder;
import com.b2international.snowowl.core.repository.RepositoryRequests;
import com.b2international.snowowl.core.request.BaseResourceCreateRequest;
import com.b2international.snowowl.core.request.ResourceRequests;
import com.b2international.snowowl.core.version.Version;
import com.google.common.base.Strings;

/**
 * @since 4.7
 */
final class CodeSystemCreateRequest extends BaseResourceCreateRequest {

	private static final long serialVersionUID = 2L;

	// specialized resource fields
	// optional OID, but if defined it must be unique
	String oid;
	
	String branchPath;
	
	@NotEmpty
	String toolingId;
	
	ResourceURI extensionOf;
	ResourceURI upgradeOf;
	Map<String, Object> settings;
	
	private transient String parentPath;
	
	CodeSystemCreateRequest() {}

	@Override
	protected Builder completeResource(Builder builder) {
		return builder.resourceType(CodeSystem.RESOURCE_TYPE)
				.oid(oid)
				.branchPath(branchPath)
				.toolingId(toolingId)
				.extensionOf(extensionOf)
				.upgradeOf(upgradeOf)
				.settings(settings);
	}
	
	@Override
	protected void preExecute(final TransactionContext context) {
		// Create branch if null or empty path was specified in the request
		final boolean createBranch = StringUtils.isEmpty(branchPath);
		
		final Optional<Version> extensionOfVersion = checkCodeSystem(context, createBranch);
		
		// Set the parent path if a branch needs to be created
		if (createBranch) {
			parentPath = extensionOfVersion
				.map(Version::getBranchPath)
				.orElse(Branch.MAIN_PATH); // TODO totally separate branching system?? MAIN could be removed
		}

		checkBranchPath(context, createBranch);
		checkSettings();
		
		// Set branchPath to the path of the created branch 
		if (createBranch) {
			branchPath = RepositoryRequests.branching()
				.prepareCreate()
				.setParent(parentPath)
				.setName(getId())
				.build(toolingId)
				.getRequest()
				.execute(context);
		}
	}

	private void checkBranchPath(final RepositoryContext context, final boolean create) {
		// If no branch is created, the branch should already exist
		if (!create && !branchExists(branchPath, context)) {
			throw new BadRequestException("Branch path '%s' should point to an existing branch if given.", branchPath);
		}
		
		// If the branch should be created, it branch should not exist, however 
		if (create) {
			final String newBranchPath = Branch.get(parentPath, getId());
			if (branchExists(newBranchPath, context)) {
				throw new AlreadyExistsException("Code system branch", newBranchPath);
			}
		}
	}

	private Optional<Version> checkCodeSystem(final RepositoryContext context, final boolean create) {
		// OID must be unique if defined
		if (!Strings.isNullOrEmpty(oid)) {
			final boolean existingOid = CodeSystemRequests.prepareSearchCodeSystem()
					.setLimit(0)
					.filterByOid(oid)
					.build()
					.execute(context)
					.getTotal() > 0;
			if (existingOid) {
				throw new AlreadyExistsException("Resource", "oid", oid);
			}<commit_msg>fix!: extends OID validation to every resource<commit_after>/*
 * Copyright 2011-2021 B2i Healthcare Pte Ltd, http://b2i.sg
 * 
 * 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.b2international.snowowl.core.codesystem;

import java.util.Map;
import java.util.Optional;

import org.hibernate.validator.constraints.NotEmpty;

import com.b2international.commons.StringUtils;
import com.b2international.commons.exceptions.AlreadyExistsException;
import com.b2international.commons.exceptions.BadRequestException;
import com.b2international.snowowl.core.RepositoryManager;
import com.b2international.snowowl.core.ResourceURI;
import com.b2international.snowowl.core.ServiceProvider;
import com.b2international.snowowl.core.branch.Branch;
import com.b2international.snowowl.core.branch.Branches;
import com.b2international.snowowl.core.domain.RepositoryContext;
import com.b2international.snowowl.core.domain.TransactionContext;
import com.b2international.snowowl.core.internal.ResourceDocument.Builder;
import com.b2international.snowowl.core.repository.RepositoryRequests;
import com.b2international.snowowl.core.request.BaseResourceCreateRequest;
import com.b2international.snowowl.core.request.ResourceRequests;
import com.b2international.snowowl.core.version.Version;
import com.google.common.base.Strings;

/**
 * @since 4.7
 */
final class CodeSystemCreateRequest extends BaseResourceCreateRequest {

	private static final long serialVersionUID = 2L;

	// specialized resource fields
	// optional OID, but if defined it must be unique
	String oid;
	
	String branchPath;
	
	@NotEmpty
	String toolingId;
	
	ResourceURI extensionOf;
	ResourceURI upgradeOf;
	Map<String, Object> settings;
	
	private transient String parentPath;
	
	CodeSystemCreateRequest() {}

	@Override
	protected Builder completeResource(Builder builder) {
		return builder.resourceType(CodeSystem.RESOURCE_TYPE)
				.oid(oid)
				.branchPath(branchPath)
				.toolingId(toolingId)
				.extensionOf(extensionOf)
				.upgradeOf(upgradeOf)
				.settings(settings);
	}
	
	@Override
	protected void preExecute(final TransactionContext context) {
		// Create branch if null or empty path was specified in the request
		final boolean createBranch = StringUtils.isEmpty(branchPath);
		
		final Optional<Version> extensionOfVersion = checkCodeSystem(context, createBranch);
		
		// Set the parent path if a branch needs to be created
		if (createBranch) {
			parentPath = extensionOfVersion
				.map(Version::getBranchPath)
				.orElse(Branch.MAIN_PATH); // TODO totally separate branching system?? MAIN could be removed
		}

		checkBranchPath(context, createBranch);
		checkSettings();
		
		// Set branchPath to the path of the created branch 
		if (createBranch) {
			branchPath = RepositoryRequests.branching()
				.prepareCreate()
				.setParent(parentPath)
				.setName(getId())
				.build(toolingId)
				.getRequest()
				.execute(context);
		}
	}

	private void checkBranchPath(final RepositoryContext context, final boolean create) {
		// If no branch is created, the branch should already exist
		if (!create && !branchExists(branchPath, context)) {
			throw new BadRequestException("Branch path '%s' should point to an existing branch if given.", branchPath);
		}
		
		// If the branch should be created, it branch should not exist, however 
		if (create) {
			final String newBranchPath = Branch.get(parentPath, getId());
			if (branchExists(newBranchPath, context)) {
				throw new AlreadyExistsException("Code system branch", newBranchPath);
			}
		}
	}

	private Optional<Version> checkCodeSystem(final RepositoryContext context, final boolean create) {
		// OID must be unique if defined
		if (!Strings.isNullOrEmpty(oid)) {
			final boolean existingOid = ResourceRequests.prepareSearch()
					.setLimit(0)
					.filterByOid(oid)
					.build()
					.execute(context)
					.getTotal() > 0;
			if (existingOid) {
				throw new AlreadyExistsException("Resource", "oid", oid);
			}
{'fraction_non_alphanumeric': 0.0896358543417367, 'fraction_numerical': 0.00784313725490196, 'mean_word_length': 4.568309419837804, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, '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': '5223163', 'n_tokens_mistral': 2841, 'n_tokens_neox': 2501, 'n_words': 716}