Skip to content

Commit

Permalink
Merge branch 'master' into MODDICORE-420
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanChernetskyi authored Oct 16, 2024
2 parents 055291f + 360ba1d commit 0e2eff0
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 16 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## 2024-xx-xx v3.9.0-SNAPSHOT
* [MODSOURMAN-1232](https://folio-org.atlassian.net/browse/MODSOURMAN-1232) Add the option to exclude job profile names to GET "/metadata-provider/jobExecutions" endpoint
* [MODSOURMAN-1195](https://folio-org.atlassian.net/browse/MODSOURMAN-1195) Save job execution progress in batches
* [MODSOURMAN-1166](https://folio-org.atlassian.net/browse/MODSOURMAN-1166) Sorting by Autority, Order and Error columns is not working on Log details page
* [MODDATAIMP-1029](https://folio-org.atlassian.net/browse/MODDATAIMP-1029) The authority record loaded via data-import using Default - Create SRS MARC Authority job profile is duplicated on the job-summary page
Expand All @@ -18,6 +19,7 @@
* [MODSOURMAN-1212](https://folio-org.atlassian.net/browse/MODSOURMAN-1212) Update MARC bib-instance default mapping for subject source and subject type
* [MODDATAIMP-1085](https://folio-org.atlassian.net/browse/MODDATAIMP-1085) Provide module permissions for subject types and sources
* [MODDICORE-415](https://folio-org.atlassian.net/browse/MODDICORE-415) Adjust mapping of Subject source specified in subfield 2
* [MODSOURMAN-1228](https://folio-org.atlassian.net/browse/MODSOURMAN-1212) Update default mapping for Date type, Date 1, and Date 2 fields

## 2023-03-22 v3.8.0
* [MODSOURMAN-1131](https://folio-org.atlassian.net/browse/MODSOURMAN-1131) The import of file for creating orders is completed with errors
Expand Down
59 changes: 59 additions & 0 deletions RuleProcessorApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,65 @@ If ending punctuation of the last mapped subfield of the field is a period or co
```
##### **NOTE**: Regarding ending punctuation - if the mapped text ends with (".", ",", ";") then it will be(the last symbol) removed for the matching with Contributor Type.

#### Map single JsonObject
If there is a need to map not arrays or string but json object with simple fields inside (strings), there can be used "createSingleObject" rule, which will create a single json object with specified fields:

```json
Building Dates json object:
{
"target": "dates.dateTypeId",
"description": "Date type ID",
"subfield": [],
"createSingleObject": true,
"rules": [
{
"conditions": [
{
"type": "set_date_type_id"
}
]
}
]
},
{
"target": "dates.date1",
"description": "Date 1",
"subfield": [],
"createSingleObject": true,
"rules": [
{
"conditions": [
{
"type": "char_select",
"parameter": {
"from": 7,
"to": 11
}
}
]
}
]
},
{
"target": "dates.date2",
"description": "Date 2",
"subfield": [],
"createSingleObject": true,
"rules": [
{
"conditions": [
{
"type": "char_select",
"parameter": {
"from": 11,
"to": 15
}
}
]
}
]
}
```
#
### REST API
When the source-record-manager starts up, it performs initialization for default mapping rules for given tenant.
Expand Down
5 changes: 4 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@
"inventory-storage.statistical-codes.collection.get",
"inventory-storage.subject-sources.collection.get",
"inventory-storage.subject-types.collection.get",
"inventory-storage.subject-types.collection.get",
"inventory-storage.instance-date-types.collection.get",
"mapping-metadata.get",
"orders.po-lines.collection.get",
"source-storage.records.get",
Expand Down Expand Up @@ -608,7 +610,8 @@
"inventory-storage.statistical-code-types.collection.get",
"inventory-storage.statistical-codes.collection.get",
"inventory-storage.subject-sources.collection.get",
"inventory-storage.subject-types.collection.get"
"inventory-storage.subject-types.collection.get",
"inventory-storage.instance-date-types.collection.get"
]
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import java.util.stream.Collectors;

import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.folio.dao.util.JobExecutionDBConstants.COMPLETED_DATE_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.FILE_NAME_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.HRID_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.IS_DELETED_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.JOB_PROFILE_HIDDEN_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.JOB_PROFILE_ID_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.JOB_PROFILE_NAME_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.STATUS_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.SUBORDINATION_TYPE_FIELD;
import static org.folio.dao.util.JobExecutionDBConstants.UI_STATUS_FIELD;
Expand All @@ -24,6 +26,7 @@
public class JobExecutionFilter {
public static final String LIKE = "LIKE";
public static final String ILIKE = "ILIKE";
private static final String NOT = "NOT";
private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
private List<JobExecution.Status> statusAny;
private List<String> profileIdNotAny;
Expand All @@ -37,6 +40,7 @@ public class JobExecutionFilter {
private String userId;
private Date completedAfter;
private Date completedBefore;
private String excludeJobProfileName;

public JobExecutionFilter withStatusAny(List<JobExecution.Status> statusAny) {
this.statusAny = statusAny;
Expand Down Expand Up @@ -68,6 +72,11 @@ public JobExecutionFilter withFileNamePattern(String fileNamePattern) {
return this;
}

public JobExecutionFilter withExcludeJobProfileName(String excludeJobProfileName) {
this.excludeJobProfileName = excludeJobProfileName;
return this;
}

public JobExecutionFilter withFileNameNotAny(List<String> fileNameNotAny) {
this.fileNameNotAny = fileNameNotAny;
return this;
Expand Down Expand Up @@ -121,16 +130,19 @@ public String buildCriteria() {
addCondition(conditionBuilder, buildInCondition(UI_STATUS_FIELD, uiStatuses));
}
if (isNotEmpty(hrIdPattern) && isNotEmpty(fileNamePattern)) {
conditionBuilder.append(String.format(" AND (%s OR %s)", buildCaseSensitiveLikeCondition(HRID_FIELD, hrIdPattern),
buildCaseInsensitiveLikeCondition(FILE_NAME_FIELD, fileNamePattern)));
conditionBuilder.append(String.format(" AND (%s OR %s)", buildCaseSensitiveLikeCondition(HRID_FIELD, hrIdPattern, false),
buildCaseInsensitiveLikeCondition(FILE_NAME_FIELD, fileNamePattern, false)));
} else {
if (isNotEmpty(hrIdPattern)) {
addCondition(conditionBuilder, buildCaseSensitiveLikeCondition(HRID_FIELD, hrIdPattern));
addCondition(conditionBuilder, buildCaseSensitiveLikeCondition(HRID_FIELD, hrIdPattern, false));
}
if (isNotEmpty(fileNamePattern)) {
addCondition(conditionBuilder, buildCaseInsensitiveLikeCondition(FILE_NAME_FIELD, fileNamePattern));
addCondition(conditionBuilder, buildCaseInsensitiveLikeCondition(FILE_NAME_FIELD, fileNamePattern, false));
}
}
if (isNotEmpty(excludeJobProfileName)) {
addCondition(conditionBuilder, buildCaseInsensitiveLikeCondition(JOB_PROFILE_NAME_FIELD, excludeJobProfileName, true));
}
if (isNotEmpty(fileNameNotAny)) {
addCondition(conditionBuilder, buildNotInCondition(FILE_NAME_FIELD, fileNameNotAny));
}
Expand Down Expand Up @@ -195,18 +207,19 @@ private String buildLessThanOrEqualCondition(String columnName, String value) {
return String.format("%s <= '%s'", columnName, value);
}

private String buildCaseSensitiveLikeCondition(String columnName, String pattern) {
return buildLikeCondition(columnName, pattern, true);
private String buildCaseSensitiveLikeCondition(String columnName, String pattern, boolean denial) {
return buildLikeCondition(columnName, pattern, true, denial);
}

private String buildCaseInsensitiveLikeCondition(String columnName, String pattern) {
return buildLikeCondition(columnName, pattern, false);
private String buildCaseInsensitiveLikeCondition(String columnName, String pattern, boolean denial) {
return buildLikeCondition(columnName, pattern, false, denial);
}

private String buildLikeCondition(String columnName, String pattern, boolean isCaseSensitive) {
private String buildLikeCondition(String columnName, String pattern, boolean isCaseSensitive, boolean denial) {
String preparedLikePattern = pattern.replace("*", "%");
String likeOperator = isCaseSensitive ? LIKE : ILIKE;
return String.format("%s::text %s '%s'", columnName, likeOperator, preparedLikePattern);
String denyOperator = denial ? NOT : EMPTY;
return String.format("%s::text %s %s '%s'", columnName, denyOperator, likeOperator, preparedLikePattern);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ public MetadataProviderImpl(Vertx vertx, String tenantId) { //NOSONAR
}

@Override
public void getMetadataProviderJobExecutions(List<String> statusAny, List<String> profileIdNotAny, String statusNot,
List<String> uiStatusAny, String hrId, String fileName, List<String> fileNameNotAny,
public void getMetadataProviderJobExecutions(String excludeJobProfileName, List<String> statusAny, List<String> profileIdNotAny,
String statusNot, List<String> uiStatusAny, String hrId, String fileName, List<String> fileNameNotAny,
List<String> profileIdAny, List<String> subordinationTypeNotAny, String userId, Date completedAfter,
Date completedBefore, List<String> sortBy, String totalRecords, int offset, int limit, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
Expand All @@ -72,7 +72,7 @@ public void getMetadataProviderJobExecutions(List<String> statusAny, List<String
LOGGER.debug("getMetadataProviderJobExecutions:: sortBy {}", sortBy);
List<SortField> sortFields = mapSortQueryToSortFields(sortBy);
JobExecutionFilter filter = buildJobExecutionFilter(statusAny, profileIdNotAny, statusNot, uiStatusAny, hrId, fileName, fileNameNotAny, profileIdAny,
subordinationTypeNotAny, userId, completedAfter, completedBefore);
subordinationTypeNotAny, userId, completedAfter, completedBefore, excludeJobProfileName);
jobExecutionService.getJobExecutionsWithoutParentMultiple(filter, sortFields, offset, limit, tenantId)
.map(GetMetadataProviderJobExecutionsResponse::respond200WithApplicationJson)
.map(Response.class::cast)
Expand Down Expand Up @@ -223,7 +223,8 @@ public void getMetadataProviderIncomingRecordsByRecordId(String recordId, Map<St
private JobExecutionFilter buildJobExecutionFilter(List<String> statusAny, List<String> profileIdNotAny, String statusNot,
List<String> uiStatusAny, String hrIdPattern, String fileNamePattern,
List<String> fileNameNotAny, List<String> profileIdAny, List<String> subordinationTypeNotAny,
String userId, Date completedAfter, Date completedBefore) {
String userId, Date completedAfter, Date completedBefore,
String excludeJobProfileName) {
List<JobExecution.Status> statuses = statusAny.stream()
.map(JobExecution.Status::fromValue)
.toList();
Expand All @@ -239,6 +240,7 @@ private JobExecutionFilter buildJobExecutionFilter(List<String> statusAny, List<
return new JobExecutionFilter()
.withStatusAny(statuses)
.withProfileIdNotAny(profileIdNotAny)
.withExcludeJobProfileName(excludeJobProfileName)
.withStatusNot(statusNot == null ? null : JobExecution.Status.fromValue(statusNot))
.withUiStatusAny(uiStatuses)
.withHrIdPattern(hrIdPattern)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
import org.folio.Identifiertypes;
import org.folio.IllPolicy;
import org.folio.Illpolicies;
import org.folio.InstanceDateType;
import org.folio.InstanceDateTypes;
import org.folio.InstanceFormat;
import org.folio.InstanceNoteType;
import org.folio.InstanceRelationshipType;
Expand Down Expand Up @@ -134,6 +136,7 @@ public class MappingParametersProvider {
private static final String AUTHORITY_SOURCE_FILES_RESPONSE_PARAM = "authoritySourceFiles";
private static final String SUBJECTS_SOURCES_RESPONSE_PARAM = "subjectSources";
private static final String SUBJECTS_TYPES_RESPONSE_PARAM = "subjectTypes";
private static final String INSTANCE_DATE_TYPES_RESPONSE_PARAM = "instanceDateTypes";

private static final String CONFIGS_VALUE_RESPONSE = "configs";
private static final String VALUE_RESPONSE = "value";
Expand Down Expand Up @@ -193,6 +196,7 @@ private Future<MappingParameters> initializeParameters(MappingParameters mapping
Future<List<AuthoritySourceFile>> authoritySourceFilesFuture = getAuthoritySourceFiles(okapiParams);
Future<List<SubjectSource>> subjectSourcesFuture = getSubjectSources(okapiParams);
Future<List<SubjectType>> subjectTypesFuture = getSubjectTypes(okapiParams);
Future<List<InstanceDateType>> instanceDateTypesFuture = getInstanceDateTypes(okapiParams);
Future<List<MarcFieldProtectionSetting>> marcFieldProtectionSettingsFuture = getMarcFieldProtectionSettings(okapiParams);
Future<String> tenantConfigurationZoneFuture = getTenantConfigurationZone(okapiParams);
Future<List<LinkingRuleDto>> linkingRulesFuture = getLinkingRules(okapiParams);
Expand All @@ -202,7 +206,7 @@ private Future<MappingParameters> initializeParameters(MappingParameters mapping
contributorTypesFuture, contributorNameTypesFuture, electronicAccessRelationshipsFuture, instanceNoteTypesFuture, alternativeTitleTypesFuture,
issuanceModesFuture, instanceStatusesFuture, natureOfContentTermsFuture, instanceRelationshipTypesFuture, holdingsTypesFuture, holdingsNoteTypesFuture,
illPoliciesFuture, callNumberTypesFuture, statisticalCodesFuture, statisticalCodeTypesFuture, locationsFuture, materialTypesFuture, itemDamagedStatusesFuture,
loanTypesFuture, itemNoteTypesFuture, authorityNoteTypesFuture, authoritySourceFilesFuture,subjectSourcesFuture, subjectTypesFuture, marcFieldProtectionSettingsFuture, tenantConfigurationZoneFuture,
loanTypesFuture, itemNoteTypesFuture, authorityNoteTypesFuture, authoritySourceFilesFuture,subjectSourcesFuture, subjectTypesFuture, instanceDateTypesFuture, marcFieldProtectionSettingsFuture, tenantConfigurationZoneFuture,
linkingRulesFuture))
.map(ar ->
mappingParams
Expand Down Expand Up @@ -236,6 +240,7 @@ private Future<MappingParameters> initializeParameters(MappingParameters mapping
.withAuthoritySourceFiles(authoritySourceFilesFuture.result())
.withSubjectSources(subjectSourcesFuture.result())
.withSubjectTypes(subjectTypesFuture.result())
.withInstanceDateTypes(instanceDateTypesFuture.result())
.withMarcFieldProtectionSettings(marcFieldProtectionSettingsFuture.result())
.withTenantConfigurationZone(tenantConfigurationZoneFuture.result())
.withLinkingRules(linkingRulesFuture.result())
Expand Down Expand Up @@ -486,6 +491,19 @@ private Future<List<SubjectType>> getSubjectTypes(OkapiConnectionParams params)
response -> response.mapTo(SubjectTypes.class).getSubjectTypes());
}

/**
* Requests for Instance Date Types from application Settings (mod-inventory-storage)
* *
*
* @param params Okapi connection parameters
* @return List Instance date types
*/
private Future<List<InstanceDateType>> getInstanceDateTypes(OkapiConnectionParams params) {
String instanceDateTypesUrl = "/instance-date-types?limit=" + settingsLimit;
return loadData(params, instanceDateTypesUrl, INSTANCE_DATE_TYPES_RESPONSE_PARAM,
response -> response.mapTo(InstanceDateTypes.class).getInstanceDateTypes());
}

/**
* Requests for tenant configuration from mod-configuration.
* *
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,59 @@
]
}
]
},
{
"target": "dates.dateTypeId",
"description": "Date type ID",
"subfield": [],
"createSingleObject": true,
"rules": [
{
"conditions": [
{
"type": "set_date_type_id"
}
]
}
]
},
{
"target": "dates.date1",
"description": "Date 1",
"subfield": [],
"createSingleObject": true,
"rules": [
{
"conditions": [
{
"type": "char_select",
"parameter": {
"from": 7,
"to": 11
}
}
]
}
]
},
{
"target": "dates.date2",
"description": "Date 2",
"subfield": [],
"createSingleObject": true,
"rules": [
{
"conditions": [
{
"type": "char_select",
"parameter": {
"from": 11,
"to": 15
}
}
]
}
]
}
],
"010": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ public abstract class AbstractRestTest {
protected static final String FIELD_PROTECTION_SETTINGS_URL = "/field-protection-settings/marc?limit=1000";
protected static final String SUBJECT_SOURCES_URL = "/subject-sources?limit=1000";
protected static final String SUBJECT_TYPES_URL = "/subject-types?limit=1000";
protected static final String INSTANCE_DATE_TYPES_URL = "/instance-date-types?limit=1000";


protected static final String TENANT_CONFIGURATION_ZONE_SETTINGS_URL = "/configurations/entries?query=" + URLEncoder.encode("(module==ORG and configName==localeSettings)", StandardCharsets.UTF_8);

Expand Down Expand Up @@ -504,6 +506,7 @@ public void setUp(TestContext context) throws IOException {
WireMock.stubFor(get(AUTHORITY_SOURCE_FILES_URL).willReturn(okJson(new JsonObject().put("authoritySourceFiles", new JsonArray()).toString())));
WireMock.stubFor(get(SUBJECT_SOURCES_URL).willReturn(okJson(new JsonObject().put("subjectSources", new JsonArray()).toString())));
WireMock.stubFor(get(SUBJECT_TYPES_URL).willReturn(okJson(new JsonObject().put("subjectTypes", new JsonArray()).toString())));
WireMock.stubFor(get(INSTANCE_DATE_TYPES_URL).willReturn(okJson(new JsonObject().put("instanceDateTypes", new JsonArray()).toString())));

WireMock.stubFor(get(FIELD_PROTECTION_SETTINGS_URL).willReturn(okJson(new JsonObject().put("marcFieldProtectionSettings", new JsonArray()).toString())));
WireMock.stubFor(get(TENANT_CONFIGURATION_ZONE_SETTINGS_URL).willReturn(okJson(new JsonObject().put("configs", new JsonArray()).toString())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,7 @@ public void shouldProcessChunksAndRequestForMappingParameters1Time(TestContext t
verify(1, getRequestedFor(urlEqualTo(AUTHORITY_SOURCE_FILES_URL)));
verify(1, getRequestedFor(urlEqualTo(SUBJECT_SOURCES_URL)));
verify(1, getRequestedFor(urlEqualTo(SUBJECT_TYPES_URL)));
verify(1, getRequestedFor(urlEqualTo(INSTANCE_DATE_TYPES_URL)));
verify(1, getRequestedFor(urlEqualTo(FIELD_PROTECTION_SETTINGS_URL)));
verify(1, getRequestedFor(urlEqualTo(TENANT_CONFIGURATION_ZONE_SETTINGS_URL)));
async.complete();
Expand Down
Loading

0 comments on commit 0e2eff0

Please sign in to comment.