diff --git a/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/SnomedReasonerPlugin.java b/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/SnomedReasonerPlugin.java index 9688cf2eba..d986fb4ec8 100644 --- a/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/SnomedReasonerPlugin.java +++ b/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/SnomedReasonerPlugin.java @@ -22,6 +22,7 @@ import com.b2international.index.Index; import com.b2international.snowowl.core.RepositoryManager; import com.b2international.snowowl.core.config.SnowOwlConfiguration; +import com.b2international.snowowl.core.plugin.ClassPathScanner; import com.b2international.snowowl.core.plugin.Component; import com.b2international.snowowl.core.repository.TerminologyRepositoryConfigurer; import com.b2international.snowowl.core.setup.Environment; @@ -29,6 +30,7 @@ import com.b2international.snowowl.snomed.common.SnomedTerminologyComponentConstants; import com.b2international.snowowl.snomed.datastore.config.SnomedCoreConfiguration; import com.b2international.snowowl.snomed.reasoner.classification.ClassificationTracker; +import com.b2international.snowowl.snomed.reasoner.equivalence.IEquivalentConceptMerger; import com.b2international.snowowl.snomed.reasoner.index.*; /** @@ -45,8 +47,10 @@ public void run(final SnowOwlConfiguration configuration, final Environment env) final int maximumReasonerRuns = snomedConfig.getMaxReasonerRuns(); final long classificationCleanUpInterval = snomedConfig.getClassificationCleanUpInterval(); final ClassificationTracker classificationTracker = new ClassificationTracker(repositoryIndex, maximumReasonerRuns, TimeUnit.MINUTES.toMillis(classificationCleanUpInterval)); - env.services().registerService(ClassificationTracker.class, classificationTracker); + + final ClassPathScanner scanner = env.service(ClassPathScanner.class); + env.services().registerService(IEquivalentConceptMerger.Registry.class, new IEquivalentConceptMerger.Registry(scanner)); } } diff --git a/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/equivalence/IEquivalentConceptMerger.java b/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/equivalence/IEquivalentConceptMerger.java index 4b629f63ea..4cd7bccbfe 100644 --- a/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/equivalence/IEquivalentConceptMerger.java +++ b/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/equivalence/IEquivalentConceptMerger.java @@ -16,10 +16,15 @@ package com.b2international.snowowl.snomed.reasoner.equivalence; import java.util.Collections; +import java.util.List; import java.util.Set; +import com.b2international.snowowl.core.plugin.ClassPathScanner; +import com.b2international.snowowl.core.plugin.Component; import com.b2international.snowowl.snomed.core.domain.SnomedConcept; +import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; +import com.google.common.collect.Ordering; /** * Implementations of this interface can define a customized way for @@ -45,6 +50,16 @@ public interface IEquivalentConceptMerger { */ String PREFIX_UPDATED = "U_"; + /** + * @return the name of this equivalent concept merging strategy (must be unique for each implementation) + */ + String getName(); + + /** + * @return the priority of the implementation, highest priority wins + */ + int getPriority(); + /** * Adds changes to the specified bulk request builder that effectively merges * equivalent concepts into their corresponding suggested replacement. @@ -84,11 +99,36 @@ public interface IEquivalentConceptMerger { * * @since 6.14 */ + @Component class Default implements IEquivalentConceptMerger { + @Override + public String getName() { + return "default"; + } + + @Override + public int getPriority() { + return 0; + } + @Override public Set merge(final Multimap equivalentConcepts) { return Collections.emptySet(); } } + + final class Registry { + private final List implsByPriority; + + public Registry(ClassPathScanner scanner) { + this.implsByPriority = Ordering.natural() + .onResultOf(IEquivalentConceptMerger::getPriority) + .immutableSortedCopy(scanner.getComponentsByInterface(IEquivalentConceptMerger.class)); + } + + public IEquivalentConceptMerger getHighestPriority() { + return Iterables.getLast(implsByPriority); + } + } } diff --git a/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/request/SaveJobRequest.java b/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/request/SaveJobRequest.java index b9926f781a..ed3638b17e 100644 --- a/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/request/SaveJobRequest.java +++ b/snomed/com.b2international.snowowl.snomed.reasoner/src/com/b2international/snowowl/snomed/reasoner/request/SaveJobRequest.java @@ -26,11 +26,8 @@ import java.util.Set; import java.util.stream.Collectors; -import jakarta.validation.constraints.NotNull; - import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; -import jakarta.validation.constraints.NotEmpty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +46,6 @@ import com.b2international.snowowl.core.identity.User; import com.b2international.snowowl.core.internal.locks.DatastoreLockContextDescriptions; import com.b2international.snowowl.core.locks.Locks; -import com.b2international.snowowl.core.plugin.Extensions; import com.b2international.snowowl.core.repository.RepositoryRequests; import com.b2international.snowowl.core.request.CommitResult; import com.b2international.snowowl.snomed.common.SnomedRf2Headers; @@ -69,6 +65,9 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + /** * Represents a request that saves pre-recorded changes of a classification, * usually running in a remote job. @@ -439,15 +438,10 @@ private Set mergeEquivalentConcepts(final BranchContext context, 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 IEquivalentConceptMerger.Registry mergerRegistry = context.service(IEquivalentConceptMerger.Registry.class); + final IEquivalentConceptMerger merger = mergerRegistry.getHighestPriority(); + final String mergerName = merger.getName(); + LOG.info("Reasoner service will use '{}' implementation for equivalent concept merging.", mergerName); final Set conceptIdsToSkip = merger.merge(equivalentConcepts); final Set conceptIdsToKeep = equivalentConcepts.keySet()