package eu.dnetlib.openaire.dsm.dao.utils; import java.sql.Date; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import com.fasterxml.jackson.databind.ObjectMapper; import eu.dnetlib.data.transform.xml.AbstractDNetXsltFunctions; import eu.dnetlib.miscutils.datetime.DateUtils; import eu.dnetlib.openaire.dsm.domain.ApiDetails; import eu.dnetlib.openaire.dsm.domain.DatasourceDetails; import eu.dnetlib.openaire.dsm.domain.DatasourceDetailsUpdate; import eu.dnetlib.openaire.dsm.domain.DatasourceSnippetExtended; import eu.dnetlib.openaire.dsm.domain.OrganizationDetails; import eu.dnetlib.openaire.dsm.domain.db.ApiDbEntry; import eu.dnetlib.openaire.dsm.domain.db.DatasourceDbEntry; import eu.dnetlib.openaire.dsm.domain.db.OrganizationDbEntry; public class DsmMappingUtils { public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String ID_SEPARATOR = "::"; public static final String ID_PREFIX = "api_________" + ID_SEPARATOR; public static String createId(final ApiDetails api) { return ID_PREFIX + api.getDatasource() + ID_SEPARATOR + RandomStringUtils.randomAlphanumeric(8); } public static DatasourceDetails asDetails(final DatasourceDbEntry d) { final DatasourceDetails details = _convert(d, DatasourceDetails.class); return details.setOpenaireId(asOpenaireId(details.getId())); } public static DatasourceSnippetExtended asSnippetExtended(final DatasourceDbEntry d) { final DatasourceSnippetExtended ds = new DatasourceSnippetExtended(); ds.setId(d.getId()); ds.setOfficialname(d.getOfficialname()); ds.setEnglishname(d.getEnglishname()); ds.setRegisteredby(d.getRegisteredby()); ds.setWebsiteurl(d.getWebsiteurl()); ds.setTypology(d.getTypology()); ds.setRegistrationdate(d.getRegistrationdate()); ds.setLogoUrl(d.getLogourl()); ds.setDescription(d.getDescription()); ds.setConsentTermsOfUse(d.getConsentTermsOfUse()); ds.setConsentTermsOfUseDate(d.getConsentTermsOfUseDate()); ds.setFullTextDownload(d.getFullTextDownload()); if (d.getOrganizations() != null) { ds.setOrganizations(d.getOrganizations().stream().map(DsmMappingUtils::asOrganizationDetail).collect(Collectors.toSet())); } return ds; } private static OrganizationDetails asOrganizationDetail(final OrganizationDbEntry o) { return new OrganizationDetails() .setCountry(o.getCountry()) .setLegalname(o.getLegalname()) .setLegalshortname(o.getLegalshortname()) .setWebsiteurl(o.getWebsiteurl()) .setLogourl(o.getLogourl()); } public static ApiDetails asDetails(final ApiDbEntry d) { return _convert(d, ApiDetails.class); } public static ApiDbEntry asDbEntry(final ApiDetails d) { final ApiDbEntry apiDbEntry = _convert(d, ApiDbEntry.class); // Need to complete the references among objects, because you know, referential integrity ... apiDbEntry.getApiParams().forEach(ap -> ap.getId().setApi(apiDbEntry)); return apiDbEntry; } public static DatasourceDbEntry asDbEntry(final DatasourceDetails d) { final DatasourceDbEntry dbe = _convert(d, DatasourceDbEntry.class); if (dbe.getOrganizations() != null) { dbe.getOrganizations().forEach(o -> { final String prefix = StringUtils.isNotBlank(dbe.getNamespaceprefix()) ? dbe.getNamespaceprefix() : dbe.getId(); o.setId(prefix + ID_SEPARATOR + o.getLegalname()); if (o.getDateofcollection() == null) { o.setDateofcollection(new Date(System.currentTimeMillis())); } o.setCollectedfrom(dbe.getCollectedfrom()); }); } return dbe; } public static DatasourceDbEntry asDbEntry(final DatasourceDetailsUpdate d) { return _convert(d, DatasourceDbEntry.class); } public static String asRepositoryProfile(final DatasourceDetails ds) { final Element root = DocumentHelper.createElement("RESOURCE_PROFILE"); final Element header = root.addElement("HEADER"); header.addElement("RESOURCE_IDENTIFIER").addAttribute("value", ""); header.addElement("RESOURCE_TYPE").addAttribute("value", "RepositoryServiceResourceType"); header.addElement("RESOURCE_KIND").addAttribute("value", "RepositoryServiceResources"); header.addElement("RESOURCE_URI").addAttribute("value", ""); header.addElement("DATE_OF_CREATION").addAttribute("value", DateUtils.now_ISO8601()); header.addElement("PROTOCOL"); final Element body = root.addElement("BODY"); final Element conf = body.addElement("CONFIGURATION"); conf.addElement("DATASOURCE_TYPE").setText(ds.getTypology()); final Element origId = conf.addElement("DATASOURCE_ORIGINAL_ID"); origId.addAttribute("provenance", "D-NET"); origId.setText(ds.getId()); conf.addElement("DATASOURCE_AGGREGATED").setText("false"); conf.addElement("ENVIRONMENTS").addElement("ENVIRONMENT").setText("OPENAIRE"); conf.addElement("TYPOLOGY").setText("" + ds.getTypology()); conf.addElement("MAX_SIZE_OF_DATASTRUCTURE").setText("0"); conf.addElement("AVAILABLE_DISKSPACE").setText("0"); conf.addElement("MAX_NUMBER_OF_DATASTRUCTURE").setText("0"); final String officialName = ds.getOfficialname(); conf.addElement("OFFICIAL_NAME").setText(officialName); final String englishName = ds.getEnglishname(); conf.addElement("ENGLISH_NAME").setText(StringUtils.isNotBlank(englishName) ? englishName : officialName); conf.addElement("ICON_URI").setText("" + ds.getLogourl()); final OrganizationDetails org = getOrganization(ds); conf.addElement("COUNTRY").setText(org != null ? org.getCountry() : ""); final Element location = conf.addElement("LOCATION"); location.addElement("LONGITUDE").setText("" + ds.getLongitude()); location.addElement("LATITUDE").setText("" + ds.getLatitude()); location.addElement("TIMEZONE").setText("" + ds.getTimezone()); conf.addElement("REPOSITORY_WEBPAGE").setText(ds.getWebsiteurl()); getOrganization(ds); conf.addElement("REPOSITORY_INSTITUTION").setText(org != null ? org.getLegalname() : ""); conf.addElement("ADMIN_INFO").setText(ds.getContactemail()); conf.addElement("INTERFACES"); final Element extraFields = conf.addElement("EXTRA_FIELDS"); addExtraField(extraFields, "OpenAireDataSourceId", ds.getId()); addExtraField(extraFields, "ACTIVATION_ID", ds.getActivationId()); addExtraField(extraFields, "NamespacePrefix", ds.getNamespaceprefix()); addExtraField(extraFields, "aggregatorName", ds.getAggregator()); addExtraField(extraFields, "dateOfCollection", "" + ds.getDateofcollection()); addExtraField(extraFields, "dateOfValidation", "" + ds.getDateofvalidation()); conf.addElement("REGISTERED_BY").setText(ds.getRegisteredby()); final Element status = body.addElement("STATUS"); status.addElement("NUMBER_OF_OBJECTS").setText("0"); status.addElement("LAST_UPDATE").addAttribute("value", DateUtils.now_ISO8601()); final Element qos = body.addElement("QOS"); qos.addElement("AVAILABILITY").setText("0"); qos.addElement("CAPACITY"); qos.addElement("THROUGHPUT").setText("0"); body.addElement("SECURITY_PARAMETERS"); body.addElement("BLACKBOARD"); return root.asXML(); } public static String asRepositoryInterfce(final ApiDetails api) { final Element iface = DocumentHelper.createElement("INTERFACE"); iface.addAttribute("active", String.valueOf(api.getActive())) .addAttribute("compliance", api.getCompatibility()) .addAttribute("contentDescription", api.getContentdescription()) .addAttribute("id", api.getId()) .addAttribute("label", String.format("%s (%s)", api.getTypology(), api.getCompatibility())) .addAttribute("removable", String.valueOf(api.getRemovable())) .addAttribute("typology", api.getTypology()); iface.addElement("ACCESS_PROTOCOL").setText(api.getProtocol()); if (api.getApiParams() != null) { final Element accessProtocol = (Element) iface.selectSingleNode("./ACCESS_PROTOCOL"); api.getApiParams().forEach(ap -> { accessProtocol.addAttribute(ap.getParam(), ap.getValue()); }); } iface.addElement("BASE_URL").setText(api.getBaseurl()); iface.addElement("INTERFACE_EXTRA_FIELD").addAttribute("name", "last_collection_date"); iface.addElement("INTERFACE_EXTRA_FIELD").addAttribute("name", "last_collection_mdId"); iface.addElement("INTERFACE_EXTRA_FIELD").addAttribute("name", "last_collection_total"); iface.addElement("INTERFACE_EXTRA_FIELD").addAttribute("name", "last_aggregation_date"); iface.addElement("INTERFACE_EXTRA_FIELD").addAttribute("name", "last_aggregation_mdId"); iface.addElement("INTERFACE_EXTRA_FIELD").addAttribute("name", "last_aggregation_total"); final Element mdPathNode = iface.addElement("INTERFACE_EXTRA_FIELD"); mdPathNode.addAttribute("name", "metadata_identifier_path"); if (StringUtils.isNotBlank(api.getMetadataIdentifierPath())) { mdPathNode.setText(api.getMetadataIdentifierPath()); } return iface.asXML(); } // HELPERS private static T _convert(final Object o, final Class clazz) { final ObjectMapper mapper = new ObjectMapper(); return mapper.convertValue(o, clazz); } private static OrganizationDetails getOrganization(final DatasourceDetails ds) { if (ds.getOrganizations() != null && !ds.getOrganizations().isEmpty()) { return ds.getOrganizations().stream().findFirst().get(); } return null; } private static void addExtraField(final Element extraFields, final String field, final String value) { final Element f = extraFields.addElement("FIELD"); f.addElement("key").setText(field); f.addElement("value").setText(value != null ? value : ""); } private static String asOpenaireId(final String id) { final String prefix = StringUtils.substringBefore(id, ID_SEPARATOR); final String md5 = StringUtils.substringAfter(id, ID_SEPARATOR); return prefix + ID_SEPARATOR + AbstractDNetXsltFunctions.md5(md5); } public static void copyNonNullProperties(final Object src, final Object target) { BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); } public static String[] getNullPropertyNames(final Object source) { final BeanWrapper src = new BeanWrapperImpl(source); final java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); final Set emptyNames = new HashSet<>(); for (final java.beans.PropertyDescriptor pd : pds) { final Object srcValue = src.getPropertyValue(pd.getName()); if (srcValue == null) { emptyNames.add(pd.getName()); } } final String[] result = new String[emptyNames.size()]; return emptyNames.toArray(result); } }