diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000000..3a2013a489f --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,170 @@ +config = [ + agentLabel: '', + maven: 'Maven 3', + jdk: 'Zulu 17', + extraMavenArguments: '-U -Ddkpro.core.testCachePath="${WORKSPACE}/cache/dkpro-core-datasets" -Dmaven.artifact.threads=15', + wipeWorkspaceBeforeBuild: true, + wipeWorkspaceAfterBuild: true + ] + +pipeline { + parameters { + string( + name: 'extraMavenArguments', + defaultValue: config.extraMavenArguments, + description: "Extra arguments to be passed to Maven (for testing; overrides only current build)") + string( + name: 'agentLabel', + defaultValue: config.agentLabel, + description: "Eligible agents (in case a build keeps running on a broken agent; overrides only current build)") + booleanParam( + name: 'wipeWorkspaceBeforeBuild', + defaultValue: config.wipeWorkspaceBeforeBuild, + description: "Wipe workspace before build (for testing; next build only)") + booleanParam( + name: 'wipeWorkspaceAfterBuild', + defaultValue: config.wipeWorkspaceAfterBuild, + description: "Wipe workspace after build (for testing; next build only)") + } + + agent { + label params.agentLabel + } + + tools { + maven config.maven + jdk config.jdk + } + + options { + buildDiscarder(logRotator( + numToKeepStr: '25', + artifactNumToKeepStr: '5' + )) + skipDefaultCheckout() + } + + stages { + stage("Checkout code") { + steps { + script { + if (params.wipeWorkspaceBeforeBuild) { + echo "Wiping workspace..." + cleanWs(cleanWhenNotBuilt: true, + deleteDirs: true, + disableDeferredWipeout: true, + notFailBuild: true) + } + } + + dir('checkout') { + checkout scm + } + } + } + + // Display information about the build environment. This can be useful for debugging + // build issues. + stage("Info") { + steps { + echo '=== Environment variables ===' + script { + if (isUnix()) { + sh 'printenv' + } + else { + bat 'set' + } + } + } + } + + // Perform a merge request build. This is a conditional stage executed with the GitLab + // sources plugin triggers a build for a merge request. To avoid conflicts with other + // builds, this stage should not deploy artifacts to the Maven repository server and + // also not install them locally. + stage("PR build") { + when { branch 'PR-*' } + + steps { + script { + currentBuild.description = 'Triggered by: ' + BRANCH_NAME + + ': ' + env.CHANGE_BRANCH + ' (' + env.CHANGE_AUTHOR_DISPLAY_NAME + ')' + } + + dir('checkout') { + withMaven(maven: config.maven, jdk: config.jdk, mavenLocalRepo: "$WORKSPACE/.repository") { + script { + def mavenCommand = 'mvn ' + + params.extraMavenArguments + + ' -B -Dmaven.test.failure.ignore=true -T 4 -Pjacoco clean verify javadoc:javadoc'; + + if (isUnix()) { + sh script: mavenCommand + } + else { + bat script: mavenCommand + } + } + } + + script { + def mavenConsoleIssues = scanForIssues tool: mavenConsole() + def javaIssues = scanForIssues tool: java() + def javaDocIssues = scanForIssues tool: javaDoc() + publishIssues id: "analysis", issues: [mavenConsoleIssues, javaIssues, javaDocIssues] + } + } + } + } + + // Perform a SNAPSHOT build of a main branch. This stage is typically executed after a + // merge request has been merged. On success, it deploys the generated artifacts to the + // Maven repository server. + stage("SNAPSHOT build") { + when { branch pattern: "main|release/.*", comparator: "REGEXP" } + + steps { + dir('checkout') { + withMaven(maven: config.maven, jdk: config.jdk, mavenLocalRepo: "$WORKSPACE/.repository") { + script { + def mavenCommand = 'mvn ' + + params.extraMavenArguments + + ' -B -Dmaven.test.failure.ignore=true -Pjacoco,full-tests clean verify javadoc:javadoc' + + if (isUnix()) { + sh script: mavenCommand + } + else { + bat script: mavenCommand + } + } + } + + script { + def mavenConsoleIssues = scanForIssues tool: mavenConsole() + def javaIssues = scanForIssues tool: java() + def javaDocIssues = scanForIssues tool: javaDoc() + def spotBugsIssues = scanForIssues tool: spotBugs() + def taskScannerIssues = scanForIssues tool: taskScanner() + publishIssues id: "analysis", issues: [mavenConsoleIssues, javaIssues, javaDocIssues, spotBugsIssues, taskScannerIssues] + } + } + } + } + } + + post { + success { + script { + if (params.wipeWorkspaceAfterBuild) { + echo "Wiping workspace..." + cleanWs(cleanWhenNotBuilt: false, + deleteDirs: true, + disableDeferredWipeout: true, + notFailBuild: true) + } + } + } + } +} \ No newline at end of file diff --git a/inception/inception-active-learning/pom.xml b/inception/inception-active-learning/pom.xml index 4dbf7740403..28dc6403940 100644 --- a/inception/inception-active-learning/pom.xml +++ b/inception/inception-active-learning/pom.xml @@ -20,7 +20,7 @@ de.tudarmstadt.ukp.inception.app inception-app - 29.0-SNAPSHOT + 30.0-SNAPSHOT .. inception-active-learning diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningService.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningService.java index 4cd7e362f4c..2549de5f2a4 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningService.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningService.java @@ -25,7 +25,6 @@ import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; import de.tudarmstadt.ukp.clarin.webanno.security.model.User; import de.tudarmstadt.ukp.inception.active.learning.ActiveLearningServiceImpl.ActiveLearningUserState; -import de.tudarmstadt.ukp.inception.recommendation.api.model.LearningRecord; import de.tudarmstadt.ukp.inception.recommendation.api.model.LearningRecordType; import de.tudarmstadt.ukp.inception.recommendation.api.model.SpanSuggestion; import de.tudarmstadt.ukp.inception.recommendation.api.model.SuggestionGroup; @@ -44,15 +43,6 @@ public interface ActiveLearningService */ List> getSuggestions(User aDataOwner, AnnotationLayer aLayer); - /** - * @param aRecord - * record to check - * @return if the suggestions from which the given record was created (or an equivalent one) is - * visible to the user. This is useful to check if the suggestion can be highlighted - * when clicking on a history record. - */ - boolean isSuggestionVisible(LearningRecord aRecord); - /** * @return if the are any records of type {@link LearningRecordType#SKIPPED} in the history of * the given layer for the given user. @@ -64,8 +54,8 @@ public interface ActiveLearningService */ boolean hasSkippedSuggestions(String aSessionOwner, User aDataOwner, AnnotationLayer aLayer); - void hideRejectedOrSkippedAnnotations(String aSessionOwner, User aDataOwner, AnnotationLayer aLayer, - boolean aFilterSkippedRecommendation, + void hideRejectedOrSkippedAnnotations(String aSessionOwner, User aDataOwner, + AnnotationLayer aLayer, boolean aFilterSkippedRecommendation, List> aSuggestionGroups); Optional> generateNextSuggestion(String aSessionOwner, User aDataOwner, diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningServiceImpl.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningServiceImpl.java index 5a9dffbc25f..df12932ac33 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningServiceImpl.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/ActiveLearningServiceImpl.java @@ -27,8 +27,8 @@ import java.io.IOException; import java.io.Serializable; +import java.lang.invoke.MethodHandles; import java.util.List; -import java.util.Map; import java.util.Optional; import org.slf4j.Logger; @@ -49,10 +49,7 @@ import de.tudarmstadt.ukp.inception.recommendation.api.LearningRecordService; import de.tudarmstadt.ukp.inception.recommendation.api.RecommendationService; import de.tudarmstadt.ukp.inception.recommendation.api.model.AnnotationSuggestion; -import de.tudarmstadt.ukp.inception.recommendation.api.model.LearningRecord; -import de.tudarmstadt.ukp.inception.recommendation.api.model.Predictions; import de.tudarmstadt.ukp.inception.recommendation.api.model.SpanSuggestion; -import de.tudarmstadt.ukp.inception.recommendation.api.model.SuggestionDocumentGroup; import de.tudarmstadt.ukp.inception.recommendation.api.model.SuggestionGroup; import de.tudarmstadt.ukp.inception.recommendation.api.model.SuggestionGroup.Delta; import de.tudarmstadt.ukp.inception.schema.AnnotationSchemaService; @@ -68,7 +65,7 @@ public class ActiveLearningServiceImpl implements ActiveLearningService { - private final Logger log = LoggerFactory.getLogger(getClass()); + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final ApplicationEventPublisher applicationEventPublisher; private final DocumentService documentService; @@ -97,39 +94,20 @@ public ActiveLearningServiceImpl(DocumentService aDocumentService, @Override public List> getSuggestions(User aUser, AnnotationLayer aLayer) { - Predictions predictions = recommendationService.getPredictions(aUser, aLayer.getProject()); + var predictions = recommendationService.getPredictions(aUser, aLayer.getProject()); if (predictions == null) { return emptyList(); } - Map> recommendationsMap = predictions - .getPredictionsForWholeProject(SpanSuggestion.class, aLayer, documentService); + var recommendationsMap = predictions.getPredictionsForWholeProject(SpanSuggestion.class, + aLayer, documentService); return recommendationsMap.values().stream() // .flatMap(docMap -> docMap.stream()) // .collect(toList()); } - @Override - public boolean isSuggestionVisible(LearningRecord aRecord) - { - var aSessionOwner = userService.get(aRecord.getUser()); - var suggestionGroups = getSuggestions(aSessionOwner, aRecord.getLayer()); - for (var suggestionGroup : suggestionGroups) { - if (suggestionGroup.stream().anyMatch(suggestion -> suggestion.getDocumentName() - .equals(aRecord.getSourceDocument().getName()) - && suggestion.getFeature().equals(aRecord.getAnnotationFeature().getName()) - && suggestion.labelEquals(aRecord.getAnnotation()) - && suggestion.getBegin() == aRecord.getOffsetBegin() - && suggestion.getEnd() == aRecord.getOffsetEnd() // - && suggestion.isVisible())) { - return true; - } - } - return false; - } - @Override public boolean hasSkippedSuggestions(String aSessionOwner, User aDataOwner, AnnotationLayer aLayer) @@ -174,27 +152,31 @@ public Optional> generateNextSuggestion(String aSessionOwn long startTimer = System.currentTimeMillis(); var suggestionGroups = alState.getSuggestions(); long getRecommendationsFromRecommendationService = System.currentTimeMillis(); - log.trace("Getting recommendations from recommender system took {} ms.", + LOG.trace("Getting recommendations from recommender system took {} ms.", (getRecommendationsFromRecommendationService - startTimer)); - // remove duplicate recommendations - suggestionGroups = suggestionGroups.stream() // - .map(it -> removeDuplicateRecommendations(it)) // - .collect(toList()); - long removeDuplicateRecommendation = System.currentTimeMillis(); - log.trace("Removing duplicate recommendations took {} ms.", - (removeDuplicateRecommendation - getRecommendationsFromRecommendationService)); - // hide rejected recommendations hideRejectedOrSkippedAnnotations(aSessionOwner, aDataOwner, alState.getLayer(), true, suggestionGroups); long removeRejectedSkippedRecommendation = System.currentTimeMillis(); - log.trace("Removing rejected or skipped ones took {} ms.", - (removeRejectedSkippedRecommendation - removeDuplicateRecommendation)); + LOG.trace("Hiding rejected or skipped ones took {} ms.", + (removeRejectedSkippedRecommendation + - getRecommendationsFromRecommendationService)); + + // remove duplicate recommendations + suggestionGroups = suggestionGroups.stream() // + .map(it -> removeDuplicatesAndHiddenSuggestions(it)) // + .filter(it -> !it.isEmpty()) // + .collect(toList()); + long removeDuplicateRecommendation = System.currentTimeMillis(); + LOG.trace("Removing duplicate recommendations took {} ms.", + (removeDuplicateRecommendation - removeRejectedSkippedRecommendation)); var pref = recommendationService.getPreferences(aDataOwner, alState.getLayer().getProject()); - return alState.getStrategy().generateNextSuggestion(pref, suggestionGroups); + var nextSuggestion = alState.getStrategy().generateNextSuggestion(pref, suggestionGroups); + assert nextSuggestion.get().getFirst().isVisible() : "Generated suggestion must be visible"; + return nextSuggestion; } @Override @@ -296,35 +278,40 @@ public void skipSpanSuggestion(String aSessionOwner, User aDataOwner, Annotation alternativeSuggestions)); } - private static SuggestionGroup removeDuplicateRecommendations( - SuggestionGroup unmodifiedRecommendationList) + private static SuggestionGroup removeDuplicatesAndHiddenSuggestions( + SuggestionGroup aSuggestionGroup) { - SuggestionGroup cleanRecommendationList = new SuggestionGroup<>(); + var cleanSuggestionGroup = new SuggestionGroup(); - unmodifiedRecommendationList.forEach(recommendationItem -> { - if (!isAlreadyInCleanList(cleanRecommendationList, recommendationItem)) { - cleanRecommendationList.add(recommendationItem); + aSuggestionGroup.forEach(suggestion -> { + if (!suggestion.isVisible()) { + return; + } + + if (!isAlreadyInCleanList(cleanSuggestionGroup, suggestion)) { + cleanSuggestionGroup.add(suggestion); } }); - return cleanRecommendationList; + return cleanSuggestionGroup; } private static boolean isAlreadyInCleanList( SuggestionGroup cleanRecommendationList, AnnotationSuggestion recommendationItem) { - String source = recommendationItem.getRecommenderName(); - String annotation = recommendationItem.getLabel(); - String documentName = recommendationItem.getDocumentName(); + var source = recommendationItem.getRecommenderName(); + var annotation = recommendationItem.getLabel(); + var documentName = recommendationItem.getDocumentName(); - for (AnnotationSuggestion existingRecommendation : cleanRecommendationList) { - boolean areLabelsEqual = existingRecommendation.labelEquals(annotation); + for (var existingRecommendation : cleanRecommendationList) { + var areLabelsEqual = existingRecommendation.labelEquals(annotation); if (existingRecommendation.getRecommenderName().equals(source) && areLabelsEqual && existingRecommendation.getDocumentName().equals(documentName)) { return true; } } + return false; } diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java index c5b026063d0..60f8a33aea1 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java @@ -75,7 +75,6 @@ import de.tudarmstadt.ukp.clarin.webanno.model.ReorderableTag; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; import de.tudarmstadt.ukp.clarin.webanno.security.UserDao; -import de.tudarmstadt.ukp.clarin.webanno.security.model.User; import de.tudarmstadt.ukp.clarin.webanno.support.bootstrap.BootstrapModalDialog; import de.tudarmstadt.ukp.clarin.webanno.support.lambda.LambdaAjaxButton; import de.tudarmstadt.ukp.clarin.webanno.support.lambda.LambdaAjaxLink; @@ -302,10 +301,10 @@ private List listLayersWithRecommenders() private void actionStartSession(AjaxRequestTarget aTarget, Form form) { - ActiveLearningUserState alState = alStateModel.getObject(); - AnnotatorState state = getModelObject(); - String userName = state.getUser().getUsername(); - Project project = state.getProject(); + var alState = alStateModel.getObject(); + var state = getModelObject(); + var userName = state.getUser().getUsername(); + var project = state.getProject(); recommendationService.setPredictForAllDocuments(userName, project, true); recommendationService.triggerPrediction(userName, "ActionStartActiveLearningSession", @@ -333,6 +332,7 @@ private void actionStartSession(AjaxRequestTarget aTarget, Form form) */ private void requestClearningSelectionAndJumpingToSuggestion() { + LOG.trace("Requesting clearing and jumping"); RequestCycle.get().setMetaData(ClearSelectionAndJumpToSuggestionKey.INSTANCE, true); } @@ -365,7 +365,7 @@ private void actionStopSession(AjaxRequestTarget aTarget) private void setActiveLearningHighlight(SpanSuggestion aSuggestion) { - assert aSuggestion.isVisible(); + assert aSuggestion.isVisible() : "Cannot highlight hidden suggestions"; if (protectHighlight) { LOG.trace("Active learning sidebar not updating protected highlights"); @@ -519,12 +519,18 @@ private LambdaAjaxLink createJumpToSuggestionLink() private void actionJumpToSuggestion(AjaxRequestTarget aTarget) throws IOException { - ActiveLearningUserState alState = alStateModel.getObject(); - SpanSuggestion suggestion = alState.getSuggestion().get(); + var alState = alStateModel.getObject(); + var suggestion = alState.getSuggestion().get(); + + if (!suggestion.isVisible()) { + error("Cannot jump to hidden suggestion"); + aTarget.addChildren(getPage(), IFeedback.class); + return; + } if (LOG.isDebugEnabled()) { LOG.debug("Active suggestion: {}", suggestion); - Optional updatedSuggestion = getMatchingSuggestion(activeLearningService + var updatedSuggestion = getMatchingSuggestion(activeLearningService .getSuggestions(getModelObject().getUser(), alState.getLayer()), suggestion) .stream().findFirst(); updatedSuggestion.ifPresent(s -> LOG.debug("Update suggestion: {}", s)); @@ -732,13 +738,14 @@ private void moveToNextSuggestion(AjaxRequestTarget aTarget) var sessionOwner = userService.getCurrentUser(); // Generate the next recommendation but remember the current one - Optional prevSuggestion = alState.getSuggestion(); - alState.setCurrentDifference(activeLearningService - .generateNextSuggestion(sessionOwner.getUsername(), dataOwner, alState)); + var currentSuggestion = alState.getSuggestion(); + var nextSuggestion = activeLearningService + .generateNextSuggestion(sessionOwner.getUsername(), dataOwner, alState); + alState.setCurrentDifference(nextSuggestion); // If there is no new suggestion, nothing left to do here if (!alState.getSuggestion().isPresent()) { - if (prevSuggestion.isPresent()) { + if (currentSuggestion.isPresent()) { infoOnce(aTarget, "There are no more recommendations right now."); } @@ -749,10 +756,11 @@ private void moveToNextSuggestion(AjaxRequestTarget aTarget) } // If the active suggestion has changed, inform the user - if (prevSuggestion.isPresent() - && !alState.getSuggestion().get().equals(prevSuggestion.get())) { + if (currentSuggestion.isPresent() + && !alState.getSuggestion().get().equals(currentSuggestion.get())) { // infoOnce(aTarget, "Active learning has moved to next best suggestion."); - LOG.trace("Moving from {} to {}", prevSuggestion.get(), alState.getSuggestion().get()); + LOG.trace("Moving from {} to {}", currentSuggestion.get(), + alState.getSuggestion().get()); } // If there is a suggestion, open it in the sidebar and take the main editor to its location @@ -778,7 +786,7 @@ private void moveToNextSuggestion(AjaxRequestTarget aTarget) private void clearSelectedAnnotationAndJumpToSuggestion(AjaxRequestTarget aTarget) { - ActiveLearningUserState alState = alStateModel.getObject(); + var alState = alStateModel.getObject(); if (!alState.getSuggestion().isPresent()) { return; } @@ -787,11 +795,11 @@ private void clearSelectedAnnotationAndJumpToSuggestion(AjaxRequestTarget aTarge // I.e. we must not make the editor/feature details jump to the next suggestion but rather // keep the view and selected annotation that the user has chosen to provide the opportunity // to the user to continue editing on it - SpanSuggestion suggestion = alState.getSuggestion().get(); - AnnotatorState state = getModelObject(); - Project project = state.getProject(); - User user = state.getUser(); - SourceDocument sourceDocument = documentService.getSourceDocument(project, + var suggestion = alState.getSuggestion().get(); + var state = getModelObject(); + var project = state.getProject(); + var user = state.getUser(); + var sourceDocument = documentService.getSourceDocument(project, suggestion.getDocumentName()); LOG.trace("Jumping to {}", suggestion); @@ -829,12 +837,12 @@ private void loadSuggestionInActiveLearningSidebar(AjaxRequestTarget aTarget, // Obtain some left and right context of the active suggestion while we have easy // access to the document which contains the current suggestion try { - CAS cas = documentService.readAnnotationCas(sourceDocument, + var cas = documentService.readAnnotationCas(sourceDocument, getModelObject().getUser().getUsername(), AUTO_CAS_UPGRADE, SHARED_READ_ONLY_ACCESS); - String text = cas.getDocumentText(); + var text = cas.getDocumentText(); - ActiveLearningUserState alState = alStateModel.getObject(); + var alState = alStateModel.getObject(); alState.setLeftContext( text.substring(Math.max(0, suggestion.getBegin() - 20), suggestion.getBegin())); alState.setRightContext(text.substring(suggestion.getEnd(), @@ -872,8 +880,8 @@ private ListView createLearningHistoryListView() @Override protected void populateItem(ListItem item) { - LearningRecord rec = item.getModelObject(); - AnnotationFeature recAnnotationFeature = rec.getAnnotationFeature(); + var rec = item.getModelObject(); + var recAnnotationFeature = rec.getAnnotationFeature(); String recFeatureValue; if (recAnnotationFeature != null) { FeatureSupport featureSupport = featureSupportRegistry @@ -885,7 +893,7 @@ protected void populateItem(ListItem item) recFeatureValue = rec.getAnnotation(); } - LambdaAjaxLink textLink = new LambdaAjaxLink(CID_JUMP_TO_ANNOTATION, + var textLink = new LambdaAjaxLink(CID_JUMP_TO_ANNOTATION, _target -> actionSelectHistoryItem(_target, item.getModelObject())); textLink.setBody(rec::getTokenText); item.add(textLink); @@ -923,10 +931,10 @@ private void actionSelectHistoryItem(AjaxRequestTarget aTarget, LearningRecord a // Since we have switched documents above (if it was necessary), the editor CAS should // now point to the correct one - CAS cas = getCasProvider().get(); + var cas = getCasProvider().get(); // ... if a matching annotation exists, highlight the annotaiton - Optional annotation = getMatchingAnnotation(cas, aRecord); + var annotation = getMatchingAnnotation(cas, aRecord); if (annotation.isPresent()) { setActiveLearningHighlight(aRecord.getSourceDocument(), annotation.get()); @@ -976,7 +984,8 @@ private List getMatchingSuggestion( && (aFeature == null || aFeature.equals(group.getFeature())) && (aBegin == -1 || aBegin == ((Offset) group.getPosition()).getBegin()) && (aEnd == -1 || aEnd == ((Offset) group.getPosition()).getEnd())) - .flatMap(group -> group.stream()) + .flatMap(group -> group.stream()) // + .filter(suggestion -> suggestion.isVisible()) // .filter(suggestion -> aLabel == null || aLabel.equals(suggestion.getLabel())) .collect(toList()); } @@ -1360,10 +1369,10 @@ private void refreshAvailableSuggestions() { LOG.trace("refreshAvailableSuggestions()"); - AnnotatorState state = getModelObject(); - ActiveLearningUserState alState = alStateModel.getObject(); - alState.setSuggestions( - activeLearningService.getSuggestions(state.getUser(), alState.getLayer())); + var state = getModelObject(); + var alState = alStateModel.getObject(); + var suggestions = activeLearningService.getSuggestions(state.getUser(), alState.getLayer()); + alState.setSuggestions(suggestions); } @OnEvent @@ -1420,11 +1429,11 @@ private void refreshCurrentSuggestionOrMoveToNextSuggestion(AjaxRequestTarget aT // is still relevant - if yes, we need to replace it with its current counterpart since. // if no counterpart exists in the current suggestions, then we need to load a // suggestion from the current list. - ActiveLearningUserState alState = alStateModel.getObject(); - SpanSuggestion activeSuggestion = alState.getSuggestion().get(); + var alState = alStateModel.getObject(); + var activeSuggestion = alState.getSuggestion().get(); // Find the groups which matches the active recommendation - Optional updatedSuggestion = getMatchingSuggestion(alState.getSuggestions(), - activeSuggestion).stream().findFirst(); + var updatedSuggestion = getMatchingSuggestion(alState.getSuggestions(), activeSuggestion) + .stream().findFirst(); if (updatedSuggestion.isEmpty()) { moveToNextSuggestion(aTarget); @@ -1432,8 +1441,7 @@ private void refreshCurrentSuggestionOrMoveToNextSuggestion(AjaxRequestTarget aT } LOG.debug("Replacing outdated suggestion {} with new suggestion {}", - alState.getCurrentDifference().get().getFirst().getId(), - updatedSuggestion.get().getId()); + alState.getCurrentDifference().get().getFirst(), updatedSuggestion.get()); // Update the highlight if (alState.getSuggestion().get().getVID().equals(highlightVID)) { diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/strategy/UncertaintySamplingStrategy.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/strategy/UncertaintySamplingStrategy.java index a35a5f092e0..79eec16243e 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/strategy/UncertaintySamplingStrategy.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/strategy/UncertaintySamplingStrategy.java @@ -34,9 +34,9 @@ public class UncertaintySamplingStrategy @Override public Optional> generateNextSuggestion(Preferences aPreferences, - List> suggestions) + List> aSuggestions) { - return suggestions.stream() + return aSuggestions.stream() // Fetch the top deltas per recommender .flatMap(group -> group.getTopDeltas(aPreferences).values().stream()) // ... sort them in ascending order (smallest delta first) diff --git a/inception/inception-agreement/pom.xml b/inception/inception-agreement/pom.xml index 6f4d888a263..80115d97405 100644 --- a/inception/inception-agreement/pom.xml +++ b/inception/inception-agreement/pom.xml @@ -20,7 +20,7 @@ de.tudarmstadt.ukp.inception.app inception-app - 29.0-SNAPSHOT + 30.0-SNAPSHOT inception-agreement INCEpTION - Core - Agreement diff --git a/inception/inception-annotation-storage/pom.xml b/inception/inception-annotation-storage/pom.xml index a66f8c98e93..6fdce78d46c 100644 --- a/inception/inception-annotation-storage/pom.xml +++ b/inception/inception-annotation-storage/pom.xml @@ -22,7 +22,7 @@ de.tudarmstadt.ukp.inception.app inception-app - 29.0-SNAPSHOT + 30.0-SNAPSHOT inception-annotation-storage INCEpTION - Core - Annotation Storage @@ -124,41 +124,10 @@ - - org.springframework.boot - spring-boot-test - test - - - org.springframework.boot - spring-boot-test-autoconfigure - test - org.apache.uima uimaj-document-annotation test - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - - org.springframework.boot:spring-boot-test - org.springframework.boot:spring-boot-starter-data-jpa - org.hsqldb:hsqldb - - - - - - \ No newline at end of file diff --git a/inception/inception-api-annotation/pom.xml b/inception/inception-api-annotation/pom.xml index 3bd9420fe42..78d7d90b4a1 100644 --- a/inception/inception-api-annotation/pom.xml +++ b/inception/inception-api-annotation/pom.xml @@ -20,7 +20,7 @@ de.tudarmstadt.ukp.inception.app inception-app - 29.0-SNAPSHOT + 30.0-SNAPSHOT inception-api-annotation INCEpTION - Core - Annotation API diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringRulesConfigurationPanel.html b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringRulesConfigurationPanel.html index 04b40babe1a..f1b6fbf54f4 100644 --- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringRulesConfigurationPanel.html +++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringRulesConfigurationPanel.html @@ -32,16 +32,18 @@ -
-
-
- -
-
- - - -
+
+
+ + + + + + +