diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/ReferCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/ReferCrosswalk.java index 519d9531cb7..6797f284da9 100644 --- a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/ReferCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/ReferCrosswalk.java @@ -50,6 +50,8 @@ import org.dspace.content.crosswalk.CrosswalkObjectNotSupported; import org.dspace.content.integration.crosswalks.evaluators.ConditionEvaluator; import org.dspace.content.integration.crosswalks.evaluators.ConditionEvaluatorMapper; +import org.dspace.content.integration.crosswalks.evaluators.MetadataValueConditionEvaluator; +import org.dspace.content.integration.crosswalks.evaluators.MetadataValueConditionEvaluatorMapper; import org.dspace.content.integration.crosswalks.model.TemplateLine; import org.dspace.content.integration.crosswalks.virtualfields.VirtualField; import org.dspace.content.integration.crosswalks.virtualfields.VirtualFieldMapper; @@ -71,6 +73,7 @@ * Item starting from a template. * * @author Luca Giamminonni (luca.giamminonni at 4science.it) + * @author Florian Gantner (florian.gantner@uni-bamberg.de) * */ public class ReferCrosswalk implements ItemExportCrosswalk { @@ -94,6 +97,9 @@ public class ReferCrosswalk implements ItemExportCrosswalk { @Autowired private ConditionEvaluatorMapper conditionEvaluatorMapper; + @Autowired + private MetadataValueConditionEvaluatorMapper metadataconditionEvaluatorMapper; + @Autowired private MetadataSecurityService metadataSecurityService; @@ -264,7 +270,8 @@ private TemplateLine buildTemplateLine(String templateLine) { if (templateLineObj.isIfGroupField()) { String conditionName = templateLineObj.getIfConditionName(); - if (!conditionEvaluatorMapper.contains(conditionName)) { + if (!conditionEvaluatorMapper.contains(conditionName) + && !metadataconditionEvaluatorMapper.contains(conditionName)) { throw new IllegalStateException("Unknown condition evaluator found in the template '" + templateFileName + "': " + conditionName); } @@ -356,6 +363,24 @@ private List getMetadataValuesForLine(Context context, TemplateLine line } + private List getMetadataValuesForField(Context context, String field, Item item) { + if (field.contains("-")) { + field = field.replaceAll("-","."); + } + if (field.contains("_")) { + String[] langs = field.split("_"); + String lang = langs[1]; + field = langs[0]; + return metadataSecurityService.getPermissionFilteredMetadataValues(context, item, field).stream() + .filter(md -> md.getLanguage() != null && md.getLanguage().startsWith(lang)) + .map(MetadataValue::getValue) + .collect(Collectors.toList()); + } + return metadataSecurityService.getPermissionFilteredMetadataValues(context, item, field).stream() + .map(MetadataValue::getValue) + .collect(Collectors.toList()); + } + private void handleMetadataGroup(Context context, Item item, Iterator iterator, String groupName, List lines) throws IOException { @@ -365,17 +390,71 @@ private void handleMetadataGroup(Context context, Item item, Iterator> metadataValues = new HashMap<>(); for (int i = 0; i < groupSize; i++) { + String ifgroup = null; + boolean ifconditionresult = false; + String currentrelationname = null; + + for (int gi = 0; gi < groupLines.size(); gi++) { + TemplateLine line = groupLines.get(gi); + // Uniba Added Check for relations + if (currentrelationname != null && !line.isRelationGroupEndField(currentrelationname)) { + continue; // if within relation, Skip line until end of relation + } + + if (currentrelationname != null && line.isRelationGroupEndField(currentrelationname)) { + currentrelationname = null; + continue; + } + + if (ifgroup != null && !line.isIfGroupEndField(ifgroup) && !ifconditionresult) { + continue; + } - for (TemplateLine line : groupLines) { + // Uniba added checks for one single if condition inside metadatagroup to check the metadatavalue + // at the specific position. Nested Conditions are more complex and not supported (yet) + if (line.isIfGroupStartField()) { + ifgroup = line.getIfCondition(); + //Perhaps create some own method? + String fieldname = line.getIfConditionValue(); + String metadatatocheck = null; + List metadatastocheck = getMetadataValuesForField(context, fieldname, item); + if (metadatastocheck != null && !metadatastocheck.isEmpty() && (i < metadatastocheck.size())) { + metadatatocheck = metadatastocheck.get(i); + } + if (!metadataconditionEvaluatorMapper.contains(line.getIfConditionName())) { + throw new IllegalStateException("Unknown condition evaluator found in the template '" + + templateFileName + "': " + line.getIfConditionName()); + } + MetadataValueConditionEvaluator evaluator = + metadataconditionEvaluatorMapper.getConditionEvaluator(line.getIfConditionName()); + ifconditionresult = evaluator.test(context, metadatatocheck, line.getIfCondition()); + continue; //otherwise field is being requested + } + + if (ifgroup != null && line.isIfGroupEndField(ifgroup)) { + ifgroup = null; + ifconditionresult = false; + continue; + } String field = line.getField(); + if (line.isRelationGroupStartField()) { + //this considers the whole item + //Should only handle the item at position gi+1 + List relatedgroup = groupLines.subList(gi + 1, groupLines.size()); + handleRelationWithinGroup(context, item,relatedgroup.iterator(), line.getRelationName(), lines, + true, i); + currentrelationname = line.getRelationName(); + continue; + } + if (StringUtils.isBlank(line.getField())) { lines.add(line.getBeforeField()); continue; } - List metadata = null; + List metadata; if (metadataValues.containsKey(field)) { metadata = metadataValues.get(field); } else { @@ -418,6 +497,28 @@ private void handleRelationGroup(Context context, Item item, Iterator iterator, + String relationName, List lines, boolean findRelatedItems, int position) throws IOException { + + List groupLines = getGroupLines(iterator, line -> line.isRelationGroupEndField(relationName)); + + if (!findRelatedItems) { + return; + } + + Iterator relatedItems = findRelatedItems(context, item, relationName); + int cnt = 0; + while (relatedItems.hasNext()) { + Item relatedItem = relatedItems.next(); + if (cnt == position) { + Iterator lineIterator = groupLines.iterator(); + appendLines(context, relatedItem, lineIterator, lines, findRelatedItems); + } + cnt++; + } + + } + private void handleIfGroup(Context context, Item item, Iterator iterator, TemplateLine conditionLine, List lines, boolean findRelatedItems) throws IOException { @@ -430,7 +531,6 @@ private void handleIfGroup(Context context, Item item, Iterator it if (evaluator.test(context, item, condition)) { appendLines(context, item, groupLines.iterator(), lines, findRelatedItems); } - } private List getGroupLines(Iterator iterator, Predicate breakPredicate) { diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValueConditionEvaluator.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValueConditionEvaluator.java new file mode 100644 index 00000000000..3ff98d89f63 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValueConditionEvaluator.java @@ -0,0 +1,65 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.content.integration.crosswalks.evaluators; + +import org.apache.commons.lang3.StringUtils; +import org.dspace.core.Context; + +/** + * Class that can be extended to evaluate a given condition on some metadatavalue. + * + * @author Luca Giamminonni (luca.giamminonni at 4science.it) + * @author Florian Gantner (florian.gantner@uni-bamberg.de) + * + */ +public abstract class MetadataValueConditionEvaluator { + + /** + * Test the given condition on the given metadtavalue. + * The condition should have the format [not].evaluatorIdentifier.value, + * where: + *
    + *
  • not can be used to negate the result of the condition + *
  • evaluatorIdentifier is the unique identifier of the evaluator + *
  • value can be any string useful to the evaluator + *
+ * + * @param context the DSpace Context + * @param value the item to evaluate + * @param condition the condition to evaluate + * @return the evaluation result + */ + public final boolean test(Context context, String value, String condition) { + if (StringUtils.isBlank(condition)) { + return false; + } + + if (condition.startsWith("not.")) { + return !doTest(context, value, condition.substring("not.".length())); + } + + return doTest(context, value, condition); + + } + + /** + * Test the given condition on the given item. + * The condition should have the format evaluatorIdentifier.value, where: + *
    + *
  • evaluatorIdentifier is the unique identifier of the evaluator + *
  • value can be any string useful to the evaluator + *
+ * + * @param context the DSpace Context + * @param value the metadatavalue to evaluate + * @param condition the condition to evaluate + * @return the evaluation result + */ + protected abstract boolean doTest(Context context, String value, String condition); + +} diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValueConditionEvaluatorMapper.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValueConditionEvaluatorMapper.java new file mode 100644 index 00000000000..e8029296912 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValueConditionEvaluatorMapper.java @@ -0,0 +1,40 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.content.integration.crosswalks.evaluators; + +import java.util.Map; +import java.util.Set; + +/** + * A Mapper between instances of {@link MetadataValueConditionEvaluator} and their identifiers. + * + * @author Luca Giamminonni (luca.giamminonni at 4science.it) + * @author Florian Gantner (florian.gantner@uni-bamberg.de) + * + */ +public class MetadataValueConditionEvaluatorMapper { + + private final Map conditionEvaluators; + + public MetadataValueConditionEvaluatorMapper(Map conditionEvaluators) { + this.conditionEvaluators = conditionEvaluators; + } + + public Set getConditionEvaluatorNames() { + return conditionEvaluators.keySet(); + } + + public MetadataValueConditionEvaluator getConditionEvaluator(String name) { + return conditionEvaluators.get(name); + } + + public boolean contains(String name) { + return conditionEvaluators.containsKey(name); + } + +} diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValuePlaceholderOrNullCondition.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValuePlaceholderOrNullCondition.java new file mode 100644 index 00000000000..bd03a0d03d1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/evaluators/MetadataValuePlaceholderOrNullCondition.java @@ -0,0 +1,26 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.content.integration.crosswalks.evaluators; + +import org.dspace.core.Context; +import org.dspace.core.CrisConstants; + +/** + * Implementation of {@link MetadataValueConditionEvaluator} to evaluate + * if the given Metadata Value is null or some Placeholder Value + * + * @author Florian Gantner (florian.gantner@uni-bamberg.de) + * + */ +public class MetadataValuePlaceholderOrNullCondition extends MetadataValueConditionEvaluator { + + @Override + protected boolean doTest(Context context, String value, String condition) { + return value == null || value.contentEquals(CrisConstants.PLACEHOLDER_PARENT_METADATA_VALUE); + } +} diff --git a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/model/TemplateLine.java b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/model/TemplateLine.java index 8636cb52e73..756f775397a 100644 --- a/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/model/TemplateLine.java +++ b/dspace-api/src/main/java/org/dspace/content/integration/crosswalks/model/TemplateLine.java @@ -151,6 +151,12 @@ public String getIfCondition() { } + public String getIfConditionValue() { + return isIfGroupField() ? + join(".", Arrays.copyOfRange(fieldBits, (fieldBits[1].equals("not")) ? 3 : 2, fieldBits.length - 1)) : null; + + } + public String getIfConditionName() { if (!isIfGroupField()) { return null; diff --git a/dspace/config/spring/api/crosswalks.xml b/dspace/config/spring/api/crosswalks.xml index 9184a56482d..3e09fa62843 100644 --- a/dspace/config/spring/api/crosswalks.xml +++ b/dspace/config/spring/api/crosswalks.xml @@ -731,6 +731,20 @@ + + + + + + + + + + + +