diff --git a/mycore-base/src/main/java/org/mycore/datamodel/classifications2/mapping/MCRXPathClassificationMappingCondition.java b/mycore-base/src/main/java/org/mycore/datamodel/classifications2/mapping/MCRXPathClassificationMappingCondition.java
index 3133a3127f..7942610f4d 100644
--- a/mycore-base/src/main/java/org/mycore/datamodel/classifications2/mapping/MCRXPathClassificationMappingCondition.java
+++ b/mycore-base/src/main/java/org/mycore/datamodel/classifications2/mapping/MCRXPathClassificationMappingCondition.java
@@ -31,13 +31,13 @@
/**
* A {@link MCRXPathClassificationMappingCondition} is a {@link Condition} that
- * determines the condition of a MyCoRe object based on a configurable X-Path evaluating the
+ * determines the condition of a MyCoRe object based on a configurable XPath evaluating the
* XML representation of the MyCoRe object.
*
* The following configuration options are available:
*
* The property suffix {@link MCRXPathClassificationMappingCondition#X_PATH_KEY} can be used to
- * specify the X-Path to be used.
+ * specify the XPath to be used.
*
* Example:
*
@@ -53,7 +53,7 @@ public final class MCRXPathClassificationMappingCondition implements Condition {
private final String xPath;
public MCRXPathClassificationMappingCondition(String xPath) {
- this.xPath = Objects.requireNonNull(xPath, "X-Path must not be null");
+ this.xPath = Objects.requireNonNull(xPath, "XPath must not be null");
}
@Override
diff --git a/mycore-mods/src/main/java/org/mycore/mods/classification/mapping/MCRMODSXMappingClassificationGenerator.java b/mycore-mods/src/main/java/org/mycore/mods/classification/mapping/MCRMODSXMappingClassificationGenerator.java
index b07fb28850..cc9870f5c3 100644
--- a/mycore-mods/src/main/java/org/mycore/mods/classification/mapping/MCRMODSXMappingClassificationGenerator.java
+++ b/mycore-mods/src/main/java/org/mycore/mods/classification/mapping/MCRMODSXMappingClassificationGenerator.java
@@ -57,9 +57,9 @@
* The property suffix {@link MCRXMappingClassificationGeneratorBase#EVALUATOR_KEY} can be used to
* specify the evaluator used to obtain category IDs from.
* For the evaluator, the property suffix {@link MCRSentinel#DEFAULT_KEY} can be used to
- * exclude the evaluator from the configuration and use a default {@link MCRSimpleXMappingEvaluator} instead.
+ * exclude the evaluator from the configuration and use a default {@link MCRSimpleXMappingEvaluator} instead.
* The property suffix {@link MCRXMappingClassificationGeneratorBase#ON_MISSING_MAPPED_CATEGORY_KEY} can be used to
- * specify the behaviour, when a mapped classification value is missing.
+ * specify the behavior, when a mapped classification value is missing.
*
* Example:
*
diff --git a/mycore-pi/src/main/java/org/mycore/pi/MCRGenericPIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/MCRGenericPIGenerator.java
index e1a833eb4b..57a041e4c2 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/MCRGenericPIGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/MCRGenericPIGenerator.java
@@ -18,22 +18,20 @@
package org.mycore.pi;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.getCountPattern;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.readCountFromDatabase;
+
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Predicate;
-import java.util.regex.Matcher;
+import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -49,223 +47,235 @@
import org.mycore.common.MCRConstants;
import org.mycore.common.MCRException;
import org.mycore.common.config.MCRConfigurationException;
-import org.mycore.common.config.annotation.MCRPostConstruction;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.common.config.annotation.MCRPropertyList;
+import org.mycore.common.config.annotation.MCRPropertyMap;
import org.mycore.datamodel.metadata.MCRBase;
import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.datamodel.metadata.MCRObjectService;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.pi.urn.MCRDNBURN;
/**
- *
- * MCR.PI.Generator.myGenerator.Class=org.mycore.pi.urn.MCRGenericPIGenerator
- *
- * Set a generic pattern.
- *
- * MCR.PI.Generator.myGenerator.GeneralPattern=urn:nbn:de:gbv:$CurrentDate-$1-$2-$ObjectType-$ObjectProject-$ObjectNumber-$Count-
- * MCR.PI.Generator.myGenerator.GeneralPattern=urn:nbn:de:gbv:$ObjectDate-$ObjectType-$Count
- * MCR.PI.Generator.myGenerator.GeneralPattern=urn:nbn:de:gbv:$ObjectDate-$Count
- * MCR.PI.Generator.myGenerator.GeneralPattern=urn:nbn:de:gbv:$ObjectType-$Count
- * MCR.PI.Generator.myGenerator.GeneralPattern=urn:nbn:de:gbv:$0-$1-$Count
- *
- * Set an optional DateFormat, if not set the ddMMyyyy is just used as value. (SimpleDateFormat)
- *
- * MCR.PI.Generator.myGenerator.DateFormat=ddMMyyyy
- *
- * Set an optional ObjectType mapping, if not set the ObjectType is just used as value
- *
- * MCR.PI.Generator.myGenerator.TypeMapping=document:doc,disshab:diss,Thesis:Thesis,bundle:doc,mods:test
- *
- * You can also map the projectid
- *
- * Set an optional Count precision, if not set or set to -1 the pure number is used (1,2,.., 999).
- * Count always relativ to type and date.
- *
- * MCR.PI.Generator.myGenerator.CountPrecision=3 # will produce 001, 002, ... , 999
+ * {@link MCRGenericPIGenerator} is a {@link MCRPIGenerator} for arbitrary identifiers
+ * that generates identifiers using a general pattern and other information dependent on the
+ * replacement markers contained in that pattern.
+ *
+ *
+ * The replacement marker {@link MCRGenericPIGenerator#PLACE_HOLDER_CURRENT_DATE}
+ * will be replaced with the current date, formatted by the given date format.
+ *
+ *
+ * The replacement marker {@link MCRGenericPIGenerator#PLACE_HOLDER_OBJECT_DATE}
+ * will be replaced with the objects creation date, formatted by the given date format.
+ *
+ *
+ * The replacement marker {@link MCRGenericPIGenerator#PLACE_HOLDER_OBJECT_PROJECT}
+ * will be replaced with the object IDs {@link MCRObjectID#getProjectId()}, mapped by the given project mapping.
+ *
+ *
+ * The replacement marker {@link MCRGenericPIGenerator#PLACE_HOLDER_OBJECT_TYPE}
+ * will be replaced with the object IDs {@link MCRObjectID#getTypeId()}, mapped by the given type mapping.
+ *
+ *
+ * The replacement marker {@link MCRGenericPIGenerator#PLACE_HOLDER_OBJECT_NUMBER}
+ * will be replaced with the object IDs {@link MCRObjectID#getNumberAsString()}.
+ *
+ *
+ * The replacement marker of form {@link MCRGenericPIGenerator#XPATH_PATTERN}
+ * will be replaced with the result of evaluating the objects XML representation with
+ * a given xPath, using the n -th given xPath, when the pattern represents the number n .
+ *
+ *
+ * The replacement marker {@link MCRGenericPIGenerator#PLACE_HOLDER_COUNT}
+ * will be replaced with a unique count number with the given count precision.
+ *
+ *
*
- * Set the Type of the generated pi.
+ * Example patterns:
+ *
+ * urn:nbn:de:gbv:$CurrentDate-$1-$2-$ObjectType-$ObjectProject-$ObjectNumber-$Count-
+ * urn:nbn:de:gbv:$ObjectDate-$ObjectType-$Count
+ * urn:nbn:de:gbv:$ObjectDate-$Count
+ * urn:nbn:de:gbv:$ObjectType-$Count
+ * urn:nbn:de:gbv:$0-$1-$Count
+ *
*
- * MCR.PI.Generator.myGenerator.Type=dnbURN
- *
- *
- * Set the Xpaths
- *
- * MCR.PI.Generator.myGenerator.XPath.1=/mycoreobject/metadata/def.shelf/shelf/
- * MCR.PI.Generator.myGenerator.XPath.2=/mycoreobject/metadata/def.path2/path2/
- *
- * @author Sebastian Hofmann
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRGenericPIGenerator#GENERAL_PATTERN_KEY} can be used to
+ * specify the pattern.
+ * The property suffix {@link MCRGenericPIGenerator#DATE_FORMAT_KEY} can be used to
+ * specify the date format to be used (optional, defaults to {@link MCRGenericPIGenerator#DEFAULT_DATE_FORMAT}).
+ * The property suffix {@link MCRGenericPIGenerator#OBJECT_PROJECT_MAPPING_KEY} can be used to
+ * specify the project ID mappings to be used.
+ * The property suffix {@link MCRGenericPIGenerator#OBJECT_TYPE_MAPPING_KEY} can be used to
+ * specify the type ID mapping to be used.
+ * The property suffix {@link MCRGenericPIGenerator#COUNT_PRECISION_KEY} can be used to
+ * specify number of digits to be used for the count (optional, defaults to -1,
+ * which uses the natural number of digits).
+ * The property suffix {@link MCRGenericPIGenerator#TYPE_KEY} can be used to
+ * specify identifier type.
+ * The property suffix {@link MCRGenericPIGenerator#X_PATH_KEY} can be used to
+ * specify the list of xPaths.
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.org.mycore.pi.MCRGenericPIGenerator
+ * [...].GeneralPattern=urn:nbn:de:gbv:$CurrentDate-$1-$2-$ObjectType-$ObjectProject-$ObjectNumber-$Count-
+ * [...].DateFormat=yyyy-MM-dd
+ * [...].ObjectProjectMapping.mycore=MyCoRe
+ * [...].ObjectTypeMapping.mods=MODS
+ * [...].CountPrecision=6
+ * [...].Type=dnbUrn
+ * [...].XPath.1=/mycoreobject/metadata//mods:typeOfResource/text()
+ * [...].XPath.2=substring-after(/mycoreobject/metadata//mods:genre/@valueURI,'#')
+ *
*/
-public class MCRGenericPIGenerator extends MCRPIGenerator {
-
- static final String PLACE_HOLDER_CURRENT_DATE = "$CurrentDate";
+@MCRConfigurationProxy(proxyClass = MCRGenericPIGenerator.Factory.class)
+public class MCRGenericPIGenerator implements MCRPIGenerator {
- static final String PLACE_HOLDER_OBJECT_DATE = "$ObjectDate";
+ public static final String DEFAULT_DATE_FORMAT = "ddMMyyyy";
- static final String PLACE_HOLDER_OBJECT_TYPE = "$ObjectType";
+ public static final Locale DEFAULT_DATE_LOCALE = Locale.ROOT;
- static final String PLACE_HOLDER_OBJECT_PROJECT = "$ObjectProject";
+ public static final String GENERAL_PATTERN_KEY = "GeneralPattern";
- static final String PLACE_HOLDER_COUNT = "$Count";
+ public static final String DATE_FORMAT_KEY = "DateFormat";
- static final String PLACE_HOLDER_OBJECT_NUMBER = "$ObjectNumber";
+ public static final String OBJECT_PROJECT_MAPPING_KEY = "ObjectProjectMapping";
- private static final Logger LOGGER = LogManager.getLogger();
+ public static final String OBJECT_TYPE_MAPPING_KEY = "ObjectTypeMapping";
- private static final String PROPERTY_KEY_GENERAL_PATTERN = "GeneralPattern";
+ public static final String COUNT_PRECISION_KEY = "CountPrecision";
- private static final String PROPERTY_KEY_DATE_FORMAT = "DateFormat";
+ public static final String TYPE_KEY = "Type";
- private static final String PROPERTY_KEY_OBJECT_TYPE_MAPPING = "ObjectTypeMapping";
+ public static final String X_PATH_KEY = "XPath";
- private static final String PROPERTY_KEY_OBJECT_PROJECT_MAPPING = "ObjectProjectMapping";
+ public static final String PLACE_HOLDER_CURRENT_DATE = "$CurrentDate";
- private static final String PROPERTY_KEY_COUNT_PRECISION = "CountPrecision";
+ public static final String PLACE_HOLDER_OBJECT_DATE = "$ObjectDate";
- private static final String PROPERTY_KEY_XPATH = "XPath";
-
- private static final String PROPERTY_KEY_TYPE = "Type";
-
- private static final Map PATTERN_COUNT_MAP = new HashMap<>();
-
- private static final Pattern XPATH_PATTERN = Pattern.compile("\\$([0-9]+)", Pattern.DOTALL);
+ public static final String PLACE_HOLDER_OBJECT_PROJECT = "$ObjectProject";
- private String generalPattern;
+ public static final String PLACE_HOLDER_OBJECT_TYPE = "$ObjectType";
- private SimpleDateFormat dateFormat;
+ public static final String PLACE_HOLDER_COUNT = "$Count";
- private String objectTypeMapping;
+ public static final String PLACE_HOLDER_OBJECT_NUMBER = "$ObjectNumber";
- private String objectProjectMapping;
-
- private int countPrecision;
-
- private String type;
-
- private String[] xpath;
+ private static final Logger LOGGER = LogManager.getLogger();
- public MCRGenericPIGenerator() {
- super();
- }
+ private static final Map PATTERN_COUNT_MAP = new HashMap<>();
- @Override
- @MCRPostConstruction
- public void init(String property) {
- super.init(property);
- final Map properties = getProperties();
+ private static final Pattern XPATH_PATTERN = Pattern.compile("\\$([0-9]+)", Pattern.DOTALL);
- setGeneralPattern(properties.get(PROPERTY_KEY_GENERAL_PATTERN));
+ private final String generalPattern;
- setDateFormat(Optional.ofNullable(properties.get(PROPERTY_KEY_DATE_FORMAT))
- .map(format -> new SimpleDateFormat(format, Locale.ROOT))
- .orElse(new SimpleDateFormat("ddMMyyyy", Locale.ROOT)));
+ private final String dateFormat;
- setObjectTypeMapping(properties.get(PROPERTY_KEY_OBJECT_TYPE_MAPPING));
- setObjectProjectMapping(properties.get(PROPERTY_KEY_OBJECT_PROJECT_MAPPING));
+ private final Map projectIdMappings;
- setCountPrecision(Optional.ofNullable(properties.get(PROPERTY_KEY_COUNT_PRECISION))
- .map(Integer::parseInt)
- .orElse(-1));
+ private final Map typeIdMappings;
- setType(properties.get(PROPERTY_KEY_TYPE));
+ private final int countPrecision;
- List xpaths = new ArrayList<>();
- int count = 1;
- while (properties.containsKey(PROPERTY_KEY_XPATH + "." + count)) {
- xpaths.add(properties.get(PROPERTY_KEY_XPATH + "." + count));
- count++;
- }
+ private final String type;
- setXpath(xpaths.toArray(new String[0]));
- validateProperties();
- }
+ private final List xPaths;
- // for testing purposes
- MCRGenericPIGenerator(String generalPattern, SimpleDateFormat dateFormat,
- String objectTypeMapping, String objectProjectMapping,
- int countPrecision, String type, String... xpaths) {
- super();
- setObjectProjectMapping(objectProjectMapping);
- setGeneralPattern(generalPattern);
- setDateFormat(dateFormat);
- setObjectTypeMapping(objectTypeMapping);
- setCountPrecision(countPrecision);
- setType(type);
+ public MCRGenericPIGenerator(String generalPattern, String dateFormat,
+ Map projectIdMappings, Map typeIdMappings,
+ int countPrecision, String type, List xPaths) {
+ this.generalPattern = Objects.requireNonNull(generalPattern, "General pattern must not be null");
+ this.dateFormat = Objects.requireNonNull(dateFormat, "Date format must not be null");
+ this.projectIdMappings = Objects.requireNonNull(projectIdMappings, "Project ID mappings must not be null");
+ this.typeIdMappings = Objects.requireNonNull(typeIdMappings, "Type ID mappings must not be null");
+ this.countPrecision = countPrecision;
+ this.type = Objects.requireNonNull(type, "Type must not be null");
+ this.xPaths = Objects.requireNonNull(xPaths, "XPaths must not be null");
validateProperties();
- setXpath(xpaths);
- }
-
- private void setXpath(String... xpaths) {
- this.xpath = xpaths;
}
private void validateProperties() {
- if (countPrecision == -1 && "dnbUrn".equals(getType())) {
+ if (countPrecision == -1 && MCRDNBURN.TYPE.equals(type)) {
throw new MCRConfigurationException(
- PROPERTY_KEY_COUNT_PRECISION + "=-1 and " + PROPERTY_KEY_TYPE + "=urn is not supported!");
+ "Combination of count precision -1 and type 'urn' is not supported!");
}
}
@Override
- public MCRPersistentIdentifier generate(MCRBase mcrBase, String additional)
+ public MCRPersistentIdentifier generate(MCRBase base, String additional)
throws MCRPersistentIdentifierException {
- String resultingPI = getGeneralPattern();
+ String resultingPI = generalPattern;
if (resultingPI.contains(PLACE_HOLDER_CURRENT_DATE)) {
- resultingPI = resultingPI.replace(PLACE_HOLDER_CURRENT_DATE, getDateFormat().format(new Date()));
+ SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat, DEFAULT_DATE_LOCALE);
+ resultingPI = resultingPI.replace(PLACE_HOLDER_CURRENT_DATE, dateFormatter.format(new Date()));
}
if (resultingPI.contains(PLACE_HOLDER_OBJECT_DATE)) {
- final Date objectCreateDate = mcrBase.getService().getDate(MCRObjectService.DATE_TYPE_CREATEDATE);
- resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_DATE, getDateFormat().format(objectCreateDate));
+ final Date objectCreateDate = base.getService().getDate(MCRObjectService.DATE_TYPE_CREATEDATE);
+ if (objectCreateDate == null) {
+ throw new MCRPersistentIdentifierException("Object " + base.getId() + " doesn't have a create date!");
+ }
+ SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat, DEFAULT_DATE_LOCALE);
+ resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_DATE, dateFormatter.format(objectCreateDate));
}
- if (resultingPI.contains(PLACE_HOLDER_OBJECT_TYPE)) {
- final String mappedObjectType = getMappedType(mcrBase.getId());
- resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_TYPE, mappedObjectType);
+ if (resultingPI.contains(PLACE_HOLDER_OBJECT_PROJECT)) {
+ final String projectId = base.getId().getProjectId();
+ final String mappedProjectId = projectIdMappings.getOrDefault(projectId, projectId);
+ resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_PROJECT, mappedProjectId);
}
- if (resultingPI.contains(PLACE_HOLDER_OBJECT_PROJECT)) {
- final String mappedObjectProject = getMappedProject(mcrBase.getId());
- resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_PROJECT, mappedObjectProject);
+ if (resultingPI.contains(PLACE_HOLDER_OBJECT_TYPE)) {
+ final String typeId = base.getId().getTypeId();
+ final String mappedTypeId = typeIdMappings.getOrDefault(typeId, typeId);
+ resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_TYPE, mappedTypeId);
}
if (resultingPI.contains(PLACE_HOLDER_OBJECT_NUMBER)) {
- resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_NUMBER, mcrBase.getId().getNumberAsString());
+ resultingPI = resultingPI.replace(PLACE_HOLDER_OBJECT_NUMBER, base.getId().getNumberAsString());
}
if (XPATH_PATTERN.asPredicate().test(resultingPI)) {
resultingPI = XPATH_PATTERN.matcher(resultingPI).replaceAll((mr) -> {
final String xpathNumberString = mr.group(1);
final int xpathNumber = Integer.parseInt(xpathNumberString, 10) - 1;
- if (this.xpath.length <= xpathNumber || xpathNumber < 0) {
+ if (this.xPaths.size() <= xpathNumber || xpathNumber < 0) {
throw new MCRException(
- "The index of " + xpathNumber + " is out of bounds of xpath array (" + xpath.length + ")");
+ "The index of " + xpathNumber + " is out of bounds of xpath array (" + xPaths.size() + ")");
}
- final String xpathString = this.xpath[xpathNumber];
+ final String xpathString = this.xPaths.get(xpathNumber);
XPathFactory factory = XPathFactory.instance();
XPathExpression expr = factory.compile(xpathString, Filters.fpassthrough(), null,
MCRConstants.getStandardNamespaces());
- final Object content = expr.evaluateFirst(mcrBase.createXML());
+ final Object content = expr.evaluateFirst(base.createXML());
return switch (content) {
case Text text -> text.getTextNormalize();
case Attribute attribute -> attribute.getValue();
case Element element -> element.getTextNormalize();
- case null, default -> content.toString();
+ case null -> "";
+ default -> content.toString();
};
});
LOGGER.info(resultingPI);
}
final MCRPIParser parser = MCRPIManager.getInstance()
- .getParserForType(getType());
+ .getParserForType(type);
String result;
result = applyCount(resultingPI);
- if (getType().equals("dnbUrn")) {
+ if (MCRDNBURN.TYPE.equals(type)) {
result = result + "C"; // will be replaced by the URN-Parser
}
@@ -278,19 +288,10 @@ public MCRPersistentIdentifier generate(MCRBase mcrBase, String additional)
private String applyCount(String resultingPI) {
String result;
if (resultingPI.contains(PLACE_HOLDER_COUNT)) {
- final int countPrecision = getCountPrecision();
- String regexpStr;
-
- if (countPrecision == -1) {
- regexpStr = "([0-9]+)";
- } else {
- regexpStr = "("
- + IntStream.range(0, countPrecision).mapToObj((i) -> "[0-9]").collect(Collectors.joining(""))
- + ")";
- }
- String counterPattern = resultingPI.replace(PLACE_HOLDER_COUNT, regexpStr);
- if (getType().equals("dnbUrn")) {
+ String counterPattern = resultingPI.replace(PLACE_HOLDER_COUNT, getCountPattern(countPrecision));
+
+ if (MCRDNBURN.TYPE.equals(type)) {
counterPattern = counterPattern + "[0-9]";
}
@@ -300,7 +301,8 @@ private String applyCount(String resultingPI) {
LOGGER.info("Count is {}", count);
final String pattern = IntStream.range(0, Math.abs(countPrecision)).mapToObj((i) -> "0")
.collect(Collectors.joining(""));
- DecimalFormat decimalFormat = new DecimalFormat(pattern, DecimalFormatSymbols.getInstance(Locale.ROOT));
+ DecimalFormat decimalFormat =
+ new DecimalFormat(pattern, DecimalFormatSymbols.getInstance(Locale.ROOT));
final String countAsString = countPrecision != -1 ? decimalFormat.format(count) : String.valueOf(count);
result = resultingPI.replace(PLACE_HOLDER_COUNT, countAsString);
} else {
@@ -309,117 +311,55 @@ private String applyCount(String resultingPI) {
return result;
}
- private String getMappedType(MCRObjectID id) {
- String mapping = getObjectTypeMapping();
- String typeID = id.getTypeId();
-
- return Optional.ofNullable(mapping)
- .map(mappingStr -> mappingStr.split(","))
- .map(Arrays::asList)
- .filter(o -> o.getFirst().equals(typeID))
- .map(o -> o.get(1))
- .orElse(typeID);
- }
-
- private String getMappedProject(MCRObjectID id) {
- String mapping = getObjectProjectMapping();
- String projectID = id.getProjectId();
-
- return Optional.ofNullable(mapping)
- .map(mappingStr -> mappingStr.split(","))
- .map(Arrays::asList)
- .filter(o -> o.getFirst().equals(projectID))
- .map(o -> o.get(1))
- .orElse(projectID);
- }
-
- protected AtomicInteger readCountFromDatabase(String countPattern) {
- Pattern regExpPattern = Pattern.compile(countPattern);
- Predicate matching = regExpPattern.asPredicate();
-
- List list = MCRPIManager.getInstance()
- .getList(getType(), -1, -1);
-
- // extract the number of the PI
- Optional highestNumber = list.stream()
- .map(MCRPIRegistrationInfo::getIdentifier)
- .filter(matching)
- .map(pi -> {
- // extract the number of the PI
- Matcher matcher = regExpPattern.matcher(pi);
- if (matcher.find() && matcher.groupCount() == 1) {
- String group = matcher.group(1);
- return Integer.parseInt(group, 10);
- } else {
- return null;
- }
- }).filter(Objects::nonNull)
- .min(Comparator.reverseOrder())
- .map(n -> n + 1);
- return new AtomicInteger(highestNumber.orElse(0));
- }
-
- private String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
+ /**
+ * Gets the count for a specific pattern and increase the internal counter. If there is no internal counter it will
+ * look into the Database and detect the highest count with the pattern.
+ *
+ * @param pattern a regex pattern which will be used to detect the highest count. The first group is the count.
+ * e.G. [0-9]+-mods-2017-([0-9][0-9][0-9][0-9])-[0-9] will match 31-mods-2017-0003-3 and the returned
+ * count will be 4 (3+1).
+ * @return the next count
+ */
+ public final synchronized int getCount(String pattern) {
+ return PATTERN_COUNT_MAP
+ .computeIfAbsent(pattern, p -> readCountFromDatabase(type, p))
+ .getAndIncrement();
}
- public String getGeneralPattern() {
- return generalPattern;
- }
+ public static class Factory implements Supplier {
- public void setGeneralPattern(String generalPattern) {
- this.generalPattern = generalPattern;
- }
+ @MCRProperty(name = GENERAL_PATTERN_KEY)
+ public String generalPattern;
- public SimpleDateFormat getDateFormat() {
- return dateFormat;
- }
+ @MCRProperty(name = DATE_FORMAT_KEY, required = false)
+ public String dateFormat;
- public void setDateFormat(SimpleDateFormat dateFormat) {
- this.dateFormat = dateFormat;
- }
+ @MCRPropertyMap(name = OBJECT_PROJECT_MAPPING_KEY, required = false)
+ public Map projectIdMappings;
- public String getObjectTypeMapping() {
- return objectTypeMapping;
- }
+ @MCRPropertyMap(name = OBJECT_TYPE_MAPPING_KEY, required = false)
+ public Map typeIdMappings;
- public void setObjectTypeMapping(String typeMapping) {
- this.objectTypeMapping = typeMapping;
- }
+ @MCRProperty(name = COUNT_PRECISION_KEY, required = false)
+ public String countPrecision = "-1";
- public int getCountPrecision() {
- return countPrecision;
- }
+ @MCRProperty(name = TYPE_KEY)
+ public String type;
- public void setCountPrecision(int countPrecision) {
- this.countPrecision = countPrecision;
- }
+ @MCRPropertyList(name = X_PATH_KEY, required = false)
+ public List xPaths;
- /**
- * Gets the count for a specific pattern and increase the internal counter. If there is no internal counter it will
- * look into the Database and detect the highest count with the pattern.
- *
- * @param pattern a reg exp pattern which will be used to detect the highest count. The first group is the count.
- * e.G. [0-9]+-mods-2017-([0-9][0-9][0-9][0-9])-[0-9] will match 31-mods-2017-0003-3 and the returned
- * count will be 4 (3+1).
- * @return the next count
- */
- public final synchronized int getCount(String pattern) {
- AtomicInteger count = PATTERN_COUNT_MAP
- .computeIfAbsent(pattern, this::readCountFromDatabase);
+ @Override
+ public MCRGenericPIGenerator get() {
+ return new MCRGenericPIGenerator(generalPattern, getDateFormat(),
+ projectIdMappings, typeIdMappings,
+ Integer.parseInt(countPrecision), type, xPaths);
+ }
- return count.getAndIncrement();
- }
+ private String getDateFormat() {
+ return dateFormat != null ? dateFormat : DEFAULT_DATE_FORMAT;
+ }
- public String getObjectProjectMapping() {
- return objectProjectMapping;
}
- public void setObjectProjectMapping(String objectProjectMapping) {
- this.objectProjectMapping = objectProjectMapping;
- }
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/MCRPICreationEventHandler.java b/mycore-pi/src/main/java/org/mycore/pi/MCRPICreationEventHandler.java
index 53197da451..2ff68d2d3d 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/MCRPICreationEventHandler.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/MCRPICreationEventHandler.java
@@ -21,7 +21,6 @@
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
import org.mycore.access.MCRAccessException;
import org.mycore.common.MCRException;
@@ -45,24 +44,32 @@ protected void handleObjectUpdated(MCREvent evt, MCRObject obj) {
private void processPIServices(MCRObject obj) {
List registered = MCRPIManager.getInstance().getRegistered(obj);
- final List services = registered.stream().map(MCRPIRegistrationInfo::getService)
- .collect(Collectors.toList());
+ final List services = registered.stream().map(MCRPIRegistrationInfo::getService).toList();
- List> listOfServicesWithCreatablePIs = MCRPIServiceManager
- .getInstance().getAutoCreationList().stream()
- .filter(Predicate.not(s -> services.contains(s.getServiceID())))
- .filter(Predicate.not(s -> MCRPIService.hasFlag(obj, "", s)))
- .filter(s -> s.getCreationPredicate().test(obj))
- .collect(Collectors.toList());
+ List> autoCreatingPIServices = MCRPIServiceManager
+ .getInstance().getAutoCreationList();
- listOfServicesWithCreatablePIs
- .forEach((serviceToRegister) -> {
+ boolean mayCreatePI = true;
+ while (mayCreatePI) {
+
+ mayCreatePI = false;
+
+ List> listOfServicesWithCreatablePIs = autoCreatingPIServices.stream()
+ .filter(Predicate.not(s -> services.contains(s.getServiceID())))
+ .filter(Predicate.not(s -> MCRPIService.hasFlag(obj, "", s)))
+ .filter(s -> s.getCreationPredicate().test(obj))
+ .toList();
+
+ for (MCRPIService serviceToRegister : listOfServicesWithCreatablePIs) {
try {
serviceToRegister.register(obj, "", false);
+ mayCreatePI = true;
} catch (MCRAccessException | MCRPersistentIdentifierException | ExecutionException
| InterruptedException e) {
throw new MCRException("Error while register pi for object " + obj.getId().toString(), e);
}
- });
+ }
+ }
+
}
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/MCRPIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/MCRPIGenerator.java
index ee9f300d13..85cc2b962e 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/MCRPIGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/MCRPIGenerator.java
@@ -18,59 +18,19 @@
package org.mycore.pi;
-import static org.mycore.pi.MCRPIService.GENERATOR_CONFIG_PREFIX;
-
-import java.util.Map;
-
-import org.mycore.common.config.MCRConfigurationException;
-import org.mycore.common.config.annotation.MCRPostConstruction;
-import org.mycore.common.config.annotation.MCRRawProperties;
import org.mycore.datamodel.metadata.MCRBase;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
-public abstract class MCRPIGenerator {
-
- private String generatorID;
-
- private Map properties;
-
- public final Map getProperties() {
- return properties;
- }
-
- @MCRPostConstruction
- public void init(String property) {
- generatorID = property.substring(GENERATOR_CONFIG_PREFIX.length());
- }
-
- @MCRRawProperties(namePattern = "*", required = false)
- public void setProperties(Map properties) {
- this.properties = properties;
- }
+public interface MCRPIGenerator {
/**
* generates a {@link MCRPersistentIdentifier}
*
- * @param mcrBase the mycore object for which the identifier is generated
+ * @param base the mycore object for which the identifier is generated
* @param additional additional information dedicated to the object like a mcrpath
* @return a unique persistence identifier
* @throws MCRPersistentIdentifierException if something goes wrong while generating
*/
- public abstract T generate(MCRBase mcrBase, String additional) throws MCRPersistentIdentifierException;
-
- /**
- * checks if the property exists and throws a exception if not.
- * @param propertyName to check
- * @throws MCRConfigurationException if property does not exist
- */
- protected void checkPropertyExists(final String propertyName) throws MCRConfigurationException {
- if (!getProperties().containsKey(propertyName)) {
- throw new MCRConfigurationException(
- "Missing property " + GENERATOR_CONFIG_PREFIX + getGeneratorID() + "." + propertyName);
- }
- }
+ T generate(MCRBase base, String additional) throws MCRPersistentIdentifierException;
- public String getGeneratorID() {
- return generatorID;
- }
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/MCRPIService.java b/mycore-pi/src/main/java/org/mycore/pi/MCRPIService.java
index 7e2393f031..3a4c38a9a0 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/MCRPIService.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/MCRPIService.java
@@ -208,6 +208,31 @@ private static boolean matches(MCRPI flag, MCRPIService> piService, String add
&& Objects.equals(flag.getService(), piService.getServiceID());
}
+ public static boolean hasFlag(MCRBase obj, String additional, MCRPIService> piService, String type) {
+ MCRObjectService service = obj.getService();
+ List flags = service.getFlags(PI_FLAG);
+ Gson gson = getGson();
+ return flags.stream()
+ .map(s -> gson.fromJson(s, MCRPI.class))
+ .anyMatch(flag -> matches(flag, piService, type, additional));
+ }
+
+ public static List getFlags(MCRBase obj, String additional, MCRPIService> piService, String type) {
+ MCRObjectService service = obj.getService();
+ List flags = service.getFlags(PI_FLAG);
+ Gson gson = getGson();
+ return flags.stream()
+ .map(s -> gson.fromJson(s, MCRPI.class))
+ .filter(flag -> matches(flag, piService, type, additional))
+ .toList();
+ }
+
+ private static boolean matches(MCRPI flag, MCRPIService> piService, String type, String additional) {
+ return flag.getAdditional().equals(additional)
+ && Objects.equals(flag.getService(), piService.getServiceID())
+ && Objects.equals(flag.getType(), type);
+ }
+
public static void updateFlagsInDatabase(MCRBase obj) {
Gson gson = getGson();
obj.getService().getFlags(PI_FLAG).stream()
diff --git a/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPICreatedPredicate.java b/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPICreatedPredicate.java
index 1ebf1c81af..fe59a3e061 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPICreatedPredicate.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPICreatedPredicate.java
@@ -19,7 +19,9 @@
import org.mycore.common.config.annotation.MCRProperty;
import org.mycore.datamodel.metadata.MCRBase;
-import org.mycore.pi.MCRPIManager;
+import org.mycore.pi.MCRPIService;
+import org.mycore.pi.MCRPIServiceManager;
+import org.mycore.pi.MCRPersistentIdentifier;
/**
* PI Predicate, that checks if another PersistentIdentifier was created within the PI component
@@ -49,7 +51,12 @@ public class MCRPIOtherPICreatedPredicate extends MCRPIPredicateBase
@Override
public boolean test(MCRBase mcrBase) {
- return MCRPIManager.getInstance().isCreated(mcrBase.getId(), "", type, service);
+
+ MCRPIServiceManager serviceManager = MCRPIServiceManager.getInstance();
+ MCRPIService service = serviceManager.getRegistrationService(this.service);
+
+ return MCRPIService.hasFlag(mcrBase, "", service, this.type);
+
}
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPIRegisteredPredicate.java b/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPIRegisteredPredicate.java
index 6315d24d1b..76ffd68e0c 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPIRegisteredPredicate.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/condition/MCRPIOtherPIRegisteredPredicate.java
@@ -19,7 +19,10 @@
import org.mycore.common.config.annotation.MCRProperty;
import org.mycore.datamodel.metadata.MCRBase;
-import org.mycore.pi.MCRPIManager;
+import org.mycore.pi.MCRPIService;
+import org.mycore.pi.MCRPIServiceManager;
+import org.mycore.pi.MCRPersistentIdentifier;
+import org.mycore.pi.backend.MCRPI;
/**
* PI Predicate, that checks if another PersistentIdentifier was registered within the PI component
@@ -49,7 +52,18 @@ public class MCRPIOtherPIRegisteredPredicate extends MCRPIPredicateBase
@Override
public boolean test(MCRBase mcrBase) {
- return MCRPIManager.getInstance().isRegistered(mcrBase.getId(), "", type, service);
+
+ MCRPIServiceManager serviceManager = MCRPIServiceManager.getInstance();
+ MCRPIService service = serviceManager.getRegistrationService(this.service);
+
+ for (MCRPI pi : MCRPIService.getFlags(mcrBase, "", service, this.type)) {
+ if (pi.getRegistered() != null) {
+ return true;
+ }
+ }
+
+ return false;
+
}
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCreateDateDOIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCreateDateDOIGenerator.java
index 0712d41472..69ad838aed 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCreateDateDOIGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCreateDateDOIGenerator.java
@@ -18,96 +18,127 @@
package org.mycore.pi.doi;
-import java.util.Comparator;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.formatCount;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.getCountPattern;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.getCreateDate;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.readCountFromDatabase;
+
import java.util.Date;
import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Predicate;
-import java.util.regex.Matcher;
+import java.util.function.Supplier;
import java.util.regex.Pattern;
-import org.mycore.common.MCRException;
-import org.mycore.common.MCRPersistenceException;
-import org.mycore.common.config.MCRConfiguration2;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
import org.mycore.datamodel.common.MCRISO8601Date;
import org.mycore.datamodel.metadata.MCRBase;
-import org.mycore.datamodel.metadata.MCRObjectService;
import org.mycore.pi.MCRPIGenerator;
-import org.mycore.pi.MCRPIManager;
-import org.mycore.pi.MCRPIRegistrationInfo;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+
+/**
+ * {@link MCRCreateDateDOIGenerator} is a {@link MCRPIGenerator} for {@link MCRDigitalObjectIdentifier} identifiers
+ * that generates identifiers using a given prefix and the current date and a per-date counter for the suffix.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRCreateDateDOIGenerator#DATE_FORMAT_KEY} can be used to
+ * specify the date format to be used (optional, defaults to {@link MCRCreateDateDOIGenerator#DEFAULT_DATE_FORMAT}).
+ * The property suffix {@link MCRCreateDateDOIGenerator#PREFIX_KEY} can be used to
+ * specify the prefix.
+ * The property suffix {@link MCRCreateDateDOIGenerator#COUNT_PRECISION_KEY} can be used to
+ * specify number of digits to be used for the count (optional, defaults to -1,
+ * which uses the natural number of digits).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.doi.MCRCreateDateDOIGenerator
+ * [...].DateFormat=yyyy-MM-dd
+ * [...].Prefix=10.1234
+ * [...].CountPrecision=6
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCRCreateDateDOIGenerator.Factory.class)
+public class MCRCreateDateDOIGenerator extends MCRDOIGeneratorBase {
+
+ public static final String DEFAULT_DATE_FORMAT = "yyyyMMdd-HHmmss";
-public class MCRCreateDateDOIGenerator extends MCRPIGenerator {
+ public static final Locale DEFAULT_DATE_LOCALE = Locale.ENGLISH;
- private static final String DATE_PATTERN = "yyyyMMdd-HHmmss";
+ public static final String DATE_FORMAT_KEY = "DateFormat";
- private static final String CREATE_DATE_PLACEHOLDER = "$createDate$";
+ public static final String PREFIX_KEY = "Prefix";
- private static final String DATE_REGEXP = CREATE_DATE_PLACEHOLDER + "-([0-9]+)";
+ public static final String COUNT_PRECISION_KEY = "CountPrecision";
private static final Map PATTERN_COUNT_MAP = new HashMap<>();
- private final MCRDOIParser mcrdoiParser;
+ private final String dateFormat;
- private final String prefix = MCRConfiguration2.getStringOrThrow("MCR.DOI.Prefix");
+ private final String prefix;
- public MCRCreateDateDOIGenerator() {
- super();
- mcrdoiParser = new MCRDOIParser();
+ private final int countPrecision;
+
+ private final String countPattern;
+
+ public MCRCreateDateDOIGenerator(MCRDOIParser parser, String dateFormat, String prefix,
+ int countPrecision) {
+ super(parser);
+ this.dateFormat = Objects.requireNonNull(dateFormat, "Date format must not be null");
+ this.prefix = Objects.requireNonNull(prefix, "Prefix must not be null");
+ this.countPrecision = countPrecision;
+ this.countPattern = getCountPattern(countPrecision);
}
@Override
- public MCRDigitalObjectIdentifier generate(MCRBase mcrObj, String additional) {
- Date createdate = mcrObj.getService().getDate(MCRObjectService.DATE_TYPE_CREATEDATE);
- if (createdate != null) {
- MCRISO8601Date mcrdate = new MCRISO8601Date();
- mcrdate.setDate(createdate);
- String createDate = mcrdate.format(DATE_PATTERN, Locale.ENGLISH);
- final int count = getCountForCreateDate(createDate);
- Optional parse = mcrdoiParser.parse(prefix + "/" + createDate + "-" + count);
- return parse.orElseThrow(() -> new MCRException("Error while parsing default doi!"));
- } else {
- throw new MCRPersistenceException("The object " + mcrObj.getId() + " doesn't have a createdate!");
- }
+ protected String buildDOI(MCRBase base, String additional) throws MCRPersistentIdentifierException {
+
+ String prefixWithDate = prefix + "/" + formatDate(getCreateDate(base)) + "-";
+ int count = getCount(Pattern.quote(prefixWithDate) + countPattern);
+
+ return prefixWithDate + formatCount(count, countPrecision);
+
}
- private int getCountForCreateDate(String createDate) {
- return getCount(prefix + "/" + DATE_REGEXP.replace(CREATE_DATE_PLACEHOLDER, createDate));
+ private String formatDate(Date date) {
+
+ MCRISO8601Date isoDate = new MCRISO8601Date();
+ isoDate.setDate(date);
+
+ return isoDate.format(dateFormat, DEFAULT_DATE_LOCALE);
+
}
private synchronized int getCount(final String pattern) {
- AtomicInteger count = PATTERN_COUNT_MAP.computeIfAbsent(pattern, p -> {
- Pattern regExpPattern = Pattern.compile(p);
- Predicate matching = regExpPattern.asPredicate();
-
- List list = MCRPIManager.getInstance()
- .getList(MCRDigitalObjectIdentifier.TYPE, -1, -1);
-
- Comparator integerComparator = Integer::compareTo;
- // extract the number of the PI
- Optional highestNumber = list.stream()
- .map(MCRPIRegistrationInfo::getIdentifier)
- .filter(matching)
- .map(pi -> {
- // extract the number of the PI
- Matcher matcher = regExpPattern.matcher(pi);
- if (matcher.find() && matcher.groupCount() == 1) {
- String group = matcher.group(1);
- return Integer.parseInt(group, 10);
- } else {
- return null;
- }
- }).filter(Objects::nonNull)
- .max(integerComparator)
- .map(n -> n + 1);
- return new AtomicInteger(highestNumber.orElse(0));
- });
-
- return count.getAndIncrement();
+ return PATTERN_COUNT_MAP
+ .computeIfAbsent(pattern, p -> readCountFromDatabase(MCRDigitalObjectIdentifier.TYPE, p))
+ .getAndIncrement();
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = DATE_FORMAT_KEY, required = false)
+ public String dateFormat;
+
+ @MCRProperty(name = PREFIX_KEY, defaultName = "MCR.DOI.Prefix")
+ public String prefix;
+
+ @MCRProperty(name = COUNT_PRECISION_KEY, required = false)
+ public String countPrecision = "-1";
+
+ @Override
+ public MCRCreateDateDOIGenerator get() {
+ return new MCRCreateDateDOIGenerator(new MCRDOIParser(), getDateFormat(), prefix,
+ Integer.parseInt(countPrecision));
+ }
+
+ private String getDateFormat() {
+ return dateFormat != null ? dateFormat : DEFAULT_DATE_FORMAT;
+ }
+
}
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCurrentDateDOIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCurrentDateDOIGenerator.java
new file mode 100644
index 0000000000..9c0e81daab
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRCurrentDateDOIGenerator.java
@@ -0,0 +1,94 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.doi;
+
+import java.util.Date;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.util.MCRFLDateScrambler;
+
+/**
+ * {@link MCRCurrentDateDOIGenerator} is a {@link MCRPIGenerator} for {@link MCRDigitalObjectIdentifier} identifiers
+ * that generates identifiers using a given prefix and the current date (in seconds) value as the suffix.
+ *
+ * Only one suffix per second will be generated.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRCurrentDateDOIGenerator#PREFIX_KEY} can be used to
+ * specify the prefix.
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.doi.MCRCurrentDateDOIGenerator
+ * [...].Prefix=10.1234
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCRCurrentDateDOIGenerator.Factory.class)
+public class MCRCurrentDateDOIGenerator extends MCRDOIGeneratorBase {
+
+ public static final String PREFIX_KEY = "Prefix";
+
+ private final String prefix;
+
+ private String lastSuffix;
+
+ public MCRCurrentDateDOIGenerator(MCRDOIParser parser, String prefix) {
+ super(parser);
+ this.prefix = Objects.requireNonNull(prefix, "Prefix must not be null");
+ }
+
+ @Override
+ protected synchronized String buildDOI(MCRBase base, String additional) {
+
+ Date date = new Date((System.currentTimeMillis() / 1000) * 1000);
+ String suffix = MCRFLDateScrambler.scrambleDate(date);
+
+ if (suffix.equals(lastSuffix)) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException ignored) {
+ }
+ return buildDOI(base, additional);
+ }
+
+ lastSuffix = suffix;
+
+ return prefix + "/" + suffix;
+
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = PREFIX_KEY, defaultName = "MCR.DOI.Prefix")
+ public String prefix;
+
+ @Override
+ public MCRCurrentDateDOIGenerator get() {
+ return new MCRCurrentDateDOIGenerator(new MCRDOIParser(), prefix);
+ }
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRStaticDOIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRDOIGeneratorBase.java
similarity index 55%
rename from mycore-pi/src/main/java/org/mycore/pi/doi/MCRStaticDOIGenerator.java
rename to mycore-pi/src/main/java/org/mycore/pi/doi/MCRDOIGeneratorBase.java
index ff8132d985..afa4a603e0 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRStaticDOIGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRDOIGeneratorBase.java
@@ -18,28 +18,27 @@
package org.mycore.pi.doi;
-import java.util.Optional;
+import java.util.Objects;
-import org.mycore.common.config.MCRConfigurationException;
import org.mycore.datamodel.metadata.MCRBase;
import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
-/**
- * Just for testing. Provides the doi in the doi property.
- */
-public class MCRStaticDOIGenerator extends MCRPIGenerator {
+public abstract class MCRDOIGeneratorBase implements MCRPIGenerator {
+
+ private final MCRDOIParser parser;
- public MCRStaticDOIGenerator() {
- super();
- checkPropertyExists("doi");
+ public MCRDOIGeneratorBase(MCRDOIParser parser) {
+ this.parser = Objects.requireNonNull(parser, "Parser must not be null");
}
@Override
- public MCRDigitalObjectIdentifier generate(MCRBase mcrBase, String additional) {
- final String doi = getProperties().get("doi");
- final Optional generatedDOI = new MCRDOIParser().parse(doi);
- return generatedDOI
- .orElseThrow(() -> new MCRConfigurationException("The property " + doi + " is not a valid doi!"));
+ public final MCRDigitalObjectIdentifier generate(MCRBase base, String additional)
+ throws MCRPersistentIdentifierException {
+ return parser.parse(buildDOI(base, additional)).get();
}
+ protected abstract String buildDOI(MCRBase base, String additional)
+ throws MCRPersistentIdentifierException;
+
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRMapObjectIDDOIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRMapObjectIDDOIGenerator.java
index fe239b7dd4..9abcf89329 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRMapObjectIDDOIGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRMapObjectIDDOIGenerator.java
@@ -18,44 +18,73 @@
package org.mycore.pi.doi;
-import java.util.Optional;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRPropertyMap;
import org.mycore.datamodel.metadata.MCRBase;
import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.pi.MCRPIGenerator;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
/**
- * Uses mapping from MCRObjectID base to DOI prefix to generate DOIs.
- * e.g. MCR.PI.Generator.MapObjectIDDOI.Prefix.mycore_mods = 10.5072/my. will map
- * mycore_mods_00004711 to 10.5072/my.4711
- *
- * @author Thomas Scheffler (yagee)
+ * {@link MCRMapObjectIDDOIGenerator} is a {@link MCRPIGenerator} for {@link MCRDigitalObjectIdentifier} identifiers
+ * that generates identifiers by concatenating a {@link MCRObjectID#getBase}-dependent value and the numerical
+ * part of the {@link MCRObjectID} of the {@link MCRBase}.
+ *
+ * Example: Prefix mapping mycore_mods=10.1234/MODS. will map mycore_mods_00000123
+ * to 10.1234/MODS.123
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRMapObjectIDDOIGenerator#PREFIX_KEY} can be used to
+ * specify the prefix mappings to be used.
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.doi.MCRMapObjectIDDOIGenerator
+ * [...].Prefix.mycore_mods=10.1234/MODS.
+ * [...].Prefix.mycore_alto=10.9876/ALTO.
+ *
*/
-public class MCRMapObjectIDDOIGenerator extends MCRPIGenerator {
+@MCRConfigurationProxy(proxyClass = MCRMapObjectIDDOIGenerator.Factory.class)
+public class MCRMapObjectIDDOIGenerator extends MCRDOIGeneratorBase {
- private final MCRDOIParser mcrdoiParser;
+ public static final String PREFIX_KEY = "Prefix";
- private String generatorID;
+ private final Map prefixMap;
- public MCRMapObjectIDDOIGenerator() {
- super();
- mcrdoiParser = new MCRDOIParser();
+ public MCRMapObjectIDDOIGenerator(MCRDOIParser parser, Map prefixMap) {
+ super(parser);
+ this.prefixMap = Objects.requireNonNull(prefixMap, "Prefix map must not be null");
}
@Override
- public MCRDigitalObjectIdentifier generate(MCRBase mcrObject, String additional)
- throws MCRPersistentIdentifierException {
- final MCRObjectID objectId = mcrObject.getId();
- return Optional.ofNullable(getProperties().get("Prefix." + objectId.getBase()))
- .map(prefix -> {
- final int objectIdNumberAsInteger = objectId.getNumberAsInteger();
- return prefix.contains("/") ? prefix + objectIdNumberAsInteger
- : prefix + '/' + objectIdNumberAsInteger;
- })
- .flatMap(mcrdoiParser::parse).map(MCRDigitalObjectIdentifier.class::cast)
- .orElseThrow(() -> new MCRPersistentIdentifierException("Prefix." + objectId.getBase() +
- " is not defined in " + generatorID + "."));
+ protected String buildDOI(MCRBase base, String additional) throws MCRPersistentIdentifierException {
+
+ MCRObjectID objectId = base.getId();
+ String prefix = prefixMap.get(objectId.getBase());
+
+ if (prefix == null) {
+ throw new MCRPersistentIdentifierException("Missing prefix for base " + objectId.getBase());
+ }
+
+ int objectIdNumberAsInteger = objectId.getNumberAsInteger();
+ return prefix.contains("/") ? prefix + objectIdNumberAsInteger : prefix + '/' + objectIdNumberAsInteger;
+
}
+ public static class Factory implements Supplier {
+
+ @MCRPropertyMap(name = PREFIX_KEY)
+ public Map prefixMap;
+
+ @Override
+ public MCRMapObjectIDDOIGenerator get() {
+ return new MCRMapObjectIDDOIGenerator(new MCRDOIParser(), prefixMap);
+ }
+
+ }
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/doi/MCROtherPIDOIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/doi/MCROtherPIDOIGenerator.java
new file mode 100644
index 0000000000..e644d29ade
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/doi/MCROtherPIDOIGenerator.java
@@ -0,0 +1,103 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.doi;
+
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.util.MCROtherPIValueExtractor;
+
+/**
+ * {@link MCROtherPIDOIGenerator} is a {@link MCRPIGenerator} for {@link MCRDigitalObjectIdentifier} identifiers
+ * that generates identifiers using a given prefix and a value extracted from another PI
+ * that is already assigned as the suffix.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCROtherPIDOIGenerator#PREFIX_KEY} can be used to
+ * specify the prefix.
+ * The property suffix {@link MCROtherPIDOIGenerator#TYPE_KEY} can be used to
+ * specify the type of the assigned PI.
+ * The property suffix {@link MCROtherPIDOIGenerator#SERVICE_KEY} can be used to
+ * specify the service of the assigned PI.
+ * The property suffix {@link MCROtherPIDOIGenerator#PATTERN_KEY} can be used to
+ * specify the pattern (must contain a single capture group).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.doi.MCROtherPIDOIGenerator
+ * [...].Prefix=10.1234
+ * [...].Type=dnbUrn
+ * [...].Service=DNBURN
+ * [...].Pattern=urn:nbn:de:xzy-(.+)-[0-9]
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCROtherPIDOIGenerator.Factory.class)
+public class MCROtherPIDOIGenerator extends MCRDOIGeneratorBase {
+
+ public static final String TYPE_KEY = "Type";
+
+ public static final String SERVICE_KEY = "Service";
+
+ public static final String PATTERN_KEY = "Pattern";
+
+ public static final String PREFIX_KEY = "Prefix";
+
+ private final String prefix;
+
+ private final MCROtherPIValueExtractor extractor;
+
+ public MCROtherPIDOIGenerator(MCRDOIParser parser, String prefix, MCROtherPIValueExtractor extractor) {
+ super(parser);
+ this.prefix = Objects.requireNonNull(prefix, "Prefix must not be null");
+ this.extractor = Objects.requireNonNull(extractor, "Extractor must not be null");
+ }
+
+ @Override
+ protected String buildDOI(MCRBase base, String additional) {
+ return prefix + "/" + extractor.extractValue(base);
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = PREFIX_KEY, defaultName = "MCR.DOI.Prefix")
+ public String prefix;
+
+ @MCRProperty(name = TYPE_KEY)
+ public String type;
+
+ @MCRProperty(name = SERVICE_KEY)
+ public String service;
+
+ @MCRProperty(name = PATTERN_KEY)
+ public String pattern;
+
+ @Override
+ public MCROtherPIDOIGenerator get() {
+ MCROtherPIValueExtractor extractor = new MCROtherPIValueExtractor(type, service, pattern);
+ return new MCROtherPIDOIGenerator(new MCRDOIParser(), prefix, extractor);
+ }
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRUUIDDOIGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRUUIDDOIGenerator.java
index b686ee1805..7b88fe60b7 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/doi/MCRUUIDDOIGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/doi/MCRUUIDDOIGenerator.java
@@ -18,29 +18,57 @@
package org.mycore.pi.doi;
-import java.util.Optional;
+import java.util.Objects;
import java.util.UUID;
+import java.util.function.Supplier;
-import org.mycore.common.config.MCRConfiguration2;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
import org.mycore.datamodel.metadata.MCRBase;
import org.mycore.pi.MCRPIGenerator;
-import org.mycore.pi.MCRPersistentIdentifier;
-public class MCRUUIDDOIGenerator extends MCRPIGenerator {
+/**
+ * {@link MCRUUIDDOIGenerator} is a {@link MCRPIGenerator} for {@link MCRDigitalObjectIdentifier} identifiers
+ * that generates identifiers using a given prefix and a {@link UUID} as the suffix.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRUUIDDOIGenerator#PREFIX_KEY} can be used to
+ * specify the prefix.
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.doi.MCRUUIDDOIGenerator
+ * [...].Prefix=10.1234
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCRUUIDDOIGenerator.Factory.class)
+public class MCRUUIDDOIGenerator extends MCRDOIGeneratorBase {
- private final MCRDOIParser mcrdoiParser;
+ public static final String PREFIX_KEY = "Prefix";
- private String prefix = MCRConfiguration2.getStringOrThrow("MCR.DOI.Prefix");
+ private final String prefix;
- public MCRUUIDDOIGenerator() {
- super();
- mcrdoiParser = new MCRDOIParser();
+ public MCRUUIDDOIGenerator(MCRDOIParser parser, String prefix) {
+ super(parser);
+ this.prefix = Objects.requireNonNull(prefix, "Prefix must not be null");
}
@Override
- public MCRDigitalObjectIdentifier generate(MCRBase mcrObject, String additional) {
- Optional parse = mcrdoiParser.parse(prefix + "/" + UUID.randomUUID());
- MCRPersistentIdentifier doi = parse.get();
- return (MCRDigitalObjectIdentifier) doi;
+ protected String buildDOI(MCRBase base, String additional) {
+ return prefix + "/" + UUID.randomUUID();
}
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = PREFIX_KEY, defaultName = "MCR.DOI.Prefix")
+ public String prefix;
+
+ @Override
+ public MCRUUIDDOIGenerator get() {
+ return new MCRUUIDDOIGenerator(new MCRDOIParser(), prefix);
+ }
+
+ }
+
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/purl/MCRIDPURLGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/purl/MCRIDPURLGenerator.java
index 14cdb4fb24..0e5bbc1ecd 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/purl/MCRIDPURLGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/purl/MCRIDPURLGenerator.java
@@ -21,37 +21,77 @@
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
-import java.net.URL;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.pi.MCRPIGenerator;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
/**
- * The property BaseURLTemplate is your url and the {@link MCRIDPURLGenerator}
- * will replace $ID with the actual MyCoRe-ID.
+ * {@link MCRIDPURLGenerator} is a {@link MCRPIGenerator} for {@link MCRPURL} identifiers
+ * that generates identifiers using a template and the {@link MCRObjectID} of the {@link MCRBase}.
+ *
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRIDPURLGenerator#BASE_URL_TEMPLATE_KEY} can be used to
+ * specify the template (must contain the replacement marker $ID).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.purl.MCRIDPURLGenerator
+ * [...].BaseURLTemplate=https://purl.example.com/$ID
+ *
*/
-public class MCRIDPURLGenerator extends MCRPIGenerator {
+@MCRConfigurationProxy(proxyClass = MCRIDPURLGenerator.Factory.class)
+public class MCRIDPURLGenerator implements MCRPIGenerator {
- @Override
- public MCRPURL generate(MCRBase mcrObj, String additional)
- throws MCRPersistentIdentifierException {
+ public static final String BASE_URL_TEMPLATE_KEY = "BaseURLTemplate";
+
+ private final String baseUrlTemplate;
+
+ public MCRIDPURLGenerator(String baseUrlTemplate) {
+ Objects.requireNonNull(baseUrlTemplate, "Base URL template must not be null");
+ this.baseUrlTemplate = checkBaseUrlTemplate(baseUrlTemplate);
+ }
- String baseUrlTemplate = getProperties().getOrDefault("BaseURLTemplate", "");
+ private static String checkBaseUrlTemplate(String baseUrlTemplate) {
+ if (!baseUrlTemplate.contains("$ID")) {
+ throw new IllegalArgumentException("Base URL template doesn't contain replacement marker $ID: "
+ + baseUrlTemplate);
+ }
+ return baseUrlTemplate;
+ }
- String replace = baseUrlTemplate;
- String before;
+ @Override
+ public MCRPURL generate(MCRBase base, String additional) throws MCRPersistentIdentifierException {
- do {
- before = replace;
- replace = baseUrlTemplate.replace("$ID", mcrObj.getId().toString());
- } while (!replace.equals(before));
+ String id = base.getId().toString();
+ String baseUrl = baseUrlTemplate.replaceAll(Pattern.quote("$ID"), id);
try {
- URL url = new URI(replace).toURL();
- return new MCRPURL(url);
+ return new MCRPURL(new URI(baseUrl).toURL());
} catch (MalformedURLException | URISyntaxException e) {
- throw new MCRPersistentIdentifierException("Error while creating URL object from string: " + replace, e);
+ throw new MCRPersistentIdentifierException("Error while creating base URL for " + id + ": " + baseUrl, e);
}
+
}
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = BASE_URL_TEMPLATE_KEY)
+ public String baseUrlTemplate;
+
+ @Override
+ public MCRIDPURLGenerator get() {
+ return new MCRIDPURLGenerator(baseUrlTemplate);
+ }
+
+ }
+
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGenerator.java
index 274cba8032..baaa828b8e 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGenerator.java
@@ -18,70 +18,14 @@
package org.mycore.pi.urn;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Predicate;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.mycore.pi.MCRPIManager;
-import org.mycore.pi.MCRPIRegistrationInfo;
-
/**
- * A Generator which helps to generate a URN with a counter inside.
+ * @deprecated Use {@link MCRCountingDNBURNGeneratorBase} instead.
*/
-public abstract class MCRCountingDNBURNGenerator extends MCRDNBURNGenerator {
-
- private static final Map PATTERN_COUNT_MAP = new HashMap<>();
+@Deprecated(forRemoval = true)
+public abstract class MCRCountingDNBURNGenerator extends MCRCountingDNBURNGeneratorBase {
- MCRCountingDNBURNGenerator() {
- super();
+ MCRCountingDNBURNGenerator(String namespace) {
+ super(namespace, "");
}
- protected AtomicInteger readCountFromDatabase(String countPattern) {
- Pattern regExpPattern = Pattern.compile(countPattern);
- Predicate matching = regExpPattern.asPredicate();
-
- List list = MCRPIManager.getInstance()
- .getList(MCRDNBURN.TYPE, -1, -1);
-
- // extract the number of the PI
- Optional highestNumber = list.stream()
- .map(MCRPIRegistrationInfo::getIdentifier)
- .filter(matching)
- .map(pi -> {
- // extract the number of the PI
- Matcher matcher = regExpPattern.matcher(pi);
- if (matcher.find() && matcher.groupCount() == 1) {
- String group = matcher.group(1);
- return Integer.parseInt(group, 10);
- } else {
- return null;
- }
- }).filter(Objects::nonNull)
- .min(Comparator.reverseOrder())
- .map(n -> n + 1);
- return new AtomicInteger(highestNumber.orElse(0));
- }
-
- /**
- * Gets the count for a specific pattern and increase the internal counter. If there is no internal counter it will
- * look into the Database and detect the highest count with the pattern.
- *
- * @param pattern a reg exp pattern which will be used to detect the highest count. The first group is the count.
- * e.G. [0-9]+-mods-2017-([0-9][0-9][0-9][0-9])-[0-9] will match 31-mods-2017-0003-3 and the returned
- * count will be 4 (3+1).
- * @return the next count
- */
- public final synchronized int getCount(String pattern) {
- AtomicInteger count = PATTERN_COUNT_MAP
- .computeIfAbsent(pattern, this::readCountFromDatabase);
-
- return count.getAndIncrement();
- }
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGeneratorBase.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGeneratorBase.java
new file mode 100644
index 0000000000..63acce463e
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCountingDNBURNGeneratorBase.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import static org.mycore.pi.util.MCRPIGeneratorUtils.readCountFromDatabase;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A Generator which helps to generate a URN with a counter inside.
+ */
+public abstract class MCRCountingDNBURNGeneratorBase extends MCRDNBURNGeneratorBase {
+
+ private static final Map PATTERN_COUNT_MAP = new HashMap<>();
+
+ MCRCountingDNBURNGeneratorBase(String namespace, String delimiter) {
+ super(namespace, delimiter);
+ }
+
+ MCRCountingDNBURNGeneratorBase(String namespace) {
+ super(namespace, "");
+ }
+
+ /**
+ * Gets the count for a specific pattern and increase the internal counter. If there is no internal counter it will
+ * look into the Database and detect the highest count with the pattern.
+ *
+ * @param pattern a regex pattern which will be used to detect the highest count. The first group is the count.
+ * e.G. [0-9]+-mods-2017-([0-9][0-9][0-9][0-9])-[0-9] will match 31-mods-2017-0003-3 and the returned
+ * count will be 4 (3+1).
+ * @return the next count
+ */
+ public final synchronized int getCount(String pattern) {
+ return PATTERN_COUNT_MAP
+ .computeIfAbsent(pattern, p -> readCountFromDatabase(MCRDNBURN.TYPE, p))
+ .getAndIncrement();
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCreateDateDNBURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCreateDateDNBURNGenerator.java
new file mode 100644
index 0000000000..dc3018b0f1
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCreateDateDNBURNGenerator.java
@@ -0,0 +1,150 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import static org.mycore.pi.util.MCRPIGeneratorUtils.formatCount;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.getCountPattern;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.getCreateDate;
+import static org.mycore.pi.util.MCRPIGeneratorUtils.readCountFromDatabase;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.datamodel.common.MCRISO8601Date;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+
+/**
+ * {@link MCRCreateDateDNBURNGenerator} is a {@link MCRPIGenerator} for {@link MCRDNBURN} identifiers
+ * that generates identifiers using a given prefix and the current date and a per-date counter for the suffix.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRCreateDateDNBURNGenerator#DATE_FORMAT_KEY} can be used to
+ * specify the date format to be used (optional, defaults to {@link MCRCreateDateDNBURNGenerator#DEFAULT_DATE_FORMAT}).
+ * The property suffix {@link MCRCreateDateDNBURNGenerator#NAMESPACE_KEY} can be used to
+ * specify the namespace.
+ * The property suffix {@link MCRCreateDateDNBURNGenerator#DELIMITER_KEY} can be used to
+ * specify a delimiter to be placed before and after the NISS (optional, defaults to the empty string).
+ * The property suffix {@link MCRCreateDateDNBURNGenerator#COUNT_PRECISION_KEY} can be used to
+ * specify number of digits to be used for the count (optional, defaults to -1,
+ * which uses the natural number of digits).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.urn.MCRCreateDateDNBURNGenerator
+ * [...].DateFormat=yyyy-MM-dd
+ * [...].Namespace=urn:nbn:de:gbv:xyz
+ * [...].Delimiter=-
+ * [...].CountPrecision=6
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCRCreateDateDNBURNGenerator.Factory.class)
+public class MCRCreateDateDNBURNGenerator extends MCRDNBURNGeneratorBase {
+
+ public static final String DEFAULT_DATE_FORMAT = "yyyyMMdd-HHmmss";
+
+ public static final Locale DEFAULT_DATE_LOCALE = Locale.ENGLISH;
+
+ public static final String DATE_FORMAT_KEY = "DateFormat";
+
+ public static final String NAMESPACE_KEY = "Namespace";
+
+ public static final String DELIMITER_KEY = "Delimiter";
+
+ public static final String COUNT_PRECISION_KEY = "CountPrecision";
+
+ private static final Map PATTERN_COUNT_MAP = new HashMap<>();
+
+ private final String dateFormat;
+
+ private final int countPrecision;
+
+ private final String countPattern;
+
+ public MCRCreateDateDNBURNGenerator(String dateFormat, String namespace,
+ String delimiter, int countPrecision) {
+ super(namespace, delimiter);
+ this.dateFormat = Objects.requireNonNull(dateFormat, "Date format must not be null");
+ this.countPrecision = countPrecision;
+ this.countPattern = getCountPattern(countPrecision);
+ }
+
+ @Override
+ protected String buildNISS(MCRBase base, String additional) throws MCRPersistentIdentifierException {
+
+ String prefixWithDate = formatDate(getCreateDate(base)) + "-";
+ int count = getCount(Pattern.quote(namespace() + delimiter() + prefixWithDate)
+ + countPattern + Pattern.quote(delimiter()) + "[0-9]");
+
+ return prefixWithDate + formatCount(count, countPrecision);
+
+ }
+
+ private String formatDate(Date date) {
+
+ MCRISO8601Date isoDate = new MCRISO8601Date();
+ isoDate.setDate(date);
+
+ return isoDate.format(dateFormat, DEFAULT_DATE_LOCALE);
+
+ }
+
+ private synchronized int getCount(final String pattern) {
+ return PATTERN_COUNT_MAP
+ .computeIfAbsent(pattern, p -> readCountFromDatabase(MCRDNBURN.TYPE, p))
+ .getAndIncrement();
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = DATE_FORMAT_KEY, required = false)
+ public String dateFormat;
+
+ @MCRProperty(name = NAMESPACE_KEY)
+ public String namespace;
+
+ @MCRProperty(name = DELIMITER_KEY, required = false)
+ public String delimiter = "";
+
+ @MCRProperty(name = COUNT_PRECISION_KEY, required = false)
+ public String countPrecision = "-1";
+
+ @Override
+ public MCRCreateDateDNBURNGenerator get() {
+ return new MCRCreateDateDNBURNGenerator(getDateFormat(), namespace, delimiter,
+ Integer.parseInt(countPrecision));
+ }
+
+ private String getDateFormat() {
+ return dateFormat != null ? dateFormat : DEFAULT_DATE_FORMAT;
+ }
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCurrentDateDNBURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCurrentDateDNBURNGenerator.java
new file mode 100644
index 0000000000..d64ba10452
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRCurrentDateDNBURNGenerator.java
@@ -0,0 +1,98 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import java.util.Date;
+import java.util.function.Supplier;
+
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.util.MCRFLDateScrambler;
+
+/**
+ * {@link MCRCurrentDateDNBURNGenerator} is a {@link MCRPIGenerator} for {@link MCRDNBURN} identifiers
+ * that generates identifiers using a given namespace and the current date (in seconds) value as the NISS.
+ *
+ * Only one suffix per second will be generated.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRCurrentDateDNBURNGenerator#NAMESPACE_KEY} can be used to
+ * specify the namespace.
+ * The property suffix {@link MCRCurrentDateDNBURNGenerator#DELIMITER_KEY} can be used to
+ * specify a delimiter to be placed before and after the NISS (optional, defaults to the empty string).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.urn.MCRCurrentDateDNBURNGenerator
+ * [...].Namespace=urn:nbn:de:gbv:xyz
+ * [...].Delimiter=-
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCRCurrentDateDNBURNGenerator.Factory.class)
+public class MCRCurrentDateDNBURNGenerator extends MCRDNBURNGeneratorBase {
+
+ public static final String NAMESPACE_KEY = "Namespace";
+
+ public static final String DELIMITER_KEY = "Delimiter";
+
+ private String lastNIss;
+
+ public MCRCurrentDateDNBURNGenerator(String namespace, String delimiter) {
+ super(namespace, delimiter);
+ }
+
+ @Override
+ protected synchronized String buildNISS(MCRBase base, String additional) {
+
+ Date date = new Date((System.currentTimeMillis() / 1000) * 1000);
+ String niss = MCRFLDateScrambler.scrambleDate(date);
+
+ if (niss.equals(lastNIss)) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException ignored) {
+ }
+ return buildNISS(base, additional);
+ }
+
+ lastNIss = niss;
+
+ return niss;
+
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = NAMESPACE_KEY)
+ public String namespace;
+
+ @MCRProperty(name = DELIMITER_KEY, required = false)
+ public String delimiter = "";
+
+ @Override
+ public MCRCurrentDateDNBURNGenerator get() {
+ return new MCRCurrentDateDNBURNGenerator(namespace, delimiter);
+ }
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGenerator.java
index 9fcb994a21..78b397e3c4 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGenerator.java
@@ -18,46 +18,14 @@
package org.mycore.pi.urn;
-import java.util.Objects;
-
-import org.mycore.datamodel.metadata.MCRBase;
-import org.mycore.datamodel.metadata.MCRObjectID;
-import org.mycore.pi.MCRPIGenerator;
-
-import jakarta.validation.constraints.NotNull;
-
-public abstract class MCRDNBURNGenerator extends MCRPIGenerator {
-
- private static final String URN_NBN_DE = "urn:nbn:de:";
-
- protected abstract String buildNISS(MCRObjectID mcrID, String additional);
-
- /**
- * Allows the generation of a URN with a specific Namespace
- *
- * @param namespace the namespace of the generated URN
- * @param mcrID the mycore object for which the identifier is generated
- * @param additional additional information dedicated to the object like a mcrpath
- * @return a unique persistence identifier
- */
- protected MCRDNBURN generate(@NotNull String namespace, MCRObjectID mcrID, String additional) {
- Objects.requireNonNull(namespace, "Namespace for an URN must not be null!");
- return new MCRDNBURN(namespace, buildNISS(mcrID, additional));
- }
-
- @Override
- public MCRDNBURN generate(MCRBase mcrObj, String additional) {
- return generate(getNamespace(), mcrObj.getId(), additional);
- }
-
- public String getNamespace() {
- String namespace = getProperties().get("Namespace").trim();
-
- if (namespace.startsWith(URN_NBN_DE)) {
- namespace = namespace.substring(URN_NBN_DE.length());
- }
+/**
+ * @deprecated Use {@link MCRDNBURNGeneratorBase} instead.
+ */
+@Deprecated(forRemoval = true)
+public abstract class MCRDNBURNGenerator extends MCRDNBURNGeneratorBase {
- return namespace;
+ public MCRDNBURNGenerator(String namespace) {
+ super(namespace, "");
}
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGeneratorBase.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGeneratorBase.java
new file mode 100644
index 0000000000..76cb6e4c40
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRDNBURNGeneratorBase.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import java.util.Objects;
+
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+
+public abstract class MCRDNBURNGeneratorBase implements MCRPIGenerator {
+
+ private static final String URN_NBN_DE = "urn:nbn:de:";
+
+ private final String namespace;
+
+ private final String delimiter;
+
+ public MCRDNBURNGeneratorBase(String namespace, String delimiter) {
+ this.namespace = checkNamespace(Objects.requireNonNull(namespace, "Namespace must not be null"));
+ this.delimiter = Objects.requireNonNull(delimiter, "Delimiter must not be null");
+ }
+
+ private static String checkNamespace(String namespace) {
+ if (namespace.startsWith(URN_NBN_DE)) {
+ namespace = namespace.substring(URN_NBN_DE.length());
+ }
+ return namespace;
+ }
+
+ protected final String namespace() {
+ return namespace;
+ }
+
+ protected final String delimiter() {
+ return delimiter;
+ }
+
+ @Override
+ public MCRDNBURN generate(MCRBase base, String additional)
+ throws MCRPersistentIdentifierException {
+ return new MCRDNBURN(namespace, delimiter + buildNISS(base, additional) + delimiter);
+ }
+
+ protected abstract String buildNISS(MCRBase base, String additional)
+ throws MCRPersistentIdentifierException;
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRFLURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRFLURNGenerator.java
index 8c0e9669e1..1f5c4a34f7 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRFLURNGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRFLURNGenerator.java
@@ -18,51 +18,35 @@
package org.mycore.pi.urn;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
+import java.util.function.Supplier;
-import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
/**
- * Builds a new, unique NISS based on the current date and time expressed
- * in seconds. The resulting NISS is non-speaking, but unique and somewhat
- * optimized for the nbn:de checksum algorithm. Only one NISS per second
- * will be generated.
- *
- * @author Frank Lützenkirchen
+ * @deprecated Use {@link MCRCurrentDateDNBURNGenerator} instead.
*/
-public class MCRFLURNGenerator extends MCRDNBURNGenerator {
- private String last;
+@Deprecated(forRemoval = true)
+@MCRConfigurationProxy(proxyClass = MCRFLURNGenerator.Factory.class)
+public class MCRFLURNGenerator extends MCRCurrentDateDNBURNGenerator {
- @Override
- protected synchronized String buildNISS(MCRObjectID mcrID, String additional) {
- Calendar now = new GregorianCalendar(TimeZone.getTimeZone("GMT+01:00"), Locale.ENGLISH);
- int yyy = 2268 - now.get(Calendar.YEAR);
- int ddd = 500 - now.get(Calendar.DAY_OF_YEAR);
- int hh = now.get(Calendar.HOUR_OF_DAY);
- int mm = now.get(Calendar.MINUTE);
- int ss = now.get(Calendar.SECOND);
- int sss = 99_999 - (hh * 3600 + mm * 60 + ss);
+ public MCRFLURNGenerator(String namespace, String delimiter) {
+ super(namespace, delimiter);
+ }
- String ddddd = String.valueOf(yyy * 366 + ddd);
+ public static class Factory implements Supplier {
- String niss = String.valueOf(ddddd.charAt(4)) + ddddd.charAt(2) + ddddd.charAt(1) + ddddd.charAt(3)
- + ddddd.charAt(0)
- + sss;
+ @MCRProperty(name = NAMESPACE_KEY)
+ public String namespace;
- if (niss.equals(last)) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException ignored) {
- }
+ @MCRProperty(name = DELIMITER_KEY, required = false)
+ public String delimiter = "";
- return buildNISS(mcrID, additional);
- } else {
- last = niss;
- return niss;
+ @Override
+ public MCRFLURNGenerator get() {
+ return new MCRFLURNGenerator(namespace, delimiter);
}
+
}
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCROtherPIDNBURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCROtherPIDNBURNGenerator.java
new file mode 100644
index 0000000000..b3ff5f11a3
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCROtherPIDNBURNGenerator.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.util.MCROtherPIValueExtractor;
+
+/**
+ * {@link MCROtherPIDNBURNGenerator} is a {@link MCRPIGenerator} for {@link MCRDNBURN} identifiers
+ * that generates identifiers using a given namespace and a value extracted from another PI
+ * that is already assigned as the NISS.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCROtherPIDNBURNGenerator#NAMESPACE_KEY} can be used to
+ * specify the namespace.
+ * The property suffix {@link MCROtherPIDNBURNGenerator#DELIMITER_KEY} can be used to
+ * specify a delimiter to be placed before and after the NISS (optional, defaults to the empty string).
+ * The property suffix {@link MCROtherPIDNBURNGenerator#TYPE_KEY} can be used to
+ * specify the type of the assigned PI.
+ * The property suffix {@link MCROtherPIDNBURNGenerator#SERVICE_KEY} can be used to
+ * specify the service of the assigned PI.
+ * The property suffix {@link MCROtherPIDNBURNGenerator#PATTERN_KEY} can be used to
+ * specify the pattern (must contain a single capture group).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.urn.MCROtherPIDNBURNGenerator
+ * [...].Namespace=urn:nbn:de:gbv:xyz
+ * [...].Delimiter=-
+ * [...].Type=doi
+ * [...].Service=Datacite
+ * [...].Pattern=10.1234/(.+)
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCROtherPIDNBURNGenerator.Factory.class)
+public class MCROtherPIDNBURNGenerator extends MCRDNBURNGeneratorBase {
+
+ public static final String TYPE_KEY = "Type";
+
+ public static final String SERVICE_KEY = "Service";
+
+ public static final String PATTERN_KEY = "Pattern";
+
+ public static final String NAMESPACE_KEY = "Namespace";
+
+ public static final String DELIMITER_KEY = "Delimiter";
+
+ private final MCROtherPIValueExtractor extractor;
+
+ public MCROtherPIDNBURNGenerator(String namespace, String delimiter, MCROtherPIValueExtractor extractor) {
+ super(namespace, delimiter);
+ this.extractor = Objects.requireNonNull(extractor, "Extractor must not be null");
+ }
+
+ @Override
+ protected String buildNISS(MCRBase base, String additional) {
+ return extractor.extractValue(base);
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = NAMESPACE_KEY)
+ public String namespace;
+
+ @MCRProperty(name = DELIMITER_KEY, required = false)
+ public String delimiter = "";
+
+ @MCRProperty(name = TYPE_KEY)
+ public String type;
+
+ @MCRProperty(name = SERVICE_KEY)
+ public String service;
+
+ @MCRProperty(name = PATTERN_KEY)
+ public String pattern;
+
+ @Override
+ public MCROtherPIDNBURNGenerator get() {
+ MCROtherPIValueExtractor extractor = new MCROtherPIValueExtractor(type, service, pattern);
+ return new MCROtherPIDNBURNGenerator(namespace, delimiter, extractor);
+ }
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDDNBURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDDNBURNGenerator.java
new file mode 100644
index 0000000000..f8ea12ef8e
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDDNBURNGenerator.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import java.util.UUID;
+import java.util.function.Supplier;
+
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIGenerator;
+
+/**
+ * {@link MCRUUIDDNBURNGenerator} is a {@link MCRPIGenerator} for {@link MCRDNBURN} identifiers
+ * that generates identifiers using a given namespace and a {@link UUID} as the NISS.
+ *
+ * The following configuration options are available:
+ *
+ * The property suffix {@link MCRUUIDDNBURNGenerator#NAMESPACE_KEY} can be used to
+ * specify the namespace.
+ * The property suffix {@link MCRUUIDDNBURNGenerator#DELIMITER_KEY} can be used to
+ * specify a delimiter to be placed before and after the NISS (optional, defaults to the empty string).
+ *
+ * Example:
+ *
+ * [...].Class=org.mycore.pi.urn.MCRUUIDDNBURNGenerator
+ * [...].Namespace=urn:nbn:de:gbv:xyz
+ * [...].Delimiter=-
+ *
+ */
+@MCRConfigurationProxy(proxyClass = MCRUUIDDNBURNGenerator.Factory.class)
+public class MCRUUIDDNBURNGenerator extends MCRDNBURNGeneratorBase {
+
+ public static final String NAMESPACE_KEY = "Namespace";
+
+ public static final String DELIMITER_KEY = "Delimiter";
+
+ public MCRUUIDDNBURNGenerator(String namespace, String delimiter) {
+ super(namespace, delimiter);
+ }
+
+ @Override
+ protected String buildNISS(MCRBase base, String additional) {
+ return UUID.randomUUID().toString();
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = NAMESPACE_KEY)
+ public String namespace;
+
+ @MCRProperty(name = DELIMITER_KEY, required = false)
+ public String delimiter = "";
+
+ @Override
+ public MCRUUIDDNBURNGenerator get() {
+ return new MCRUUIDDNBURNGenerator(namespace, delimiter);
+ }
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDURNGenerator.java b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDURNGenerator.java
index 12c45eef62..ce40223dcb 100644
--- a/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDURNGenerator.java
+++ b/mycore-pi/src/main/java/org/mycore/pi/urn/MCRUUIDURNGenerator.java
@@ -18,27 +18,35 @@
package org.mycore.pi.urn;
-import java.util.UUID;
+import java.util.function.Supplier;
-import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.common.config.annotation.MCRConfigurationProxy;
+import org.mycore.common.config.annotation.MCRProperty;
/**
- * Builds a new, unique NISS using Java implementation of the UUID
- * specification. java.util.UUID creates 'only' version 4 UUIDs.
- * Version 4 UUIDs are generated from a large random number and do
- * not include the MAC address.
- *
- * UUID = 8*HEX "-" 4*HEX "-" 4*HEX "-" 4*HEX "-" 12*HEX
- * Example One: 067e6162-3b6f-4ae2-a171-2470b63dff00
- * Example Two: 54947df8-0e9e-4471-a2f9-9af509fb5889
- *
- * @author Kathleen Neumann (kkrebs)
- * @author Sebastian Hofmann
+ * @deprecated Use {@link MCRUUIDDNBURNGenerator} instead.
*/
-public class MCRUUIDURNGenerator extends MCRDNBURNGenerator {
+@Deprecated(forRemoval = true)
+@MCRConfigurationProxy(proxyClass = MCRUUIDURNGenerator.Factory.class)
+public class MCRUUIDURNGenerator extends MCRUUIDDNBURNGenerator {
+
+ public MCRUUIDURNGenerator(String namespace, String delimiter) {
+ super(namespace, delimiter);
+ }
+
+ public static class Factory implements Supplier {
+
+ @MCRProperty(name = NAMESPACE_KEY)
+ public String namespace;
+
+ @MCRProperty(name = DELIMITER_KEY, required = false)
+ public String delimiter = "";
+
+ @Override
+ public MCRUUIDURNGenerator get() {
+ return new MCRUUIDURNGenerator(namespace, delimiter);
+ }
- @Override
- protected String buildNISS(MCRObjectID mcrID, String additional) {
- return UUID.randomUUID().toString();
}
+
}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/util/MCRFLDateScrambler.java b/mycore-pi/src/main/java/org/mycore/pi/util/MCRFLDateScrambler.java
new file mode 100644
index 0000000000..4604c698f1
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/util/MCRFLDateScrambler.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.util;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Utility class that provides a date scrambling algorithm introduced by F rank L ützenkirchen .
+ */
+public final class MCRFLDateScrambler {
+
+ private MCRFLDateScrambler() {
+ }
+
+ public static String scrambleDate(Date date) {
+
+ Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+01:00"), Locale.ENGLISH);
+ calendar.setTime(date);
+
+ int yyy = 2268 - calendar.get(Calendar.YEAR);
+ int ddd = 500 - calendar.get(Calendar.DAY_OF_YEAR);
+ int hh = calendar.get(Calendar.HOUR_OF_DAY);
+ int mm = calendar.get(Calendar.MINUTE);
+ int ss = calendar.get(Calendar.SECOND);
+ int sss = 99_999 - (hh * 3600 + mm * 60 + ss);
+ String ddddd = String.valueOf(yyy * 366 + ddd);
+
+ return String.valueOf(ddddd.charAt(4)) + ddddd.charAt(2)
+ + ddddd.charAt(1) + ddddd.charAt(3) + ddddd.charAt(0) + sss;
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/util/MCROtherPIValueExtractor.java b/mycore-pi/src/main/java/org/mycore/pi/util/MCROtherPIValueExtractor.java
new file mode 100644
index 0000000000..0bde929183
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/util/MCROtherPIValueExtractor.java
@@ -0,0 +1,89 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.util;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.mycore.common.MCRException;
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.pi.MCRPIService;
+import org.mycore.pi.MCRPIServiceManager;
+import org.mycore.pi.MCRPersistentIdentifier;
+import org.mycore.pi.backend.MCRPI;
+
+public final class MCROtherPIValueExtractor {
+
+ private final String type;
+
+ private final String service;
+
+ private final Pattern pattern;
+
+ public MCROtherPIValueExtractor(String type, String service, String pattern) {
+ this.type = Objects.requireNonNull(type);
+ this.service = Objects.requireNonNull(service);
+ this.pattern = checkPattern(Pattern.compile(Objects.requireNonNull(pattern)));
+ }
+
+ private static Pattern checkPattern(Pattern pattern) {
+
+ Matcher matcher = pattern.matcher("");
+
+ boolean hasExactlyOneCaptureGroup = matcher.groupCount() == 1;
+ if (!hasExactlyOneCaptureGroup) {
+ throw new IllegalArgumentException("Pattern doesn't have exactly one capture group: " + pattern.pattern());
+ }
+
+ return pattern;
+
+ }
+
+ public String extractValue(MCRBase base) {
+
+ MCRPIServiceManager serviceManager = MCRPIServiceManager.getInstance();
+ MCRPIService service = serviceManager.getRegistrationService(this.service);
+ List pis = MCRPIService.getFlags(base, "", service, this.type);
+
+ if (pis.isEmpty()) {
+ throw new MCRException("No identifier found " + base + ", type " + type + " and service " + service);
+ }
+
+ String identifier = pis.getFirst().getIdentifier();
+ Matcher matcher = pattern.matcher(identifier);
+
+ if (!matcher.find()) {
+ throw new MCRException("Identifier " + identifier + " found for " + base + ", type " + type
+ + " and service " + service + " doesn't match pattern " + pattern.pattern());
+ }
+
+ String value = matcher.group(1);
+
+ if (value.isEmpty()) {
+ throw new MCRException("Identifier " + identifier + " found for " + base + ", type " + type
+ + " and service " + service + " contains empty value for pattern " + pattern.pattern());
+ }
+
+ return value;
+
+ }
+
+}
diff --git a/mycore-pi/src/main/java/org/mycore/pi/util/MCRPIGeneratorUtils.java b/mycore-pi/src/main/java/org/mycore/pi/util/MCRPIGeneratorUtils.java
new file mode 100644
index 0000000000..1246d402fc
--- /dev/null
+++ b/mycore-pi/src/main/java/org/mycore/pi/util/MCRPIGeneratorUtils.java
@@ -0,0 +1,115 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.util;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.mycore.datamodel.metadata.MCRBase;
+import org.mycore.datamodel.metadata.MCRObjectService;
+import org.mycore.pi.MCRPIGenerator;
+import org.mycore.pi.MCRPIManager;
+import org.mycore.pi.MCRPIRegistrationInfo;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+
+/**
+ * Utility class providing functions commonly used by implementations of {@link MCRPIGenerator}.
+ */
+public final class MCRPIGeneratorUtils {
+
+ private MCRPIGeneratorUtils() {
+ }
+
+ public static AtomicInteger readCountFromDatabase(String type, String countPattern) {
+
+ Pattern pattern = Pattern.compile(countPattern);
+ Predicate matching = pattern.asPredicate();
+
+ List list = MCRPIManager.getInstance().getList(type, -1, -1);
+
+ // extract the number of the PI
+ Optional highestNumber = list.stream()
+ .map(MCRPIRegistrationInfo::getIdentifier)
+ .filter(matching)
+ .map(pi -> {
+ // extract the number of the PI
+ Matcher matcher = pattern.matcher(pi);
+ if (matcher.find() && matcher.groupCount() == 1) {
+ String group = matcher.group(1);
+ return Integer.parseInt(group, 10);
+ } else {
+ return null;
+ }
+ }).filter(Objects::nonNull)
+ .max(Comparator.naturalOrder())
+ .map(n -> n + 1);
+
+ return new AtomicInteger(highestNumber.orElse(0));
+
+ }
+
+ public static String getCountPattern(int countPrecision) {
+ String countPattern;
+ if (countPrecision == -1) {
+ countPattern = "([0-9]+)";
+ } else {
+ countPattern = "(" + "[0-9]".repeat(countPrecision) + ")";
+ }
+ return countPattern;
+ }
+
+ public static String formatCount(int count, int counterPrecision)
+ throws MCRPersistentIdentifierException {
+
+ if (counterPrecision == -1) {
+ return String.valueOf(count);
+ }
+
+ int actualLength = String.valueOf(Math.abs(count)).length();
+ if (actualLength > counterPrecision) {
+ throw new MCRPersistentIdentifierException(
+ "Count " + count + " (" + actualLength + " digits) exceeds counter precision of "
+ + counterPrecision + " digits.");
+ }
+
+ DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ROOT);
+ DecimalFormat decimalFormat = new DecimalFormat("0".repeat(counterPrecision), symbols);
+ return decimalFormat.format(count);
+
+ }
+
+ public static Date getCreateDate(MCRBase base) throws MCRPersistentIdentifierException {
+ Date createDate = base.getService().getDate(MCRObjectService.DATE_TYPE_CREATEDATE);
+ if (createDate == null) {
+ throw new MCRPersistentIdentifierException("Object " + base.getId() + " doesn't have a create date!");
+ }
+ return createDate;
+ }
+
+}
diff --git a/mycore-pi/src/main/resources/components/pi/config/mycore.properties b/mycore-pi/src/main/resources/components/pi/config/mycore.properties
index d5b190bb31..a8e0685a38 100644
--- a/mycore-pi/src/main/resources/components/pi/config/mycore.properties
+++ b/mycore-pi/src/main/resources/components/pi/config/mycore.properties
@@ -49,6 +49,7 @@ MCR.PI.Default.Service.LinkedUpdatedTriggerUpdate=true
# Generators
MCR.PI.Generator.UUIDDOI.Class=org.mycore.pi.doi.MCRUUIDDOIGenerator
+MCR.PI.Generator.DateDOI.Class=org.mycore.pi.doi.MCRCreateDateDOIGenerator
MCR.PI.Generator.MapObjectIDDOI.Class=org.mycore.pi.doi.MCRMapObjectIDDOIGenerator
#MCR.PI.Generator.IDPURLGenerator.Class=org.mycore.pi.purl.MCRIDPURLGenerator
#MCR.PI.Generator.IDPURLGenerator.BaseURLTemplate=http://purl.meineUrl.de/$ID
diff --git a/mycore-pi/src/test/java/org/mycore/pi/MCRGenericPIGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/MCRGenericPIGeneratorTest.java
index bc25d26db5..39c26b4b49 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/MCRGenericPIGeneratorTest.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/MCRGenericPIGeneratorTest.java
@@ -19,10 +19,15 @@
package org.mycore.pi;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mycore.pi.MCRGenericPIGenerator.DEFAULT_DATE_FORMAT;
+import static org.mycore.pi.MCRGenericPIGenerator.DEFAULT_DATE_LOCALE;
import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Locale;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
import org.jdom2.Element;
import org.junit.jupiter.api.Test;
@@ -31,7 +36,9 @@
import org.mycore.common.MCRTestProperty;
import org.mycore.datamodel.metadata.MCRObject;
import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.doi.MCRDigitalObjectIdentifier;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.pi.urn.MCRDNBURN;
import org.mycore.test.MCRJPAExtension;
import org.mycore.test.MCRMetadataExtension;
import org.mycore.test.MyCoReTest;
@@ -44,33 +51,74 @@
})
public class MCRGenericPIGeneratorTest {
- public static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR);
-
@Test
public void testGenerate() throws MCRPersistentIdentifierException {
- final MCRGenericPIGenerator generator = new MCRGenericPIGenerator(
- "urn:nbn:de:gbv:$CurrentDate-$1-$2-$ObjectType-$ObjectProject-$ObjectNumber-$Count-",
- new SimpleDateFormat("yyyy", Locale.ROOT), null, null, 3,
- "dnbUrn", "/mycoreobject/metadata/test1/test2/text()", "/mycoreobject/metadata/test1/test3/text()");
-
- //generator.init(MCRPIService.GENERATOR_CONFIG_PREFIX + "test1");
-
- MCRObjectID testID = MCRObjectID.getInstance("my_test_00000001");
- MCRObject mcrObject = new MCRObject();
- mcrObject.setSchema("test");
- mcrObject.setId(testID);
- final Element metadata = new Element("metadata");
- final Element testElement = new Element("test1");
- metadata.addContent(testElement);
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ Element testElement = new Element("test1");
testElement.setAttribute("class", "MCRMetaXML");
testElement.addContent(new Element("test2").setText("result1"));
testElement.addContent(new Element("test3").setText("result2"));
- mcrObject.getMetadata().setFromDOM(metadata);
- final String pi1 = generator.generate(mcrObject, "").asString();
- final String pi2 = generator.generate(mcrObject, "").asString();
- assertEquals("urn:nbn:de:gbv:" + CURRENT_YEAR + "-result1-result2-test-my-00000001-000-", pi1.substring(0, pi1.length() - 1));
- assertEquals("urn:nbn:de:gbv:" + CURRENT_YEAR + "-result1-result2-test-my-00000001-001-", pi2.substring(0, pi2.length() - 1));
+ Element metadata = new Element("metadata");
+ metadata.addContent(testElement);
+
+ object.getMetadata().setFromDOM(metadata);
+
+ MCRGenericPIGenerator generator = new MCRGenericPIGenerator(
+ "urn:nbn:de:gbv:xyz:$CurrentDate-$1-$2-$ObjectType-$ObjectProject-$ObjectNumber-$Count-",
+ DEFAULT_DATE_FORMAT,
+ Map.of("my", "MY"),
+ Map.of("test", "TEST"),
+ 3,
+ MCRDNBURN.TYPE,
+ List.of("/mycoreobject/metadata/test1/test2/text()", "/mycoreobject/metadata/test1/test3/text()"));
+
+ String pi = generator.generate(object, "").asString();
+
+ SimpleDateFormat dateFormatter = new SimpleDateFormat(DEFAULT_DATE_FORMAT, DEFAULT_DATE_LOCALE);
+ String currenDate = dateFormatter.format(new Date());
+
+ assertEquals("urn:nbn:de:gbv:xyz:" + currenDate + "-result1-result2-TEST-MY-00000123-000-",
+ pi.substring(0, pi.length() - 1));
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRGenericPIGenerator generator = new MCRGenericPIGenerator(
+ "10.1234/$ObjectType-$Count",
+ DEFAULT_DATE_FORMAT,
+ Map.of(),
+ Map.of(),
+ -1,
+ MCRDigitalObjectIdentifier.TYPE,
+ List.of());
+
+ String doi1 = generator.generate(object, "").asString();
+ String doi2 = generator.generate(object, "").asString();
+ String doi3 = generator.generate(object, "").asString();
+
+ assertNotEquals(doi1, doi2);
+ assertNotEquals(doi2, doi3);
+ assertNotEquals(doi3, doi1);
+
+ assertTrue(doi1.startsWith("10.1234/test-"));
+ assertTrue(doi2.startsWith("10.1234/test-"));
+ assertTrue(doi3.startsWith("10.1234/test-"));
+
+ assertTrue(doi1.endsWith("-0"));
+ assertTrue(doi2.endsWith("-1"));
+ assertTrue(doi3.endsWith("-2"));
+
}
}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierGenerator.java b/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierGenerator.java
index 256b597f52..3d39fd9c93 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierGenerator.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierGenerator.java
@@ -18,21 +18,15 @@
package org.mycore.pi;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
import org.mycore.datamodel.metadata.MCRBase;
-public class MCRMockIdentifierGenerator extends MCRPIGenerator {
-
- public static final String TEST_PROPERTY = "mockProperty";
-
- public static final String TEST_PROPERTY_VALUE = "mockPropertyValue";
+public class MCRMockIdentifierGenerator implements MCRPIGenerator {
@Override
- public MCRMockIdentifier generate(MCRBase mcrBase, String additional) {
- assertEquals(TEST_PROPERTY_VALUE, getProperties().get(TEST_PROPERTY), "Test properties should be set!");
-
- return (MCRMockIdentifier) new MCRMockIdentifierParser()
- .parse(MCRMockIdentifier.MOCK_SCHEME + mcrBase.getId() + ":" + additional).get();
+ public MCRMockIdentifier generate(MCRBase base, String additional) {
+ return new MCRMockIdentifierParser()
+ .parse(MCRMockIdentifier.MOCK_SCHEME + base.getId() + ":" + additional)
+ .get();
}
+
}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierParser.java b/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierParser.java
index 7dbe51a740..9c63fc752e 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierParser.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/MCRMockIdentifierParser.java
@@ -20,10 +20,10 @@
import java.util.Optional;
-public class MCRMockIdentifierParser implements MCRPIParser {
+public class MCRMockIdentifierParser implements MCRPIParser {
@Override
- public Optional parse(String identifier) {
+ public Optional parse(String identifier) {
if (!identifier.startsWith(MCRMockIdentifier.MOCK_SCHEME)) {
return Optional.empty();
}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/MCRPIManagerTest.java b/mycore-pi/src/test/java/org/mycore/pi/MCRPIManagerTest.java
index 49330fbdf6..0f33587af1 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/MCRPIManagerTest.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/MCRPIManagerTest.java
@@ -67,10 +67,6 @@
+ MCRMockMetadataService.TEST_PROPERTY, string = MCRMockMetadataService.TEST_PROPERTY_VALUE),
@MCRTestProperty(key = "MCR.PI.Generator." + MCRPIManagerTest.MOCK_PID_GENERATOR + ".Class",
classNameOf = MCRMockIdentifierGenerator.class),
- @MCRTestProperty(key = "MCR.PI.Generator." + MCRPIManagerTest.MOCK_PID_GENERATOR + "."
- + MCRMockIdentifierGenerator.TEST_PROPERTY, string = MCRMockIdentifierGenerator.TEST_PROPERTY_VALUE),
- @MCRTestProperty(key = "MCR.PI.Generator." + MCRPIManagerTest.MOCK_PID_GENERATOR + ".Namespace",
- string = "frontend-"),
@MCRTestProperty(key = "MCR.PI.Parsers." + MCRMockIdentifierService.TYPE,
classNameOf = MCRMockIdentifierParser.class),
@MCRTestProperty(key = "MCR.QueuedJob.activated", string = "true"),
diff --git a/mycore-pi/src/test/java/org/mycore/pi/MCRPIUtils.java b/mycore-pi/src/test/java/org/mycore/pi/MCRPIUtils.java
index 7985aaa60d..40399b76c8 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/MCRPIUtils.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/MCRPIUtils.java
@@ -30,8 +30,9 @@
import org.mycore.datamodel.metadata.MCRObject;
import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.pi.backend.MCRPI;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
import org.mycore.pi.urn.MCRDNBURN;
-import org.mycore.pi.urn.MCRUUIDURNGenerator;
+import org.mycore.pi.urn.MCRUUIDDNBURNGenerator;
import org.mycore.pi.urn.rest.MCRDNBURNRestClient;
import org.mycore.pi.urn.rest.MCRURNJsonBundle;
@@ -44,9 +45,10 @@ public class MCRPIUtils {
private static final Logger LOGGER = LogManager.getLogger();
- public static MCRPI generateMCRPI(String fileName, String serviceID) {
+ public static MCRPI generateMCRPI(String fileName, String serviceID, String namespace)
+ throws MCRPersistentIdentifierException {
MCRObjectID mycoreID = getNextFreeID();
- return new MCRPI(generateURNFor(mycoreID).asString(), MCRDNBURN.TYPE,
+ return new MCRPI(generateURNFor(mycoreID, namespace).asString(), MCRDNBURN.TYPE,
mycoreID.toString(), fileName, serviceID, null);
}
@@ -54,13 +56,12 @@ public static MCRObjectID getNextFreeID() {
return MCRMetadataManager.getMCRObjectIDGenerator().getNextFreeId("MyCoRe_test");
}
- private static MCRDNBURN generateURNFor(MCRObjectID mycoreID) {
- String testGenerator = "testGenerator";
- MCRUUIDURNGenerator mcruuidurnGenerator = new MCRUUIDURNGenerator();
- mcruuidurnGenerator.init(MCRPIService.GENERATOR_CONFIG_PREFIX + testGenerator);
+ private static MCRDNBURN generateURNFor(MCRObjectID mycoreID, String namespace)
+ throws MCRPersistentIdentifierException {
+ MCRUUIDDNBURNGenerator generator = new MCRUUIDDNBURNGenerator(namespace, "");
MCRObject mcrObject1 = new MCRObject();
mcrObject1.setId(mycoreID);
- return mcruuidurnGenerator.generate(mcrObject1, "");
+ return generator.generate(mcrObject1, "");
}
public static String randomFilename() {
diff --git a/mycore-pi/src/test/java/org/mycore/pi/doi/MCRCreateDateDOIGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRCreateDateDOIGeneratorTest.java
new file mode 100644
index 0000000000..fa5f55dd45
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRCreateDateDOIGeneratorTest.java
@@ -0,0 +1,102 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.doi;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.common.MCRISO8601Date;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.test.MCRJPAExtension;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@ExtendWith({ MCRJPAExtension.class })
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+})
+public class MCRCreateDateDOIGeneratorTest {
+
+ public static final String DATE_FORMAT = "yyyyMMdd";
+
+ public static final String PREFIX = "10.1234";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCreateDateDOIGenerator generator = new MCRCreateDateDOIGenerator(new MCRDOIParser(), DATE_FORMAT, PREFIX, 3);
+ String doi = generator.generate(object, "").asString();
+
+ assertTrue(doi.startsWith(PREFIX));
+ assertEquals('/', doi.charAt(PREFIX.length()));
+
+ String value = doi.substring(PREFIX.length() + 1);
+
+ assertTrue(value.startsWith(formatDate(new Date()) + "-"));
+ assertTrue(value.endsWith("-000"));
+
+ }
+
+ private String formatDate(Date date) {
+
+ MCRISO8601Date isoDate = new MCRISO8601Date();
+ isoDate.setDate(date);
+
+ return isoDate.format(DATE_FORMAT, Locale.ROOT);
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCreateDateDOIGenerator generator =
+ new MCRCreateDateDOIGenerator(new MCRDOIParser(), DATE_FORMAT, PREFIX, -1);
+ String doi1 = generator.generate(object, "").asString();
+ String doi2 = generator.generate(object, "").asString();
+ String doi3 = generator.generate(object, "").asString();
+
+ assertNotEquals(doi1, doi2);
+ assertNotEquals(doi2, doi3);
+ assertNotEquals(doi3, doi1);
+
+ assertTrue(doi1.endsWith("-0"));
+ assertTrue(doi2.endsWith("-1"));
+ assertTrue(doi3.endsWith("-2"));
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/doi/MCRCurrentDateDOIGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRCurrentDateDOIGeneratorTest.java
new file mode 100644
index 0000000000..8524b935ee
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRCurrentDateDOIGeneratorTest.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.doi;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.mycore.access.MCRAccessBaseImpl;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Access.Class", classNameOf = MCRAccessBaseImpl.class),
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+})
+public class MCRCurrentDateDOIGeneratorTest {
+
+ public static final String PREFIX = "10.1234";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCurrentDateDOIGenerator generator = new MCRCurrentDateDOIGenerator(new MCRDOIParser(), PREFIX);
+ String doi = generator.generate(object, "").asString();
+
+ assertTrue(doi.startsWith(PREFIX));
+ assertEquals('/', doi.charAt(PREFIX.length()));
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCurrentDateDOIGenerator generator = new MCRCurrentDateDOIGenerator(new MCRDOIParser(), PREFIX);
+ String doi1 = generator.generate(object, "").asString();
+ String doi2 = generator.generate(object, "").asString();
+ String doi3 = generator.generate(object, "").asString();
+
+ assertNotEquals(doi1, doi2);
+ assertNotEquals(doi2, doi3);
+ assertNotEquals(doi3, doi1);
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/doi/MCRMapObjectIDDOIGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRMapObjectIDDOIGeneratorTest.java
index 08c42765df..ba3ef98c43 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/doi/MCRMapObjectIDDOIGeneratorTest.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRMapObjectIDDOIGeneratorTest.java
@@ -20,60 +20,77 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mycore.pi.doi.MCRDigitalObjectIdentifier.TEST_DOI_PREFIX;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Map;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mycore.common.MCRTestConfiguration;
import org.mycore.common.MCRTestProperty;
-import org.mycore.common.config.MCRConfiguration2;
import org.mycore.datamodel.metadata.MCRObject;
import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
import org.mycore.test.MyCoReTest;
-/**
- * @author Thomas Scheffler (yagee)
- */
@MyCoReTest
@MCRTestConfiguration(properties = {
@MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
- @MCRTestProperty(key = "MCR.PI.Generator.MapObjectIDDOI.Class", classNameOf = MCRMapObjectIDDOIGenerator.class),
- @MCRTestProperty(key = "MCR.PI.Generator.MapObjectIDDOI.Prefix.junit_test", string = TEST_DOI_PREFIX),
- @MCRTestProperty(key = "MCR.PI.Generator.MapObjectIDDOI.Prefix.my_test", string = TEST_DOI_PREFIX + "/my.")
})
public class MCRMapObjectIDDOIGeneratorTest {
- MCRMapObjectIDDOIGenerator doiGenerator;
+ public static final String PREFIX = "10.1234";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ Map prefixMap = Map.of("my_test", PREFIX);
+ MCRMapObjectIDDOIGenerator generator = new MCRMapObjectIDDOIGenerator(new MCRDOIParser(), prefixMap);
+ String doi = generator.generate(object, "").asString();
+
+ assertTrue(doi.startsWith(PREFIX));
+ assertEquals('/', doi.charAt(PREFIX.length()));
+
+ String value = doi.substring(PREFIX.length() + 1);
+
+ assertEquals("123", value);
- @BeforeEach
- public void setUp() {
- doiGenerator = MCRConfiguration2.getInstanceOfOrThrow(
- MCRMapObjectIDDOIGenerator.class, "MCR.PI.Generator.MapObjectIDDOI");
}
@Test
- public void generate() throws Exception {
- MCRObjectID testID1 = MCRObjectID.getInstance("junit_test_00004711");
- MCRObject mcrObject1 = new MCRObject();
- mcrObject1.setId(testID1);
- MCRObjectID testID2 = MCRObjectID.getInstance("my_test_00000815");
- MCRObject mcrObject2 = new MCRObject();
- mcrObject2.setId(testID2);
- assertEquals(TEST_DOI_PREFIX + "/4711", doiGenerator.generate(mcrObject1, null).asString());
- assertEquals(TEST_DOI_PREFIX + "/my.815", doiGenerator.generate(mcrObject2, null).asString());
+ public void generateWithInfix() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ Map prefixMap = Map.of("my_test", PREFIX + "/xyz-");
+ MCRMapObjectIDDOIGenerator generator = new MCRMapObjectIDDOIGenerator(new MCRDOIParser(), prefixMap);
+ String doi = generator.generate(object, "").asString();
+
+ assertTrue(doi.startsWith(PREFIX));
+ assertEquals('/', doi.charAt(PREFIX.length()));
+
+ String value = doi.substring(PREFIX.length() + 1);
+
+ assertEquals("xyz-123", value);
+
}
@Test
- public void missingMappingTest() {
- assertThrows(
- MCRPersistentIdentifierException.class,
- () -> {
- MCRObjectID testID = MCRObjectID.getInstance("brandNew_test_00000001");
- MCRObject mcrObject = new MCRObject();
- mcrObject.setId(testID);
- doiGenerator.generate(mcrObject, null);
- });
+ public void missingMapping() {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ Map prefixMap = Map.of();
+ MCRMapObjectIDDOIGenerator generator = new MCRMapObjectIDDOIGenerator(new MCRDOIParser(), prefixMap);
+
+ assertThrows(MCRPersistentIdentifierException.class, () -> generator.generate(object, ""));
}
}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/doi/MCROtherPIDOIGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/doi/MCROtherPIDOIGeneratorTest.java
new file mode 100644
index 0000000000..f6c6205015
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/doi/MCROtherPIDOIGeneratorTest.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.doi;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mycore.pi.MCRMockMetadataService.TEST_PROPERTY;
+import static org.mycore.pi.MCRMockMetadataService.TEST_PROPERTY_VALUE;
+
+import java.util.concurrent.ExecutionException;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mycore.access.MCRAccessBaseImpl;
+import org.mycore.access.MCRAccessException;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.MCRMockIdentifierGenerator;
+import org.mycore.pi.MCRMockIdentifierService;
+import org.mycore.pi.MCRMockMetadataService;
+import org.mycore.pi.MCRPIService;
+import org.mycore.pi.MCRPIServiceManager;
+import org.mycore.pi.MCRPersistentIdentifier;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.pi.util.MCROtherPIValueExtractor;
+import org.mycore.test.MCRJPAExtension;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@ExtendWith({ MCRJPAExtension.class })
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Access.Class", classNameOf = MCRAccessBaseImpl.class),
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+ @MCRTestProperty(key = "MCR.PI.Service.Mock.Class", classNameOf = MCRMockIdentifierService.class),
+ @MCRTestProperty(key = "MCR.PI.Service.Mock.Generator", string = "Mock"),
+ @MCRTestProperty(key = "MCR.PI.Service.Mock.MetadataService", string = "Mock"),
+ @MCRTestProperty(key = "MCR.PI.Generator.Mock.Class", classNameOf = MCRMockIdentifierGenerator.class),
+ @MCRTestProperty(key = "MCR.PI.MetadataService.Mock.Class", classNameOf = MCRMockMetadataService.class),
+ @MCRTestProperty(key = "MCR.PI.MetadataService.Mock." + TEST_PROPERTY, string = TEST_PROPERTY_VALUE),
+})
+public class MCROtherPIDOIGeneratorTest {
+
+ public static final String PREFIX = "10.1234";
+
+ @Test
+ public void generate()
+ throws MCRPersistentIdentifierException, MCRAccessException, ExecutionException, InterruptedException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRPIServiceManager manager = MCRPIServiceManager.getInstance();
+ MCRPIService mockService = manager.getRegistrationService("Mock");
+ mockService.register(object, "", true);
+
+ MCROtherPIValueExtractor extractor = new MCROtherPIValueExtractor("mock", "Mock", "MOCK:my_test_(.*):");
+ MCROtherPIDOIGenerator generator = new MCROtherPIDOIGenerator(new MCRDOIParser(), PREFIX, extractor);
+ String doi = generator.generate(object, "").asString();
+
+ assertTrue(doi.startsWith(PREFIX));
+ assertEquals('/', doi.charAt(PREFIX.length()));
+
+ String value = doi.substring(PREFIX.length() + 1);
+
+ assertEquals("00000123", value);
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/doi/MCRUUIDDOIGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRUUIDDOIGeneratorTest.java
new file mode 100644
index 0000000000..7b08673b82
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/doi/MCRUUIDDOIGeneratorTest.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.doi;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.UUID;
+
+import org.junit.jupiter.api.Test;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+})
+public class MCRUUIDDOIGeneratorTest {
+
+ public static final String PREFIX = "10.1234";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRUUIDDOIGenerator generator = new MCRUUIDDOIGenerator(new MCRDOIParser(), PREFIX);
+ String doi = generator.generate(object, "").asString();
+
+ assertTrue(doi.startsWith(PREFIX));
+ assertEquals('/', doi.charAt(PREFIX.length()));
+
+ String uuid = doi.substring(PREFIX.length() + 1);
+
+ try {
+ UUID.fromString(uuid);
+ } catch (Exception e) {
+ fail("NISS is not a valid UUID", e);
+ }
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRUUIDDOIGenerator generator = new MCRUUIDDOIGenerator(new MCRDOIParser(), PREFIX);
+ String doi1 = generator.generate(object, "").asString();
+ String doi2 = generator.generate(object, "").asString();
+ String doi3 = generator.generate(object, "").asString();
+
+ assertNotEquals(doi1, doi2);
+ assertNotEquals(doi2, doi3);
+ assertNotEquals(doi3, doi1);
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/purl/MCRIDPURLGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/purl/MCRIDPURLGeneratorTest.java
index de7d93be54..8e508a4410 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/purl/MCRIDPURLGeneratorTest.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/purl/MCRIDPURLGeneratorTest.java
@@ -19,12 +19,10 @@
package org.mycore.pi.purl;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mycore.pi.MCRPIService.GENERATOR_CONFIG_PREFIX;
import org.junit.jupiter.api.Test;
import org.mycore.common.MCRTestConfiguration;
import org.mycore.common.MCRTestProperty;
-import org.mycore.common.config.MCRConfiguration2;
import org.mycore.datamodel.metadata.MCRObject;
import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
@@ -33,40 +31,34 @@
@MyCoReTest
@MCRTestConfiguration(properties = {
@MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
- @MCRTestProperty(key = GENERATOR_CONFIG_PREFIX + MCRIDPURLGeneratorTest.GENERATOR_1 + ".Class",
- classNameOf = MCRIDPURLGenerator.class),
- @MCRTestProperty(key = GENERATOR_CONFIG_PREFIX + MCRIDPURLGeneratorTest.GENERATOR_1 + ".BaseURLTemplate",
- string = MCRIDPURLGeneratorTest.TEST_BASE_1),
- @MCRTestProperty(key = GENERATOR_CONFIG_PREFIX + MCRIDPURLGeneratorTest.GENERATOR_2 + ".Class",
- classNameOf = MCRIDPURLGenerator.class),
- @MCRTestProperty(key = GENERATOR_CONFIG_PREFIX + MCRIDPURLGeneratorTest.GENERATOR_2 + ".BaseURLTemplate",
- string = MCRIDPURLGeneratorTest.TEST_BASE_2)
})
public class MCRIDPURLGeneratorTest {
- public static final String TEST_BASE_1 = "http://purl.myurl.de/$ID";
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
- public static final String TEST_BASE_2 = "http://purl.myurl.de/$ID/$ID/$ID";
+ MCRIDPURLGenerator generator = new MCRIDPURLGenerator("https://purl.example.com/$ID");
+ String purl = generator.generate(object, "").asString();
- public static final String GENERATOR_1 = "IDPURLGenerator";
+ assertEquals("https://purl.example.com/my_test_00000123", purl, "");
- public static final String GENERATOR_2 = GENERATOR_1 + "2";
+ }
@Test
- public void generate() throws MCRPersistentIdentifierException {
- MCRObjectID testID = MCRObjectID.getInstance("my_test_00000001");
- MCRObject mcrObject = new MCRObject();
- mcrObject.setId(testID);
+ public void generateWithMultipleReplacements() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
- MCRIDPURLGenerator generator1 = MCRConfiguration2.getInstanceOfOrThrow(
- MCRIDPURLGenerator.class, GENERATOR_CONFIG_PREFIX + GENERATOR_1);
- assertEquals("http://purl.myurl.de/my_test_00000001",
- generator1.generate(mcrObject, "").asString(), "");
+ MCRIDPURLGenerator generator = new MCRIDPURLGenerator("https://purl.example.com/$ID/$ID/XYZ");
+ String purl = generator.generate(object, "").asString();
- MCRIDPURLGenerator generator2 = MCRConfiguration2.getInstanceOfOrThrow(
- MCRIDPURLGenerator.class, GENERATOR_CONFIG_PREFIX + GENERATOR_2);
- assertEquals("http://purl.myurl.de/my_test_00000001/my_test_00000001/my_test_00000001",
- generator2.generate(mcrObject, "").asString(), "");
+ assertEquals("https://purl.example.com/my_test_00000123/my_test_00000123/XYZ", purl, "");
}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/MCRCreateDateDNBURNGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRCreateDateDNBURNGeneratorTest.java
new file mode 100644
index 0000000000..7078ccba56
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRCreateDateDNBURNGeneratorTest.java
@@ -0,0 +1,104 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.common.MCRISO8601Date;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.test.MCRJPAExtension;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@ExtendWith({ MCRJPAExtension.class })
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+})
+public class MCRCreateDateDNBURNGeneratorTest {
+
+ public static final String DATE_FORMAT = "yyyyMMdd";
+
+ public static final String NAMESPACE = "urn:nbn:de:gbv:xyz";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCreateDateDNBURNGenerator generator = new MCRCreateDateDNBURNGenerator(DATE_FORMAT, NAMESPACE, "-", 3);
+ String urn = generator.generate(object, "").asString();
+
+ assertTrue(urn.startsWith(NAMESPACE));
+ assertEquals('-', urn.charAt(NAMESPACE.length()));
+ assertEquals('-', urn.charAt(urn.length() - 2));
+
+ String value = urn.substring(NAMESPACE.length() + 1, urn.length() - 2);
+ char checksum = Character.forDigit(new MCRDNBURN("gbv:xyz", "-" + value + "-").calculateChecksum(), 10);
+
+ assertTrue(value.startsWith(formatDate(new Date()) + "-"));
+ assertTrue(value.endsWith("-000"));
+ assertEquals(checksum, urn.charAt(urn.length() - 1));
+
+ }
+
+ private String formatDate(Date date) {
+
+ MCRISO8601Date isoDate = new MCRISO8601Date();
+ isoDate.setDate(date);
+
+ return isoDate.format(DATE_FORMAT, Locale.ROOT);
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCreateDateDNBURNGenerator generator = new MCRCreateDateDNBURNGenerator(DATE_FORMAT, NAMESPACE, "", -1);
+ String urn1 = generator.generate(object, "").asString();
+ String urn2 = generator.generate(object, "").asString();
+ String urn3 = generator.generate(object, "").asString();
+
+ assertNotEquals(urn1, urn2);
+ assertNotEquals(urn2, urn3);
+ assertNotEquals(urn3, urn1);
+
+ assertTrue(urn1.substring(0, urn1.length() - 1).endsWith("-0"));
+ assertTrue(urn2.substring(0, urn2.length() - 1).endsWith("-1"));
+ assertTrue(urn3.substring(0, urn3.length() - 1).endsWith("-2"));
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/MCRCurrentDateDNBURNGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRCurrentDateDNBURNGeneratorTest.java
new file mode 100644
index 0000000000..1033560c11
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRCurrentDateDNBURNGeneratorTest.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.mycore.access.MCRAccessBaseImpl;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Access.Class", classNameOf = MCRAccessBaseImpl.class),
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+})
+public class MCRCurrentDateDNBURNGeneratorTest {
+
+ public static final String NAMESPACE = "urn:nbn:de:gbv:xyz";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCurrentDateDNBURNGenerator generator = new MCRCurrentDateDNBURNGenerator(NAMESPACE, "-");
+ String urn = generator.generate(object, "").asString();
+
+ assertTrue(urn.startsWith(NAMESPACE));
+ assertEquals('-', urn.charAt(NAMESPACE.length()));
+ assertEquals('-', urn.charAt(urn.length() - 2));
+
+ String value = urn.substring(NAMESPACE.length() + 1, urn.length() - 2);
+ char checksum = Character.forDigit(new MCRDNBURN("gbv:xyz", "-" + value + "-").calculateChecksum(), 10);
+
+ assertEquals(checksum, urn.charAt(urn.length() - 1));
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRCurrentDateDNBURNGenerator generator = new MCRCurrentDateDNBURNGenerator(NAMESPACE, "-");
+ String urn1 = generator.generate(object, "").asString();
+ String urn2 = generator.generate(object, "").asString();
+ String urn3 = generator.generate(object, "").asString();
+
+ assertNotEquals(urn1, urn2);
+ assertNotEquals(urn2, urn3);
+ assertNotEquals(urn3, urn1);
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/MCRDNBURNGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRDNBURNGeneratorTest.java
deleted file mode 100644
index c4538ad9bf..0000000000
--- a/mycore-pi/src/test/java/org/mycore/pi/urn/MCRDNBURNGeneratorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * This file is part of *** M y C o R e ***
- * See https://www.mycore.de/ for details.
- *
- * MyCoRe is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * MyCoRe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MyCoRe. If not, see .
- */
-
-package org.mycore.pi.urn;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mycore.access.MCRAccessBaseImpl;
-import org.mycore.common.MCRTestConfiguration;
-import org.mycore.common.MCRTestProperty;
-import org.mycore.common.config.MCRConfiguration2;
-import org.mycore.datamodel.metadata.MCRMetadataManager;
-import org.mycore.datamodel.metadata.MCRObject;
-import org.mycore.datamodel.metadata.MCRObjectID;
-import org.mycore.test.MCRJPAExtension;
-import org.mycore.test.MCRMetadataExtension;
-import org.mycore.test.MyCoReTest;
-
-@MyCoReTest
-@ExtendWith(MCRJPAExtension.class)
-@ExtendWith(MCRMetadataExtension.class)
-@MCRTestConfiguration(properties = {
- @MCRTestProperty(key = "MCR.Access.Class", classNameOf = MCRAccessBaseImpl.class),
- @MCRTestProperty(key = "MCR.Metadata.Type.mock", string = "true"),
- @MCRTestProperty(key = "MCR.Metadata.Type.unregisterd", string = "true"),
- @MCRTestProperty(key = "MCR.PI.Generator." + MCRDNBURNGeneratorTest.GENERATOR_ID + ".Class",
- classNameOf = MCRFLURNGenerator.class),
- @MCRTestProperty(key = "MCR.PI.Generator." + MCRDNBURNGeneratorTest.GENERATOR_ID + ".Namespace",
- string = "urn:nbn:de:gbv")
-})
-public class MCRDNBURNGeneratorTest {
-
- public static final String GENERATOR_ID = "TESTDNBURN1";
-
- private static final Logger LOGGER = LogManager.getLogger();
-
- @Test
- public void generate() {
- MCRObjectID getID = MCRMetadataManager.getMCRObjectIDGenerator().getNextFreeId("test", "mock");
- MCRObject mcrObject1 = new MCRObject();
- mcrObject1.setId(getID);
- MCRFLURNGenerator flGenerator = MCRConfiguration2.getInstanceOfOrThrow(
- MCRFLURNGenerator.class, "MCR.PI.Generator." + GENERATOR_ID);
- MCRDNBURN generated = flGenerator.generate(mcrObject1, "");
-
- String urn = generated.asString();
- LOGGER.info("THE URN IS: {}", urn);
-
- assertFalse(urn.startsWith("urn:nbn:de:urn:nbn:de"));
- }
-
-}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/MCROtherPIDNBURNGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/MCROtherPIDNBURNGeneratorTest.java
new file mode 100644
index 0000000000..d6c211184c
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/urn/MCROtherPIDNBURNGeneratorTest.java
@@ -0,0 +1,91 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mycore.pi.MCRMockMetadataService.TEST_PROPERTY;
+import static org.mycore.pi.MCRMockMetadataService.TEST_PROPERTY_VALUE;
+
+import java.util.concurrent.ExecutionException;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mycore.access.MCRAccessBaseImpl;
+import org.mycore.access.MCRAccessException;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.MCRMockIdentifierGenerator;
+import org.mycore.pi.MCRMockIdentifierService;
+import org.mycore.pi.MCRMockMetadataService;
+import org.mycore.pi.MCRPIService;
+import org.mycore.pi.MCRPIServiceManager;
+import org.mycore.pi.MCRPersistentIdentifier;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.pi.util.MCROtherPIValueExtractor;
+import org.mycore.test.MCRJPAExtension;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@ExtendWith({ MCRJPAExtension.class })
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Access.Class", classNameOf = MCRAccessBaseImpl.class),
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+ @MCRTestProperty(key = "MCR.PI.Service.Mock.Class", classNameOf = MCRMockIdentifierService.class),
+ @MCRTestProperty(key = "MCR.PI.Service.Mock.Generator", string = "Mock"),
+ @MCRTestProperty(key = "MCR.PI.Service.Mock.MetadataService", string = "Mock"),
+ @MCRTestProperty(key = "MCR.PI.Generator.Mock.Class", classNameOf = MCRMockIdentifierGenerator.class),
+ @MCRTestProperty(key = "MCR.PI.MetadataService.Mock.Class", classNameOf = MCRMockMetadataService.class),
+ @MCRTestProperty(key = "MCR.PI.MetadataService.Mock." + TEST_PROPERTY, string = TEST_PROPERTY_VALUE),
+})
+public class MCROtherPIDNBURNGeneratorTest {
+
+ public static final String NAMESPACE = "urn:nbn:de:gbv:xyz";
+
+ @Test
+ public void generate()
+ throws MCRPersistentIdentifierException, MCRAccessException, ExecutionException, InterruptedException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRPIServiceManager manager = MCRPIServiceManager.getInstance();
+ MCRPIService mockService = manager.getRegistrationService("Mock");
+ mockService.register(object, "", true);
+
+ MCROtherPIValueExtractor extractor = new MCROtherPIValueExtractor("mock", "Mock", "MOCK:my_test_(.*):");
+ MCROtherPIDNBURNGenerator generator = new MCROtherPIDNBURNGenerator(NAMESPACE, "-", extractor);
+ String urn = generator.generate(object, "").asString();
+
+ assertTrue(urn.startsWith(NAMESPACE));
+ assertEquals('-', urn.charAt(NAMESPACE.length()));
+ assertEquals('-', urn.charAt(urn.length() - 2));
+
+ String value = urn.substring(NAMESPACE.length() + 1, urn.length() - 2);
+ char checksum = Character.forDigit(new MCRDNBURN("gbv:xyz", "-" + value + "-").calculateChecksum(), 10);
+
+ assertEquals("00000123", value);
+ assertEquals(checksum, urn.charAt(urn.length() - 1));
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/MCRUUIDDNBURNGeneratorTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRUUIDDNBURNGeneratorTest.java
new file mode 100644
index 0000000000..673fdc0eac
--- /dev/null
+++ b/mycore-pi/src/test/java/org/mycore/pi/urn/MCRUUIDDNBURNGeneratorTest.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of *** M y C o R e ***
+ * See https://www.mycore.de/ for details.
+ *
+ * MyCoRe is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MyCoRe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MyCoRe. If not, see .
+ */
+
+package org.mycore.pi.urn;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.UUID;
+
+import org.junit.jupiter.api.Test;
+import org.mycore.common.MCRTestConfiguration;
+import org.mycore.common.MCRTestProperty;
+import org.mycore.datamodel.metadata.MCRObject;
+import org.mycore.datamodel.metadata.MCRObjectID;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
+import org.mycore.test.MyCoReTest;
+
+@MyCoReTest
+@MCRTestConfiguration(properties = {
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
+})
+public class MCRUUIDDNBURNGeneratorTest {
+
+ public static final String NAMESPACE = "urn:nbn:de:gbv:xyz";
+
+ @Test
+ public void generate() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRUUIDDNBURNGenerator generator = new MCRUUIDDNBURNGenerator(NAMESPACE, "-");
+ String urn = generator.generate(object, "").asString();
+
+ assertTrue(urn.startsWith(NAMESPACE));
+ assertEquals('-', urn.charAt(NAMESPACE.length()));
+ assertEquals('-', urn.charAt(urn.length() - 2));
+
+ String uuid = urn.substring(NAMESPACE.length() + 1, urn.length() - 2);
+ char checksum = Character.forDigit(new MCRDNBURN("gbv:xyz", "-" + uuid + "-").calculateChecksum(), 10);
+
+ try {
+ UUID.fromString(uuid);
+ } catch (Exception e) {
+ fail("NISS is not a valid UUID", e);
+ }
+ assertEquals(checksum, urn.charAt(urn.length() - 1));
+
+ }
+
+ @Test
+ public void generateMultiple() throws MCRPersistentIdentifierException {
+
+ MCRObject object = new MCRObject();
+ object.setSchema("http://www.w3.org/2001/XMLSchema");
+ object.setId(MCRObjectID.getInstance("my_test_00000123"));
+
+ MCRUUIDDNBURNGenerator generator = new MCRUUIDDNBURNGenerator(NAMESPACE, "-");
+ String urn1 = generator.generate(object, "").asString();
+ String urn2 = generator.generate(object, "").asString();
+ String urn3 = generator.generate(object, "").asString();
+
+ assertNotEquals(urn1, urn2);
+ assertNotEquals(urn2, urn3);
+ assertNotEquals(urn3, urn1);
+
+ }
+
+}
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTRegistrationTaskTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTRegistrationTaskTest.java
index 963fe68a21..9ef7b55783 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTRegistrationTaskTest.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTRegistrationTaskTest.java
@@ -38,6 +38,7 @@
import org.mycore.pi.MCRPIRegistrationInfo;
import org.mycore.pi.MCRPIUtils;
import org.mycore.pi.backend.MCRPI;
+import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
import org.mycore.pi.urn.MCRDNBURN;
import org.mycore.test.MCRMetadataExtension;
import org.mycore.test.MyCoReTest;
@@ -50,8 +51,7 @@
@MyCoReTest
@ExtendWith(MCRMetadataExtension.class)
@MCRTestConfiguration(properties = {
- @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true"),
- @MCRTestProperty(key = "MCR.PI.Generator.testGenerator.Namespace", string = "frontend-")
+ @MCRTestProperty(key = "MCR.Metadata.Type.test", string = "true")
})
public class MCRURNGranularRESTRegistrationTaskTest {
private static final String countRegistered = "select count(u) from MCRPI u "
@@ -64,10 +64,9 @@ public class MCRURNGranularRESTRegistrationTaskTest {
@Disabled
@Test
- public void run() {
- MCRPI urn1 = generateMCRPI(randomFilename(), countRegistered);
- MCREntityManagerProvider.getCurrentEntityManager()
- .persist(urn1);
+ public void run() throws MCRPersistentIdentifierException {
+ MCRPI urn1 = generateMCRPI(randomFilename(), countRegistered, "frontend-");
+ MCREntityManagerProvider.getCurrentEntityManager().persist(urn1);
assertNull(urn1.getRegistered(), "Registered date should be null.");
diff --git a/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTServiceTest.java b/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTServiceTest.java
index 7df0fd9942..b4f2f68eab 100644
--- a/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTServiceTest.java
+++ b/mycore-pi/src/test/java/org/mycore/pi/urn/rest/MCRURNGranularRESTServiceTest.java
@@ -58,7 +58,7 @@
import org.mycore.datamodel.niofs.MCRPath;
import org.mycore.pi.MCRPIRegistrationInfo;
import org.mycore.pi.urn.MCRDNBURN;
-import org.mycore.pi.urn.MCRUUIDURNGenerator;
+import org.mycore.pi.urn.MCRUUIDDNBURNGenerator;
import org.mycore.test.MCRJPAExtension;
import org.mycore.test.MCRMetadataExtension;
import org.mycore.test.MyCoReTest;
@@ -82,7 +82,7 @@
@MCRTestProperty(key = "MCR.IFS2.Store.mycore_derivate.SlotLayout", string = "4-2-2"),
@MCRTestProperty(key = "MCR.EventHandler.MCRDerivate.020.Class", classNameOf = MCRXMLMetadataEventHandler.class),
@MCRTestProperty(key = "MCR.EventHandler.MCRDerivate.030.Class", classNameOf = MCRLinkTableEventHandler.class),
- @MCRTestProperty(key = "MCR.PI.Generator.UUID.Class", classNameOf = MCRUUIDURNGenerator.class),
+ @MCRTestProperty(key = "MCR.PI.Generator.UUID.Class", classNameOf = MCRUUIDDNBURNGenerator.class),
@MCRTestProperty(key = "MCR.PI.Generator.UUID.Namespace", string = "frontend-"),
@MCRTestProperty(key = "MCR.PI.DNB.Credentials.Login", string = "test"),
@MCRTestProperty(key = "MCR.PI.DNB.Credentials.Password", string = "test")