Search in sources :

Example 6 with Merge

use of com.b2international.snowowl.core.merge.Merge in project snow-owl by b2ihealthcare.

the class SearchMergeRequest method doExecute.

@Override
public Merges doExecute(RepositoryContext context) {
    final ExpressionBuilder queryBuilder = Expressions.builder();
    // add mergerequest type filter
    queryBuilder.filter(RemoteJobEntry.Expressions.matchRequestType(ImmutableSet.of(BranchRebaseRequest.class.getSimpleName(), BranchMergeRequest.class.getSimpleName())));
    if (containsKey(OptionKey.SOURCE)) {
        queryBuilder.filter(RemoteJobEntry.Expressions.matchParameter(SOURCE_FIELD, getCollection(OptionKey.SOURCE, String.class)));
    }
    if (containsKey(OptionKey.TARGET)) {
        queryBuilder.filter(RemoteJobEntry.Expressions.matchParameter(TARGET_FIELD, getCollection(OptionKey.TARGET, String.class)));
    }
    if (containsKey(OptionKey.STATUS)) {
        queryBuilder.filter(RemoteJobEntry.Expressions.matchParameter(STATUS_FIELD, getCollection(OptionKey.STATUS, String.class)));
    }
    final RemoteJobs jobs = context.service(RemoteJobTracker.class).search(queryBuilder.build(), Integer.MAX_VALUE);
    final ObjectMapper mapper = context.service(ObjectMapper.class);
    final List<Merge> items = jobs.stream().map(job -> createMergefromJobEntry(job, mapper)).collect(Collectors.toList());
    return new Merges(items, jobs.getSearchAfter(), jobs.getLimit(), jobs.getTotal());
}
Also used : RepositoryContext(com.b2international.snowowl.core.domain.RepositoryContext) ImmutableSet(com.google.common.collect.ImmutableSet) Status(com.b2international.snowowl.core.merge.Merge.Status) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Merge(com.b2international.snowowl.core.merge.Merge) RemoteJobEntry(com.b2international.snowowl.core.jobs.RemoteJobEntry) Collectors(java.util.stream.Collectors) SearchResourceRequest(com.b2international.snowowl.core.request.SearchResourceRequest) List(java.util.List) Merges(com.b2international.snowowl.core.merge.Merges) Expressions(com.b2international.index.query.Expressions) AccessControl(com.b2international.snowowl.core.authorization.AccessControl) Map(java.util.Map) ApiError(com.b2international.commons.exceptions.ApiError) RemoteJobs(com.b2international.snowowl.core.jobs.RemoteJobs) ExpressionBuilder(com.b2international.index.query.Expressions.ExpressionBuilder) Permission(com.b2international.snowowl.core.identity.Permission) Builder(com.b2international.snowowl.core.merge.Merge.Builder) NotImplementedException(com.b2international.commons.exceptions.NotImplementedException) RemoteJobTracker(com.b2international.snowowl.core.jobs.RemoteJobTracker) RemoteJobs(com.b2international.snowowl.core.jobs.RemoteJobs) Merges(com.b2international.snowowl.core.merge.Merges) RemoteJobTracker(com.b2international.snowowl.core.jobs.RemoteJobTracker) Merge(com.b2international.snowowl.core.merge.Merge) ExpressionBuilder(com.b2international.index.query.Expressions.ExpressionBuilder) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper)

Example 7 with Merge

use of com.b2international.snowowl.core.merge.Merge in project snow-owl by b2ihealthcare.

the class SnomedBranchRequestTest method createBranchAndCommitToParent.

@Test
public void createBranchAndCommitToParent() throws Exception {
    final Branching branches = RepositoryRequests.branching();
    final Merging merges = RepositoryRequests.merging();
    final String branchA = UUID.randomUUID().toString();
    final String branchB = UUID.randomUUID().toString();
    final String first = branches.prepareCreate().setParent(branchPath).setName(branchA).build(REPOSITORY_ID).execute(bus).getSync();
    final SnomedDescriptionCreateRequestBuilder fsnBuilder = SnomedRequests.prepareNewDescription().setIdFromNamespace(SnomedIdentifiers.INT_NAMESPACE).setModuleId(Concepts.MODULE_ROOT).setTerm("FSN " + branchA).setTypeId(Concepts.FULLY_SPECIFIED_NAME).setAcceptability(ImmutableMap.of(Concepts.REFSET_LANGUAGE_TYPE_UK, Acceptability.PREFERRED));
    final SnomedDescriptionCreateRequestBuilder ptBuilder = SnomedRequests.prepareNewDescription().setIdFromNamespace(SnomedIdentifiers.INT_NAMESPACE).setModuleId(Concepts.MODULE_ROOT).setTerm("PT " + branchA).setTypeId(Concepts.SYNONYM).setAcceptability(ImmutableMap.of(Concepts.REFSET_LANGUAGE_TYPE_UK, Acceptability.PREFERRED));
    final AsyncRequest<CommitResult> conceptRequest = SnomedRequests.prepareNewConcept().setModuleId(Concepts.MODULE_ROOT).setIdFromNamespace(SnomedIdentifiers.INT_NAMESPACE).addParent(Concepts.ROOT_CONCEPT).addDescription(fsnBuilder).addDescription(ptBuilder).build(first, RestExtensions.USER, "Created new concept");
    final CommitResult info = conceptRequest.execute(bus).getSync();
    final String conceptId = info.getResultAs(String.class);
    final String firstParentPath = BranchPathUtils.createPath(first).getParentPath();
    final Request<ServiceProvider, Merge> mergeRequest = merges.prepareCreate().setSource(first).setTarget(firstParentPath).setUserId(User.SYSTEM.getUsername()).setCommitComment("Merging changes").build(REPOSITORY_ID).getRequest();
    final String mergeJobId = JobRequests.prepareSchedule().setDescription("Merging changes").setRequest(mergeRequest).setUser(User.SYSTEM.getUsername()).buildAsync().execute(bus).getSync();
    final RemoteJobEntry mergeJobResult = JobRequests.waitForJob(bus, mergeJobId);
    final Merge merge = mergeJobResult.getResultAs(JsonSupport.getDefaultObjectMapper(), Merge.class);
    assertEquals(true, merge.getConflicts().isEmpty());
    String second = branches.prepareCreate().setParent(firstParentPath).setName(branchB).build(REPOSITORY_ID).execute(bus).getSync();
    final Branch sourceBranch = branches.prepareGet(merge.getSource()).build(REPOSITORY_ID).execute(bus).getSync();
    final Branch secondBranch = branches.prepareGet(second).build(REPOSITORY_ID).execute(bus).getSync();
    assertBranchesCreated(branchA, branchB, sourceBranch, secondBranch);
    assertBranchSegmentsValid(merge.getTarget(), sourceBranch.path(), secondBranch.path());
    // Check that the concept is visible on parent
    SnomedRequests.prepareGetConcept(conceptId).build(firstParentPath).execute(bus).getSync();
}
Also used : BaseRevisionBranching(com.b2international.index.revision.BaseRevisionBranching) Branching(com.b2international.snowowl.core.branch.Branching) Merge(com.b2international.snowowl.core.merge.Merge) Merging(com.b2international.snowowl.core.branch.Merging) CommitResult(com.b2international.snowowl.core.request.CommitResult) RevisionBranch(com.b2international.index.revision.RevisionBranch) Branch(com.b2international.snowowl.core.branch.Branch) ServiceProvider(com.b2international.snowowl.core.ServiceProvider) SnomedDescriptionCreateRequestBuilder(com.b2international.snowowl.snomed.datastore.request.SnomedDescriptionCreateRequestBuilder) RemoteJobEntry(com.b2international.snowowl.core.jobs.RemoteJobEntry) Test(org.junit.Test)

Example 8 with Merge

use of com.b2international.snowowl.core.merge.Merge in project snow-owl by b2ihealthcare.

the class AbstractBranchChangeRequest method execute.

@Override
public Merge execute(RepositoryContext context) {
    try {
        final Branch source = RepositoryRequests.branching().prepareGet(sourcePath).build().execute(context);
        final Branch target = RepositoryRequests.branching().prepareGet(targetPath).build().execute(context);
        Merge merge = Merge.builder().source(sourcePath).target(targetPath).build();
        try {
            Commit commit = applyChanges(context, source, target);
            if (commit != null) {
                context.service(RepositoryCommitNotificationSender.class).publish(context, commit);
            }
            return merge.completed();
        } catch (BranchMergeConflictException e) {
            return merge.failedWithConflicts(e.getMessage(), toMergeConflicts(e.getConflicts()));
        } catch (ApiException e) {
            return merge.failed(e.toApiError());
        } catch (RuntimeException e) {
            context.log().error("Failed to merge {} into {}", sourcePath, targetPath, e);
            return merge.failed(ApiError.of(e.getMessage()));
        }
    } catch (NotFoundException e) {
        throw e.toBadRequestException();
    }
}
Also used : Merge(com.b2international.snowowl.core.merge.Merge) RepositoryCommitNotificationSender(com.b2international.snowowl.core.repository.RepositoryCommitNotificationSender) NotFoundException(com.b2international.commons.exceptions.NotFoundException) ApiException(com.b2international.commons.exceptions.ApiException)

Example 9 with Merge

use of com.b2international.snowowl.core.merge.Merge 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 10 with Merge

use of com.b2international.snowowl.core.merge.Merge in project snow-owl by b2ihealthcare.

the class SnomedMergeConflictTest method noMergeNewDescriptionToUnrelatedBranch.

@Test
public void noMergeNewDescriptionToUnrelatedBranch() {
    String conceptId = createNewConcept(branchPath);
    IBranchPath a = BranchPathUtils.createPath(branchPath, "a");
    branching.createBranch(a).statusCode(201);
    /*
		 * XXX: Creating a new description on the concept itself would result in a DELETED_WHILE_CHANGED conflict;
		 * by referring to it as the type, the deletion will generate a CAUSES_MISSING_REFERENCE conflict instead.
		 */
    createNewDescription(a, Concepts.ROOT_CONCEPT, conceptId);
    IBranchPath b = BranchPathUtils.createPath(branchPath, "b");
    branching.createBranch(b).statusCode(201);
    deleteComponent(b, SnomedComponentType.CONCEPT, conceptId, false).statusCode(204);
    Collection<MergeConflict> conflicts = merge(a, b, "Merged new description to unrelated branch").body("status", equalTo(Merge.Status.CONFLICTS.name())).extract().as(Merge.class).getConflicts();
    assertEquals(1, conflicts.size());
    MergeConflict conflict = Iterables.getOnlyElement(conflicts);
    assertEquals(conceptId, conflict.getComponentId());
    assertEquals("concept", conflict.getComponentType());
    assertEquals(ConflictType.CAUSES_MISSING_REFERENCE, conflict.getType());
    assertEquals(0, conflict.getConflictingAttributes().size());
}
Also used : MergeConflict(com.b2international.snowowl.core.merge.MergeConflict) Merge(com.b2international.snowowl.core.merge.Merge) IBranchPath(com.b2international.snowowl.core.api.IBranchPath) Test(org.junit.Test) AbstractSnomedApiTest(com.b2international.snowowl.snomed.core.rest.AbstractSnomedApiTest)

Aggregations

Merge (com.b2international.snowowl.core.merge.Merge)15 MergeConflict (com.b2international.snowowl.core.merge.MergeConflict)12 Test (org.junit.Test)11 IBranchPath (com.b2international.snowowl.core.api.IBranchPath)10 AbstractSnomedApiTest (com.b2international.snowowl.snomed.core.rest.AbstractSnomedApiTest)10 ConflictingAttribute (com.b2international.snowowl.core.merge.ConflictingAttribute)6 ApiError (com.b2international.commons.exceptions.ApiError)3 BadRequestException (com.b2international.commons.exceptions.BadRequestException)2 ConflictException (com.b2international.commons.exceptions.ConflictException)2 ResourceURI (com.b2international.snowowl.core.ResourceURI)2 Branch (com.b2international.snowowl.core.branch.Branch)2 RepositoryContext (com.b2international.snowowl.core.domain.RepositoryContext)2 RemoteJobEntry (com.b2international.snowowl.core.jobs.RemoteJobEntry)2 List (java.util.List)2 Map (java.util.Map)2 ApiException (com.b2international.commons.exceptions.ApiException)1 NotFoundException (com.b2international.commons.exceptions.NotFoundException)1 NotImplementedException (com.b2international.commons.exceptions.NotImplementedException)1 Expressions (com.b2international.index.query.Expressions)1 ExpressionBuilder (com.b2international.index.query.Expressions.ExpressionBuilder)1