From 1449fe1addd7c61cc650483c4698fa6609636e7c Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho
Date: Sun, 3 Mar 2024 18:41:38 +0100
Subject: [PATCH] #4583 - Ability to configure layer visibility via a sidebar
- Added the sidebar
- Started also saving some legacy preferences in the new preferences system so that eventually we may get away from the old preferences file
- Bit of cleaning up here and there
---
.../sidebar/ActiveLearningSidebarFactory.java | 2 +
.../coloring/ColoringServiceImpl.java | 6 +-
.../config/AnnotationAutoConfiguration.java | 5 +-
.../AnnotationPreferencesDialogContent.java | 71 ++++---
.../preferences/UserPreferencesService.java | 2 +-
.../UserPreferencesServiceImpl.java | 181 ++++++++++++------
.../annotation/rendering/ColorRenderer.java | 3 +-
inception/inception-api-render/pom.xml | 4 +
...our.java => ReadonlyColoringStrategy.java} | 4 +-
.../AnnotationLayerVisibilityState.java | 75 ++++++++
.../AnnotationPageLayoutState.java | 84 ++++++++
.../editorstate/AnnotationPreference.java | 68 ++++---
.../editorstate/ColoringPreferences.java | 4 +-
.../diam/sidebar/DiamSidebarFactory.java | 2 +
.../image/sidebar/ImageSidebarFactory.java | 2 +
.../DocumentMetadataSidebarFactory.java | 2 +
.../preferences/PreferencesService.java | 3 +
.../preferences/PreferencesServiceImpl.java | 32 +++-
.../sidebar/RecommendationSidebarFactory.java | 2 +
.../inception/bootstrap/IconToggleBox.java | 6 +-
.../webanno/ui/annotation/AnnotationPage.java | 4 +-
.../config/AnnotationUIAutoConfiguration.java | 7 +
.../AnnotationSidebarFactory_ImplBase.java | 9 +-
.../sidebar/AnnotationSidebar_ImplBase.java | 16 +-
.../sidebar/SidebarTabbedPanel.java | 8 +-
.../docinfo/DocumentInfoSidebarFactory.java | 2 +
.../sidebar/layer/LayerVisibilitySidebar.html | 37 ++++
.../sidebar/layer/LayerVisibilitySidebar.java | 117 +++++++++++
.../layer/LayerVisibilitySidebar.properties | 18 ++
.../layer/LayerVisibilitySidebarFactory.java | 63 ++++++
.../sidebar/CurationSidebarFactory.java | 2 +
...xternalSearchAnnotationSidebarFactory.java | 2 +
.../SearchAnnotationSidebarFactory.java | 2 +
.../StatisticsAnnotationSidebarFactory.java | 2 +
34 files changed, 677 insertions(+), 170 deletions(-)
rename inception/inception-api-render/src/main/java/de/tudarmstadt/ukp/inception/rendering/coloring/{ReadonlyColoringBehaviour.java => ReadonlyColoringStrategy.java} (91%)
create mode 100644 inception/inception-api-render/src/main/java/de/tudarmstadt/ukp/inception/rendering/editorstate/AnnotationLayerVisibilityState.java
create mode 100644 inception/inception-api-render/src/main/java/de/tudarmstadt/ukp/inception/rendering/editorstate/AnnotationPageLayoutState.java
create mode 100644 inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/sidebar/layer/LayerVisibilitySidebar.html
create mode 100644 inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/sidebar/layer/LayerVisibilitySidebar.java
create mode 100644 inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/sidebar/layer/LayerVisibilitySidebar.properties
create mode 100644 inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/sidebar/layer/LayerVisibilitySidebarFactory.java
diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarFactory.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarFactory.java
index d06a1889f6f..7f368adbb32 100644
--- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarFactory.java
+++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarFactory.java
@@ -20,6 +20,7 @@
import org.apache.wicket.Component;
import org.apache.wicket.model.IModel;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
import de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasProvider;
import de.tudarmstadt.ukp.clarin.webanno.model.Project;
@@ -37,6 +38,7 @@
* {@link ActiveLearningAutoConfiguration#activeLearningSidebarFactory}.
*
*/
+@Order(4000)
public class ActiveLearningSidebarFactory
extends AnnotationSidebarFactory_ImplBase
{
diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringServiceImpl.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringServiceImpl.java
index 9434b316a44..58e5d3146f0 100644
--- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringServiceImpl.java
+++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/coloring/ColoringServiceImpl.java
@@ -26,7 +26,7 @@
import static de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategyType.GRAY;
import static de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategyType.LEGACY;
import static de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategyType.STATIC_PASTELLE;
-import static de.tudarmstadt.ukp.inception.rendering.coloring.ReadonlyColoringBehaviour.NORMAL;
+import static de.tudarmstadt.ukp.inception.rendering.coloring.ReadonlyColoringStrategy.NORMAL;
import static de.tudarmstadt.ukp.inception.support.WebAnnoConst.SPAN_TYPE;
import static java.lang.Integer.MAX_VALUE;
import static java.util.Arrays.asList;
@@ -50,7 +50,7 @@
import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringService;
import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategy;
import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategyType;
-import de.tudarmstadt.ukp.inception.rendering.coloring.ReadonlyColoringBehaviour;
+import de.tudarmstadt.ukp.inception.rendering.coloring.ReadonlyColoringStrategy;
import de.tudarmstadt.ukp.inception.rendering.editorstate.ColoringPreferences;
import de.tudarmstadt.ukp.inception.schema.api.AnnotationSchemaService;
import de.tudarmstadt.ukp.inception.schema.api.event.LayerConfigurationChangedEvent;
@@ -85,7 +85,7 @@ public ColoringStrategy getStrategy(AnnotationLayer aLayer, ColoringPreferences
Map> aColorQueues)
{
ColoringStrategyType t = aPreferences.getColorPerLayer().get(aLayer.getId());
- ReadonlyColoringBehaviour rt = aPreferences.getReadonlyLayerColoringBehaviour();
+ ReadonlyColoringStrategy rt = aPreferences.getReadonlyLayerColoringBehaviour();
if (aLayer.isReadonly() && rt != NORMAL) {
t = rt.getColoringStrategy();
diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/config/AnnotationAutoConfiguration.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/config/AnnotationAutoConfiguration.java
index fd5d784a812..e6a6edc9c9e 100644
--- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/config/AnnotationAutoConfiguration.java
+++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/config/AnnotationAutoConfiguration.java
@@ -33,6 +33,7 @@
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.PreRenderer;
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.PreRendererImpl;
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.rendering.RenderNotificationRenderStep;
+import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
import de.tudarmstadt.ukp.inception.documents.api.RepositoryProperties;
import de.tudarmstadt.ukp.inception.preferences.PreferencesService;
import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringService;
@@ -89,10 +90,10 @@ public UserPreferencesService userPreferencesService(
AnnotationSchemaService aAnnotationService, RepositoryProperties aRepositoryProperties,
ColoringService aColoringService,
AnnotationSchemaProperties aAnnotationEditorProperties,
- PreferencesService aPreferencesService)
+ PreferencesService aPreferencesService, UserDao aUserService)
{
return new UserPreferencesServiceImpl(aDefaultPreferences, aAnnotationService,
aRepositoryProperties, aColoringService, aAnnotationEditorProperties,
- aPreferencesService);
+ aPreferencesService, aUserService);
}
}
diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/AnnotationPreferencesDialogContent.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/AnnotationPreferencesDialogContent.java
index b1dc9b8523f..5015950afc9 100755
--- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/AnnotationPreferencesDialogContent.java
+++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/AnnotationPreferencesDialogContent.java
@@ -20,6 +20,8 @@
import static de.tudarmstadt.ukp.clarin.webanno.api.annotation.page.AnnotationEditorState.KEY_EDITOR_STATE;
import static de.tudarmstadt.ukp.clarin.webanno.model.Mode.ANNOTATION;
import static de.tudarmstadt.ukp.clarin.webanno.model.Mode.CURATION;
+import static de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference.FONT_ZOOM_MAX;
+import static de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference.FONT_ZOOM_MIN;
import static de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference.SIDEBAR_SIZE_MAX;
import static de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference.SIDEBAR_SIZE_MIN;
import static de.tudarmstadt.ukp.inception.support.WebAnnoConst.CHAIN_TYPE;
@@ -30,10 +32,10 @@
import java.io.IOException;
import java.io.Serializable;
+import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
@@ -54,7 +56,6 @@
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
-import de.tudarmstadt.ukp.clarin.webanno.api.annotation.page.AnnotationEditorState;
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer;
import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
import de.tudarmstadt.ukp.inception.editor.AnnotationEditorFactory;
@@ -62,8 +63,7 @@
import de.tudarmstadt.ukp.inception.preferences.PreferencesService;
import de.tudarmstadt.ukp.inception.project.api.ProjectService;
import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategyType;
-import de.tudarmstadt.ukp.inception.rendering.coloring.ReadonlyColoringBehaviour;
-import de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference;
+import de.tudarmstadt.ukp.inception.rendering.coloring.ReadonlyColoringStrategy;
import de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotatorState;
import de.tudarmstadt.ukp.inception.schema.api.AnnotationSchemaService;
import de.tudarmstadt.ukp.inception.schema.api.config.AnnotationSchemaProperties;
@@ -80,7 +80,7 @@ public class AnnotationPreferencesDialogContent
{
private static final long serialVersionUID = -2102136855109258306L;
- private static final Logger LOG = getLogger(AnnotationPreferencesDialogContent.class);
+ private static final Logger LOG = getLogger(MethodHandles.lookup().lookupClass());
private @SpringBean AnnotationSchemaService annotationService;
private @SpringBean ProjectService projectService;
@@ -105,35 +105,35 @@ public AnnotationPreferencesDialogContent(String aId, IModel aMo
editorChoices = getEditorChoices();
onChangeAction = aOnChangeAction;
- form = new Form<>("form", new CompoundPropertyModel<>(loadModel(stateModel.getObject())));
+ form = new Form<>("form", new CompoundPropertyModel<>(loadPreferences(stateModel.getObject())));
- NumberTextField windowSizeField = new NumberTextField<>("windowSize");
+ var windowSizeField = new NumberTextField("windowSize");
windowSizeField.setType(Integer.class);
windowSizeField.setMinimum(1);
form.add(windowSizeField);
- NumberTextField sidebarSizeLeftField = new NumberTextField<>("sidebarSizeLeft");
+ var sidebarSizeLeftField = new NumberTextField("sidebarSizeLeft");
sidebarSizeLeftField.setType(Integer.class);
sidebarSizeLeftField.setMinimum(SIDEBAR_SIZE_MIN);
sidebarSizeLeftField.setMaximum(SIDEBAR_SIZE_MAX);
form.add(sidebarSizeLeftField);
- NumberTextField sidebarSizeRightField = new NumberTextField<>("sidebarSizeRight");
+ var sidebarSizeRightField = new NumberTextField("sidebarSizeRight");
sidebarSizeRightField.setType(Integer.class);
sidebarSizeRightField.setMinimum(SIDEBAR_SIZE_MIN);
sidebarSizeRightField.setMaximum(SIDEBAR_SIZE_MAX);
form.add(sidebarSizeRightField);
- NumberTextField fontZoomField = new NumberTextField<>("fontZoom");
+ var fontZoomField = new NumberTextField("fontZoom");
fontZoomField.setType(Integer.class);
- fontZoomField.setMinimum(AnnotationPreference.FONT_ZOOM_MIN);
- fontZoomField.setMaximum(AnnotationPreference.FONT_ZOOM_MAX);
+ fontZoomField.setMinimum(FONT_ZOOM_MIN);
+ fontZoomField.setMaximum(FONT_ZOOM_MAX);
form.add(fontZoomField);
- AnnotationEditorState state = preferencesService
- .loadDefaultTraitsForProject(KEY_EDITOR_STATE, stateModel.getObject().getProject());
+ var state = preferencesService.loadDefaultTraitsForProject(KEY_EDITOR_STATE,
+ stateModel.getObject().getProject());
- DropDownChoice> editor = new DropDownChoice<>("editor");
+ var editor = new DropDownChoice>("editor");
editor.setChoiceRenderer(new ChoiceRenderer<>("value"));
editor.setChoices(editorChoices);
editor.add(
@@ -145,19 +145,19 @@ public AnnotationPreferencesDialogContent(String aId, IModel aMo
form.add(createLayerContainer());
// Add a check box to enable/disable automatic page navigations while annotating
- CheckBox scrollCheckBox = new CheckBox("scrollPage");
+ var scrollCheckBox = new CheckBox("scrollPage");
scrollCheckBox.setOutputMarkupId(true);
form.add(scrollCheckBox);
// Add a check box to enable/disable arc collapsing
- CheckBox collapseCheckBox = new CheckBox("collapseArcs");
+ var collapseCheckBox = new CheckBox("collapseArcs");
collapseCheckBox.setOutputMarkupId(true);
form.add(collapseCheckBox);
// Add global read-only coloring strategy combo box
- DropDownChoice readOnlyColor = new DropDownChoice<>(
+ var readOnlyColor = new DropDownChoice(
"readonlyLayerColoringBehaviour");
- readOnlyColor.setChoices(asList(ReadonlyColoringBehaviour.values()));
+ readOnlyColor.setChoices(asList(ReadonlyColoringStrategy.values()));
readOnlyColor.setChoiceRenderer(new ChoiceRenderer<>("descriptiveName"));
form.add(readOnlyColor);
@@ -180,10 +180,10 @@ private List> getEditorChoices()
private void actionSave(AjaxRequestTarget aTarget, Form aForm)
{
try {
- AnnotatorState state = stateModel.getObject();
- Preferences model = form.getModelObject();
+ var state = stateModel.getObject();
+ var model = form.getModelObject();
- AnnotationPreference prefs = state.getPreferences();
+ var prefs = state.getPreferences();
prefs.setScrollPage(model.scrollPage);
prefs.setWindowSize(model.windowSize);
prefs.setSidebarSizeLeft(model.sidebarSizeLeft);
@@ -203,7 +203,7 @@ private void actionSave(AjaxRequestTarget aTarget, Form aForm)
// layers
state.refreshSelectableLayers(annotationEditorProperties::isLayerBlocked);
- userPreferencesService.savePreference(state, userDao.getCurrentUsername());
+ userPreferencesService.savePreferences(state, userDao.getCurrentUsername());
}
catch (IOException e) {
error("Preference file not found");
@@ -219,12 +219,12 @@ private void actionCancel(AjaxRequestTarget aTarget)
findParent(ModalDialog.class).close(aTarget);
}
- private Preferences loadModel(AnnotatorState state)
+ private Preferences loadPreferences(AnnotatorState aState)
{
- AnnotationPreference prefs = state.getPreferences();
+ var prefs = aState.getPreferences();
// Import current settings from the annotator
- Preferences model = new Preferences();
+ var model = new Preferences();
model.windowSize = Math.max(prefs.getWindowSize(), 1);
model.sidebarSizeLeft = prefs.getSidebarSizeLeft();
model.sidebarSizeRight = prefs.getSidebarSizeRight();
@@ -235,20 +235,20 @@ private Preferences loadModel(AnnotatorState state)
model.collapseArcs = prefs.isCollapseArcs();
model.editor = editorChoices.stream().filter(
- editor -> Objects.equals(editor.getKey(), state.getPreferences().getEditor()))
+ editor -> Objects.equals(editor.getKey(), aState.getPreferences().getEditor()))
.findFirst().orElseGet(() -> {
AnnotationEditorFactory editorFactory = annotationEditorRegistry
.getDefaultEditorFactory();
return Pair.of(editorFactory.getBeanName(), editorFactory.getDisplayName());
});
- model.annotationLayers = annotationService.listAnnotationLayer(state.getProject()).stream()
+ model.annotationLayers = annotationService.listAnnotationLayer(aState.getProject()).stream()
// hide disabled Layers
.filter(layer -> layer.isEnabled())
// hide blocked layers
.filter(layer -> !annotationEditorProperties.isLayerBlocked(layer))
.filter(layer -> !(layer.getType().equals(CHAIN_TYPE)
- && CURATION == state.getMode()))
+ && CURATION == aState.getMode()))
.collect(Collectors.toList());
return model;
@@ -263,13 +263,13 @@ private ListView createLayerContainer()
@Override
protected void populateItem(ListItem aItem)
{
- Preferences prefs = form.getModelObject();
- AnnotationLayer layer = aItem.getModelObject();
- Set hiddenLayerIds = stateModel.getObject().getPreferences()
+ var prefs = form.getModelObject();
+ var layer = aItem.getModelObject();
+ var hiddenLayerIds = stateModel.getObject().getPreferences()
.getHiddenAnnotationLayerIds();
// add visibility checkbox
- CheckBox layerVisible = new CheckBox("annotationLayerActive",
+ var layerVisible = new CheckBox("annotationLayerActive",
Model.of(!hiddenLayerIds.contains(layer.getId())));
layerVisible.add(new LambdaAjaxFormComponentUpdatingBehavior("change", _target -> {
@@ -283,8 +283,7 @@ protected void populateItem(ListItem aItem)
aItem.add(layerVisible);
// add coloring strategy choice
- DropDownChoice layerColor = new DropDownChoice<>(
- "layercoloring");
+ var layerColor = new DropDownChoice("layercoloring");
layerColor.setModel(Model.of(prefs.colorPerLayer.get(layer.getId())));
layerColor.setChoiceRenderer(new ChoiceRenderer<>("descriptiveName"));
layerColor.setChoices(asList(ColoringStrategyType.values()));
@@ -338,7 +337,7 @@ private static class Preferences
private int fontZoom;
private boolean scrollPage;
private List annotationLayers;
- private ReadonlyColoringBehaviour readonlyLayerColoringBehaviour;
+ private ReadonlyColoringStrategy readonlyLayerColoringBehaviour;
private Map colorPerLayer;
private boolean collapseArcs;
}
diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesService.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesService.java
index 4d34b975a0d..ff7d688b4ee 100644
--- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesService.java
+++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesService.java
@@ -42,7 +42,7 @@ public interface UserPreferencesService
AnnotationPreference loadPreferences(Project aProject, String aUsername, Mode aMode)
throws IOException;
- void savePreference(AnnotatorState aState, String aUsername) throws IOException;
+ void savePreferences(AnnotatorState aState, String aUsername) throws IOException;
void savePreferences(Project aProject, String aUsername, Mode aMode, AnnotationPreference aPref)
throws IOException;
diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesServiceImpl.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesServiceImpl.java
index e73aa196718..d9648131899 100644
--- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesServiceImpl.java
+++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/api/annotation/preferences/UserPreferencesServiceImpl.java
@@ -19,9 +19,12 @@
import static de.tudarmstadt.ukp.inception.project.api.ProjectService.PROJECT_FOLDER;
import static de.tudarmstadt.ukp.inception.project.api.ProjectService.SETTINGS_FOLDER;
-import static java.util.stream.Collectors.toList;
+import static de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationLayerVisibilityState.KEY_LAYERS_STATE;
+import static de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPageLayoutState.KEY_LAYOUT_STATE;
+import static java.util.Arrays.asList;
+import static java.util.stream.Collectors.toMap;
+import static org.apache.commons.lang3.StringUtils.replaceChars;
-import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -31,17 +34,10 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Objects;
-import java.util.Optional;
import java.util.Properties;
-import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyAccessorFactory;
@@ -49,14 +45,14 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.config.AnnotationAutoConfiguration;
-import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer;
import de.tudarmstadt.ukp.clarin.webanno.model.Mode;
import de.tudarmstadt.ukp.clarin.webanno.model.Project;
+import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
+import de.tudarmstadt.ukp.clarin.webanno.security.model.User;
import de.tudarmstadt.ukp.inception.documents.api.RepositoryProperties;
import de.tudarmstadt.ukp.inception.preferences.Key;
import de.tudarmstadt.ukp.inception.preferences.PreferencesService;
import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringService;
-import de.tudarmstadt.ukp.inception.rendering.coloring.ColoringStrategyType;
import de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference;
import de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotatorState;
import de.tudarmstadt.ukp.inception.schema.api.AnnotationSchemaService;
@@ -83,13 +79,14 @@ public class UserPreferencesServiceImpl
private final ColoringService coloringService;
private final AnnotationSchemaProperties annotationEditorProperties;
private final PreferencesService preferencesService;
+ private final UserDao userService;
public UserPreferencesServiceImpl(
AnnotationEditorDefaultPreferencesProperties aDefaultPreferences,
AnnotationSchemaService aAnnotationService, RepositoryProperties aRepositoryProperties,
ColoringService aColoringService,
AnnotationSchemaProperties aAnnotationEditorProperties,
- PreferencesService aPreferencesService)
+ PreferencesService aPreferencesService, UserDao aUserService)
{
defaultPreferences = aDefaultPreferences;
annotationService = aAnnotationService;
@@ -97,29 +94,28 @@ public UserPreferencesServiceImpl(
coloringService = aColoringService;
annotationEditorProperties = aAnnotationEditorProperties;
preferencesService = aPreferencesService;
+ userService = aUserService;
}
@Override
public void loadPreferences(AnnotatorState aState, String aUsername)
throws BeansException, IOException
{
- AnnotationPreference preference = loadPreferences(aState.getProject(), aUsername,
- aState.getMode());
+ var preference = loadPreferences(aState.getProject(), aUsername, aState.getMode());
aState.setPreferences(preference);
// set layers according to preferences
- List allLayers = annotationService
- .listAnnotationLayer(aState.getProject());
+ var allLayers = annotationService.listAnnotationLayer(aState.getProject());
aState.setAllAnnotationLayers(allLayers);
aState.setAnnotationLayers(allLayers.stream() //
.filter(l -> !annotationEditorProperties.isLayerBlocked(l)) //
.filter(l -> l.isEnabled()) //
.filter(l -> !preference.getHiddenAnnotationLayerIds().contains(l.getId()))
- .collect(toList()));
+ .toList());
// set default layer according to preferences
- Optional defaultLayer = aState.getAnnotationLayers().stream()
+ var defaultLayer = aState.getAnnotationLayers().stream()
.filter(layer -> Objects.equals(layer.getId(), preference.getDefaultLayer()))
.findFirst();
@@ -133,32 +129,99 @@ public void loadPreferences(AnnotatorState aState, String aUsername)
}
@Override
- public void savePreference(AnnotatorState aState, String aUsername) throws IOException
+ public void savePreferences(AnnotatorState aState, String aSessionOwnerName) throws IOException
{
- savePreferences(aState.getProject(), aUsername, aState.getMode(), aState.getPreferences());
+ savePreferences(aState.getProject(), aSessionOwnerName, aState.getMode(),
+ aState.getPreferences());
}
@Override
- public synchronized AnnotationPreference loadPreferences(Project aProject, String aUsername,
- Mode aMode)
+ public synchronized AnnotationPreference loadPreferences(Project aProject,
+ String aSessionOwnerName, Mode aMode)
throws IOException
{
// TODO Use modular preference loading once it is available and if there is a corresponding
// data file. Otherwise, fall back to loading the legacy preferences
- AnnotationPreference pref = loadLegacyPreferences(aProject, aUsername, aMode);
+ var preferences = loadLegacyPreferences(aProject, aSessionOwnerName, aMode);
+
+ var sessionOwner = userService.get(aSessionOwnerName);
+
+ upgradeLayerVisibilityPreferences(aProject, sessionOwner, preferences);
+ upgradeLayoutStatePreferences(aProject, sessionOwner, preferences);
+
+ return preferences;
+ }
+
+ private void upgradeLayerVisibilityPreferences(Project aProject, User aSessionOwner,
+ AnnotationPreference preferences)
+ {
+ var maybeLayersState = preferencesService
+ .loadOptionalTraitsForUserAndProject(KEY_LAYERS_STATE, aSessionOwner, aProject);
+ if (maybeLayersState.isPresent()) {
+ var layersState = maybeLayersState.get();
+ preferences.setColorPerLayer(layersState.getLayerColoringStrategy());
+ preferences.setReadonlyLayerColoringBehaviour(
+ layersState.getReadonlyLayerColoringStrategy());
+ preferences.setHiddenAnnotationLayerIds(layersState.getHiddenLayers());
+ return;
+ }
+
+ saveLayerVisibilityPreferences(aProject, aSessionOwner, preferences);
+ }
+
+ private void saveLayerVisibilityPreferences(Project aProject, User aSessionOwner,
+ AnnotationPreference preferences)
+ {
+ var layersState = preferencesService.loadTraitsForUserAndProject(KEY_LAYERS_STATE,
+ aSessionOwner, aProject);
+ layersState.setLayerColoringStrategy(preferences.getColorPerLayer());
+ layersState
+ .setReadonlyLayerColoringStrategy(preferences.getReadonlyLayerColoringBehaviour());
+ layersState.setHiddenLayers(preferences.getHiddenAnnotationLayerIds());
+ preferencesService.saveTraitsForUserAndProject(KEY_LAYERS_STATE, aSessionOwner, aProject,
+ layersState);
+ }
+
+ private void upgradeLayoutStatePreferences(Project aProject, User aSessionOwner,
+ AnnotationPreference preferences)
+ {
+ var maybeLayoutState = preferencesService
+ .loadOptionalTraitsForUserAndProject(KEY_LAYOUT_STATE, aSessionOwner, aProject);
+ if (maybeLayoutState.isPresent()) {
+ var layoutState = maybeLayoutState.get();
+ preferences.setSidebarSizeLeft(layoutState.getSidebarSizeLeft());
+ preferences.setSidebarSizeRight(layoutState.getSidebarSizeRight());
+ return;
+ }
+
+ saveLayoutStatePreferences(aProject, aSessionOwner, preferences);
+ }
- return pref;
+ private void saveLayoutStatePreferences(Project aProject, User aSessionOwner,
+ AnnotationPreference preferences)
+ {
+ var layoutState = preferencesService.loadTraitsForUserAndProject(KEY_LAYOUT_STATE,
+ aSessionOwner, aProject);
+ layoutState.setSidebarSizeLeft(preferences.getSidebarSizeLeft());
+ layoutState.setSidebarSizeRight(preferences.getSidebarSizeRight());
+ preferencesService.saveTraitsForUserAndProject(KEY_LAYOUT_STATE, aSessionOwner, aProject,
+ layoutState);
}
@Override
- public synchronized void savePreferences(Project aProject, String aUsername, Mode aMode,
+ public synchronized void savePreferences(Project aProject, String aSessionOwnerName, Mode aMode,
AnnotationPreference aPref)
throws IOException
{
// TODO Switch to a new and modular way of writing preferences
- saveLegacyPreferences(aProject, aUsername, aMode, aPref);
+ var sessionOwner = userService.get(aSessionOwnerName);
+
+ saveLayerVisibilityPreferences(aProject, sessionOwner, aPref);
+ saveLayoutStatePreferences(aProject, sessionOwner, aPref);
+
+ saveLegacyPreferences(aProject, aSessionOwnerName, aMode, aPref);
}
/**
@@ -177,26 +240,27 @@ public synchronized void savePreferences(Project aProject, String aUsername, Mod
* @throws IOException
* if an I/O error occurs.
*/
+ @Deprecated
private void saveLegacyPreferences(Project aProject, String aUsername, Mode aMode,
AnnotationPreference aPref)
throws IOException
{
- BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(aPref);
- Properties props = new Properties();
- for (PropertyDescriptor value : wrapper.getPropertyDescriptors()) {
+ var wrapper = PropertyAccessorFactory.forBeanPropertyAccess(aPref);
+ var props = new Properties();
+ for (var value : wrapper.getPropertyDescriptors()) {
if (wrapper.getPropertyValue(value.getName()) == null) {
continue;
}
props.setProperty(aMode + "." + value.getName(),
wrapper.getPropertyValue(value.getName()).toString());
}
- String propertiesPath = repositoryProperties.getPath().getAbsolutePath() + "/"
- + PROJECT_FOLDER + "/" + aProject.getId() + "/" + SETTINGS_FOLDER + "/" + aUsername;
+ var propertiesPath = repositoryProperties.getPath().getAbsolutePath() + "/" + PROJECT_FOLDER
+ + "/" + aProject.getId() + "/" + SETTINGS_FOLDER + "/" + aUsername;
// append existing preferences for the other mode
if (new File(propertiesPath, ANNOTATION_PREFERENCE_PROPERTIES_FILE).exists()) {
- Properties properties = loadLegacyPreferencesFile(aUsername, aProject);
- for (Entry