diff --git a/inception/inception-layer-docmetadata/pom.xml b/inception/inception-layer-docmetadata/pom.xml index d2c09feb7ea..3c5552b55c9 100644 --- a/inception/inception-layer-docmetadata/pom.xml +++ b/inception/inception-layer-docmetadata/pom.xml @@ -69,6 +69,10 @@ de.tudarmstadt.ukp.inception.app inception-log + + de.tudarmstadt.ukp.inception.app + inception-recommendation-api + org.apache.uima diff --git a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationDetailPanel.java b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationDetailPanel.java index 5028339407b..db70460af95 100644 --- a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationDetailPanel.java +++ b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationDetailPanel.java @@ -50,6 +50,7 @@ import de.tudarmstadt.ukp.clarin.webanno.model.Project; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; import de.tudarmstadt.ukp.clarin.webanno.model.Tag; +import de.tudarmstadt.ukp.clarin.webanno.security.model.User; import de.tudarmstadt.ukp.clarin.webanno.ui.annotation.AnnotationPage; import de.tudarmstadt.ukp.inception.annotation.feature.link.LinkFeatureDeletedEvent; import de.tudarmstadt.ukp.inception.annotation.feature.link.LinkFeatureEditor; @@ -88,13 +89,13 @@ public class DocumentMetadataAnnotationDetailPanel private final CasProvider jcasProvider; private final IModel project; private final IModel sourceDocument; - private final IModel username; + private final IModel user; private final ListView featureList; private final AnnotationActionHandler actionHandler; private final AnnotatorState state; public DocumentMetadataAnnotationDetailPanel(String aId, IModel aModel, - IModel aDocument, IModel aUsername, CasProvider aCasProvider, + IModel aDocument, IModel aUser, CasProvider aCasProvider, IModel aProject, AnnotationPage aAnnotationPage, AnnotationActionHandler aActionHandler, AnnotatorState aState) { @@ -103,7 +104,7 @@ public DocumentMetadataAnnotationDetailPanel(String aId, IModel aModel, setOutputMarkupPlaceholderTag(true); sourceDocument = aDocument; - username = aUsername; + user = aUser; annotationPage = aAnnotationPage; jcasProvider = aCasProvider; project = aProject; @@ -324,8 +325,8 @@ private void writeFeatureEditorModelsToCas(TypeAdapter aAdapter, CAS aCas) LOG.trace("writeFeatureEditorModelsToCas() " + featureState.feature.getUiName() + " = " + featureState.value); - aAdapter.setFeatureValue(sourceDocument.getObject(), username.getObject(), aCas, - getModelObject().getId(), featureState.feature, featureState.value); + aAdapter.setFeatureValue(sourceDocument.getObject(), user.getObject().getUsername(), + aCas, getModelObject().getId(), featureState.feature, featureState.value); } } diff --git a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.html b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.html index bf25ca1468e..c2839306f57 100644 --- a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.html +++ b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.html @@ -46,9 +46,9 @@ -
+
diff --git a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java index 381f00851ca..d6e06550658 100644 --- a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java +++ b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java @@ -17,24 +17,20 @@ */ package de.tudarmstadt.ukp.inception.ui.core.docanno.sidebar; +import static de.tudarmstadt.ukp.inception.support.lambda.HtmlElementEvents.CLICK; import static de.tudarmstadt.ukp.inception.support.lambda.LambdaBehavior.enabledWhen; import static de.tudarmstadt.ukp.inception.support.lambda.LambdaBehavior.visibleWhen; import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.uima.UIMAException; -import org.apache.uima.cas.AnnotationBaseFS; import org.apache.uima.cas.CAS; -import org.apache.uima.cas.FeatureStructure; import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxEventBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.feedback.IFeedback; import org.apache.wicket.markup.html.WebMarkupContainer; @@ -55,22 +51,22 @@ import de.tudarmstadt.ukp.clarin.webanno.api.annotation.page.AnnotationPageBase; import de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasProvider; -import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature; import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer; import de.tudarmstadt.ukp.clarin.webanno.model.Project; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; +import de.tudarmstadt.ukp.clarin.webanno.security.model.User; import de.tudarmstadt.ukp.clarin.webanno.ui.annotation.AnnotationPage; import de.tudarmstadt.ukp.inception.annotation.events.FeatureValueUpdatedEvent; import de.tudarmstadt.ukp.inception.editor.action.AnnotationActionHandler; -import de.tudarmstadt.ukp.inception.rendering.Renderer; +import de.tudarmstadt.ukp.inception.recommendation.api.RecommendationService; import de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotatorState; import de.tudarmstadt.ukp.inception.rendering.vmodel.VID; import de.tudarmstadt.ukp.inception.schema.api.AnnotationSchemaService; import de.tudarmstadt.ukp.inception.schema.api.adapter.AnnotationException; -import de.tudarmstadt.ukp.inception.schema.api.adapter.TypeAdapter; import de.tudarmstadt.ukp.inception.schema.api.feature.TypeUtil; import de.tudarmstadt.ukp.inception.schema.api.layer.LayerSupport; import de.tudarmstadt.ukp.inception.schema.api.layer.LayerSupportRegistry; +import de.tudarmstadt.ukp.inception.support.lambda.LambdaAjaxEventBehavior; import de.tudarmstadt.ukp.inception.support.lambda.LambdaAjaxFormComponentUpdatingBehavior; import de.tudarmstadt.ukp.inception.support.lambda.LambdaAjaxLink; import de.tudarmstadt.ukp.inception.support.uima.ICasUtil; @@ -97,12 +93,13 @@ public class DocumentMetadataAnnotationSelectionPanel private @SpringBean LayerSupportRegistry layerSupportRegistry; private @SpringBean AnnotationSchemaService annotationService; + private @SpringBean RecommendationService recommendationService; private final AnnotationPage annotationPage; private final CasProvider jcasProvider; private final IModel project; private final IModel sourceDocument; - private final IModel username; + private final IModel user; private final IModel selectedLayer; private final IModel> annotations; private final WebMarkupContainer annotationsContainer; @@ -113,7 +110,7 @@ public class DocumentMetadataAnnotationSelectionPanel private final AnnotatorState state; public DocumentMetadataAnnotationSelectionPanel(String aId, IModel aProject, - IModel aDocument, IModel aUsername, CasProvider aCasProvider, + IModel aDocument, IModel aUser, CasProvider aCasProvider, AnnotationPage aAnnotationPage, AnnotationActionHandler aActionHandler, AnnotatorState aState) { @@ -123,17 +120,16 @@ public DocumentMetadataAnnotationSelectionPanel(String aId, IModel aPro annotationPage = aAnnotationPage; sourceDocument = aDocument; - username = aUsername; + user = aUser; jcasProvider = aCasProvider; project = aProject; selectedLayer = Model.of(listCreatableMetadataLayers().stream().findFirst().orElse(null)); - IModel> availableLayers = LoadableDetachableModel - .of(this::listCreatableMetadataLayers); + var availableLayers = LoadableDetachableModel.of(this::listCreatableMetadataLayers); actionHandler = aActionHandler; state = aState; annotations = LoadableDetachableModel.of(this::listAnnotations); - WebMarkupContainer content = new WebMarkupContainer("content"); + var content = new WebMarkupContainer("content"); add(content); annotationsContainer = new WebMarkupContainer(CID_ANNOTATIONS_CONTAINER); @@ -144,7 +140,7 @@ public DocumentMetadataAnnotationSelectionPanel(String aId, IModel aPro || !annotations.map(List::isEmpty).orElse(true).getObject())); content.add(annotationsContainer); - DropDownChoice layer = new DropDownChoice<>(CID_LAYER); + var layer = new DropDownChoice(CID_LAYER); layer.setModel(selectedLayer); layer.setChoices(availableLayers); layer.setChoiceRenderer(new ChoiceRenderer<>("uiName")); @@ -157,7 +153,7 @@ public DocumentMetadataAnnotationSelectionPanel(String aId, IModel aPro .add(visibleWhen( () -> !availableLayers.map(List::isEmpty).orElse(true).getObject()))); - WebMarkupContainer noLayersWarning = new WebMarkupContainer("noLayersWarning"); + var noLayersWarning = new WebMarkupContainer("noLayersWarning"); noLayersWarning .add(visibleWhen(() -> availableLayers.map(List::isEmpty).orElse(true).getObject() && annotations.map(List::isEmpty).orElse(true).getObject())); @@ -175,11 +171,10 @@ private void actionCreate(AjaxRequestTarget aTarget) throws AnnotationException, try { annotationPage.ensureIsEditable(); - DocumentMetadataLayerAdapter adapter = (DocumentMetadataLayerAdapter) annotationService + var adapter = (DocumentMetadataLayerAdapter) annotationService .getAdapter(selectedLayer.getObject()); - CAS cas = jcasProvider.get(); - AnnotationBaseFS fs = adapter.add(sourceDocument.getObject(), username.getObject(), - cas); + var cas = jcasProvider.get(); + var fs = adapter.add(sourceDocument.getObject(), user.getObject().getUsername(), cas); createdAnnotationAddress = fs.getAddress(); annotationPage.writeEditorCas(cas); @@ -200,14 +195,14 @@ private void actionDelete(AjaxRequestTarget aTarget, annotationPage.ensureIsEditable(); // Load the boiler-plate - CAS cas = jcasProvider.get(); - FeatureStructure fs = ICasUtil.selectFsByAddr(cas, - aDetailPanel.getModelObject().getId()); - AnnotationLayer layer = annotationService.findLayer(project.getObject(), fs); - TypeAdapter adapter = annotationService.getAdapter(layer); + var cas = jcasProvider.get(); + var fs = ICasUtil.selectFsByAddr(cas, aDetailPanel.getModelObject().getId()); + var layer = annotationService.findLayer(project.getObject(), fs); + var adapter = annotationService.getAdapter(layer); // Perform actual actions - adapter.delete(sourceDocument.getObject(), username.getObject(), cas, new VID(fs)); + adapter.delete(sourceDocument.getObject(), user.getObject().getUsername(), cas, + VID.of(fs)); // persist changes annotationPage.writeEditorCas(cas); @@ -275,26 +270,18 @@ protected void populateItem(ListItem aItem) { aItem.setModel(CompoundPropertyModel.of(aItem.getModel())); - VID vid = new VID(aItem.getModelObject().addr); + var vid = aItem.getModelObject().vid; - WebMarkupContainer container = new WebMarkupContainer("annotation"); + var container = new WebMarkupContainer("annotation"); aItem.add(container); - DocumentMetadataAnnotationDetailPanel detailPanel = new DocumentMetadataAnnotationDetailPanel( - CID_ANNOTATION_DETAILS, Model.of(vid), sourceDocument, username, - jcasProvider, project, annotationPage, actionHandler, state); + var detailPanel = new DocumentMetadataAnnotationDetailPanel(CID_ANNOTATION_DETAILS, + Model.of(vid), sourceDocument, user, jcasProvider, project, annotationPage, + actionHandler, state); aItem.add(detailPanel); - container.add(new AjaxEventBehavior("click") - { - private static final long serialVersionUID = 1L; - - @Override - protected void onEvent(AjaxRequestTarget aTarget) - { - actionSelect(aTarget, container, detailPanel); - } - }); + container.add(new LambdaAjaxEventBehavior(CLICK, + $ -> actionSelect($, container, detailPanel))); detailPanel.add(visibleWhen(() -> isExpanded(aItem, container))); @@ -304,12 +291,12 @@ protected void onEvent(AjaxRequestTarget aTarget) selectedDetailPanel = detailPanel; } - WebMarkupContainer close = new WebMarkupContainer("close"); + var close = new WebMarkupContainer("close"); close.add(visibleWhen(() -> isExpanded(aItem, container))); close.setOutputMarkupId(true); container.add(close); - WebMarkupContainer open = new WebMarkupContainer("open"); + var open = new WebMarkupContainer("open"); open.add(visibleWhen(() -> !isExpanded(aItem, container))); open.setOutputMarkupId(true); container.add(open); @@ -319,11 +306,10 @@ protected void onEvent(AjaxRequestTarget aTarget) .add(visibleWhen(() -> !aItem.getModelObject().singleton))); container.setOutputMarkupId(true); - aItem.add(new LambdaAjaxLink(CID_DELETE, - _target -> actionDelete(_target, detailPanel)) - .add(visibleWhen(() -> !aItem.getModelObject().singleton)) - .add(enabledWhen(() -> annotationPage.isEditable() - && !aItem.getModelObject().layer.isReadonly()))); + aItem.add(new LambdaAjaxLink(CID_DELETE, $ -> actionDelete($, detailPanel)) + .add(visibleWhen(() -> !aItem.getModelObject().singleton)) + .add(enabledWhen(() -> annotationPage.isEditable() + && !aItem.getModelObject().layer.isReadonly()))); aItem.setOutputMarkupId(true); } @@ -340,16 +326,16 @@ private List listMetadataLayers() { return annotationService.listAnnotationLayer(getModelObject()).stream() .filter(layer -> DocumentMetadataLayerSupport.TYPE.equals(layer.getType()) - && layer.isEnabled()) - .collect(Collectors.toList()); + && layer.isEnabled()) // + .toList(); } private List listCreatableMetadataLayers() { return listMetadataLayers().stream() // .filter(layer -> !layer.isReadonly()) // - .filter(layer -> !getLayerSupport(layer).readTraits(layer).isSingleton()) - .collect(toList()); + .filter(layer -> !getLayerSupport(layer).readTraits(layer).isSingleton()) // + .toList(); } private DocumentMetadataLayerSupport getLayerSupport(AnnotationLayer aLayer) @@ -368,24 +354,28 @@ private List listAnnotations() return emptyList(); } - List items = new ArrayList<>(); - for (AnnotationLayer layer : listMetadataLayers()) { - List features = annotationService.listSupportedFeatures(layer); - TypeAdapter adapter = annotationService.getAdapter(layer); + var items = new ArrayList(); + + for (var layer : listMetadataLayers()) { + var features = annotationService.listSupportedFeatures(layer); + var adapter = annotationService.getAdapter(layer); LayerSupport layerSupport = layerSupportRegistry.getLayerSupport(layer); - Renderer renderer = layerSupport.createRenderer(layer, + var renderer = layerSupport.createRenderer(layer, () -> annotationService.listAnnotationFeature(layer)); - boolean singleton = getLayerSupport(layer).readTraits(layer).isSingleton(); - - for (FeatureStructure fs : cas.select(adapter.getAnnotationType(cas))) { - Map renderedFeatures = renderer.renderLabelFeatureValues(adapter, - fs, features); - String labelText = TypeUtil.getUiLabelText(renderedFeatures); - items.add( - new AnnotationListItem(ICasUtil.getAddr(fs), labelText, layer, singleton)); + var singleton = getLayerSupport(layer).readTraits(layer).isSingleton(); + + for (var fs : cas.select(adapter.getAnnotationType(cas))) { + var renderedFeatures = renderer.renderLabelFeatureValues(adapter, fs, features); + var labelText = TypeUtil.getUiLabelText(renderedFeatures); + items.add(new AnnotationListItem(VID.of(fs), labelText, layer, singleton)); } } + var predictions = recommendationService.getPredictions(user.getObject(), getModelObject()); + if (predictions != null) { + predictions.getPredictionsByDocument(sourceDocument.getObject().getName()); + } + return items; } @@ -409,15 +399,6 @@ public void onFeatureValueUpdated(FeatureValueUpdatedEvent aEvent) } }); - // // If a feature value is updated refresh the annotation list since it might mean that - // // a label has changed - // if (selectedAnnotation != null) { - // aEvent.getRequestTarget().add(selectedAnnotation); - // } - // if (selectedDetailPanel != null) { - // aEvent.getRequestTarget().add(selectedDetailPanel); - // } - findParent(AnnotationPageBase.class) .actionRefreshDocument((aEvent.getRequestTarget().orElse(null))); } @@ -446,19 +427,20 @@ protected static void handleException(Component aComponent, AjaxRequestTarget aT } } - @SuppressWarnings("unused") private class AnnotationListItem + implements Serializable { - final int addr; + private static final long serialVersionUID = -8505492366690693091L; + + final VID vid; final String label; final AnnotationLayer layer; final boolean singleton; - public AnnotationListItem(int aAddr, String aLabel, AnnotationLayer aLayer, + public AnnotationListItem(VID aVid, String aLabel, AnnotationLayer aLayer, boolean aSingleton) { - super(); - addr = aAddr; + vid = aVid; label = aLabel; layer = aLayer; singleton = aSingleton; diff --git a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataSidebar.java b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataSidebar.java index fca2d26c1f3..427a00d4cbb 100644 --- a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataSidebar.java +++ b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataSidebar.java @@ -18,11 +18,8 @@ package de.tudarmstadt.ukp.inception.ui.core.docanno.sidebar; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LoadableDetachableModel; import de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasProvider; -import de.tudarmstadt.ukp.clarin.webanno.model.Project; -import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; import de.tudarmstadt.ukp.clarin.webanno.ui.annotation.AnnotationPage; import de.tudarmstadt.ukp.clarin.webanno.ui.annotation.sidebar.AnnotationSidebar_ImplBase; import de.tudarmstadt.ukp.inception.editor.action.AnnotationActionHandler; @@ -39,13 +36,11 @@ public DocumentMetadataSidebar(String aId, IModel aModel, { super(aId, aModel, aActionHandler, aCasProvider, aAnnotationPage); - IModel project = LoadableDetachableModel.of(() -> aModel.getObject().getProject()); - IModel sourceDocument = LoadableDetachableModel - .of(() -> aModel.getObject().getDocument()); - IModel username = LoadableDetachableModel - .of(() -> aModel.getObject().getUser().getUsername()); + var project = aModel.map(AnnotatorState::getProject); + var sourceDocument = aModel.map(AnnotatorState::getDocument); + var user = aModel.map(AnnotatorState::getUser); add(new DocumentMetadataAnnotationSelectionPanel("annotations", project, sourceDocument, - username, aCasProvider, aAnnotationPage, aActionHandler, getModelObject())); + user, aCasProvider, aAnnotationPage, aActionHandler, getModelObject())); } } diff --git a/inception/inception-support/src/main/java/de/tudarmstadt/ukp/inception/support/lambda/HtmlElementEvents.java b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/inception/support/lambda/HtmlElementEvents.java index a31f81765ff..a6a67144e86 100644 --- a/inception/inception-support/src/main/java/de/tudarmstadt/ukp/inception/support/lambda/HtmlElementEvents.java +++ b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/inception/support/lambda/HtmlElementEvents.java @@ -38,4 +38,6 @@ public interface HtmlElementEvents public static final String KEYUP_EVENT = "keyup"; public static final String KEYPRESS_EVENT = "keypress"; + + public static final String CLICK = "click"; }