package eu.dnetlib.openaire.community; import com.google.common.base.Functions; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import eu.dnetlib.openaire.common.ISClient; import eu.dnetlib.openaire.context.Context; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; import static eu.dnetlib.openaire.community.CommunityConstants.*; @Component @ConditionalOnProperty(value = "openaire.exporter.enable.community", havingValue = "true") public class CommunityApiCore {//implements CommunityClient{ private static final Log log = LogFactory.getLog(CommunityApiCore.class); @Autowired private CommunityClient cci; @Autowired private ISClient isClient; @Autowired private CommunityCommon cc; public List listCommunities() throws CommunityException { return cc.listCommunities(); } public CommunityDetails getCommunity(final String id) throws CommunityException, CommunityNotFoundException { return cc.getCommunity(id); } public void setCommunity(final String id, final CommunityWritableProperties details) throws CommunityException, CommunityNotFoundException { cc.getCommunity(id); // ensure the community exists. if(details.getShortName() != null) { isClient.updateContextAttribute(id, CLABEL, details.getShortName()); } if (details.getName() != null){ isClient.updateContextParam(id, CSUMMARY_NAME, details.getName()); } if(details.getDescription() != null) { isClient.updateContextParam(id, CSUMMARY_DESCRIPTION, details.getDescription()); } if(details.getLogoUrl()!=null){ isClient.updateContextParam(id, CSUMMARY_LOGOURL, details.getLogoUrl()); } if (details.getStatus() != null) { isClient.updateContextParam(id, CSUMMARY_STATUS, details.getStatus().name()); } if (details.getSubjects() != null) { isClient.updateContextParam(id, CPROFILE_SUBJECT, Joiner.on(CSV_DELIMITER).join(details.getSubjects())); } if (details.getMainZenodoCommunity() != null) { isClient.updateContextParam(id, CSUMMARY_ZENODOC, details.getMainZenodoCommunity()); } cc.updateCommunity(id, details); } public List getCommunityProjects(final String id) throws CommunityException, CommunityNotFoundException { cc.getCommunity(id); // ensure the community exists. return cc.getCommunityInfo(id, PROJECTS_ID_SUFFIX, c -> CommunityMappingUtils.asCommunityProject(id, c)); } public CommunityProject addCommunityProject(final String id, final CommunityProject project) throws CommunityException, CommunityNotFoundException { if (!StringUtils.equalsIgnoreCase(id, project.getCommunityId())) { throw new CommunityException("parameters 'id' and project.communityId must be coherent"); } final TreeMap projects = getCommunityProjectMap(id); String project_id = project.getId(); if (project_id != null && projects.keySet().contains(Integer.valueOf(project_id))){ if (project.getName() != null) { isClient.updateConceptParam(id + PROJECTS_ID_SUFFIX + ID_SEPARATOR + project_id, CPROJECT_FULLNAME,project.getName()); } if(project.getAcronym()!= null){ isClient.updateConceptParam(id + PROJECTS_ID_SUFFIX + ID_SEPARATOR + project_id, CPROJECT_ACRONYM,project.getAcronym()); } if (project.getOpenaireId() != null){ isClient.updateConceptParam(id + PROJECTS_ID_SUFFIX + ID_SEPARATOR + project_id, OPENAIRE_ID, project.getOpenaireId()); } if (project.getFunder() != null){ isClient.updateConceptParam(id + PROJECTS_ID_SUFFIX + ID_SEPARATOR + project_id, CPROJECT_FUNDER, project.getFunder()); } if(project.getGrantId() != null){ isClient.updateConceptParam(id + PROJECTS_ID_SUFFIX + ID_SEPARATOR + project_id, CPROJECT_NUMBER, project.getGrantId()); } }else { project.setId(nextId(projects != null && !projects.isEmpty() ? projects.lastKey() : 0)); isClient.addConcept(id, id + PROJECTS_ID_SUFFIX, CommunityMappingUtils.asProjectXML(id, project)); } cc.updateProject(id, project ); return project; } private String nextId(final Integer id) { return String.valueOf(id + 1); } public void removeCommunityProject(final String id, final Integer projectId) throws CommunityException, CommunityNotFoundException { final Map projects = getCommunityProjectMap(id); if (!projects.containsKey(projectId)) { throw new CommunityNotFoundException(String.format("project '%s' doesn't exist within context '%s'", projectId, id)); } isClient.removeConcept( id, id + PROJECTS_ID_SUFFIX, id + PROJECTS_ID_SUFFIX + ID_SEPARATOR + projectId); cc.removeFromCategory(id, PROJECTS_ID_SUFFIX, String.valueOf(projectId)); } public List getCommunityContentproviders(final String id) throws CommunityException, CommunityNotFoundException { cc.getCommunity(id); // ensure the community exists. return cc.getCommunityInfo(id, CONTENTPROVIDERS_ID_SUFFIX, c -> CommunityMappingUtils.asCommunityDataprovider(id, c)); } public CommunityContentprovider addCommunityContentprovider(final String id, final CommunityContentprovider cp) throws CommunityException, CommunityNotFoundException { log.info("content provider to add " + cp.toString()); if (!StringUtils.equalsIgnoreCase(id, cp.getCommunityId())) { throw new CommunityException("parameters 'id' and cp.communityId must be coherent"); } final TreeMap cps = getCommunityContentproviderMap(id); final String concept_id = cp.getId(); if (concept_id != null && cps.keySet().contains(Integer.valueOf(concept_id))){ if (cp.getName() != null) { isClient.updateConceptParam(id + CONTENTPROVIDERS_ID_SUFFIX + ID_SEPARATOR + concept_id, CCONTENTPROVIDER_NAME,cp.getName()); } if(cp.getOfficialname()!= null){ isClient.updateConceptParam(id + CONTENTPROVIDERS_ID_SUFFIX + ID_SEPARATOR + concept_id, CCONTENTPROVIDER_OFFICIALNAME,cp.getOfficialname()); } if (cp.getOpenaireId() != null){ isClient.updateConceptParam(id + CONTENTPROVIDERS_ID_SUFFIX + ID_SEPARATOR + concept_id, OPENAIRE_ID,cp.getOpenaireId()); } if(cp.getSelectioncriteria() != null){ isClient.updateConceptParamNoEscape(id + CONTENTPROVIDERS_ID_SUFFIX + ID_SEPARATOR + concept_id, CCONTENTPROVIDER_SELCRITERIA, cp.toXML()); } }else{ log.info("adding new concept for community " + id); cp.setId(nextId(!cps.isEmpty() ? cps.lastKey() : 0)); isClient.addConcept(id, id + CONTENTPROVIDERS_ID_SUFFIX, CommunityMappingUtils.asContentProviderXML(id, cp)); } cc.updateDatasource(id, cp); return cp; } public void removeCommunityContentProvider(final String id, final Integer contentproviderId) throws CommunityException, CommunityNotFoundException { final Map providers = getCommunityContentproviderMap(id); if (!providers.containsKey(contentproviderId)) { throw new CommunityNotFoundException(String.format("content provider '%s' doesn't exist within context '%s'", contentproviderId, id)); } isClient.removeConcept( id, id + CONTENTPROVIDERS_ID_SUFFIX, id + CONTENTPROVIDERS_ID_SUFFIX + ID_SEPARATOR + contentproviderId); cc.removeFromCategory(id, CONTENTPROVIDERS_ID_SUFFIX, String.valueOf(contentproviderId)); } public void removeCommunityOrganization(String id, Integer organizationId) throws CommunityException, CommunityNotFoundException { final Map organizations = getCommunityOrganizationMap(id); if (!organizations.containsKey(organizationId)) { throw new CommunityNotFoundException(String.format("organization '%s' doesn't exist within context '%s'", organizationId, id)); } isClient.removeConcept( id, id + ORGANIZATION_ID_SUFFIX, id + ORGANIZATION_ID_SUFFIX + ID_SEPARATOR + organizationId); cc.removeFromCategory(id, ORGANIZATION_ID_SUFFIX, String.valueOf(organizationId)); } public List getCommunityZenodoCommunities(final String id) throws CommunityException, CommunityNotFoundException { return cc.getCommunityZenodoCommunities(id); } public List getCommunityOrganizations(final String id) throws CommunityException, CommunityNotFoundException { cc.getCommunity(id); return cc.getCommunityInfo(id,ORGANIZATION_ID_SUFFIX,c->CommunityMappingUtils.asCommunityOrganization(id,c)); } public CommunityDetails addCommunitySubjects(final String id, final List subjects) throws CommunityException, CommunityNotFoundException { final CommunityDetails cd = new CommunityDetails(); final Set current = Sets.newHashSet(cc.getCommunity(id).getSubjects()); current.addAll(subjects); cd.setSubjects(Lists.newArrayList(current)); setCommunity(id, CommunityWritableProperties.fromDetails(cd)); return cd; } public CommunityDetails removeCommunitySubjects(final String id, final List subjects) throws CommunityException, CommunityNotFoundException { final CommunityDetails cd = new CommunityDetails(); final Set current = Sets.newHashSet(cc.getCommunity(id).getSubjects()); current.removeAll(subjects); cd.setSubjects(Lists.newArrayList(current)); setCommunity(id, CommunityWritableProperties.fromDetails(cd)); return cd; } @CacheEvict(value="community-cache",allEntries = true) public void removeCommunityZenodoCommunity(final String id, final Integer zenodoCommId) throws CommunityException, CommunityNotFoundException { final Map zcomms = getZenodoCommunityMap(id); if (!zcomms.containsKey(zenodoCommId)) { throw new CommunityNotFoundException(String.format("Zenodo community '%s' doesn't exist within context '%s'", zenodoCommId, id)); } isClient.removeConcept( id, id + ZENODOCOMMUNITY_ID_SUFFIX, id + ZENODOCOMMUNITY_ID_SUFFIX + ID_SEPARATOR + zenodoCommId); cc.removeFromCategory(id, ZENODOCOMMUNITY_ID_SUFFIX, String.valueOf(zenodoCommId)); } @CacheEvict(value="community-cache",allEntries = true) public CommunityZenodoCommunity addCommunityZenodoCommunity(final String id, final CommunityZenodoCommunity zc) throws CommunityException, CommunityNotFoundException { if (!StringUtils.equalsIgnoreCase(id, zc.getCommunityId())) { throw new CommunityException("parameters 'id' and zc.communityId must be coherent"); } if(!StringUtils.isNotBlank(zc.getZenodoid())){ throw new CommunityException("parameter zenodoid cannot be null or empty"); } final TreeMap zcs = getZenodoCommunityMap(id); for(CommunityZenodoCommunity czc : zcs.values()){ if (czc.getZenodoid().equals(zc.getZenodoid())){ throw new CommunityException("Zenodo community already associated to the RCD"); } } zc.setId(nextId(!zcs.isEmpty() ? zcs.lastKey() : 0)); isClient.addConcept(id, id + ZENODOCOMMUNITY_ID_SUFFIX, CommunityMappingUtils.asZenodoCommunityXML(id, zc)); cc.updateZenodoCommunity(id, zc); return zc; } public CommunityOpenAIRECommunities getOpenAIRECommunities(String zenodoId) throws CommunityException, CommunityNotFoundException { if(cci.getInverseZenodoCommunityMap().containsKey(zenodoId)) return new CommunityOpenAIRECommunities().setZenodoid(zenodoId).setOpenAirecommunitylist(cci.getInverseZenodoCommunityMap().get(zenodoId).stream().collect(Collectors.toList())); return new CommunityOpenAIRECommunities(); } // HELPERS private TreeMap getCommunityProjectMap(final String id) throws CommunityException, CommunityNotFoundException { return getCommunityProjects(id).stream() .collect(Collectors.toMap( p -> Integer.valueOf(p.getId()), Functions.identity(), (p1, p2) -> { log.warn(String.format("duplicate project found: '%s'", p1.getId())); return p2; }, TreeMap::new)); } private TreeMap getCommunityContentproviderMap(final String id) throws CommunityException, CommunityNotFoundException { log.info("getting community content provider map"); return getCommunityContentproviders(id).stream() .collect(Collectors.toMap( cp -> Integer.valueOf(cp.getId()), Functions.identity(), (cp1, cp2) -> { log.warn(String.format("duplicate content provider found: '%s'", cp1.getId())); return cp2; }, TreeMap::new)); } private TreeMap getZenodoCommunityMap(final String id) throws CommunityException, CommunityNotFoundException{ return getCommunityZenodoCommunities(id).stream() .collect(Collectors.toMap( cp -> Integer.valueOf(cp.getId()), Functions.identity(), (cp1, cp2) -> { log.warn(String.format("duplicate Zenodo community found: '%s'", cp1.getId())); return cp2; }, TreeMap::new)); } private TreeMap getCommunityOrganizationMap(final String id) throws CommunityException, CommunityNotFoundException { return getCommunityOrganizations(id).stream() .collect(Collectors.toMap( o -> Integer.valueOf(o.getId()), Functions.identity(), (o1, o2) -> { log.warn(String.format("duplicate content provider found: '%s'", o1.getId())); return o2; }, TreeMap::new)); } private Map getContextMap() throws CommunityException { try { return isClient.getCommunityContextMap(); } catch (IOException e) { throw new CommunityException(e); } } public CommunityOrganization addCommunityOrganization(String id, CommunityOrganization organization) throws CommunityException, CommunityNotFoundException { if (!StringUtils.equalsIgnoreCase(id, organization.getCommunityId())) { throw new CommunityException("parameters 'id' and organization.communityId must be coherent"); } final TreeMap cps = getCommunityOrganizationMap(id); final String organization_id = organization.getId(); if (organization_id != null && cps.keySet().contains(Integer.valueOf(organization_id))){ if (organization.getName() != null) { isClient.updateConceptParam(id + ORGANIZATION_ID_SUFFIX + ID_SEPARATOR + organization_id, CORGANIZATION_NAME,organization.getName()); } if(organization.getLogo_url()!= null){ isClient.updateConceptParam(id + ORGANIZATION_ID_SUFFIX + ID_SEPARATOR + organization_id, CORGANIZATION_LOGOURL, Base64.getEncoder().encodeToString(organization.getLogo_url().getBytes())); } if (organization.getWebsite_url() != null){ isClient.updateConceptParam(id + ORGANIZATION_ID_SUFFIX + ID_SEPARATOR + organization_id, CORGANIZATION_WEBSITEURL,Base64.getEncoder().encodeToString(organization.getWebsite_url().getBytes())); } }else{ organization.setId(nextId(!cps.isEmpty() ? cps.lastKey() : 0)); isClient.addConcept(id, id + ORGANIZATION_ID_SUFFIX, CommunityMappingUtils.asOrganizationXML(id, organization)); } cc.updateOrganization(id, organization); return organization; } }