Skip to content

Commit

Permalink
Merge pull request #5613 from matthias-ronge/issue-5410
Browse files Browse the repository at this point in the history
Make behaviour of repeated import configurable
  • Loading branch information
solth authored Jul 13, 2023
2 parents 8a4d7ac + 32b1469 commit 4fa4310
Show file tree
Hide file tree
Showing 20 changed files with 603 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.util.Map;
import java.util.Optional;

import org.kitodo.api.Metadata;

/**
* Interface for a service that provides access to the ruleset.
*
Expand Down Expand Up @@ -143,4 +145,20 @@ StructuralElementViewInterface getStructuralElementView(String structuralElement
* @return the “always showing” value or its default value
*/
boolean isAlwaysShowingForKey(String keyId);

/**
* Updates metadata during a repeated catalog import, depending on the
* reimport settings specified in the ruleset.
*
* @param division
* current division
* @param metadata
* current metadata
* @param acquisitionStage
* current acquisition stage
* @param updateItems
* items obtained from import
* @return number of added metadata items
*/
int updateMetadata(String division, Collection<Metadata> metadata, String acquisitionStage, Collection<Metadata> updateItems);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/

package org.kitodo.dataeditor.ruleset;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Supplier;

import org.apache.commons.lang3.ArrayUtils;
import org.kitodo.api.Metadata;
import org.kitodo.dataeditor.ruleset.xml.Reimport;

/**
* Determines the result of re-importing metadata for a single metadata key.
*/
class ReimportMetadata implements Supplier<Collection<Metadata>> {

// Metadata key for which the result of the reimport is determined.
private final String key;

// existing metadata for this key before reimport
private final Collection<Metadata> currentEntries;

// configured reimport behavior
private Reimport reimport;

// metadata fetched on reimport
private final Collection<Metadata> updateEntries;

// the maximum amount of metadata applicable here for this key
private int maxOccurs;

/**
* <b>Constructor.</b><!-- --> Generates a data set for the re-import of
* metadata for a specific key.
*
* @param key
* metadata key for which the result of the reimport is
* determined
*/
ReimportMetadata(String key) {
this.currentEntries = new ArrayList<>();
this.updateEntries = new ArrayList<>();
this.key = key;
this.maxOccurs = Integer.MAX_VALUE;
}

/**
* Sets the repeated import behavior model for this metadata key. Must be a
* value from {@link Reimport}.
*
* @param reimport
* configured reimport behavior to set
*/
void setReimport(Reimport reimport) {
this.reimport = reimport;
}

/**
* Sets the maximum number of metadata values allowed for this key. The
* setting only affects newly added metadata.
*
* @param maxOccurs
* maximum amount of metadata to set
*/
void setMaxOccurs(int maxOccurs) {
this.maxOccurs = maxOccurs;
}

/**
* Returns the metadata key. The key is that of the contained metadata.
*
* @return the metadata key
*/
String getKey() {
return key;
}

/**
* Adds a metadata entry to the current metadata entries.
*
* @param metadata
* metadata to add
*/
void addToCurrentEntries(Metadata metadata) {
assert Objects.equals(metadata.getKey(), key) : "keys should match";
currentEntries.add(metadata);
}

/**
* Adds a metadata entry to the update metadata entries.
*
* @param metadata
* metadata to add
*/
void addToUpdateEntries(Metadata metadata) {
assert Objects.equals(metadata.getKey(), key) : "keys should match";
updateEntries.add(metadata);
}

/**
* Merges the metadata of this key in the given behavior, respecting the
* maximum number.
*
* @return the metadata remaining after the repeated import
*/
@Override
public Collection<Metadata> get() {
if (!ArrayUtils.contains(Reimport.values(), reimport)) {
throw new IllegalStateException("Used not supported reimport case ".concat(Objects.toString(reimport)));
}
Collection<Metadata> result = reimport.equals(Reimport.REPLACE) && !updateEntries.isEmpty() ? new ArrayList<>()
: new ArrayList<>(currentEntries);
if (!reimport.equals(Reimport.KEEP) || result.isEmpty()) {
for (Metadata metadata : updateEntries) {
if (!result.contains(metadata) && result.size() < maxOccurs) {
result.add(metadata);
}
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale.LanguageRange;
import java.util.Map;
Expand All @@ -27,8 +28,10 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kitodo.api.Metadata;
import org.kitodo.api.dataeditor.rulesetmanagement.FunctionalDivision;
import org.kitodo.api.dataeditor.rulesetmanagement.FunctionalMetadata;
import org.kitodo.api.dataeditor.rulesetmanagement.MetadataViewInterface;
import org.kitodo.api.dataeditor.rulesetmanagement.RulesetManagementInterface;
import org.kitodo.api.dataeditor.rulesetmanagement.StructuralElementViewInterface;
import org.kitodo.dataeditor.ruleset.xml.AcquisitionStage;
Expand All @@ -48,6 +51,14 @@ public class RulesetManagement implements RulesetManagementInterface {
*/
private static final Logger logger = LogManager.getLogger(RulesetManagement.class);

/**
* English, the only language understood by the System user. This value is
* passed when a method requests a language of the user in order to display
* labels in this language, but the labels are not required from the result
* and the language passed is therefore irrelevant at this point.
*/
private static final List<LanguageRange> ENGLISH = LanguageRange.parse("en");

/**
* The ruleset.
*/
Expand Down Expand Up @@ -321,5 +332,43 @@ public boolean isAlwaysShowingForKey(String keyId) {
return false;
}

@Override
public int updateMetadata(String division, Collection<Metadata> currentMetadata, String acquisitionStage,
Collection<Metadata> updateMetadata) {

Settings settings = ruleset.getSettings(acquisitionStage);
Collection<MetadataViewInterface> allowedMetadata = getStructuralElementView(division, acquisitionStage,
ENGLISH).getAllowedMetadata();
Collection<ReimportMetadata> metadataForReimport = createListOfMetadataToMerge(currentMetadata, settings,
allowedMetadata, updateMetadata);

int sizeBefore = currentMetadata.size();
currentMetadata.clear();
for (ReimportMetadata metadataInReimport : metadataForReimport) {
currentMetadata.addAll(metadataInReimport.get());
}
return currentMetadata.size() - sizeBefore;
}

private Collection<ReimportMetadata> createListOfMetadataToMerge(Collection<Metadata> currentMetadata,
Settings settings, Collection<MetadataViewInterface> allowedMetadata, Collection<Metadata> updateMetadata) {
HashMap<String, ReimportMetadata> unifying = new HashMap<>();
for (Metadata metadata : currentMetadata) {
unifying.computeIfAbsent(metadata.getKey(), ReimportMetadata::new).addToCurrentEntries(metadata);
}
for (Metadata metadata : updateMetadata) {
unifying.computeIfAbsent(metadata.getKey(), ReimportMetadata::new).addToUpdateEntries(metadata);
}
Collection<ReimportMetadata> result = unifying.values();
for (ReimportMetadata entry : result) {
entry.setReimport(settings.getReimport(entry.getKey()));
}
for (MetadataViewInterface metadataView : allowedMetadata) {
ReimportMetadata metadataToMerge = unifying.get(metadataView.getId());
if (Objects.nonNull(metadataToMerge)) {
metadataToMerge.setMaxOccurs(metadataView.getMaxOccurs());
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.kitodo.dataeditor.ruleset.xml.Reimport;
import org.kitodo.dataeditor.ruleset.xml.Setting;

/**
Expand All @@ -44,6 +46,24 @@ public Settings(Collection<Setting> baseSettings) {
.collect(Collectors.toMap(Setting::getKey, Function.identity()));
}

/**
* Returns the reimport setting for a key.
*
* @param keyId
* key for which the query is
* @return reimport setting
*/
Reimport getReimport(String keyId) {
Setting settingForKey = currentSettings.get(keyId);
if (Objects.nonNull(settingForKey)) {
Reimport reimport = settingForKey.getReimport();
if (Objects.nonNull(reimport)) {
return reimport;
}
}
return Reimport.REPLACE;
}

/**
* Returns the settings for a key.
*
Expand Down Expand Up @@ -157,6 +177,7 @@ private List<Setting> merge(Collection<Setting> currentSettings, Collection<Sett
merged.setEditable(other.getEditable() != null ? other.getEditable() : current.getEditable());
merged.setExcluded(other.getExcluded() != null ? other.getExcluded() : current.getExcluded());
merged.setMultiline(other.getMultiline() != null ? other.getMultiline() : current.getMultiline());
merged.setReimport(other.getReimport() != null ? other.getReimport() : current.getReimport());
merged.setSettings(merge(current.getSettings(), other.getSettings()));
mergedSettings.add(merged);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/

package org.kitodo.dataeditor.ruleset.xml;

import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlEnumValue;

import org.apache.commons.lang3.ArrayUtils;

/**
* This class is a backing bean for the XML attribute reimport in the ruleset.
* With it, JAXB can map the attribute to an enum.
*/
@XmlEnum()
public enum Reimport {
/**
* The metadata should be added.
*/
@XmlEnumValue("add")
ADD,

/**
* The existing metadata should be kept.
*/
@XmlEnumValue("keep")
KEEP,

/**
* The existing metadata should be replaced.
*/
@XmlEnumValue("replace")
REPLACE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public class Setting {
@XmlAttribute
private Boolean multiline;

/**
* This will specify how to update metadata in repeated imports.
*/
@XmlAttribute
private Reimport reimport;

/**
* The settings for sub-keys.
*/
Expand Down Expand Up @@ -136,6 +142,17 @@ public Boolean getMultiline() {
return multiline;
}

/**
* Returns the value “reimport” if one is set. This getter returns
* {@code null} if the attribute was not entered. This is needed, for
* example, when merging attributes.
*
* @return the value “excluded”, if set, else {@code null}
*/
public Reimport getReimport() {
return reimport;
}

/**
* Returns the editor settings.
*
Expand Down Expand Up @@ -239,6 +256,17 @@ public void setMultiline(Boolean multiline) {
this.multiline = multiline;
}

/**
* This sets the “reimport” value. If you set the value to {@code null}, no
* attribute is written.
*
* @param reimport
* “reimport” value to set
*/
public void setReimport(Reimport reimport) {
this.reimport = reimport;
}

/**
* Sets the settings for nested keys.
*
Expand Down
Loading

0 comments on commit 4fa4310

Please sign in to comment.