Skip to content

Commit

Permalink
Merge pull request kitodo#6264 from thomaslow/load-structure-tree-nod…
Browse files Browse the repository at this point in the history
…e-label-based-on-rulset-fixes-5882

Add rulset metadata attribute for structure tree node label
  • Loading branch information
solth authored Nov 15, 2024
2 parents 897d524 + 195855c commit 2911ef0
Show file tree
Hide file tree
Showing 24 changed files with 158 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public enum FunctionalMetadata {
*/
RECORD_IDENTIFIER("recordIdentifier"),

/**
* In case the metadata key shall be used as node label in the structure tree.
*/
STRUCTURE_TREE_TITLE("structureTreeTitle"),

/**
* The title. It is used to form the author-title key or the title key.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,9 @@ public void testGettingOfSpecialFields() throws Exception {
assertThat("Periodical was not found!",
rulesetManagement.getFunctionalDivisions(FunctionalDivision.CREATE_CHILDREN_FROM_PARENT),
contains("Periodical"));
assertThat("structureTreeTitle was not found!",
rulesetManagement.getFunctionalKeys(FunctionalMetadata.STRUCTURE_TREE_TITLE),
contains("LABEL"));

// not existing uses
assertThat("Something was found!",
Expand Down
4 changes: 4 additions & 0 deletions Kitodo-DataEditor/src/test/resources/ruleset.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@
'recordIdentifier' Identifier of the data record fetched from an external data source, so that the
imported metadata entries from the data source can be updated later.

'structureTreeTitle' will be displayed as node titles of the structure tree of the metadata editor
if title is selected as the preferred display option.

'title' This field is used as the title to form the author-title key.

'groupDisplayLabel' keys of this type are displayed in the metadata update dialog of the metadata
Expand All @@ -484,6 +487,7 @@
<xs:enumeration value="higherlevelIdentifier"/>
<xs:enumeration value="processTitle"/>
<xs:enumeration value="recordIdentifier"/>
<xs:enumeration value="structureTreeTitle"/>
<xs:enumeration value="groupDisplayLabel"/>
<xs:enumeration value="title"/>
</xs:restriction>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@
<label>physical page number</label>
<label lang="de">physische Seitenzahl (Imagenummer)</label>
</key>
<key id="LABEL" domain="mets:div">
<key id="LABEL" domain="mets:div" use="structureTreeTitle">
<label>logical page number</label>
<label lang="de">logische Seitenzahl (gedruckte Zeitenzahl)</label>
</key>
Expand Down
4 changes: 4 additions & 0 deletions Kitodo/rulesets/ruleset.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@
'recordIdentifier' Identifier of the data record fetched from an external data source, so that the
imported metadata entries from the data source can be updated later.

'structureTreeTitle' will be displayed as node titles of the structure tree of the metadata editor
if title is selected as the preferred display option.

'title' This field is used as the title to form the author-title key.

'groupDisplayLabel' keys of this type are displayed in the metadata update dialog of the metadata
Expand All @@ -484,6 +487,7 @@
<xs:enumeration value="higherlevelIdentifier"/>
<xs:enumeration value="processTitle"/>
<xs:enumeration value="recordIdentifier"/>
<xs:enumeration value="structureTreeTitle"/>
<xs:enumeration value="groupDisplayLabel"/>
<xs:enumeration value="title"/>
</xs:restriction>
Expand Down
2 changes: 1 addition & 1 deletion Kitodo/rulesets/simple-book.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<label>Language</label>
<codomain namespace="http://id.loc.gov/vocabulary/iso639-2/"/>
</key>
<key id="titleDocMain">
<key id="titleDocMain" use="structureTreeTitle">
<label>Main title</label>
</key>
<key id="publisherName">
Expand Down
2 changes: 1 addition & 1 deletion Kitodo/rulesets/subhh.xml
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@
<label>subtitle</label>
<label lang="de">UnterTitel</label>
</key>
<key id="TitleDocMain" domain="source">
<key id="TitleDocMain" domain="source" use="structureTreeTitle">
<label>maint title</label>
<label lang="de">HauptTitel</label>
</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,6 @@ public enum ParameterCore implements ParameterInterface {
*/
PAGE_SEPARATORS(new Parameter<>("metsEditor.pageSeparators", "\" \"")),

/**
# Priority list of metadata keys used to display title information in the metadata editors structure and gallery
panels.
*/
TITLE_KEYS(new Parameter<>("metsEditor.titleMetadata", "")),

/*
* backup of metadata configuration
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kitodo.api.MetadataGroup;
import org.kitodo.api.dataeditor.rulesetmanagement.FunctionalMetadata;
import org.kitodo.api.dataeditor.rulesetmanagement.RulesetManagementInterface;
import org.kitodo.api.dataformat.LogicalDivision;
import org.kitodo.api.dataformat.PhysicalDivision;
Expand Down Expand Up @@ -197,6 +198,12 @@ public class DataEditorForm implements MetadataTreeTableInterface, RulesetSetupI
*/
private Task templateTask;

/**
* The list of metadata keys that are annotated with <code>use="structureTreeTitle"</code>, meaning,
* they are used to generate the tree node label in case the title is requested by the user.
*/
private Collection<String> structureTreeTitles = new ArrayList<>();

private DataEditorSetting dataEditorSetting;

private static final String DESKTOP_LINK = "/pages/desktop.jsf";
Expand Down Expand Up @@ -289,6 +296,7 @@ public void open(String processID, String referringView, String taskId) {
String metadataLanguage = user.getMetadataLanguage();
priorityList = LanguageRange.parse(metadataLanguage.isEmpty() ? "en" : metadataLanguage);
ruleset = ServiceManager.getRulesetService().openRuleset(process.getRuleset());
this.loadStructureTreeTitlesFromRuleset();
try {
mediaUpdated = openMetsFile();
} catch (MediaNotFoundException e) {
Expand Down Expand Up @@ -347,6 +355,14 @@ private void checkProjectFolderConfiguration() {
}
}

private void loadStructureTreeTitlesFromRuleset() {
structureTreeTitles = getRulesetManagement().getFunctionalKeys(FunctionalMetadata.STRUCTURE_TREE_TITLE);
if (structureTreeTitles.isEmpty()) {
Locale locale = LocaleHelper.getCurrentLocale();
Helper.setWarnMessage(Helper.getString(locale, "dataEditor.noStructureTreeTitleFoundWarning"));
}
}

/**
* Load template task from database.
*
Expand Down Expand Up @@ -983,20 +999,25 @@ void unassignView(LogicalDivision logicalDivision, View view, boolean removeLast
}

/**
* Retrieve and return 'title' value of given Object 'dataObject' if Object is instance of
* 'LogicalDivision' and if it does have a title. Uses a configurable list of metadata keys to determine
* which metadata keys should be considered.
* Retrieve and return title of dataObject if it is a 'LogicalDivision' and if it has a title.
* Uses metadata value as title if one of the provided keys exists.
* Return empty string otherwise.
*
* @param dataObject
* StructureTreeNode containing the LogicalDivision whose title is returned
* @param metadataKeys
* the list of metadata keys that are annotated with "structureTreeTitle"
* @return 'title' value of the LogicalDivision contained in the given StructureTreeNode 'treeNode'
*/
public String getStructureElementTitle(Object dataObject) {
public static String getStructureElementTitle(Object dataObject, Collection<String> metadataKeys) {
String title = "";
if (dataObject instanceof LogicalDivision) {
LogicalDivision logicalDivision = ((LogicalDivision) dataObject);
title = DataEditorService.getTitleValue(logicalDivision, structurePanel.getTitleMetadata());

title = metadataKeys.stream()
.map((key) -> DataEditorService.getTitleValue(logicalDivision, key))
.filter((t) -> !t.isEmpty()).findFirst().orElse("");

if (StringUtils.isBlank(title)) {
title = logicalDivision.getLabel();
if (StringUtils.isBlank(title)) {
Expand All @@ -1007,6 +1028,19 @@ public String getStructureElementTitle(Object dataObject) {
return title;
}

/**
* Retrieve and return title of dataObject if it is a 'LogicalDivision' and if it has a title.
* Uses metadata value as title if one of the provided keys exists.
* Return empty string otherwise.
*
* @param dataObject
* StructureTreeNode containing the LogicalDivision whose title is returned
* @return 'title' value of the LogicalDivision contained in the given StructureTreeNode 'treeNode'
*/
public String getStructureElementTitle(Object dataObject) {
return DataEditorForm.getStructureElementTitle(dataObject, structureTreeTitles);
}

/**
* Get referringView.
*
Expand Down Expand Up @@ -1121,7 +1155,7 @@ public void updateNumberOfScans() {
*/
public void saveDataEditorSetting() {
if (Objects.nonNull(dataEditorSetting)) {
if (Objects.nonNull(templateTask) && !templateTask.getId().equals(dataEditorSetting.getTaskId())) {
if (Objects.nonNull(templateTask) && !templateTask.getId().equals(dataEditorSetting.getTaskId())) {
// create a copy of the task-independent configuration
// in case the user wants to save it as task-specific config
dataEditorSetting = new DataEditorSetting(dataEditorSetting);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
Expand All @@ -30,8 +31,6 @@
import java.util.Set;
import java.util.stream.Collectors;

import javax.faces.model.SelectItem;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
Expand All @@ -50,7 +49,6 @@
import org.kitodo.production.metadata.MetadataEditor;
import org.kitodo.production.model.Subfolder;
import org.kitodo.production.services.ServiceManager;
import org.kitodo.production.services.dataeditor.DataEditorService;
import org.primefaces.event.NodeCollapseEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
Expand Down Expand Up @@ -126,7 +124,11 @@ public class StructurePanel implements Serializable {
*/
private String activeTabs;

private String titleMetadata = "type";
/**
* Stores the users choice of the drop down selection above the logical structure tree. Can be either "type"
* (default), "title" (uses metadata key annotated with "structureTreeTitle" in ruleset) or "type+title".
*/
private String nodeLabelOption = "type";

/**
* Determines whether the logical tree is built as a combination of physical media nodes and
Expand Down Expand Up @@ -1917,31 +1919,22 @@ public void unassign() {
}

/**
* Get title metadata.
* @return value of titleMetadata
* Get the node label option (either "type", "title" or "type+title").
* @return value of node label option
*/
public String getTitleMetadata() {
return titleMetadata;
public String getNodeLabelOption() {
return nodeLabelOption;
}

/**
* Set title metadata.
* @param titleMetadata as java.lang.String
* Set node label option.
* @param nodeLabelOption as java.lang.String
*/
public void setTitleMetadata(String titleMetadata) {
this.titleMetadata = titleMetadata;
}

/**
* Get list of metadata keys that are used for displaying title information from the Kitodo configuration file.
* @return list of title metadata keys
*/
public List<SelectItem> getTitleMetadataItems() {
return DataEditorService.getTitleKeys()
.stream()
.map(key -> new SelectItem(key,dataEditor.getRulesetManagement().getTranslationForKey(
key,dataEditor.getPriorityList()).orElse(key)))
.collect(Collectors.toList());
public void setNodeLabelOption(String nodeLabelOption) {
if (!Arrays.asList("type", "title", "type+title").contains(nodeLabelOption)) {
throw new IllegalArgumentException("node label option must be either type, title or type+title");
}
this.nodeLabelOption = nodeLabelOption;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -113,23 +112,12 @@ private String getXsltFolder() {
return ConfigCore.getParameter(ParameterCore.DIR_XSLT);
}

/**
* Retrieve and return list of metadata keys that are used for displaying title information in the metadata editors
* structure and gallery panels from the Kitodo configuration file.
*
* @return list of title metadata keys
*/
public static List<String> getTitleKeys() {
return Arrays.stream(ConfigCore.getParameter(ParameterCore.TITLE_KEYS, "").split(","))
.map(String::trim).collect(Collectors.toList());
}

/**
* Retrieve and return title value from given IncludedStructuralElement.
*
* @param element IncludedStructuralElement for which the title value is returned.
* @param metadataTitleKey as a String that its value will be displayed.
* @return title value of given element
* @return title value of given element or an empty string
*/
public static String getTitleValue(LogicalDivision element, String metadataTitleKey) {
String[] metadataPath = metadataTitleKey.split("@");
Expand All @@ -143,13 +131,13 @@ public static String getTitleValue(LogicalDivision element, String metadataTitle
.flatMap(metadataGroup -> metadataGroup.getMetadata().stream())
.collect(Collectors.toList());
}
Optional<String> metadataTitle = metadata.stream()
return metadata.stream()
.filter(currentMetadata -> Objects.equals(currentMetadata.getKey(), metadataPath[lastIndex]))
.filter(MetadataEntry.class::isInstance).map(MetadataEntry.class::cast)
.map(MetadataEntry::getValue)
.filter(value -> !value.isEmpty())
.findFirst();
return metadataTitle.orElse(" - ");
.findFirst()
.orElse("");
}

/**
Expand Down
3 changes: 0 additions & 3 deletions Kitodo/src/main/resources/kitodo_config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,6 @@ metsEditor.displayFileManipulation=true
# Defaults to one single white space:
metsEditor.pageSeparators=" "

# Priority list of metadata keys used to display title information in the metadata editors structure and gallery panels
metsEditor.titleMetadata=TitleDocMain

#Maximum number of media to be uploaded.
metsEditor.maxUploadedMedia=3

Expand Down
1 change: 1 addition & 0 deletions Kitodo/src/main/resources/messages/messages_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ dataEditor.invalidStructureField=\u201E{0}\u201C kann nicht gespeichert werden:
dataEditor.mediaNotFound=Es wurden keine Medien gefunden, aber mindestens eine Dateireferenz ist vorhanden. Die automatische Entfernung der fehlenden Medien aus dem Werkst\u00FCck wurde \u00FCbersprungen.
dataEditor.multipleMetadataTasksText=Sie haben mehrere Aufgaben zum Editieren von Metadaten in Bearbeitung. Bitte w\u00E4hlen Sie eine dieser Aufgaben aus!
dataEditor.noParentsError=Elternelement von {0} konnte nicht gefunden werden!
dataEditor.noStructureTreeTitleFoundWarning=Es wurden keine Matadaten-Attribute als Titel-Attribute für den Strukturbaum im Ruleset angegeben (use="structureTreeTitle").
dataEditor.numberOfScans=Anzahl von Scans
dataEditor.position.afterCurrentElement=Hinter das aktuelle Element
dataEditor.position.asFirstChildOfCurrentElement=Als erstes Subelement des aktuellen Elementes
Expand Down
1 change: 1 addition & 0 deletions Kitodo/src/main/resources/messages/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ dataEditor.invalidStructureField=Cannot save "{0}": There is no such field ({1})
dataEditor.mediaNotFound=No media found, but at least one file reference is present. The automatic removal of missing media from the workpiece was skipped.
dataEditor.multipleMetadataTasksText=There are multiple metadata editing tasks assigned to you for the current process. Please select the task you want to work on!
dataEditor.noParentsError=No parents of structure {0} found!
dataEditor.noStructureTreeTitleFoundWarning=There are no metadata keys that are selected to be used as title attributes in the structure tree (use="structureTreeTitle").
dataEditor.numberOfScans=Number of scans
dataEditor.position.afterCurrentElement=After current element
dataEditor.position.asFirstChildOfCurrentElement=As first child of current element
Expand Down
2 changes: 2 additions & 0 deletions Kitodo/src/main/resources/messages/messages_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ dataEditor.invalidStructureField=„{0}“ no se puede guardar: No existe tal ca
dataEditor.mediaNotFound=No se encontraron los archivos multimedia, pero al menos un archivo de referencia está presente. La eleminación de los archivos multimedia faltantes de la pieza de trabajo fue omitida.
dataEditor.multipleMetadataTasksText=Tiene varias tareas de edición de metadatos en curso. Por favor, seleccione una de estas tareas.
dataEditor.noParentsError=No se ha encontrado el elemento padre de {0}.
# please check google translation below and remove comment if translation is acceptable
dataEditor.noStructureTreeTitleFoundWarning=No hay claves de metadatos seleccionadas para usarse como atributos de título en el árbol de estructura (use="structureTreeTitle").
dataEditor.numberOfScans=Número de imágenes escaneadas
dataEditor.position.afterCurrentElement=Después del elemento actual
dataEditor.position.asFirstChildOfCurrentElement=Como primer subelemento del elemento actual
Expand Down
2 changes: 1 addition & 1 deletion Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css
Original file line number Diff line number Diff line change
Expand Up @@ -2877,7 +2877,7 @@ Column content
border-top: 1px solid var(--cloudy-gray);
}

#logicalStructureHeader .logicalStructureTitle {
#logicalStructureTitle {
flex-grow: 1;
flex-shrink: 1;
margin-right: var(--default-half-size);
Expand Down
Loading

0 comments on commit 2911ef0

Please sign in to comment.