package eu.eudat.service.prefillingsource; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.JsonHandlingService; import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; import eu.eudat.commons.types.descriptiontemplate.FieldEntity; import eu.eudat.commons.types.descriptiontemplate.FieldSetEntity; import eu.eudat.commons.types.descriptiontemplate.fielddata.ReferenceTypeDataEntity; import eu.eudat.commons.types.descriptiontemplate.fielddata.SelectDataEntity; import eu.eudat.commons.types.externalfetcher.*; import eu.eudat.commons.types.prefillingsource.PrefillingSourceDefinitionEntity; import eu.eudat.commons.types.prefillingsource.PrefillingSourceDefinitionFieldEntity; import eu.eudat.commons.types.prefillingsource.PrefillingSourceDefinitionFixedValueFieldEntity; import eu.eudat.convention.ConventionService; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.PrefillingSourceEntity; import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.*; import eu.eudat.model.builder.DescriptionTemplateBuilder; import eu.eudat.model.builder.PrefillingSourceBuilder; import eu.eudat.model.deleter.PrefillingSourceDeleter; import eu.eudat.model.descriptionproperties.*; import eu.eudat.model.persist.PrefillingSearchRequest; import eu.eudat.model.persist.DescriptionProfilingRequest; import eu.eudat.model.persist.PrefillingSourcePersist; import eu.eudat.model.persist.externalfetcher.*; import eu.eudat.model.persist.prefillingsourcedefinition.PrefillingSourceDefinitionFieldPersist; import eu.eudat.model.persist.prefillingsourcedefinition.PrefillingSourceDefinitionFixedValueFieldPersist; import eu.eudat.model.persist.prefillingsourcedefinition.PrefillingSourceDefinitionPersist; import eu.eudat.model.prefillingsourcedefinition.PrefillingSourceDefinition; import eu.eudat.model.referencedefinition.Definition; import eu.eudat.query.PrefillingSourceQuery; import eu.eudat.query.lookup.ReferenceSearchLookup; import eu.eudat.service.externalfetcher.ExternalFetcherService; import eu.eudat.service.externalfetcher.criteria.ExternalReferenceCriteria; import eu.eudat.service.externalfetcher.models.ExternalDataResult; import eu.eudat.service.reference.ReferenceService; import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyForbiddenException; import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.exception.MyValidationException; import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; import jakarta.xml.bind.JAXBException; import org.apache.commons.lang3.StringEscapeUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Service; import org.xml.sax.SAXException; import javax.management.InvalidApplicationException; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @Service public class PrefillingSourceServiceImpl implements PrefillingSourceService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrefillingSourceServiceImpl.class)); private final TenantEntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; private final QueryFactory queryFactory; private final ConventionService conventionService; private final MessageSource messageSource; private final XmlHandlingService xmlHandlingService; private final ExternalFetcherService externalFetcherService; private final ErrorThesaurusProperties errors; private final JsonHandlingService jsonHandlingService; private final ReferenceService referenceService; private static final String Zenodo = "Zenodo"; public PrefillingSourceServiceImpl( TenantEntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, QueryFactory queryFactory, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, ExternalFetcherService externalFetcherService, ErrorThesaurusProperties errors, JsonHandlingService jsonHandlingService, ReferenceService referenceService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; this.builderFactory = builderFactory; this.queryFactory = queryFactory; this.conventionService = conventionService; this.messageSource = messageSource; this.xmlHandlingService = xmlHandlingService; this.externalFetcherService = externalFetcherService; this.errors = errors; this.jsonHandlingService = jsonHandlingService; this.referenceService = referenceService; } public PrefillingSource persist(PrefillingSourcePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException { logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields)); this.authorizationService.authorizeForce(Permission.EditPrefillingSource); Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); PrefillingSourceEntity data; if (isUpdate) { data = this.entityManager.find(PrefillingSourceEntity.class, model.getId()); if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), PrefillingSource.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); } else { data = new PrefillingSourceEntity(); data.setId(UUID.randomUUID()); data.setIsActive(IsActive.Active); data.setCreatedAt(Instant.now()); } data.setLabel(model.getLabel()); data.setDefinition(this.xmlHandlingService.toXml(this.buildDefinitionEntity(model.getDefinition()))); data.setUpdatedAt(Instant.now()); if (isUpdate) this.entityManager.merge(data); else this.entityManager.persist(data); this.entityManager.flush(); return this.builderFactory.builder(PrefillingSourceBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, PrefillingSource._id), data); } private @NotNull PrefillingSourceDefinitionEntity buildDefinitionEntity(PrefillingSourceDefinitionPersist persist) { PrefillingSourceDefinitionEntity data = new PrefillingSourceDefinitionEntity(); if (persist == null) return data; if (!this.conventionService.isListNullOrEmpty(persist.getFields())) { data.setFields(new ArrayList<>()); for (PrefillingSourceDefinitionFieldPersist fieldPersist : persist.getFields()) { data.getFields().add(this.buildFieldEntity(fieldPersist)); } } if (!this.conventionService.isListNullOrEmpty(persist.getFixedValueFields())) { data.setFixedValueFields(new ArrayList<>()); for (PrefillingSourceDefinitionFixedValueFieldPersist fieldPersist : persist.getFixedValueFields()) { data.getFixedValueFields().add(this.buildFixedValueFieldEntity(fieldPersist)); } } if (persist.getSearchConfiguration() != null ) { data.setSearchConfiguration(this.buildExternalFetcherApiConfigEntity(persist.getSearchConfiguration())); } if (persist.getGetConfiguration() != null && persist.getGetEnabled()) { data.setGetConfiguration(this.buildExternalFetcherApiConfigEntity(persist.getGetConfiguration())); } return data; } private @NotNull PrefillingSourceDefinitionFieldEntity buildFieldEntity(PrefillingSourceDefinitionFieldPersist persist) { PrefillingSourceDefinitionFieldEntity data = new PrefillingSourceDefinitionFieldEntity(); if (persist == null) return data; data.setCode(persist.getCode()); data.setSemanticTarget(persist.getSemanticTarget()); data.setSystemFieldTarget(persist.getSystemFieldTarget()); data.setTrimRegex(persist.getTrimRegex()); return data; } private @NotNull PrefillingSourceDefinitionFixedValueFieldEntity buildFixedValueFieldEntity(PrefillingSourceDefinitionFixedValueFieldPersist persist) { PrefillingSourceDefinitionFixedValueFieldEntity data = new PrefillingSourceDefinitionFixedValueFieldEntity(); if (persist == null) return data; data.setSemanticTarget(persist.getSemanticTarget()); data.setSystemFieldTarget(persist.getSystemFieldTarget()); data.setFixedValue(persist.getFixedValue()); data.setTrimRegex(persist.getTrimRegex()); return data; } private @NotNull ExternalFetcherApiSourceConfigurationEntity buildExternalFetcherApiConfigEntity(ExternalFetcherApiSourceConfigurationPersist persist) { ExternalFetcherApiSourceConfigurationEntity data = new ExternalFetcherApiSourceConfigurationEntity(); if (persist == null) return data; data.setUrl(persist.getUrl()); if (persist.getResults() != null ) { data.setResults(this.buildResultsConfigEntity(persist.getResults())); } data.setKey(persist.getKey()); data.setLabel(persist.getLabel()); data.setOrdinal(persist.getOrdinal()); data.setType(persist.getType()); data.setReferenceTypeDependencyIds(persist.getReferenceTypeDependencyIds()); data.setPaginationPath(persist.getPaginationPath()); data.setContentType(persist.getContentType()); data.setFirstPage(persist.getFirstPage()); data.setHttpMethod(persist.getHttpMethod()); data.setRequestBody(persist.getRequestBody()); data.setFilterType(persist.getFilterType()); if (persist.getAuth() != null) { data.setAuth(this.buildAuthConfigEntity(persist.getAuth())); } if (!this.conventionService.isListNullOrEmpty(persist.getQueries())){ data.setQueries(new ArrayList<>()); for (QueryConfigPersist queryConfigPersist: (persist.getQueries())){ data.getQueries().add(this.buildQueryConfigEntity(queryConfigPersist)); } } return data; } private @NotNull ResultsConfigurationEntity buildResultsConfigEntity(ResultsConfigurationPersist persist){ ResultsConfigurationEntity data = new ResultsConfigurationEntity(); if (persist == null) return data; data.setResultsArrayPath(persist.getResultsArrayPath()); if (!this.conventionService.isListNullOrEmpty(persist.getFieldsMapping())){ data.setFieldsMapping(new ArrayList<>()); for (ResultFieldsMappingConfigurationPersist fieldsMappingPersist: persist.getFieldsMapping()) { data.getFieldsMapping().add(this.buildResultFieldsMappingConfigEntity(fieldsMappingPersist)); } } return data; } private @NotNull ResultFieldsMappingConfigurationEntity buildResultFieldsMappingConfigEntity(ResultFieldsMappingConfigurationPersist persist){ ResultFieldsMappingConfigurationEntity data = new ResultFieldsMappingConfigurationEntity(); if (persist == null) return data; data.setCode(persist.getCode()); data.setResponsePath(persist.getResponsePath()); return data; } private @NotNull AuthenticationConfigurationEntity buildAuthConfigEntity(AuthenticationConfigurationPersist persist){ AuthenticationConfigurationEntity data = new AuthenticationConfigurationEntity(); if (persist == null) return data; data.setEnabled(persist.getEnabled()); data.setAuthUrl(persist.getAuthUrl()); data.setAuthMethod(persist.getAuthMethod()); data.setAuthRequestBody(persist.getAuthRequestBody()); data.setType(persist.getType()); data.setAuthTokenPath(persist.getAuthTokenPath()); return data; } private @NotNull QueryConfigEntity buildQueryConfigEntity(QueryConfigPersist persist){ QueryConfigEntity data = new QueryConfigEntity(); if (persist == null) return data; data.setName(persist.getName()); data.setDefaultValue(persist.getDefaultValue()); if (!this.conventionService.isListNullOrEmpty(persist.getCases())){ data.setCases(new ArrayList<>()); for (QueryCaseConfigPersist queryCaseConfigPersist: persist.getCases()) { data.getCases().add(this.buildQueryCaseConfigEntity(queryCaseConfigPersist)); } } return data; } private @NotNull QueryCaseConfigEntity buildQueryCaseConfigEntity(QueryCaseConfigPersist persist){ QueryCaseConfigEntity data = new QueryCaseConfigEntity(); if (persist == null) return data; data.setReferenceTypeId(persist.getReferenceTypeId()); data.setReferenceTypeSourceKey(persist.getReferenceTypeSourceKey()); data.setSeparator(persist.getSeparator()); data.setValue(persist.getValue()); data.setLikePattern(persist.getLikePattern()); return data; } public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { logger.debug("deleting : {}", id); this.authorizationService.authorizeForce(Permission.DeletePrefillingSource); this.deleterFactory.deleter(PrefillingSourceDeleter.class).deleteAndSaveByIds(List.of(id)); } public List searchPrefillings(PrefillingSearchRequest model) { PrefillingSourceEntity prefillingSourceEntity = this.queryFactory.query(PrefillingSourceQuery.class).ids(model.getPrefillingSourceId()).isActive(IsActive.Active).first(); if (prefillingSourceEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPrefillingSourceId(), PrefillingSource.class.getSimpleName()}, LocaleContextHolder.getLocale())); PrefillingSourceDefinitionEntity prefillingSourceDefinition = this.xmlHandlingService.fromXmlSafe(PrefillingSourceDefinitionEntity.class, prefillingSourceEntity.getDefinition()); if (prefillingSourceDefinition == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPrefillingSourceId(), PrefillingSourceDefinition.class.getSimpleName()}, LocaleContextHolder.getLocale())); ExternalReferenceCriteria externalReferenceCriteria = new ExternalReferenceCriteria(); externalReferenceCriteria.setLike(model.getLike()); ExternalDataResult externalData = this.externalFetcherService.getExternalData(Stream.of(prefillingSourceDefinition.getSearchConfiguration()).collect(Collectors.toList()), externalReferenceCriteria, null); if (externalData == null || this.conventionService.isListNullOrEmpty(externalData.getResults())) { return null; } List prefillings = new ArrayList<>(); for (Map result : externalData.getResults()) { Prefilling prefilling = new Prefilling(); prefilling.setId(result.getOrDefault(Prefilling._id, null)); prefilling.setLabel(result.getOrDefault(Prefilling._label, null)); prefilling.setKey(result.getOrDefault(Prefilling._key, null)); prefilling.setTag(result.getOrDefault(Prefilling._tag, null)); prefillings.add(prefilling); } prefillings = prefillings.stream().sorted(Comparator.comparing(Prefilling::getLabel, Comparator.nullsFirst(Comparator.naturalOrder()))).collect(Collectors.toList()); return prefillings; } public Description getPrefilledDescription(DescriptionProfilingRequest model, FieldSet fieldSet) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException { PrefillingSourceEntity prefillingSourceEntity = this.queryFactory.query(PrefillingSourceQuery.class).ids(model.getPrefillingSourceId()).first(); if (prefillingSourceEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPrefillingSourceId(), PrefillingSource.class.getSimpleName()}, LocaleContextHolder.getLocale())); PrefillingSourceDefinitionEntity prefillingSourceDefinition = this.xmlHandlingService.fromXmlSafe(PrefillingSourceDefinitionEntity.class, prefillingSourceEntity.getDefinition()); if (prefillingSourceDefinition == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPrefillingSourceId(), PrefillingSourceDefinition.class.getSimpleName()}, LocaleContextHolder.getLocale())); ExternalReferenceCriteria externalReferenceCriteria = new ExternalReferenceCriteria(); externalReferenceCriteria.setLike(model.getPrefillId()); ExternalDataResult externalData = this.externalFetcherService.getExternalData(Stream.of(prefillingSourceDefinition.getGetConfiguration()).collect(Collectors.toList()), externalReferenceCriteria, null); if (externalData == null || this.conventionService.isListNullOrEmpty(externalData.getResults())) { return null; } DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, model.getDescriptionTemplateId()); if (descriptionTemplateEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale())); eu.eudat.commons.types.descriptiontemplate.DefinitionEntity descriptionTemplateDefinition = this.xmlHandlingService.fromXml(eu.eudat.commons.types.descriptiontemplate.DefinitionEntity.class, descriptionTemplateEntity.getDefinition()); Description description = new Description(); FieldSet descriptionTemplateFields = fieldSet.extractPrefixed(this.conventionService.asPrefix(Description._descriptionTemplate)); description.setDescriptionTemplate(this.builderFactory.builder(DescriptionTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(descriptionTemplateFields, descriptionTemplateEntity)); return mapPrefilledEntityToDescription(description, descriptionTemplateDefinition, prefillingSourceDefinition, prefillingSourceEntity.getLabel(), externalData.getResults().getFirst());//TODO } private Description mapPrefilledEntityToDescription(Description description, DefinitionEntity descriptionTemplateDefinition, PrefillingSourceDefinitionEntity prefillingSourceDefinition, String type, Map externalData){ if (!this.conventionService.isListNullOrEmpty(prefillingSourceDefinition.getFields())) { for (PrefillingSourceDefinitionFieldEntity field : prefillingSourceDefinition.getFields()) { String sourceValue = externalData.get(field.getCode()); this.prefillSystemValueToDescription(description, field.getSystemFieldTarget(), sourceValue); this.prefillSemanticValueToDescription(description, field.getSemanticTarget(), sourceValue, descriptionTemplateDefinition, type); } } if (!this.conventionService.isListNullOrEmpty(prefillingSourceDefinition.getFixedValueFields())){ for (PrefillingSourceDefinitionFixedValueFieldEntity field: prefillingSourceDefinition.getFixedValueFields()) { this.prefillSystemValueToDescription(description, field.getSystemFieldTarget(), field.getFixedValue()); this.prefillSemanticValueToDescription(description, field.getSemanticTarget(), field.getFixedValue(), descriptionTemplateDefinition, type); } } if (!this.conventionService.isListNullOrEmpty(prefillingSourceDefinition.getFields())) { for (PrefillingSourceDefinitionFieldEntity field : prefillingSourceDefinition.getFields()) { String sourceValue = externalData.get(field.getCode()); this.ensureZenodoFields(description, field.getSemanticTarget(), sourceValue, descriptionTemplateDefinition, type); } } if (!this.conventionService.isListNullOrEmpty(prefillingSourceDefinition.getFixedValueFields())) { for (PrefillingSourceDefinitionFixedValueFieldEntity field : prefillingSourceDefinition.getFixedValueFields()) { this.ensureZenodoFields(description, field.getSemanticTarget(), field.getFixedValue(), descriptionTemplateDefinition, type); } } return description; } private void ensureZenodoFields(Description description, String semanticTarget, String value, DefinitionEntity definition, String type) { if (!this.conventionService.isNullOrEmpty(type) && !this.conventionService.isNullOrEmpty(semanticTarget) && !this.conventionService.isNullOrEmpty(value) && type.equals(Zenodo)) { if (semanticTarget.equals("rda.dataset.distribution.data_access")) { if (value.equals("open")) { List issuedFieldEntities = definition.getAllField().stream().filter(x -> x.getSchematics() != null && x.getSchematics().contains("rda.dataset.issued")).toList(); if (!this.conventionService.isListNullOrEmpty(issuedFieldEntities)) { String issuedIdNode = issuedFieldEntities.getFirst().getId(); String issuedValue = this.conventionService.isNullOrEmpty(issuedIdNode) ? null : description.getProperties().getFieldSets().values().stream().map(PropertyDefinitionFieldSet::getItems).flatMap(List::stream) .filter(x -> x.getFields() != null && x.getFields().containsKey(issuedIdNode)).map(x -> x.getFields().get(issuedIdNode).getTextValue()).findFirst().orElse(null); if (!this.conventionService.isNullOrEmpty(issuedValue)) { List licStartFieldSetsEntities = definition.getAllFieldSets().stream().filter(x -> x.getAllField() != null && x.getAllField().stream().anyMatch(y -> y.getSchematics() != null && y.getSchematics().contains("rda.dataset.distribution.license.start_date"))).toList(); for (FieldSetEntity licStartFieldSetEntity : licStartFieldSetsEntities) { List licStartEntities = licStartFieldSetEntity.getAllField().stream().filter(x -> x.getSchematics() != null && x.getSchematics().contains("rda.dataset.distribution.license.start_date")).toList(); if (!this.conventionService.isListNullOrEmpty(licStartEntities)) { this.ensureFieldSetEntity(description, licStartFieldSetEntity); for (FieldEntity licStartDateNode : licStartEntities) { description.getProperties().getFieldSets().get(licStartFieldSetEntity.getId()).getItems().getFirst().getFields().put(licStartDateNode.getId(), buildPropertyDefinitionFieldItemValue(licStartDateNode, semanticTarget, issuedValue, type)); } } } } } } } } } private void ensureFieldSetEntity(Description description, FieldSetEntity fieldSetEntity){ if (description.getProperties() == null) description.setProperties(new PropertyDefinition()); if (description.getProperties().getFieldSets() == null) description.getProperties().setFieldSets(new HashMap<>()); if (!description.getProperties().getFieldSets().containsKey(fieldSetEntity.getId())) description.getProperties().getFieldSets().put(fieldSetEntity.getId(), new PropertyDefinitionFieldSet()); if (description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems() == null) description.getProperties().getFieldSets().get(fieldSetEntity.getId()).setItems(new ArrayList<>()); if (this.conventionService.isListNullOrEmpty(description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems())) description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems().add(new PropertyDefinitionFieldSetItem()); if (description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems().getFirst().getFields() == null) description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems().getFirst().setFields(new HashMap<>()); if (description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems().getFirst().getOrdinal() == null) description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems().getFirst().setOrdinal(0); } private void prefillSemanticValueToDescription(Description description, String semanticTarget, String parsedValue, DefinitionEntity definition, String type) { if (this.conventionService.isNullOrEmpty(semanticTarget) || this.conventionService.isNullOrEmpty(parsedValue)) return; List fieldSetsEntities = definition.getAllFieldSets().stream().filter(x-> x.getAllField() != null && x.getAllField().stream().anyMatch(y-> !this.conventionService.isListNullOrEmpty(y.getSchematics()) && y.getSchematics().contains(semanticTarget))).toList(); for (FieldSetEntity fieldSetEntity: fieldSetsEntities) { List fieldEntities = fieldSetEntity.getAllField().stream().filter(x-> !this.conventionService.isListNullOrEmpty(x.getSchematics()) && x.getSchematics().contains(semanticTarget)).toList(); if (!this.conventionService.isListNullOrEmpty(fieldEntities)) { this.ensureFieldSetEntity(description, fieldSetEntity); for (FieldEntity fieldEntity : fieldEntities){ description.getProperties().getFieldSets().get(fieldSetEntity.getId()).getItems().getFirst().getFields().put(fieldEntity.getId() , buildPropertyDefinitionFieldItemValue(fieldEntity, semanticTarget, parsedValue, type)); } } } } private void prefillSystemValueToDescription(Description description, String systemFieldTarget, String parsedValue) { if (this.conventionService.isNullOrEmpty(systemFieldTarget) || this.conventionService.isNullOrEmpty(parsedValue)) return; switch (systemFieldTarget) { case Description._description -> description.setDescription(parsedValue); case Description._label -> description.setLabel(parsedValue); case Description._descriptionTags -> { String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, parsedValue); List finalValue = valuesParsed == null ? List.of(parsedValue) : Arrays.stream(valuesParsed).toList(); for (String tagString : finalValue) { if (description.getDescriptionTags() == null) description.setDescriptionTags(new ArrayList<>()); if (description.getDescriptionTags().stream().anyMatch(x -> x.getTag() != null && x.getTag().getLabel().equals(tagString))) continue; DescriptionTag descriptionTag = new DescriptionTag(); Tag tag = new Tag(); tag.setLabel(tagString.trim()); descriptionTag.setTag(tag); description.getDescriptionTags().add(descriptionTag); } } } } private Field buildPropertyDefinitionFieldItemValue(FieldEntity fieldEntity, String semanticTarget, String value, String type) { Field field = new Field(); if (fieldEntity == null || fieldEntity.getData() == null || fieldEntity.getData().getFieldType() == null || this.conventionService.isNullOrEmpty(value)) return field; try{ switch (fieldEntity.getData().getFieldType()){ case FREE_TEXT, TEXT_AREA, RICH_TEXT_AREA, RADIO_BOX -> field.setTextValue(value.toLowerCase(Locale.ROOT)); case CHECK_BOX, BOOLEAN_DECISION -> field.setTextValue(value.trim().toLowerCase(Locale.ROOT)); case DATE_PICKER ->{ Instant instant = null; try { if (!this.conventionService.isNullOrEmpty(type) && type.equals(Zenodo) && semanticTarget.equals("rda.dataset.distribution.available_until") ) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd"); LocalDate date = LocalDate.parse(value, formatter); date = date.plusYears(20); instant = date.atStartOfDay().toInstant(ZoneOffset.UTC); } else { instant = Instant.parse(value); } } catch (DateTimeParseException ex) { instant = LocalDate.parse(value).atStartOfDay().toInstant(ZoneOffset.UTC); if (!this.conventionService.isNullOrEmpty(type) && type.equals(Zenodo) && semanticTarget.equals("rda.dataset.distribution.available_until") ) { instant.plus(20, ChronoUnit.YEARS); } } field.setDateValue(instant); } case DATASET_IDENTIFIER -> { ExternalIdentifier externalIdentifier = new ExternalIdentifier(); externalIdentifier.setIdentifier(value); if(!this.conventionService.isNullOrEmpty(type) && type.equals(Zenodo)) externalIdentifier.setType("doi"); field.setExternalIdentifier(externalIdentifier); } case SELECT -> { String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value); List finalValue = valuesParsed == null ? List.of(value) : Arrays.stream(valuesParsed).toList(); SelectDataEntity selectDataEntity = (SelectDataEntity) fieldEntity.getData(); if (selectDataEntity == null || selectDataEntity.getOptions() == null) throw new MyApplicationException("Can not cast fieldEntity data"); field.setTextListValue(new ArrayList<>()); for (SelectDataEntity.OptionEntity entity : selectDataEntity.getOptions()){ if (finalValue.contains(entity.getValue()) || finalValue.contains(entity.getLabel())){ field.getTextListValue().add(entity.getValue()); } } } case TAGS -> { String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value); field.setTextListValue(valuesParsed == null ? List.of(value) : Arrays.stream(valuesParsed).toList()); //TODO Tags, Currency is ids } case REFERENCE_TYPES -> { String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value); List finalValue = valuesParsed == null ? List.of(value) : Arrays.stream(valuesParsed).toList(); ReferenceTypeDataEntity selectDataEntity = (ReferenceTypeDataEntity) fieldEntity.getData(); if (selectDataEntity == null) throw new MyApplicationException("Can not cast fieldEntity data"); field.setReferences(new ArrayList<>()); for (String like : finalValue){ ReferenceSearchLookup externalReferenceCriteria = new ReferenceSearchLookup(); externalReferenceCriteria.setLike(like); externalReferenceCriteria.setTypeId(selectDataEntity.getReferenceTypeId()); externalReferenceCriteria.setProject((BaseFieldSet) new BaseFieldSet() .ensure(Reference._id) .ensure(Reference._label) .ensure(Reference._type) .ensure(Reference._description) .ensure(this.conventionService.asIndexer(Reference._description, Definition._fields, eu.eudat.model.referencedefinition.Field._code)) .ensure(this.conventionService.asIndexer(Reference._description, Definition._fields, eu.eudat.model.referencedefinition.Field._dataType)) .ensure(this.conventionService.asIndexer(Reference._description, Definition._fields, eu.eudat.model.referencedefinition.Field._value)) .ensure(Reference._reference) .ensure(Reference._abbreviation) .ensure(Reference._source) .ensure(Reference._isActive) .ensure(Reference._createdAt) .ensure(Reference._updatedAt) .ensure(Reference._hash) ); List references = this.referenceService.searchReferenceData(externalReferenceCriteria); for (Reference reference : references){ if (reference.getReference().equals(like) || reference.getLabel().toUpperCase(Locale.ROOT).contains(like.toUpperCase(Locale.ROOT))) { field.getReferences().add(reference); } } } } case VALIDATION, UPLOAD, INTERNAL_ENTRIES_DMPS, INTERNAL_ENTRIES_DESCRIPTIONS -> throw new MyApplicationException("invalid type " + fieldEntity.getData().getFieldType()); default -> throw new MyApplicationException("invalid type " + fieldEntity.getData().getFieldType()); } } catch (Exception e){ logger.error("Could not parse value " + value + " of field " + fieldEntity.getId() + " with type " + fieldEntity.getData().getFieldType(), e); } return field; } private T tryParseJsonAsObjectString(Class type, String value){ T item = this.jsonHandlingService.fromJsonSafe(type, value); if (item == null) item = this.jsonHandlingService.fromJsonSafe(type, StringEscapeUtils.unescapeJava(value)); if (item == null) item = this.jsonHandlingService.fromJsonSafe(type, StringEscapeUtils.unescapeJson(value)); return item; } }