use of com.b2international.snowowl.core.domain.TransactionContext in project snow-owl by b2ihealthcare.
the class EvaluateQueryRefSetMemberRequest method execute.
@Override
public QueryRefSetMemberEvaluation execute(BranchContext context) {
// TODO support pre-population???
final boolean active;
final String query;
final String targetReferenceSet;
if (context instanceof TransactionContext) {
SnomedRefSetMemberIndexEntry member = ((TransactionContext) context).lookup(memberId, SnomedRefSetMemberIndexEntry.class);
query = member.getQuery();
targetReferenceSet = member.getReferencedComponentId();
active = member.isActive();
} else {
final SnomedReferenceSetMember member = SnomedRequests.prepareGetMember(memberId).build().execute(context);
query = (String) member.getProperties().get(SnomedRf2Headers.FIELD_QUERY);
targetReferenceSet = member.getReferencedComponent().getId();
active = member.isActive();
}
if (!active) {
return new QueryRefSetMemberEvaluationImpl(memberId, targetReferenceSet, Collections.emptyList());
}
if (Strings.isNullOrEmpty(query)) {
return new QueryRefSetMemberEvaluationImpl(memberId, targetReferenceSet, Collections.emptyList());
}
// add all matching first
final Map<String, SnomedConcept> conceptsToAdd = newHashMap();
// GET matching members of a query
SnomedRequests.prepareSearchConcept().filterByEcl(query).setLimit(10_000).stream(context).flatMap(SnomedConcepts::stream).forEach(match -> conceptsToAdd.put(match.getId(), match));
final Collection<SnomedReferenceSetMember> membersToRemove = newHashSet();
final Collection<SnomedReferenceSetMember> conceptsToActivate = newHashSet();
// then re-evaluate all current members of the target simple type reference set
SnomedRequests.prepareSearchMember().filterByRefSet(targetReferenceSet).setLimit(10_000).stream(context).flatMap(SnomedReferenceSetMembers::stream).forEach(member -> {
final String referencedComponentId = member.getReferencedComponent().getId();
if (conceptsToAdd.containsKey(referencedComponentId)) {
if (!member.isActive()) {
conceptsToAdd.remove(referencedComponentId);
conceptsToActivate.add(member);
} else {
conceptsToAdd.remove(referencedComponentId);
}
} else {
if (member.isActive()) {
membersToRemove.add(member);
}
}
});
// fetch all referenced components
final Set<String> referencedConceptIds = newHashSet();
referencedConceptIds.addAll(conceptsToAdd.keySet());
referencedConceptIds.addAll(FluentIterable.from(membersToRemove).transform(SnomedReferenceSetMember::getReferencedComponent).transform(IComponent::getId).toSet());
referencedConceptIds.addAll(FluentIterable.from(conceptsToActivate).transform(SnomedReferenceSetMember::getReferencedComponent).transform(IComponent::getId).toSet());
final Map<String, SnomedConcept> concepts;
if (expand().containsKey("referencedComponent")) {
final Options expandOptions = expand().getOptions("referencedComponent");
concepts = Maps.uniqueIndex(SnomedRequests.prepareSearchConcept().filterByIds(referencedConceptIds).setLimit(referencedConceptIds.size()).setExpand(expandOptions.getOptions("expand")).setLocales(locales()).build().execute(context), IComponent::getId);
} else {
// initialize with empty SnomedConcept resources
concepts = newHashMap();
for (String referencedConceptId : referencedConceptIds) {
concepts.put(referencedConceptId, new SnomedConcept(referencedConceptId));
}
}
final Collection<MemberChange> changes = newArrayList();
for (String id : conceptsToAdd.keySet()) {
changes.add(MemberChangeImpl.added(concepts.get(id)));
}
for (SnomedReferenceSetMember memberToRemove : membersToRemove) {
changes.add(MemberChangeImpl.removed(concepts.get(memberToRemove.getReferencedComponent().getId()), memberToRemove.getId()));
}
for (SnomedReferenceSetMember conceptToActivate : conceptsToActivate) {
changes.add(MemberChangeImpl.changed(concepts.get(conceptToActivate.getReferencedComponent().getId()), conceptToActivate.getId()));
}
return new QueryRefSetMemberEvaluationImpl(memberId, targetReferenceSet, changes);
}
use of com.b2international.snowowl.core.domain.TransactionContext in project snow-owl by b2ihealthcare.
the class SnomedVersioningRequest method adjustDependencyRefSetMembers.
private void adjustDependencyRefSetMembers(TransactionContext context, Multimap<String, String> moduleDependencies, Map<String, Long> moduleToLatestEffectiveTime, long effectiveTime) {
// Update existing, add new members to moduleDependencyRefSet
if (!CompareUtils.isEmpty(moduleDependencies)) {
moduleDependencies.entries().forEach((entry) -> {
final String source = entry.getKey();
final String target = entry.getValue();
final SnomedReferenceSetMember existingLatestMember = SnomedRequests.prepareSearchMember().all().filterByModule(source).filterByReferencedComponent(target).filterByRefSet(Concepts.REFSET_MODULE_DEPENDENCY_TYPE).build().execute(context).stream().sorted((o1, o2) -> {
if (null == o1.getEffectiveTime() && null == o2.getEffectiveTime()) {
return 0;
} else if (null == o1.getEffectiveTime() && null != o2.getEffectiveTime()) {
return 1;
} else if (null != o1.getEffectiveTime() && null == o2.getEffectiveTime()) {
return -1;
}
return o1.getEffectiveTime().compareTo(o2.getEffectiveTime());
}).reduce((first, second) -> second).orElse(null);
final SnomedRefSetMemberIndexEntry.Builder updatedMember;
if (existingLatestMember == null) {
updatedMember = SnomedRefSetMemberIndexEntry.builder().id(UUID.randomUUID().toString()).active(true).refsetId(Concepts.REFSET_MODULE_DEPENDENCY_TYPE).referenceSetType(SnomedRefSetType.MODULE_DEPENDENCY).moduleId(source).referencedComponentId(target);
} else {
updatedMember = SnomedRefSetMemberIndexEntry.builder(existingLatestMember);
}
final long targetEffectiveTime = moduleToLatestEffectiveTime.get(target) == EffectiveTimes.UNSET_EFFECTIVE_TIME ? effectiveTime : moduleToLatestEffectiveTime.get(target);
updatedMember.released(true).effectiveTime(effectiveTime).field(SnomedRf2Headers.FIELD_SOURCE_EFFECTIVE_TIME, effectiveTime).field(SnomedRf2Headers.FIELD_TARGET_EFFECTIVE_TIME, targetEffectiveTime);
if (existingLatestMember == null) {
context.add(updatedMember.build());
} else {
context.update(SnomedRefSetMemberIndexEntry.builder(existingLatestMember).build(), updatedMember.build());
}
});
}
}
use of com.b2international.snowowl.core.domain.TransactionContext in project snow-owl by b2ihealthcare.
the class SnomedBulkRequest method execute.
@Override
public R execute(TransactionContext context) {
ImmutableList.Builder<SnomedComponentRequest<?>> requests = ImmutableList.builder();
ImmutableList.Builder<DeleteRequest> deletions = ImmutableList.builder();
collectNestedRequests(next(), requests, deletions);
// Prefetch all component IDs mentioned in reference set member creation requests, abort if any of them can not be found
final Set<String> requiredComponentIds = requests.build().stream().flatMap(request -> request.getRequiredComponentIds(context).stream()).filter(// just in case filter out invalid component IDs
componentId -> SnomedComponent.getTypeSafe(componentId) != null || isMember(componentId)).collect(Collectors.toSet());
final Multimap<Class<? extends SnomedDocument>, String> componentIdsByType = HashMultimap.create();
for (String requiredComponentId : requiredComponentIds) {
if (!Strings.isNullOrEmpty(requiredComponentId)) {
componentIdsByType.put(this.getDocType(requiredComponentId), requiredComponentId);
}
}
// collect all deleted IDs as well
deletions.build().stream().map(DeleteRequest::getComponentId).forEach(componentId -> componentIdsByType.put(getDocType(componentId), componentId));
try {
for (final Entry<Class<? extends SnomedDocument>, Collection<String>> idsForType : componentIdsByType.asMap().entrySet()) {
context.lookup(idsForType.getValue(), idsForType.getKey());
}
} catch (final ComponentNotFoundException e) {
throw e.toBadRequestException();
}
// bind additional caches to the context
TransactionContext newContext = context.inject().bind(SnomedOWLExpressionConverter.class, new SnomedOWLExpressionConverter(context)).build();
return next(newContext);
}
use of com.b2international.snowowl.core.domain.TransactionContext in project snow-owl by b2ihealthcare.
the class SaveJobRequest method mergeEquivalentConcepts.
private Set<String> mergeEquivalentConcepts(final BranchContext context, final BulkRequestBuilder<TransactionContext> bulkRequestBuilder, final SnomedNamespaceAndModuleAssigner assigner) {
if (!fixEquivalences) {
return Collections.emptySet();
}
// XXX: Restrict merging to active components only
final String expand = "equivalentConcepts(expand(" + "descriptions(active:true)," + "relationships(active:true)," + "inboundRelationships(active:true)," + "members(active:true)))";
final Multimap<SnomedConcept, SnomedConcept> equivalentConcepts = HashMultimap.create();
ClassificationRequests.prepareSearchEquivalentConceptSet().setLimit(SCROLL_LIMIT).setExpand(expand).filterByClassificationId(classificationId).stream(context).flatMap(EquivalentConceptSets::stream).filter(equivalentSet -> !equivalentSet.isUnsatisfiable()).forEach(equivalentSet -> {
final List<SnomedConcept> conceptsToRemove = newArrayList(equivalentSet.getEquivalentConcepts());
final SnomedConcept conceptToKeep = conceptsToRemove.remove(0);
equivalentConcepts.putAll(conceptToKeep, conceptsToRemove);
});
// Are there any equivalent concepts present? or Were all equivalent concepts unsatisfiable?
if (equivalentConcepts.isEmpty()) {
return Collections.emptySet();
}
IEquivalentConceptMerger merger = Extensions.getFirstPriorityExtension(IEquivalentConceptMerger.EXTENSION_POINT, IEquivalentConceptMerger.class);
if (merger == null) {
merger = new IEquivalentConceptMerger.Default();
}
final String mergerName = merger.getClass().getSimpleName();
LOG.info("Reasoner service will use {} for equivalent concept merging.", mergerName);
final Set<String> conceptIdsToSkip = merger.merge(equivalentConcepts);
final Set<String> conceptIdsToKeep = equivalentConcepts.keySet().stream().map(SnomedConcept::getId).collect(Collectors.toSet());
// Prepare to provide namespace-module for inbound relationship source concepts as well
final Set<String> relationshipChangeConceptIds = newHashSet(conceptIdsToKeep);
// Add source concepts on new/about to be inactivated inbound relationships, pointing to "kept" concepts
for (final SnomedConcept conceptToKeep : equivalentConcepts.keySet()) {
for (final SnomedRelationship relationship : conceptToKeep.getInboundRelationships()) {
if (relationship.getId().startsWith(IEquivalentConceptMerger.PREFIX_NEW)) {
relationshipChangeConceptIds.add(relationship.getSourceId());
} else if (!relationship.isActive()) {
relationshipChangeConceptIds.add(relationship.getSourceId());
}
}
}
assigner.collectRelationshipNamespacesAndModules(relationshipChangeConceptIds, context);
for (final SnomedConcept conceptToKeep : equivalentConcepts.keySet()) {
for (final SnomedRelationship relationship : conceptToKeep.getInboundRelationships()) {
// Already handled as another concept's outbound relationship
if (relationship.getId() == null) {
continue;
}
if (relationship.getId().startsWith(IEquivalentConceptMerger.PREFIX_NEW)) {
relationship.setId(null);
addComponent(bulkRequestBuilder, assigner, relationship);
} else if (!relationship.isActive()) {
removeOrDeactivate(bulkRequestBuilder, assigner, relationship);
}
}
for (final SnomedRelationship relationship : conceptToKeep.getRelationships()) {
// Already handled as another concept's inbound relationship
if (relationship.getId() == null) {
continue;
}
if (relationship.getId().startsWith(IEquivalentConceptMerger.PREFIX_NEW)) {
relationship.setId(null);
addComponent(bulkRequestBuilder, assigner, relationship);
} else if (!relationship.isActive()) {
removeOrDeactivate(bulkRequestBuilder, assigner, relationship);
}
}
}
// CD members are always "outbound", however, so the concept SCTID set can be reduced
assigner.clear();
assigner.collectConcreteDomainModules(conceptIdsToKeep, context);
for (final SnomedConcept conceptToKeep : equivalentConcepts.keySet()) {
for (final SnomedReferenceSetMember member : conceptToKeep.getMembers()) {
if (member.getId().startsWith(IEquivalentConceptMerger.PREFIX_NEW)) {
member.setId(null);
addComponent(bulkRequestBuilder, assigner, member);
} else if (member.getId().startsWith(IEquivalentConceptMerger.PREFIX_UPDATED)) {
// Trim the prefix from the ID to restore its original form
member.setId(member.getId().substring(IEquivalentConceptMerger.PREFIX_UPDATED.length()));
bulkRequestBuilder.add(member.toUpdateRequest());
} else if (!member.isActive()) {
removeOrDeactivate(bulkRequestBuilder, assigner, member);
}
}
}
// Descriptions are also "outbound"
assigner.clear();
assigner.collectRelationshipNamespacesAndModules(conceptIdsToKeep, context);
for (final SnomedConcept conceptToKeep : equivalentConcepts.keySet()) {
for (final SnomedDescription description : conceptToKeep.getDescriptions()) {
if (description.getId().startsWith(IEquivalentConceptMerger.PREFIX_NEW)) {
description.setId(null);
addComponent(bulkRequestBuilder, assigner, description);
} else if (description.getId().startsWith(IEquivalentConceptMerger.PREFIX_UPDATED)) {
// Trim the prefix from the ID to restore its original form
description.setId(description.getId().substring(IEquivalentConceptMerger.PREFIX_UPDATED.length()));
bulkRequestBuilder.add(description.toUpdateRequest());
} else if (!description.isActive()) {
removeOrDeactivate(bulkRequestBuilder, assigner, description);
}
}
}
// Inactivation of "removed" concepts also requires modules to be collected according to the assigner rules
assigner.clear();
assigner.collectRelationshipNamespacesAndModules(conceptIdsToSkip, context);
for (final SnomedConcept conceptToRemove : equivalentConcepts.values()) {
// Check if the concept needs to be removed or deactivated
if (!conceptToRemove.isActive()) {
removeOrDeactivate(bulkRequestBuilder, assigner, conceptToRemove);
}
}
assigner.clear();
return conceptIdsToSkip;
}
use of com.b2international.snowowl.core.domain.TransactionContext in project snow-owl by b2ihealthcare.
the class SaveJobRequest method persistChanges.
private Boolean persistChanges(final BranchContext context, final IProgressMonitor monitor) {
// Repeat the same checks as in ClassificationSaveRequest, now within the lock
final ClassificationTask classification = ClassificationRequests.prepareGetClassification(classificationId).build().execute(context);
final String branchPath = classification.getBranch();
final Branch branch = RepositoryRequests.branching().prepareGet(branchPath).build().execute(context);
if (!ClassificationSaveRequest.SAVEABLE_STATUSES.contains(classification.getStatus())) {
throw new BadRequestException("Classification '%s' is not in the expected state to start saving changes.", classificationId);
}
if (classification.getTimestamp() < branch.headTimestamp()) {
throw new BadRequestException("Classification '%s' on branch '%s' is stale (classification timestamp: %s, head timestamp: %s).", classificationId, branchPath, classification.getTimestamp(), branch.headTimestamp());
}
final ClassificationTracker classificationTracker = context.service(ClassificationTracker.class);
// Signal the state change
classificationTracker.classificationSaving(classificationId);
final SubMonitor subMonitor = SubMonitor.convert(monitor, "Persisting changes", 6);
final BulkRequestBuilder<TransactionContext> bulkRequestBuilder = BulkRequest.create();
applyChanges(subMonitor, context, bulkRequestBuilder);
long resultTimeStamp = Commit.NO_COMMIT_TIMESTAMP;
for (List<Request<TransactionContext, ?>> partition : Iterables.partition(bulkRequestBuilder.build().getRequests(), getCommitLimit(context))) {
final BulkRequestBuilder<TransactionContext> batchRequest = BulkRequest.create();
partition.forEach(request -> batchRequest.add(request));
final Request<BranchContext, CommitResult> commitRequest = SnomedRequests.prepareCommit().setBody(batchRequest.build()).setCommitComment(commitComment).setParentContextDescription(DatastoreLockContextDescriptions.SAVE_CLASSIFICATION_RESULTS).setAuthor(userId).build();
final CommitResult commitResult = new IdRequest<>(commitRequest).execute(context);
resultTimeStamp = commitResult.getCommitTimestamp();
}
if (Commit.NO_COMMIT_TIMESTAMP == resultTimeStamp) {
classificationTracker.classificationSaveFailed(classificationId);
return Boolean.FALSE;
} else {
classificationTracker.classificationSaved(classificationId, resultTimeStamp);
return Boolean.TRUE;
}
}
Aggregations