diff --git a/pom.xml b/pom.xml index cdf7caac..3c26b34d 100644 --- a/pom.xml +++ b/pom.xml @@ -303,6 +303,7 @@ ${basedir}/ramls/settings/organization_collection.json ${basedir}/ramls/settings/subjectSources.json ${basedir}/ramls/settings/subjectTypes.json + ${basedir}/ramls/settings/instanceDateTypes.json ${basedir}/ramls/settings/acquisitions_unit.json ${basedir}/ramls/settings/acquisitions_unit_collection.json ${basedir}/ramls/settings/acquisition_method.json diff --git a/ramls/instance.json b/ramls/instance.json index 3826dc7d..7d8e4e19 100644 --- a/ramls/instance.json +++ b/ramls/instance.json @@ -310,6 +310,11 @@ "type": "object", "description": "Instance Dates", "properties": { + "dateTypeId": { + "type": "string", + "description": "Date type ID", + "$ref": "raml-storage/raml-util/schemas/uuid.schema" + }, "date1": { "type": "string", "description": "Date 1", diff --git a/ramls/settings/instanceDateType.json b/ramls/settings/instanceDateType.json new file mode 100644 index 00000000..22881f4e --- /dev/null +++ b/ramls/settings/instanceDateType.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "An instance date type that indicates the type of dates given in Date 1 and Date 2", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique ID of the instance date type; a UUID", + "readonly": true + }, + "name": { + "type": "string", + "description": "Name of the instance date type", + "readonly": true + }, + "code": { + "type": "string", + "description": "Code of the instance date type", + "maxLength": 1, + "readonly": true + }, + "displayFormat": { + "type": "object", + "description": "Describes how to format Date 1 and Date 2", + "properties": { + "delimiter": { + "type": "string", + "description": "Delimiter that will be used to format Date 1 and Date 2", + "example": ",", + "readonly": true + }, + "keepDelimiter": { + "type": "boolean", + "description": "Define if formated date string should keep delimiter if one of dates is not exist", + "example": false, + "readonly": true + } + }, + "readonly": true, + "additionalProperties": false + }, + "source": { + "type": "string", + "description": "label indicating where the instance date type entry originates from, i.e. 'folio' or 'local'", + "enum": [ + "folio", + "local" + ], + "readonly": true + }, + "metadata": { + "type": "object", + "$ref": "../raml-storage/raml-util/schemas/metadata.schema", + "readonly": true + } + }, + "additionalProperties": false +} + diff --git a/ramls/settings/instanceDateTypes.json b/ramls/settings/instanceDateTypes.json new file mode 100644 index 00000000..c2e10ea3 --- /dev/null +++ b/ramls/settings/instanceDateTypes.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A collection of instance date types", + "type": "object", + "properties": { + "instanceDateTypes": { + "description": "List of instance date types", + "type": "array", + "items": { + "type": "object", + "$ref": "instanceDateType.json" + } + }, + "totalRecords": { + "description": "Estimated or exact total number of records", + "type": "integer" + } + } +} diff --git a/src/main/java/org/folio/processing/mapping/defaultmapper/processor/functions/NormalizationFunction.java b/src/main/java/org/folio/processing/mapping/defaultmapper/processor/functions/NormalizationFunction.java index f76cbdfb..522ea127 100644 --- a/src/main/java/org/folio/processing/mapping/defaultmapper/processor/functions/NormalizationFunction.java +++ b/src/main/java/org/folio/processing/mapping/defaultmapper/processor/functions/NormalizationFunction.java @@ -14,6 +14,7 @@ import org.folio.HoldingsNoteType; import org.folio.HoldingsType; import org.folio.IdentifierType; +import org.folio.InstanceDateType; import org.folio.InstanceFormat; import org.folio.InstanceNoteType; import org.folio.InstanceType; @@ -199,6 +200,38 @@ private String concatSubFields(JsonObject ruleParameter, List subfield } }, + SET_DATE_TYPE_ID() { + private static final String DEFAULT_DATE_TYPE = "No attempt to code"; + + @Override + public String apply(RuleExecutionContext context) { + String subFieldValue = context.getSubFieldValue(); + char sixthChar = subFieldValue.charAt(6); + List dateTypes = context.getMappingParameters().getInstanceDateTypes(); + if (dateTypes == null || dateTypes.isEmpty()) { + return StringUtils.EMPTY; + } + String defaultDateTypeId = findDateTypeId(dateTypes, StringUtils.EMPTY); + return matchInstanceDateTypeViaCode(sixthChar, dateTypes, defaultDateTypeId); + } + + private String findDateTypeId(List dates, String defaultId) { + return dates.stream() + .filter(date -> date.getName().equalsIgnoreCase(DEFAULT_DATE_TYPE)) + .findFirst() + .map(InstanceDateType::getId) + .orElse(defaultId); + } + + private String matchInstanceDateTypeViaCode(char sixthChar, List instanceDateTypes, String defaultId) { + return instanceDateTypes.stream() + .filter(instanceFormat -> instanceFormat.getCode().equalsIgnoreCase(String.valueOf(sixthChar))) + .findFirst() + .map(InstanceDateType::getId) + .orElse(defaultId); + } + }, + SET_PUBLISHER_ROLE() { @Override public String apply(RuleExecutionContext context) { diff --git a/src/main/java/org/folio/processing/mapping/defaultmapper/processor/parameters/MappingParameters.java b/src/main/java/org/folio/processing/mapping/defaultmapper/processor/parameters/MappingParameters.java index b31de4c5..288ddc62 100644 --- a/src/main/java/org/folio/processing/mapping/defaultmapper/processor/parameters/MappingParameters.java +++ b/src/main/java/org/folio/processing/mapping/defaultmapper/processor/parameters/MappingParameters.java @@ -17,6 +17,7 @@ import org.folio.HoldingsType; import org.folio.IdentifierType; import org.folio.IllPolicy; +import org.folio.InstanceDateType; import org.folio.InstanceFormat; import org.folio.InstanceNoteType; import org.folio.InstanceRelationshipType; @@ -57,6 +58,7 @@ public class MappingParameters { private List instanceNoteTypes = new ArrayList<>(); private List alternativeTitleTypes = new ArrayList<>(); private List issuanceModes = new ArrayList<>(); + private List instanceDateTypes = new ArrayList<>(); private List instanceStatuses = new ArrayList<>(); private List natureOfContentTerms = new ArrayList<>(); private List instanceRelationshipTypes = new ArrayList<>(); @@ -180,6 +182,15 @@ public MappingParameters withIssuanceModes(List issuanceModes) { return this; } + public List getInstanceDateTypes() { + return instanceDateTypes; + } + + public MappingParameters withInstanceDateTypes(List instanceDateTypes) { + this.instanceDateTypes = new UnmodifiableList<>(instanceDateTypes); + return this; + } + public void setInitialized(boolean initialized) { this.initialized = initialized; } diff --git a/src/test/java/org/folio/processing/mapping/functions/NormalizationFunctionTest.java b/src/test/java/org/folio/processing/mapping/functions/NormalizationFunctionTest.java index 1cacba7f..4ba4e531 100644 --- a/src/test/java/org/folio/processing/mapping/functions/NormalizationFunctionTest.java +++ b/src/test/java/org/folio/processing/mapping/functions/NormalizationFunctionTest.java @@ -5,6 +5,7 @@ import org.apache.commons.lang3.StringUtils; import org.folio.AuthorityNoteType; import org.folio.ClassificationType; +import org.folio.InstanceDateType; import org.folio.InstanceType; import org.folio.ElectronicAccessRelationship; import org.folio.InstanceFormat; @@ -270,6 +271,81 @@ public void CAPITALIZE_shouldReturnExpectedResult() { } } + @Test + public void SET_DATE_TYPE_ID_shouldReturnExpectedResult() { + // given + String expectedInstanceDateTypeId = UUID.randomUUID().toString(); + InstanceDateType firstInstanceDateType = new InstanceDateType() + .withId(UUID.randomUUID().toString()) + .withName("No attempt to code") + .withCode("|"); + + InstanceDateType secondInstanceDateType = new InstanceDateType() + .withId(expectedInstanceDateTypeId) + .withName("Single known date/probable date") + .withCode("s"); + + InstanceDateType thirdInstanceDateType = new InstanceDateType() + .withId(UUID.randomUUID().toString()) + .withName("Range of years of bulk of collection") + .withCode("k"); + + RuleExecutionContext context = new RuleExecutionContext(); + context.setSubFieldValue("901214s19910101nyua"); + context.setMappingParameters(new MappingParameters().withInstanceDateTypes(Arrays.asList(firstInstanceDateType, secondInstanceDateType, thirdInstanceDateType))); + // when + String actualInstanceDateTypeId = runFunction("set_date_type_id", context); + // then + assertEquals(expectedInstanceDateTypeId, actualInstanceDateTypeId); + } + + @Test + public void SET_DATE_TYPE_ID_shouldReturnUnspecifiedIssuanceModeIdIfNoMatchedExists() { + // given + String expectedInstanceDateTypeId = UUID.randomUUID().toString(); + InstanceDateType instanceDateType = new InstanceDateType() + .withId(expectedInstanceDateTypeId) + .withName("No attempt to code") + .withCode("|"); + + RuleExecutionContext context = new RuleExecutionContext(); + context.setSubFieldValue("zzzzzzzzzz"); + context.setMappingParameters(new MappingParameters().withInstanceDateTypes(Collections.singletonList(instanceDateType))); + // when + String actualInstanceDateTypeId = runFunction("set_date_type_id", context); + // then + assertEquals(expectedInstanceDateTypeId, actualInstanceDateTypeId); + } + @Test + public void SET_DATE_TYPE_ID_shouldReturnEmptyStringIfNoMatchedExistsAndUnspecifiedInstanceTypeIdNotExists() { + // given + String expectedInstanceDateTypeId = UUID.randomUUID().toString(); + InstanceDateType instanceDateTypeId = new InstanceDateType() + .withId(expectedInstanceDateTypeId) + .withName("Detailed date") + .withCode("e"); + + RuleExecutionContext context = new RuleExecutionContext(); + context.setSubFieldValue("zzzzzzzzzz"); + context.setMappingParameters(new MappingParameters().withInstanceDateTypes(Collections.singletonList(instanceDateTypeId))); + // when + String actualInstanceDateTypeId = runFunction("set_date_type_id", context); + // then + assertEquals(StringUtils.EMPTY, actualInstanceDateTypeId); + } + + @Test + public void SET_DATE_TYPE_MODE_ID_shouldReturnEmptyStringIfNoSettingsSpecified() { + // given + RuleExecutionContext context = new RuleExecutionContext(); + context.setMappingParameters(new MappingParameters()); + context.setSubFieldValue("901214s19910101nyua"); + // when + String actualInstanceDateTypeId = runFunction("set_date_type_id", context); + // then + assertEquals(StringUtils.EMPTY, actualInstanceDateTypeId); + } + @Test public void SET_PUBLISHER_ROLE_shouldReturnExpectedResult() { // given diff --git a/src/test/resources/org/folio/processing/mapping/instance/rules.json b/src/test/resources/org/folio/processing/mapping/instance/rules.json index b70cf9a0..eae10f58 100644 --- a/src/test/resources/org/folio/processing/mapping/instance/rules.json +++ b/src/test/resources/org/folio/processing/mapping/instance/rules.json @@ -70,6 +70,22 @@ } ] }, + { + "target": "dates.dateTypeId", + "description": "Date type ID", + "subfield": [], + "createSingleObject": true, + "rules": [ + { + "description": "", + "conditions": [ + { + "type": "set_date_type_id" + } + ] + } + ] + }, { "target": "dates.date1", "description": "Date 1",