Search in sources :

Example 1 with ConflictException

use of com.b2international.commons.exceptions.ConflictException in project snow-owl by b2ihealthcare.

the class CodeSystemUpgradeSynchronizationRequest method execute.

@Override
public Boolean execute(RepositoryContext context) {
    final String message = String.format("Merge %s into %s", source, codeSystemId);
    CodeSystem codeSystem = CodeSystemRequests.prepareGetCodeSystem(codeSystemId.getResourceId()).build().execute(context);
    if (codeSystem.getUpgradeOf() == null) {
        throw new BadRequestException("Code System '%s' is not an Upgrade Code System. It cannot be synchronized with '%s'.", codeSystemId, source);
    }
    final String sourceBranchPath = context.service(ResourceURIPathResolver.class).resolve(context, List.of(source)).stream().findFirst().get();
    // merge all changes from the source to the current upgrade of branch
    final Merge merge = RepositoryRequests.merging().prepareCreate().setSource(sourceBranchPath).setTarget(codeSystem.getBranchPath()).setUserId(context.service(User.class).getUsername()).setCommitComment(message).setSquash(false).build(codeSystem.getToolingId()).getRequest().execute(context);
    if (merge.getStatus() != Merge.Status.COMPLETED) {
        // report conflicts
        ApiError apiError = merge.getApiError();
        Collection<MergeConflict> conflicts = merge.getConflicts();
        context.log().error("Failed to sync source CodeSystem content to upgrade CodeSystem. Error: {}. Conflicts: {}", apiError.getMessage(), conflicts);
        throw new ConflictException("Upgrade code system synchronization can not be performed due to conflicting content errors.").withAdditionalInfo(Map.of("conflicts", conflicts, "mergeError", apiError.getMessage()));
    }
    if (!codeSystem.getUpgradeOf().equals(source)) {
        return new BranchRequest<>(Branch.MAIN_PATH, new ResourceRepositoryCommitRequestBuilder().setBody((tx) -> {
            ResourceDocument entry = tx.lookup(codeSystemId.getResourceId(), ResourceDocument.class);
            tx.add(ResourceDocument.builder(entry).upgradeOf(source).build());
            tx.commit(String.format("Update upgradeOf from '%s' to '%s'", codeSystem.getUpgradeOf(), source));
            return Boolean.TRUE;
        }).setCommitComment(String.format("Complete upgrade of %s to %s", codeSystem.getUpgradeOf().getResourceId(), codeSystem.getExtensionOf())).build()).execute(context).getResultAs(Boolean.class);
    } else {
        return Boolean.TRUE;
    }
}
Also used : MergeConflict(com.b2international.snowowl.core.merge.MergeConflict) BadRequestException(com.b2international.commons.exceptions.BadRequestException) BranchRequest(com.b2international.snowowl.core.request.BranchRequest) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) ConflictException(com.b2international.commons.exceptions.ConflictException) RepositoryContext(com.b2international.snowowl.core.domain.RepositoryContext) MergeConflict(com.b2international.snowowl.core.merge.MergeConflict) Collection(java.util.Collection) Request(com.b2international.snowowl.core.events.Request) ResourceURIPathResolver(com.b2international.snowowl.core.uri.ResourceURIPathResolver) Merge(com.b2international.snowowl.core.merge.Merge) NotNull(javax.validation.constraints.NotNull) Branch(com.b2international.snowowl.core.branch.Branch) RepositoryRequests(com.b2international.snowowl.core.repository.RepositoryRequests) ResourceDocument(com.b2international.snowowl.core.internal.ResourceDocument) List(java.util.List) Map(java.util.Map) ApiError(com.b2international.commons.exceptions.ApiError) ResourceRepositoryCommitRequestBuilder(com.b2international.snowowl.core.context.ResourceRepositoryCommitRequestBuilder) User(com.b2international.snowowl.core.identity.User) ResourceURI(com.b2international.snowowl.core.ResourceURI) User(com.b2international.snowowl.core.identity.User) ConflictException(com.b2international.commons.exceptions.ConflictException) ResourceDocument(com.b2international.snowowl.core.internal.ResourceDocument) Merge(com.b2international.snowowl.core.merge.Merge) BadRequestException(com.b2international.commons.exceptions.BadRequestException) ApiError(com.b2international.commons.exceptions.ApiError) ResourceRepositoryCommitRequestBuilder(com.b2international.snowowl.core.context.ResourceRepositoryCommitRequestBuilder) BranchRequest(com.b2international.snowowl.core.request.BranchRequest)

Example 2 with ConflictException

use of com.b2international.commons.exceptions.ConflictException in project snow-owl by b2ihealthcare.

the class CodeSystemUpgradeRequest method execute.

@Override
public String execute(RepositoryContext context) {
    // get available upgrades
    final CodeSystem currentCodeSystem = CodeSystemRequests.prepareGetCodeSystem(resource.getResourceId()).setExpand(CodeSystem.Expand.AVAILABLE_UPGRADES + "()").build().execute(context);
    if (currentCodeSystem.getUpgradeOf() != null) {
        throw new BadRequestException("Upgrade can not be started on an existing upgrade resource");
    }
    final List<ResourceURI> availableUpgrades = currentCodeSystem.getAvailableUpgrades();
    // report bad request if there are no upgrades available
    if (availableUpgrades.isEmpty()) {
        throw new BadRequestException("There are no upgrades available for resource '%s'.", resource.getResourceId());
    }
    // or the selected extensionOf version is not present as a valid available upgrade
    if (!availableUpgrades.contains(extensionOf)) {
        throw new BadRequestException("Upgrades can only be performed to the next available version dependency.").withDeveloperMessage("Use '%s/<VERSION_ID>', where <VERSION_ID> is one of: '%s'", extensionOf.getResourceId(), availableUpgrades);
    }
    // auto-generate the resourceId if not provided
    // auto-generated upgrade IDs consist of the original Resource's ID and the new extensionOf dependency's path, which is version at this point
    final String upgradeResourceId;
    if (resourceId == null) {
        upgradeResourceId = String.format("%s-%s-UPGRADE", resource.getResourceId(), extensionOf.getPath());
    } else if (resourceId.isBlank()) {
        throw new BadRequestException("'resourceId' property should not be empty, if provided");
    } else {
        BranchNameValidator.DEFAULT.checkName(resourceId);
        upgradeResourceId = resourceId;
    }
    String mergeContentFromBranchPath = currentCodeSystem.getBranchPath();
    // only allow HEAD or valid code system versions
    if (!resource.isHead()) {
        mergeContentFromBranchPath = new DefaultResourceURIPathResolver(false).resolve(context, List.of(resource)).stream().findFirst().get();
    }
    // create the same branch name under the new extensionOf path
    String parentBranch = context.service(ResourceURIPathResolver.class).resolve(context, List.of(extensionOf)).stream().findFirst().get();
    // merge content in the tooling repository from the current resource's to the upgrade resource's branch
    final String upgradeBranch = RepositoryRequests.branching().prepareCreate().setParent(parentBranch).setName(resource.getResourceId()).build(currentCodeSystem.getToolingId()).getRequest().execute(context);
    try {
        // merge branch content from the current code system to the new upgradeBranch
        Merge merge = RepositoryRequests.merging().prepareCreate().setSource(mergeContentFromBranchPath).setTarget(upgradeBranch).setSquash(false).build(currentCodeSystem.getToolingId()).getRequest().execute(context);
        if (merge.getStatus() != Merge.Status.COMPLETED) {
            // report conflicts
            ApiError apiError = merge.getApiError();
            Collection<MergeConflict> conflicts = merge.getConflicts();
            context.log().error("Failed to sync source CodeSystem content to upgrade CodeSystem. Error: {}. Conflicts: {}", apiError.getMessage(), conflicts);
            throw new ConflictException("Upgrade can not be performed due to content synchronization errors.").withAdditionalInfo(Map.of("conflicts", conflicts, "mergeError", apiError.getMessage()));
        }
        // and lastly create the actual CodeSystem so users will be able to browse, access and complete the upgrade
        return CodeSystemRequests.prepareNewCodeSystem().setId(upgradeResourceId).setBranchPath(upgradeBranch).setTitle(String.format("Upgrade of '%s' to '%s'", currentCodeSystem.getTitle(), extensionOf)).setUrl(currentCodeSystem.getUrl() + "?upgrade=" + upgradeResourceId).setLanguage(currentCodeSystem.getLanguage()).setDescription(currentCodeSystem.getDescription()).setStatus("draft").setCopyright(currentCodeSystem.getCopyright()).setOwner(currentCodeSystem.getOwner()).setContact(currentCodeSystem.getContact()).setUsage(currentCodeSystem.getUsage()).setPurpose(currentCodeSystem.getPurpose()).setToolingId(currentCodeSystem.getToolingId()).setExtensionOf(extensionOf).setUpgradeOf(resource).setSettings(currentCodeSystem.getSettings()).commit().setCommitComment(String.format("Start upgrade of '%s' to '%s'", resource, extensionOf)).build().execute(context.openBranch(context, Branch.MAIN_PATH)).getResultAs(String.class);
    } catch (Throwable e) {
        // delete upgrade branch if any exception have been thrown during the upgrade
        RepositoryRequests.branching().prepareDelete(upgradeBranch).build(currentCodeSystem.getToolingId()).getRequest().execute(context);
        throw e;
    }
}
Also used : MergeConflict(com.b2international.snowowl.core.merge.MergeConflict) ResourceURI(com.b2international.snowowl.core.ResourceURI) DefaultResourceURIPathResolver(com.b2international.snowowl.core.uri.DefaultResourceURIPathResolver) Merge(com.b2international.snowowl.core.merge.Merge) ConflictException(com.b2international.commons.exceptions.ConflictException) BadRequestException(com.b2international.commons.exceptions.BadRequestException) ApiError(com.b2international.commons.exceptions.ApiError)

Example 3 with ConflictException

use of com.b2international.commons.exceptions.ConflictException in project snow-owl by b2ihealthcare.

the class VersionCreateRequest method execute.

@Override
public Boolean execute(RepositoryContext context) {
    final String user = context.service(User.class).getUsername();
    if (!resource.isHead()) {
        throw new BadRequestException("Version '%s' cannot be created on unassigned branch '%s'.", version, resource).withDeveloperMessage("Did you mean to version '%s'?", resource.withoutPath());
    }
    if (resourcesById == null) {
        resourcesById = fetchResources(context);
    }
    if (!resourcesById.containsKey(resource)) {
        context.log().warn("Resource cannot be found during versioning: " + resourcesById + ", uri: " + resource);
        throw new NotFoundException("Resource", resource.getResourceId());
    }
    // validate new path
    RevisionBranch.BranchNameValidator.DEFAULT.checkName(version);
    TerminologyResource resourceToVersion = resourcesById.get(resource);
    // TODO resurrect or eliminate tooling dependencies
    final List<TerminologyResource> resourcesToVersion = List.of(resourcesById.get(resource));
    // final List<CodeSystem> resourcesToVersion = codeSystem.getDependenciesAndSelf()
    // .stream()
    // .map(resourcesById::get)
    // .collect(Collectors.toList());
    resourcesToVersion.stream().filter(cs -> cs.getUpgradeOf() != null).findAny().ifPresent(cs -> {
        throw new BadRequestException("Upgrade resource '%s' can not be versioned.", cs.getResourceURI());
    });
    for (TerminologyResource terminologyResource : resourcesToVersion) {
        // check that the new versionId does not conflict with any other currently available branch
        final String newVersionPath = String.join(Branch.SEPARATOR, terminologyResource.getBranchPath(), version);
        final String repositoryId = terminologyResource.getToolingId();
        if (!force) {
            // branch needs checking in the non-force cases only
            try {
                Branch branch = RepositoryRequests.branching().prepareGet(newVersionPath).build(repositoryId).execute(context);
                if (!branch.isDeleted()) {
                    throw new ConflictException("An existing version or branch with path '%s' conflicts with the specified version identifier.", newVersionPath);
                }
            } catch (NotFoundException e) {
            // branch does not exist, ignore
            }
        } else {
            // if there is no conflict, delete the branch (the request also ignores non-existent branches)
            deleteBranch(context, newVersionPath, repositoryId);
        }
    }
    acquireLocks(context, user, resourcesToVersion);
    final IProgressMonitor monitor = SubMonitor.convert(context.service(IProgressMonitor.class), TASK_WORK_STEP);
    try {
        // resourcesToVersion.forEach(resourceToVersion -> {
        // check that the specified effective time is valid in this code system
        validateVersion(context, resourceToVersion);
        // version components in the given repository
        new RepositoryRequest<>(resourceToVersion.getToolingId(), new BranchRequest<>(resourceToVersion.getBranchPath(), new RevisionIndexReadRequest<CommitResult>(context.service(RepositoryManager.class).get(resourceToVersion.getToolingId()).service(VersioningRequestBuilder.class).build(new VersioningConfiguration(user, resourceToVersion.getResourceURI(), version, description, effectiveTime, force))))).execute(context);
        // tag the repository
        doTag(context, resourceToVersion, monitor);
        // create a version for the resource
        return new BranchRequest<>(Branch.MAIN_PATH, new ResourceRepositoryCommitRequestBuilder().setBody(tx -> {
            tx.add(VersionDocument.builder().id(resource.withPath(version).withoutResourceType()).version(version).description(description).effectiveTime(EffectiveTimes.getEffectiveTime(effectiveTime)).resource(resource).branchPath(resourceToVersion.getRelativeBranchPath(version)).author(user).createdAt(Instant.now().toEpochMilli()).updatedAt(Instant.now().toEpochMilli()).toolingId(resourceToVersion.getToolingId()).url(buildVersionUrl(context, resourceToVersion)).build());
            return Boolean.TRUE;
        }).setCommitComment(CompareUtils.isEmpty(commitComment) ? String.format("Version '%s' as of '%s'", resource, version) : commitComment).build()).execute(context).getResultAs(Boolean.class);
    } finally {
        releaseLocks(context);
        if (null != monitor) {
            monitor.done();
        }
    }
}
Also used : EffectiveTimes(com.b2international.snowowl.core.date.EffectiveTimes) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) java.util(java.util) SubMonitor(org.eclipse.core.runtime.SubMonitor) RevisionBranch(com.b2international.index.revision.RevisionBranch) Multimap(com.google.common.collect.Multimap) Branch(com.b2international.snowowl.core.branch.Branch) RepositoryRequests(com.b2international.snowowl.core.repository.RepositoryRequests) CREATE_VERSION(com.b2international.snowowl.core.internal.locks.DatastoreLockContextDescriptions.CREATE_VERSION) HashMultimap(com.google.common.collect.HashMultimap) AccessControl(com.b2international.snowowl.core.authorization.AccessControl) DatastoreLockTarget(com.b2international.snowowl.core.internal.locks.DatastoreLockTarget) Permission(com.b2international.snowowl.core.identity.Permission) DatastoreLockContext(com.b2international.snowowl.core.internal.locks.DatastoreLockContext) CompareUtils(com.b2international.commons.CompareUtils) com.b2international.snowowl.core(com.b2international.snowowl.core) NotFoundException(com.b2international.commons.exceptions.NotFoundException) com.b2international.snowowl.core.request(com.b2international.snowowl.core.request) Version(com.b2international.snowowl.core.version.Version) BadRequestException(com.b2international.commons.exceptions.BadRequestException) ConflictException(com.b2international.commons.exceptions.ConflictException) RepositoryContext(com.b2international.snowowl.core.domain.RepositoryContext) Request(com.b2international.snowowl.core.events.Request) JsonFormat(com.fasterxml.jackson.annotation.JsonFormat) Instant(java.time.Instant) NotNull(javax.validation.constraints.NotNull) Collectors(java.util.stream.Collectors) TerminologyRegistry(com.b2international.snowowl.core.terminology.TerminologyRegistry) IProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) VersionDocument(com.b2international.snowowl.core.version.VersionDocument) NotEmpty(org.hibernate.validator.constraints.NotEmpty) LocalDate(java.time.LocalDate) Sort(com.b2international.snowowl.core.request.SearchResourceRequest.Sort) Entry(java.util.Map.Entry) IOperationLockManager(com.b2international.snowowl.core.locks.IOperationLockManager) ResourceURLSchemaSupport(com.b2international.snowowl.core.uri.ResourceURLSchemaSupport) ResourceRepositoryCommitRequestBuilder(com.b2international.snowowl.core.context.ResourceRepositoryCommitRequestBuilder) User(com.b2international.snowowl.core.identity.User) User(com.b2international.snowowl.core.identity.User) ConflictException(com.b2international.commons.exceptions.ConflictException) NotFoundException(com.b2international.commons.exceptions.NotFoundException) IProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) RevisionBranch(com.b2international.index.revision.RevisionBranch) Branch(com.b2international.snowowl.core.branch.Branch) BadRequestException(com.b2international.commons.exceptions.BadRequestException) ResourceRepositoryCommitRequestBuilder(com.b2international.snowowl.core.context.ResourceRepositoryCommitRequestBuilder)

Aggregations

BadRequestException (com.b2international.commons.exceptions.BadRequestException)3 ConflictException (com.b2international.commons.exceptions.ConflictException)3 ApiError (com.b2international.commons.exceptions.ApiError)2 ResourceURI (com.b2international.snowowl.core.ResourceURI)2 Branch (com.b2international.snowowl.core.branch.Branch)2 ResourceRepositoryCommitRequestBuilder (com.b2international.snowowl.core.context.ResourceRepositoryCommitRequestBuilder)2 RepositoryContext (com.b2international.snowowl.core.domain.RepositoryContext)2 Request (com.b2international.snowowl.core.events.Request)2 User (com.b2international.snowowl.core.identity.User)2 Merge (com.b2international.snowowl.core.merge.Merge)2 MergeConflict (com.b2international.snowowl.core.merge.MergeConflict)2 RepositoryRequests (com.b2international.snowowl.core.repository.RepositoryRequests)2 JsonProperty (com.fasterxml.jackson.annotation.JsonProperty)2 NotNull (javax.validation.constraints.NotNull)2 CompareUtils (com.b2international.commons.CompareUtils)1 NotFoundException (com.b2international.commons.exceptions.NotFoundException)1 RevisionBranch (com.b2international.index.revision.RevisionBranch)1 com.b2international.snowowl.core (com.b2international.snowowl.core)1 AccessControl (com.b2international.snowowl.core.authorization.AccessControl)1 EffectiveTimes (com.b2international.snowowl.core.date.EffectiveTimes)1