Skip to content

Commit

Permalink
Update the component to check duplicates in the following fields:
Browse files Browse the repository at this point in the history
- Metadata title
- Metadata alternative title
- Metadata resource identifier
  • Loading branch information
josegar74 committed Nov 4, 2024
1 parent 1dba46e commit 81f7fa3
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 54 deletions.
63 changes: 31 additions & 32 deletions services/src/main/java/org/fao/geonet/api/records/MetadataApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -791,21 +791,21 @@ public FeatureResponse getFeatureCatalog(

@io.swagger.v3.oas.annotations.Operation(summary = "Check if metadata title is duplicated",
description = "Verifies if the metadata title is in use.")
@PostMapping(value = "/{metadataUuid:.+}/checkDuplicatedTitle",
@PostMapping(value = "/{metadataUuid:.+}/checkDuplicatedFieldValue",
produces = {MediaType.APPLICATION_JSON_VALUE})
@PreAuthorize("hasAuthority('Editor')")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Return true if the title is duplicated or false in other case."),
@ApiResponse(responseCode = "403", description = ApiParams.API_RESPONSE_NOT_ALLOWED_CAN_VIEW)
})
public ResponseEntity<Boolean> checkMetadataTitleDuplicated(
public ResponseEntity<Boolean> checkDuplicatedFieldValue(
@Parameter(description = API_PARAM_RECORD_UUID,
required = true)
@PathVariable
String metadataUuid,
@Parameter(description = "Metadata title to check",
@Parameter(description = "Metadata field information to check",
required = true)
@RequestBody String title,
@RequestBody DuplicatedValueDto duplicatedValueDto,
HttpServletRequest request
) throws Exception {
try {
Expand All @@ -815,7 +815,18 @@ public ResponseEntity<Boolean> checkMetadataTitleDuplicated(
throw new NotAllowedException(ApiParams.API_RESPONSE_NOT_ALLOWED_CAN_VIEW);
}

boolean uuidsWithSameTitle = isMetadataTitleExistingInOtherRecords(title, metadataUuid);
List<String> validFields = Arrays.asList("title", "altTitle", "identifier");

if (!validFields.contains(duplicatedValueDto.getField())) {
throw new IllegalArgumentException(String.format("A valid Lucene field name is required:", String.join(",", validFields)));
}

if (StringUtils.isEmpty(duplicatedValueDto.getValue())) {
throw new IllegalArgumentException("A non-empty value is required.");
}


boolean uuidsWithSameTitle = MetadataUtils.isMetadataFieldValueExistingInOtherRecords(duplicatedValueDto.getValue(), duplicatedValueDto.getField(), metadataUuid);
return ResponseEntity.ok(uuidsWithSameTitle);
}

Expand All @@ -828,36 +839,24 @@ private boolean isIncludedAttributeTable(RelatedResponse.Fcat fcat) {
&& fcat.getItem().get(0).getFeatureType().getAttributeTable().getElement() != null;
}

private static class DuplicatedValueDto {
private String field;
private String value;

/**
* Check if other metadata records exist apart from the one with {code}metadataUuidToExclude{code} with
* {code}metadataTitle{code} title in the catalogue.
*
* @param metadataTitle Metadata title to check.
* @param metadataUuidToExclude Metadata identifier to exclude from the search.
* @return A list of metadata uuids that have the same metadata title.
*/
private boolean isMetadataTitleExistingInOtherRecords(String metadataTitle, String metadataUuidToExclude) {
boolean metadataWithSameTitle = false;
String jsonQuery = " {" +
" \"query_string\": {" +
" \"query\": \"+resourceTitleObject.\\\\*.keyword:\\\"%s\\\" -uuid:\\\"%s\\\"\"" +
" }" +
"}";

ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode esJsonQuery = objectMapper.readTree(String.format(jsonQuery, metadataTitle, metadataUuidToExclude));
public String getField() {
return field;
}

final SearchResponse queryResult = esSearchManager.query(
esJsonQuery,
FIELDLIST_UUID,
0, 5);
public void setField(String field) {
this.field = field;
}

public String getValue() {
return value;
}

metadataWithSameTitle = !queryResult.hits().hits().isEmpty();
} catch (Exception ex) {
Log.error(API.LOG_MODULE_NAME, ex.getMessage(), ex);
public void setValue(String value) {
this.value = value;
}
return metadataWithSameTitle;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.NodeInfo;
import org.fao.geonet.api.API;
import org.fao.geonet.api.es.EsHTTPProxy;
import org.fao.geonet.api.records.model.related.AssociatedRecord;
import org.fao.geonet.api.records.model.related.RelatedItemOrigin;
Expand Down Expand Up @@ -306,7 +307,7 @@ public static Map<RelatedItemType, List<AssociatedRecord>> getAssociated(
if (!e.fields().isEmpty()) {
FIELDLIST_RELATED_SCRIPTED.keySet().forEach(f -> {
JsonData dc = (JsonData) e.fields().get(f);

if (dc != null) {
if (associatedRecord.getProperties() == null) {
associatedRecord.setProperties(new HashMap<>());
Expand Down Expand Up @@ -774,6 +775,48 @@ public static boolean retrieveMetadataValidationStatus(AbstractMetadata metadata
return isInvalid;
}

/**
* Check if other metadata records exist apart from the one with {code}metadataUuidToExclude{code} with the same
* {code}metadataValue{code} for the field {code}metadataField{code}.
*
* @param metadataValue Metadata value to check.
* @param metadataField Metadata field to check the value.
* @param metadataUuidToExclude Metadata identifier to exclude from the search.
* @return A list of metadata uuids that have the same value for the field provided.
*/
public static boolean isMetadataFieldValueExistingInOtherRecords(String metadataValue, String metadataField, String metadataUuidToExclude) {
ApplicationContext applicationContext = ApplicationContextHolder.get();
EsSearchManager searchMan = applicationContext.getBean(EsSearchManager.class);

String esFieldName = "resourceTitleObject.\\\\*.keyword";
if (metadataField.equals("altTitle")) {
esFieldName = "resourceAltTitleObject.\\\\*.keyword";
} else if (metadataField.equals("identifier")) {
esFieldName = "resourceIdentifier.code";
}

boolean duplicatedMetadataValue = false;
String jsonQuery = " {" +
" \"query_string\": {" +
" \"query\": \"+" + esFieldName + ":\\\"%s\\\" -uuid:\\\"%s\\\"\"" +
" }" +
"}";

ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode esJsonQuery = objectMapper.readTree(String.format(jsonQuery, metadataValue, metadataUuidToExclude));

final SearchResponse queryResult = searchMan.query(
esJsonQuery,
FIELDLIST_UUID,
0, 5);

duplicatedMetadataValue = !queryResult.hits().hits().isEmpty();
} catch (Exception ex) {
Log.error(API.LOG_MODULE_NAME, ex.getMessage(), ex);
}
return duplicatedMetadataValue;
}

/**
* Checks if a result for a search query has results.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,43 +545,60 @@

/**
* @ngdoc directive
* @name gn_fields.directive:gnDuplicatedMetadataTitleChecker
* @name gn_fields.directive:gnDuplicatedMetadataValueChecker
*
* @description
* Checks if the associated control value exists in another metadata record title.
* Checks if the associated control value exists in another metadata record.
* Valid field keys:
* - title: Metadata title.
* - altTitle: Metadata alternative title.
* - identifier: Metadata resource identifier.
* Configure in your metadata schema config-editor.xml the usage of this directive
* for the title element. For example, for iso19139:
* <fields>
* ...
* <for name="gmd:title" use="data-gn-duplicated-metadata-title-checker" />
* <for name="gmd:alternateTitle" use="data-gn-duplicated-metadata-value-checker">
* <directiveAttributes
* data-field-name="ResourceName"
* data-field-key="altTitle" />
*/
module.directive("gnDuplicatedMetadataTitleChecker", [
module.directive("gnDuplicatedMetadataValueChecker", [
"gnCurrentEdit",
"$http",
"$compile",
function (gnCurrentEdit, $http, $compile) {
"$translate",
function (gnCurrentEdit, $http, $compile, $translate) {
return {
restrict: "A",
scope: {},
scope: {
fieldLabel: "@", // Field name used to match a translation message with the key: 'metadataDuplicatedField' + scope.fieldName
fieldKey: "@" // Elasticserch field name. Allowed values: _title (Metadata title), altTitle (Resource name), identifier (Resource identifier)
},
link: function (scope, element, attrs) {
var fieldName = $translate.instant(
"metadataDuplicatedField" + scope.fieldLabel
);

var messageTemplate =
"<p class='help-block' " +
"style='color: #d9534f' " +
"data-ng-show='duplicatedTitle && !hiddenControl' " +
"data-translate>metadataDuplicatedTitle</p>";
"data-ng-show='duplicatedValue && !hiddenControl' " +
"data-translate>" +
fieldName +
"</p>";
var messageTemplateCompiled = $compile(messageTemplate)(scope);

var messageTarget = element.context;
var messageTarget = document.getElementById(element[0].id);
element.blur(function () {
if (messageTarget.value !== scope.metadataTitle) {
scope.metadataTitle = messageTarget.value;
scope.checkTitle(scope.metadataTitle, scope.metadataUuid);
if (messageTarget.value !== scope.metadataFieldValue) {
scope.metadataFieldValue = messageTarget.value;
scope.checkField(scope.metadataFieldValue, scope.metadataUuid);
}
});

scope.metadataUuid = gnCurrentEdit.uuid;
scope.metadataTitle = messageTarget.value;
scope.duplicatedTitle = false;
scope.metadataFieldValue = messageTarget.value;
scope.duplicatedValue = false;
scope.hiddenControl = false;

element.after(messageTemplateCompiled);
Expand All @@ -602,18 +619,28 @@
characterData: false
});

scope.checkTitle = function (metadataTitle, metadataUuid) {
scope.checkField = function (fieldValue, metadataUuid) {
if (fieldValue === "") {
scope.duplicatedValue = false;
return;
}

var postBody = {
field: scope.fieldKey,
value: fieldValue
};

$http
.post(
"../api/records/" + metadataUuid + "/checkDuplicatedTitle",
metadataTitle
"../api/records/" + metadataUuid + "/checkDuplicatedFieldValue",
postBody
)
.then(function (response) {
scope.duplicatedTitle = response.data === true;
scope.duplicatedValue = response.data === true;
});
};

scope.checkTitle(scope.metadataTitle, scope.metadataUuid);
scope.checkField(scope.metadataFieldValue, scope.metadataUuid);
}
};
}
Expand Down
3 changes: 1 addition & 2 deletions web-ui/src/main/resources/catalog/locales/en-editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,5 @@
"associated-hasfeaturecats": "Using this feature catalog",
"associatedResourcesPanel": "Associated resources",
"validationSuccessLabel": "success",
"validationErrorLabel": "errors",
"metadataDuplicatedTitle": "The title is used in another metadata record."
"validationErrorLabel": "errors"
}

0 comments on commit 81f7fa3

Please sign in to comment.