Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/OpenaireExporterConfig.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/OpenaireExporterConfig.java	(revision 51423)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/OpenaireExporterConfig.java	(revision 51424)
@@ -19,6 +19,8 @@
 	private ClassPathResource findSolrIndexUrl;
 	private ClassPathResource findIndexDsInfo;
 	private ClassPathResource findObjectStore;
+	private ClassPathResource findFunderContexts;
+	private ClassPathResource findCommunityContexts;
 
 	private String isLookupUrl;
 	private String objectStoreServiceUrl;
@@ -342,6 +344,22 @@
 		this.findObjectStore = findObjectStore;
 	}
 
+	public ClassPathResource getFindFunderContexts() {
+		return findFunderContexts;
+	}
+
+	public void setFindFunderContexts(final ClassPathResource findFunderContexts) {
+		this.findFunderContexts = findFunderContexts;
+	}
+
+	public ClassPathResource getFindCommunityContexts() {
+		return findCommunityContexts;
+	}
+
+	public void setFindCommunityContexts(final ClassPathResource findCommunityContexts) {
+		this.findCommunityContexts = findCommunityContexts;
+	}
+
 	public void setFindIndexDsInfo(final ClassPathResource findIndexDsInfo) {
 		this.findIndexDsInfo = findIndexDsInfo;
 	}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityNotFoundException.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityNotFoundException.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityNotFoundException.java	(revision 51424)
@@ -0,0 +1,18 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseBody
+@ResponseStatus(value = HttpStatus.NOT_FOUND)
+public class CommunityNotFoundException extends Exception {
+
+	public CommunityNotFoundException(final String msg) {
+		super(msg);
+	}
+
+	public CommunityNotFoundException(final Exception e) {
+		super(e);
+	}
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityMappingUtils.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityMappingUtils.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityMappingUtils.java	(revision 51424)
@@ -0,0 +1,147 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.common.escape.Escaper;
+import com.google.common.xml.XmlEscapers;
+import eu.dnetlib.openaire.exporter.context.Concept;
+import eu.dnetlib.openaire.exporter.context.Context;
+import eu.dnetlib.openaire.exporter.context.Param;
+import org.apache.commons.lang3.StringUtils;
+
+import static eu.dnetlib.openaire.exporter.community.CommunityConstants.*;
+
+public class CommunityMappingUtils {
+
+	public static CommunitySummary asCommunitySummary(final Context c) {
+		final CommunitySummary summary = new CommunitySummary();
+
+		summary.setId(c.getId());
+		summary.setShortName(c.getLabel());
+		summary.setQueryId(c.getId() + PIPE_SEPARATOR + c.getLabel());
+
+		final Map<String, List<Param>> params = c.getParams();
+		if (params.containsKey(CSUMMARY_DESCRIPTION)) {
+			summary.setDescription(asCsv(params.get(CSUMMARY_DESCRIPTION)));
+		}
+		if (params.containsKey(CSUMMARY_LOGOURL)) {
+			summary.setLogoUrl(asCsv(params.get(CSUMMARY_LOGOURL)));
+		}
+		if (params.containsKey(CSUMMARY_NAME)) {
+			summary.setName(asCsv(params.get(CSUMMARY_NAME)));
+		}
+		if (params.containsKey(CSUMMARY_MANAGER)) {
+			summary.setManagers(splitValues(asValues(params.get(CSUMMARY_MANAGER)), CSV_DELIMITER));
+		}
+
+		return summary;
+	}
+
+	public static CommunityDetails asCommunityProfile(final Context c) {
+
+		final CommunityDetails p = new CommunityDetails(asCommunitySummary(c));
+		p.setType(c.getType());
+		p.setCreationDate(c.getDateofcreation());
+		final Map<String, List<Param>> params = c.getParams();
+		if (params.containsKey(CPROFILE_SUBJECT)) {
+			p.setSubjects(splitValues(asValues(params.get(CPROFILE_SUBJECT)), CSV_DELIMITER));
+		}
+
+		return p;
+	}
+
+	public static CommunityProject asCommunityProject(final String communityId, final Concept c) {
+
+		final Map<String, List<Param>> p = c.getParams();
+		final CommunityProject project = new CommunityProject();
+		project.setCommunityId(communityId);
+		project.setId(StringUtils.substringAfterLast(c.getId(), ID_SEPARATOR));
+		project.setOpenaireId(firstValue(p, OPENAIRE_ID));
+		project.setFunder(firstValue(p, CPROJECT_FUNDER));
+		project.setGrantId(firstValue(p, CPROJECT_NUMBER));
+		project.setName(firstValue(p, CPROJECT_FULLNAME));
+		project.setAcronym(firstValue(p, CPROJECT_ACRONYM));
+
+		return project;
+	}
+
+	public static CommunityContentprovider asCommunityDataprovider(final String communityId, final Concept c) {
+
+		final Map<String, List<Param>> p = c.getParams();
+		final CommunityContentprovider d = new CommunityContentprovider();
+		d.setCommunityId(communityId);
+		d.setId(StringUtils.substringAfterLast(c.getId(), ID_SEPARATOR));
+		d.setOpenaireId(firstValue(p, OPENAIRE_ID));
+		d.setName(firstValue(p, CCONTENTPROVIDER_NAME));
+		d.setOfficialname(firstValue(p, CCONTENTPROVIDER_OFFICIALNAME));
+
+		return d;
+	}
+
+	private static List<String> splitValues(final Stream<String> stream, final String separator) {
+		return stream.map(s -> s.split(separator))
+				.map(Arrays::asList)
+				.flatMap(List::stream)
+				.collect(Collectors.toList());
+	}
+
+	private static String firstValue(final Map<String, List<Param>> p, final String paramName) {
+		final Optional<String> first = asValues(p.get(paramName)).findFirst();
+		return first.isPresent() ? first.get() : null;
+	}
+
+	private static String asCsv(final List<Param> params) {
+		return asValues(params)
+				.collect(Collectors.joining(CSV_DELIMITER));
+	}
+
+	private static Stream<String> asValues(final List<Param> params) {
+		return params == null ? Stream.empty() : params.stream()
+				.map(Param::getValue)
+				.distinct();
+	}
+
+	public static String asProjectXML(final String contextId, final CommunityProject project) {
+		final Escaper esc = XmlEscapers.xmlAttributeEscaper();
+		final StringBuilder sb = new StringBuilder();
+		sb.append(
+				String.format(
+						"<concept claim='true' id='%s%s%s%s' label='%s'>\n",
+						escape(esc, contextId), PROJECTS_ID_SUFFIX, ID_SEPARATOR, escape(esc, String.valueOf(project.getId())), escape(esc, project.getAcronym())));
+		sb.append(paramXML(CPROJECT_FULLNAME, project.getName()));
+		sb.append(paramXML(CPROJECT_ACRONYM, project.getAcronym()));
+		sb.append(paramXML(CPROJECT_NUMBER, project.getGrantId()));
+		sb.append(paramXML(CPROJECT_FUNDER, project.getFunder()));
+		sb.append(paramXML(OPENAIRE_ID, project.getOpenaireId()));
+		sb.append("</concept>\n");
+		return sb.toString();
+	}
+
+	public static String asContentProviderXML(final String contextId, final CommunityContentprovider ccp) {
+		final Escaper esc = XmlEscapers.xmlAttributeEscaper();
+		final StringBuilder sb = new StringBuilder();
+		sb.append(
+				String.format(
+						"<concept claim='true' id='%s%s%s%s' label='%s'>\n",
+						escape(esc, contextId), CONTENTPROVIDERS_ID_SUFFIX, ID_SEPARATOR, escape(esc, String.valueOf(ccp.getId())), escape(esc, ccp.getName())));
+		sb.append(paramXML(OPENAIRE_ID, ccp.getOpenaireId()));
+		sb.append(paramXML(CCONTENTPROVIDER_NAME, ccp.getName()));
+		sb.append(paramXML(CCONTENTPROVIDER_OFFICIALNAME, ccp.getOfficialname()));
+		sb.append("</concept>\n");
+		return sb.toString();
+	}
+
+	private static String paramXML(final String paramName, final String value) {
+		return String.format("<param name='%s'>%s</param>\n", paramName, escape(XmlEscapers.xmlContentEscaper(), value));
+	}
+
+	public static String escape(final Escaper esc, final String value) {
+		return StringUtils.isNotBlank(value) ? esc.escape(value) : "";
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityConstants.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityConstants.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityConstants.java	(revision 51424)
@@ -0,0 +1,41 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+
+public class CommunityConstants {
+
+	public final static Set<String> communityBlackList = Sets.newHashSet("fet-fp7", "fet-h2020");
+
+	// common
+	public final static String OPENAIRE_ID = "openaireId";
+	public final static String PIPE_SEPARATOR = "||";
+	public final static String ID_SEPARATOR = "::";
+	public final static String CSV_DELIMITER = ", ";
+	public final static String CLABEL = "label";
+
+	// id suffixes
+	public final static String PROJECTS_ID_SUFFIX = ID_SEPARATOR + "projects";
+	public final static String CONTENTPROVIDERS_ID_SUFFIX = ID_SEPARATOR + "contentproviders";
+
+	// community summary
+	public final static String CSUMMARY_DESCRIPTION = "description";
+	public final static String CSUMMARY_LOGOURL = "logourl";
+	public final static String CSUMMARY_NAME = "name";
+	public final static String CSUMMARY_MANAGER = "manager";
+
+	// community profile
+	public final static String CPROFILE_SUBJECT = "subject";
+
+	// community project
+	public final static String CPROJECT_FUNDER = "funder";
+	public final static String CPROJECT_NUMBER = "CD_PROJECT_NUMBER";
+	public final static String CPROJECT_FULLNAME = "projectfullname";
+	public final static String CPROJECT_ACRONYM = "projectacronym";
+
+	// community content provider
+	public final static String CCONTENTPROVIDER_NAME = "name";
+	public final static String CCONTENTPROVIDER_OFFICIALNAME = "officialname";
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityApiController.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityApiController.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityApiController.java	(revision 51424)
@@ -0,0 +1,147 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.util.List;
+
+import eu.dnetlib.common.rmi.DNetRestDocumentation;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@DNetRestDocumentation
+@CrossOrigin(origins = { "*" })
+@io.swagger.annotations.Api(value = "community", description = "the OpenAIRE Community API")
+public class CommunityApiController {
+
+	@Autowired
+	private CommunityApiCore communityApiCore;
+
+	@RequestMapping(value = "/community/communities", produces = { "application/json" }, method = RequestMethod.GET)
+	@ApiOperation(
+			value = "get all community profiles",
+			notes = "get all community profiles",
+			response = CommunitySummary[].class)
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK", response = CommunitySummary[].class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public List<CommunitySummary> listCommunities() throws CommunityException {
+		return communityApiCore.listCommunities();
+	}
+
+	@RequestMapping(value = "/community/{id}", produces = { "application/json" }, method = RequestMethod.GET)
+	@ApiOperation(
+			value = "get community profile",
+			notes = "get community profile",
+			response = CommunityDetails.class)
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK", response = CommunityDetails.class),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public CommunityDetails getCommunity(@PathVariable final String id) throws CommunityException, CommunityNotFoundException {
+		return communityApiCore.getCommunity(id);
+	}
+
+	@RequestMapping(value = "/community/{id}", produces = { "application/json" }, method = RequestMethod.POST)
+	@ApiOperation(
+			value = "update community details",
+			notes = "update community details")
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK"),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public void setCommunity(
+			@PathVariable final String id,
+			@RequestBody CommunityWritableProperties properties) throws CommunityException, CommunityNotFoundException {
+
+		communityApiCore.setCommunity(id, properties);
+	}
+
+	@RequestMapping(value = "/community/{id}/projects", produces = { "application/json" }, method = RequestMethod.GET)
+	@ApiOperation(
+			value = "get community projects",
+			notes = "get community projects",
+			response = CommunityProject[].class)
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK", response = CommunityProject[].class),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public List<CommunityProject> getCommunityProjects(@PathVariable final String id) throws CommunityException, CommunityNotFoundException {
+		return communityApiCore.getCommunityProjects(id);
+	}
+
+	@RequestMapping(value = "/community/{id}/projects", produces = { "application/json" }, method = RequestMethod.POST)
+	@ApiOperation(
+			value = "associate a project to the community",
+			notes = "associate a project to the community")
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK"),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public CommunityProject addCommunityProject(
+			@PathVariable final String id,
+			@RequestBody final CommunityProject project) throws CommunityException, CommunityNotFoundException {
+
+		return communityApiCore.addCommunityProject(id, project);
+	}
+
+	@RequestMapping(value = "/community/{id}/projects", produces = { "application/json" }, method = RequestMethod.DELETE)
+	@ApiOperation(
+			value = "remove a project from the community",
+			notes = "remove a project from the community")
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK"),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public void deleteCommunityProject(
+			@PathVariable final String id,
+			@RequestBody final Integer projectId) throws CommunityException, CommunityNotFoundException {
+
+		communityApiCore.removeCommunityProject(id, projectId);
+	}
+
+	@RequestMapping(value = "/community/{id}/contentproviders", produces = { "application/json" }, method = RequestMethod.GET)
+	@ApiOperation(
+			value = "get the list of content providers associated to a given community",
+			notes = "get the list of content providers associated to a given community",
+			response = CommunityContentprovider[].class)
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK", response = CommunityContentprovider[].class),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public List<CommunityContentprovider> getCommunityContentproviders(@PathVariable final String id) throws CommunityException, CommunityNotFoundException {
+		return communityApiCore.getCommunityContentproviders(id);
+	}
+
+	@RequestMapping(value = "/community/{id}/contentproviders", produces = { "application/json" }, method = RequestMethod.POST)
+	@ApiOperation(
+			value = "associate a content provider to the community",
+			notes = "associate a content provider to the community")
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK"),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public CommunityContentprovider addCommunityContentprovider(
+			@PathVariable final String id,
+			@RequestBody final CommunityContentprovider contentprovider) throws CommunityException, CommunityNotFoundException {
+
+		return communityApiCore.addCommunityContentprovider(id, contentprovider);
+	}
+
+	@RequestMapping(value = "/community/{id}/contentproviders", produces = { "application/json" }, method = RequestMethod.DELETE)
+	@ApiOperation(
+			value = "remove the association between a content provider and the community",
+			notes = "remove the association between a content provider and the community")
+	@ApiResponses(value = {
+			@ApiResponse(code = 200, message = "OK"),
+			@ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class),
+			@ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) })
+	public void removeCommunityContentprovider(
+			@PathVariable final String id,
+			@RequestBody final Integer contentproviderId) throws CommunityException, CommunityNotFoundException {
+
+		communityApiCore.removeCommunityContentProvider(id, contentproviderId);
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunitySummary.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunitySummary.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunitySummary.java	(revision 51424)
@@ -0,0 +1,117 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import io.swagger.annotations.ApiModelProperty;
+
+@JsonAutoDetect
+public class CommunitySummary {
+
+	@ApiModelProperty("identifies the community")
+	protected String id;
+
+	@ApiModelProperty("values for this field reflect the index field _community_ in the index, e.g. 'egi||EGI Federation'")
+	protected String queryId;
+
+	@ApiModelProperty("community name")
+	protected String name;
+
+	@ApiModelProperty("community short name")
+	protected String shortName;
+
+	@ApiModelProperty("community description")
+	protected String description;
+
+	@ApiModelProperty("list of community manager emails")
+	protected List<String> managers;
+
+	@ApiModelProperty("http url for the community logo")
+	protected String logoUrl;
+
+	public CommunitySummary() {
+	}
+
+	public CommunitySummary(final String id,
+			final String queryId,
+			final String name,
+			final String shortName,
+			final String description,
+			final List<String> managers,
+			final String logoUrl) {
+		this.id = id;
+		this.queryId = queryId;
+		this.name = name;
+		this.shortName = shortName;
+		this.description = description;
+		this.managers = managers;
+		this.logoUrl = logoUrl;
+	}
+
+	public CommunitySummary(final CommunitySummary summary) {
+		this(	summary.getId(),
+				summary.getQueryId(),
+				summary.getName(),
+				summary.getShortName(),
+				summary.getDescription(),
+				summary.getManagers(),
+				summary.getLogoUrl());
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(final String id) {
+		this.id = id;
+	}
+
+	public String getQueryId() {
+		return queryId;
+	}
+
+	public void setQueryId(final String queryId) {
+		this.queryId = queryId;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(final String name) {
+		this.name = name;
+	}
+
+	public String getShortName() {
+		return shortName;
+	}
+
+	public void setShortName(final String shortName) {
+		this.shortName = shortName;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(final String description) {
+		this.description = description;
+	}
+
+	public List<String> getManagers() {
+		return managers;
+	}
+
+	public void setManagers(final List<String> managers) {
+		this.managers = managers;
+	}
+
+	public String getLogoUrl() {
+		return logoUrl;
+	}
+
+	public void setLogoUrl(final String logoUrl) {
+		this.logoUrl = logoUrl;
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityException.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityException.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityException.java	(revision 51424)
@@ -0,0 +1,20 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.io.IOException;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseBody
+@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
+public class CommunityException extends Exception {
+
+	public CommunityException(final String message) {
+		super(message);
+	}
+
+	public CommunityException(final IOException e) {
+		super(e);
+	}
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityApiCore.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityApiCore.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityApiCore.java	(revision 51424)
@@ -0,0 +1,171 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import com.google.common.base.Functions;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import eu.dnetlib.openaire.exporter.context.Category;
+import eu.dnetlib.openaire.exporter.context.Concept;
+import eu.dnetlib.openaire.exporter.context.Context;
+import org.apache.commons.collections.MapUtils;
+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.stereotype.Component;
+
+import static eu.dnetlib.openaire.exporter.community.CommunityConstants.*;
+
+@Component
+public class CommunityApiCore {
+
+	private static final Log log = LogFactory.getLog(CommunityApiCore.class);
+
+	@Autowired
+	private ISClient isClient;
+
+	public List<CommunitySummary> listCommunities() throws CommunityException {
+		return getContextMap().values().stream()
+				.filter(context -> !communityBlackList.contains(context.getId()))
+				.map(CommunityMappingUtils::asCommunitySummary)
+				.collect(Collectors.toList());
+	}
+
+	public CommunityDetails getCommunity(final String id) throws CommunityException, CommunityNotFoundException {
+		final Context context = getContextMap().get(id);
+		if (context == null || CommunityConstants.communityBlackList.contains(id)) {
+			throw new CommunityNotFoundException(String.format("community '%s' does not exist", id));
+		}
+		return CommunityMappingUtils.asCommunityProfile(context);
+	}
+
+	public void setCommunity(final String id, final CommunityWritableProperties details) throws CommunityException, CommunityNotFoundException {
+
+		getCommunity(id); // ensure the community exists.
+
+		isClient.updateContextAttribute(id, CLABEL, details.getShortName());
+		isClient.updateContextParam(id, CSUMMARY_NAME, details.getName());
+		isClient.updateContextParam(id, CSUMMARY_DESCRIPTION, details.getDescription());
+		isClient.updateContextParam(id, CSUMMARY_LOGOURL, details.getLogoUrl());
+		isClient.updateContextParam(id, CSUMMARY_MANAGER, Joiner.on(CSV_DELIMITER).join(details.getManagers()));
+		isClient.updateContextParam(id, CPROFILE_SUBJECT, Joiner.on(CSV_DELIMITER).join(details.getSubjects()));
+	}
+
+	public List<CommunityProject> getCommunityProjects(final String id) throws CommunityException, CommunityNotFoundException {
+		getCommunity(id); // ensure the community exists.
+		return _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<Integer, CommunityProject> projects = getCommunityProjectMap(id);
+		project.setId(nextId(projects != null ? projects.lastKey() : 0));
+
+		isClient.addConcept(id, id + PROJECTS_ID_SUFFIX, CommunityMappingUtils.asProjectXML(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<Integer, CommunityProject> 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);
+	}
+
+	public List<CommunityContentprovider> getCommunityContentproviders(final String id) throws CommunityException, CommunityNotFoundException {
+		getCommunity(id); // ensure the community exists.
+		return _getCommunityInfo(id, CONTENTPROVIDERS_ID_SUFFIX, c -> CommunityMappingUtils.asCommunityDataprovider(id, c));
+	}
+
+	public CommunityContentprovider addCommunityContentprovider(final String id, final CommunityContentprovider cp) throws CommunityException, CommunityNotFoundException {
+		if (!StringUtils.equalsIgnoreCase(id, cp.getCommunityId())) {
+			throw new CommunityException("parameters 'id' and cp.communityId must be coherent");
+		}
+
+		final TreeMap<Integer, CommunityContentprovider> cps = getCommunityContentproviderMap(id);
+		cp.setId(nextId(MapUtils.isNotEmpty(cps) ? cps.lastKey() : 0));
+
+		isClient.addConcept(id, id + CONTENTPROVIDERS_ID_SUFFIX, CommunityMappingUtils.asContentProviderXML(id, cp));
+
+		return cp;
+	}
+
+	public void removeCommunityContentProvider(final String id, final Integer contentproviderId) throws CommunityException, CommunityNotFoundException {
+		final Map<Integer, CommunityContentprovider> 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);
+	}
+
+	// HELPERS
+
+	private TreeMap<Integer, CommunityProject> 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<Integer, CommunityContentprovider> getCommunityContentproviderMap(final String id) throws CommunityException, CommunityNotFoundException {
+		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 Map<String, Context> getContextMap() throws CommunityException {
+		try {
+			return isClient.getCommunityContextMap();
+		} catch (IOException e) {
+			throw new CommunityException(e);
+		}
+	}
+
+	private <R> List<R> _getCommunityInfo(final String id, final String idSuffix, final Function<Concept, R> mapping) throws CommunityException {
+		final Map<String, Context> contextMap = getContextMap();
+		final Context context = contextMap.get(id);
+		if (context != null) {
+			final Map<String, Category> categories = context.getCategories();
+			final Category category = categories.get(id + idSuffix);
+			if (category != null) {
+				return category.getConcepts().stream()
+						.map(mapping)
+						.collect(Collectors.toList());
+			}
+		}
+		return Lists.newArrayList();
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/ISClient.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/ISClient.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/ISClient.java	(revision 51424)
@@ -0,0 +1,24 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.io.IOException;
+import java.util.Map;
+
+import eu.dnetlib.openaire.exporter.context.Context;
+
+public interface ISClient {
+
+	Map<String, Context> getFunderContextMap() throws IOException;
+
+	Map<String, Context> getCommunityContextMap() throws IOException;
+
+	void updateContextParam(String id, String name, String value);
+
+	void updateContextAttribute(String id, String name, String value);
+
+	void addConcept(String id, String categoryId, String data);
+
+	void removeConcept(String id, String categoryId, String conceptId);
+
+	void dropCache();
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityDetails.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityDetails.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityDetails.java	(revision 51424)
@@ -0,0 +1,51 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import io.swagger.annotations.ApiModelProperty;
+
+@JsonAutoDetect
+public class CommunityDetails extends CommunitySummary {
+
+	@ApiModelProperty("")
+	private String type;
+
+	@ApiModelProperty("date of creation for this community")
+	private Date creationDate;
+
+	@ApiModelProperty("list of subjects (keywords) that characterise this community")
+	private List<String> subjects;
+
+	public CommunityDetails() {
+	}
+
+	public CommunityDetails(final CommunitySummary summary) {
+		super(summary);
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(final String type) {
+		this.type = type;
+	}
+
+	public Date getCreationDate() {
+		return creationDate;
+	}
+
+	public void setCreationDate(final Date creationDate) {
+		this.creationDate = creationDate;
+	}
+
+	public List<String> getSubjects() {
+		return subjects;
+	}
+
+	public void setSubjects(final List<String> subjects) {
+		this.subjects = subjects;
+	}
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityContentprovider.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityContentprovider.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityContentprovider.java	(revision 51424)
@@ -0,0 +1,69 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import javax.validation.constraints.NotNull;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import io.swagger.annotations.ApiModelProperty;
+
+@JsonAutoDetect
+public class CommunityContentprovider {
+
+	@ApiModelProperty(value = "OpenAIRE identifier for this content provider, if available", required = false)
+	private String openaireId;
+
+	@NotNull
+	@ApiModelProperty(value = "the community identifier this content provider belongs to", required = true)
+	private String communityId;
+
+	@NotNull
+	@ApiModelProperty(value = "identifies this content provider within the context it belongs to", required = true)
+	private String id;
+
+	@ApiModelProperty(value = "content provider name", required = false)
+	private String name;
+
+	@NotNull
+	@ApiModelProperty(value = "content provider official name", required = true)
+	private String officialname;
+
+	public String getOpenaireId() {
+		return openaireId;
+	}
+
+	public void setOpenaireId(final String openaireId) {
+		this.openaireId = openaireId;
+	}
+
+	public String getCommunityId() {
+		return communityId;
+	}
+
+	public void setCommunityId(final String communityId) {
+		this.communityId = communityId;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(final String id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(final String name) {
+		this.name = name;
+	}
+
+	public String getOfficialname() {
+		return officialname;
+	}
+
+	public void setOfficialname(final String officialname) {
+		this.officialname = officialname;
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityProject.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityProject.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityProject.java	(revision 51424)
@@ -0,0 +1,86 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import io.swagger.annotations.ApiModelProperty;
+
+@JsonAutoDetect
+public class CommunityProject {
+
+	@ApiModelProperty(value = "OpenAIRE identifier for this project, if available", required = false)
+	private String openaireId;
+
+	@ApiModelProperty(value = "the community identifier this project belongs to", required = true)
+	private String communityId;
+
+	@ApiModelProperty(value = "identifies this project within the context it belongs to", required = true)
+	private String id;
+
+	@ApiModelProperty(value = "project name", required = true)
+	private String name;
+
+	@ApiModelProperty(value = "project acronym", required = false)
+	private String acronym;
+
+	@ApiModelProperty(value = "project funder", required = true)
+	private String funder;
+
+	@ApiModelProperty(value = "project grant id", required = true)
+	private String grantId;
+
+	public String getOpenaireId() {
+		return openaireId;
+	}
+
+	public void setOpenaireId(final String openaireId) {
+		this.openaireId = openaireId;
+	}
+
+	public String getCommunityId() {
+		return communityId;
+	}
+
+	public void setCommunityId(final String communityId) {
+		this.communityId = communityId;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(final String id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(final String name) {
+		this.name = name;
+	}
+
+	public String getAcronym() {
+		return acronym;
+	}
+
+	public void setAcronym(final String acronym) {
+		this.acronym = acronym;
+	}
+
+	public String getFunder() {
+		return funder;
+	}
+
+	public void setFunder(final String funder) {
+		this.funder = funder;
+	}
+
+	public String getGrantId() {
+		return grantId;
+	}
+
+	public void setGrantId(final String grantId) {
+		this.grantId = grantId;
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityWritableProperties.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityWritableProperties.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/CommunityWritableProperties.java	(revision 51424)
@@ -0,0 +1,76 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import io.swagger.annotations.ApiModelProperty;
+
+@JsonAutoDetect
+public class CommunityWritableProperties {
+
+	@ApiModelProperty("community name")
+	private String name;
+
+	@ApiModelProperty("community short name")
+	private String shortName;
+
+	@ApiModelProperty("community description")
+	private String description;
+
+	@ApiModelProperty("http url for the community logo")
+	private String logoUrl;
+
+	@ApiModelProperty("list of community manager emails")
+	private List<String> managers;
+
+	@ApiModelProperty("list of subjects (keywords) that characterise this community")
+	private List<String> subjects;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(final String name) {
+		this.name = name;
+	}
+
+	public String getShortName() {
+		return shortName;
+	}
+
+	public void setShortName(final String shortName) {
+		this.shortName = shortName;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(final String description) {
+		this.description = description;
+	}
+
+	public List<String> getManagers() {
+		return managers;
+	}
+
+	public void setManagers(final List<String> managers) {
+		this.managers = managers;
+	}
+
+	public String getLogoUrl() {
+		return logoUrl;
+	}
+
+	public void setLogoUrl(final String logoUrl) {
+		this.logoUrl = logoUrl;
+	}
+
+	public List<String> getSubjects() {
+		return subjects;
+	}
+
+	public void setSubjects(final List<String> subjects) {
+		this.subjects = subjects;
+	}
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/ISClientImpl.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/ISClientImpl.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/community/ISClientImpl.java	(revision 51424)
@@ -0,0 +1,178 @@
+package eu.dnetlib.openaire.exporter.community;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.Lists;
+import com.google.common.escape.Escaper;
+import com.google.common.xml.XmlEscapers;
+import eu.dnetlib.OpenaireExporterConfig;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
+import eu.dnetlib.openaire.exporter.context.Context;
+import eu.dnetlib.openaire.exporter.context.ContextMappingUtils;
+import org.apache.commons.io.IOUtils;
+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.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by claudio on 20/10/2016.
+ */
+@Component
+public class ISClientImpl implements ISClient {
+
+ 	private static final Log log = LogFactory.getLog(ISClientImpl.class);
+
+	@Autowired
+	private OpenaireExporterConfig config;
+
+	@Autowired
+	private ISLookUpService isLookUpService;
+
+	@Override
+	@Cacheable("context-cache")
+	public Map<String, Context> getFunderContextMap() throws IOException {
+		return _processContext(
+				new LinkedBlockingQueue<>(),
+				_getQuery(config.getFindFunderContexts()));
+	}
+
+	@Override
+	@Cacheable("context-cache")
+	public Map<String, Context> getCommunityContextMap() throws IOException {
+		return _processContext(
+				new LinkedBlockingQueue<>(),
+				_getQuery(config.getFindCommunityContexts()));
+	}
+
+	@Override
+	@CacheEvict(value = "context-cache", allEntries = true)
+	public void updateContextParam(final String id, final String name, final String value) {
+		final Queue<Throwable> errors = Lists.newLinkedList();
+		final Escaper esc = XmlEscapers.xmlContentEscaper();
+		_quickSeachProfile(String.format(
+				"update replace collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')" +
+				"/RESOURCE_PROFILE/BODY/CONFIGURATION/context[./@id = '%s']/param[./@name = '%s'] with <param name='%s'>%s</param>", id, name, name, escape(esc, value)),
+				errors);
+
+		if (!errors.isEmpty()) {
+			errors.forEach(e -> log.error(e));
+		}
+	}
+
+	@Override
+	@CacheEvict(value = "context-cache", allEntries = true)
+	public void updateContextAttribute(final String id, final String name, final String value) {
+		final Queue<Throwable> errors = Lists.newLinkedList();
+		final Escaper esc = XmlEscapers.xmlAttributeEscaper();
+		_quickSeachProfile(String.format(
+				"update value collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')" +
+						"/RESOURCE_PROFILE/BODY/CONFIGURATION/context[./@id = '%s']/@%s with '%s'", id, name, escape(esc, value)),
+				errors);
+
+		if (!errors.isEmpty()) {
+			errors.forEach(e -> log.error(e));
+		}
+	}
+
+	@Override
+	@CacheEvict(value = "context-cache", allEntries = true)
+	public void addConcept(final String id, final String categoryId, final String data) {
+		final Queue<Throwable> errors = Lists.newLinkedList();
+		_quickSeachProfile(String.format(
+				"update insert %s into collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')" +
+				"/RESOURCE_PROFILE/BODY/CONFIGURATION/context[./@id = '%s']/category[./@id = '%s']", data, id, categoryId), errors);
+
+		if (!errors.isEmpty()) {
+			errors.forEach(e -> log.error(e));
+		}
+	}
+
+	@Override
+	@CacheEvict(value = "context-cache", allEntries = true)
+	public void removeConcept(final String id, final String categoryId, final String conceptId) {
+		final Queue<Throwable> errors = Lists.newLinkedList();
+		_quickSeachProfile(String.format(
+				"for $concept in collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')" +
+						"/RESOURCE_PROFILE/BODY/CONFIGURATION/context[./@id = '%s']" +
+						"/category[./@id = '%s']/concept[./@id = '%s']" +
+						"return update delete $concept", id, categoryId, conceptId),
+				errors);
+		if (!errors.isEmpty()) {
+			errors.forEach(e -> log.error(e.getMessage()));
+		}
+	}
+
+	/// HELPERS
+
+	public static String escape(final Escaper esc, final String value) {
+		return StringUtils.isNotBlank(value) ? esc.escape(value) : "";
+	}
+
+	private Map<String, Context> _processContext(final Queue<Throwable> errors, final String xquery) throws IOException {
+		try {
+			return getContextProfiles(errors, xquery).stream()
+					.filter(StringUtils::isNotBlank)
+					.map(s -> ContextMappingUtils.parseContext(s, errors))
+					.collect(Collectors.toMap(
+							Context::getId,
+							Function.identity()));
+		} finally {
+			if (!errors.isEmpty()) {
+				log.error(errors);
+				errors.forEach(e -> e.printStackTrace());
+			}
+		}
+	}
+
+	private List<String> getContextProfiles(final Queue<Throwable> errors, final String xquery) throws IOException {
+		log.warn("getContextProfiles(): not using cache");
+		return _quickSeachProfile(xquery, errors);
+	}
+
+	private String _getQuery(final ClassPathResource resource) throws IOException {
+		return IOUtils.toString(resource.getInputStream(), Charset.defaultCharset());
+	}
+
+	private String _isLookUp(final String xquery) throws ISLookUpException {
+		log.debug(String.format("running xquery:\n%s", xquery));
+		final String res = isLookUpService.getResourceProfileByQuery(xquery);
+		//log.debug(String.format("query result: %s", res));
+		return res;
+	}
+
+	private List<String> _quickSeachProfile(final String xquery, final Queue<Throwable> errors) {
+		final List<String> res = Lists.newArrayList();
+		try {
+			log.debug(String.format("running xquery:\n%s", xquery));
+			final List<String> list = isLookUpService.quickSearchProfile(xquery);
+			if (list != null) {
+				res.addAll(list);
+			}
+			log.debug(String.format("query result size: %s", res.size()));
+		} catch (Throwable e) {
+			errors.add(e);
+			return Lists.newArrayList();
+		} finally {
+			return res;
+		}
+	}
+
+	@CacheEvict(cacheNames = { "context-cache" }, allEntries = true)
+	public void dropCache() {
+		log.info("dropped dsManager IS cache");
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Param.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Param.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Param.java	(revision 51424)
@@ -0,0 +1,27 @@
+package eu.dnetlib.openaire.exporter.context;
+
+public class Param {
+
+	private String name;
+
+	private String value;
+
+	public String getName() {
+		return name;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	public Param setName(final String name) {
+		this.name = name;
+		return this;
+	}
+
+	public Param setValue(final String value) {
+		this.value = value;
+		return this;
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/ContextMappingUtils.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/ContextMappingUtils.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/ContextMappingUtils.java	(revision 51424)
@@ -0,0 +1,105 @@
+package eu.dnetlib.openaire.exporter.context;
+
+import java.io.StringReader;
+import java.text.ParseException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateUtils;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+public class ContextMappingUtils {
+
+	private static final List<String> DATE_PATTERN = Lists.newArrayList(
+			"yyyy-MM-dd'T'hh:mm:ss", "yyyy-MM-dd'T'hh:mm:ss+00:00");
+
+	public static Context parseContext(final String s, final Queue<Throwable> errors) {
+
+		final SAXReader reader = new SAXReader();
+		final Document doc;
+		try {
+			doc = reader.read(new StringReader(s));
+		} catch (DocumentException e) {
+			errors.add(e);
+			return new Context();
+		}
+		try {
+			final Element eContext = (Element) doc.selectSingleNode("/RESOURCE_PROFILE/BODY/CONFIGURATION/context");
+			return new Context()
+					.setId(eContext.attributeValue("id"))
+					.setLabel(eContext.attributeValue("label"))
+					.setType(eContext.attributeValue("type"))
+					.setDateofcreation(asDate(doc.valueOf("/RESOURCE_PROFILE/HEADER/DATE_OF_CREATION/@value")))
+					.setParams(parseParams(eContext))
+					.setCategories(parseCategories(eContext));
+		} catch (Throwable e) {
+			errors.add(e);
+			return new Context();
+		}
+	}
+
+	private static Date asDate(final String s) {
+		for(String pattern : DATE_PATTERN) {
+			try {
+				return DateUtils.parseDate(s, pattern);
+			} catch (final ParseException e) {}
+		}
+		return null;
+	}
+
+	private static Map<String, Category> parseCategories(final Element eContext) {
+		final List<Element> eCategory = (List<Element>) eContext.selectNodes("//category");
+		return eCategory.stream()
+				.map(eCat -> new Category()
+						.setClaim(getClaim(eCat))
+						.setId(eCat.attributeValue("id"))
+						.setLabel(eCat.attributeValue("label"))
+						.setParams(parseParams(eCat))
+						.setConcepts(parseConcepts(eCat)))
+				.collect(Collectors.toMap(
+						Category::getId,
+						Functions.identity()
+				));
+	}
+
+	private static List<Concept> parseConcepts(final Element eCategory) {
+		final List<Element> eConcepts = (List<Element>) eCategory.selectNodes("./concept");
+		return eConcepts.stream()
+				.map(eCon -> new Concept()
+						.setClaim(getClaim(eCon))
+						.setId(eCon.attributeValue("id"))
+						.setLabel(eCon.attributeValue("label"))
+						.setParams(parseParams(eCon))
+						.setConcepts(parseConcepts(eCon)))
+				.collect(Collectors.toList());
+	}
+
+	private static Boolean getClaim(final Element eCon) {
+		final String claim = eCon.attributeValue("claim");
+		return BooleanUtils.toBooleanObject(StringUtils.isNotBlank(claim) ? claim : "false");
+	}
+
+	private static Map<String, List<Param>> parseParams(final Element e) {
+		final List<Element> params = (List<Element>) e.selectNodes("./param");
+		return params.stream()
+				.map(p -> new Param()
+						.setName(p.attributeValue("name"))
+						.setValue(p.getTextTrim()))
+				.collect(Collectors.toMap(
+						Param::getName,
+						Lists::newArrayList,
+						(p1, p2) -> {
+							List<Param> p = new ArrayList<>(p1);
+							p.addAll(p2);
+							return p;
+						}));
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Context.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Context.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Context.java	(revision 51424)
@@ -0,0 +1,76 @@
+package eu.dnetlib.openaire.exporter.context;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+public class Context {
+
+	private String id;
+
+	private String label;
+
+	private String type;
+
+	private Date dateofcreation;
+
+	private Map<String, List<Param>> params;
+
+	private Map<String, Category> categories;
+
+	public String getId() {
+		return id;
+	}
+
+	public String getLabel() {
+		return label;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public Date getDateofcreation() {
+		return dateofcreation;
+	}
+
+	public Map<String, List<Param>> getParams() {
+		return params;
+	}
+
+	public Map<String, Category> getCategories() {
+		return categories;
+	}
+
+	public Context setId(final String id) {
+		this.id = id;
+		return this;
+	}
+
+	public Context setLabel(final String label) {
+		this.label = label;
+		return this;
+	}
+
+	public Context setType(final String type) {
+		this.type = type;
+		return this;
+	}
+
+	public Context setDateofcreation(final Date dateofcreation) {
+		this.dateofcreation = dateofcreation;
+		return this;
+	}
+
+	public Context setParams(final Map<String, List<Param>> params) {
+		this.params = params;
+		return this;
+	}
+
+	public Context setCategories(final Map<String, Category> categories) {
+		this.categories = categories;
+		return this;
+	}
+
+}
+
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Concept.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Concept.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Concept.java	(revision 51424)
@@ -0,0 +1,63 @@
+package eu.dnetlib.openaire.exporter.context;
+
+import java.util.List;
+import java.util.Map;
+
+public class Concept {
+
+	private String id;
+
+	private String label;
+
+	private boolean claim;
+
+	private Map<String, List<Param>> params;
+
+	private List<Concept> concepts;
+
+	public String getId() {
+		return id;
+	}
+
+	public String getLabel() {
+		return label;
+	}
+
+	public boolean isClaim() {
+		return claim;
+	}
+
+	public Map<String, List<Param>> getParams() {
+		return params;
+	}
+
+	public List<Concept> getConcepts() {
+		return concepts;
+	}
+
+	public Concept setId(final String id) {
+		this.id = id;
+		return this;
+	}
+
+	public Concept setLabel(final String label) {
+		this.label = label;
+		return this;
+	}
+
+	public Concept setClaim(final boolean claim) {
+		this.claim = claim;
+		return this;
+	}
+
+	public Concept setParams(final Map<String, List<Param>> params) {
+		this.params = params;
+		return this;
+	}
+
+	public Concept setConcepts(final List<Concept> concepts) {
+		this.concepts = concepts;
+		return this;
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Category.java
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Category.java	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/java/eu/dnetlib/openaire/exporter/context/Category.java	(revision 51424)
@@ -0,0 +1,63 @@
+package eu.dnetlib.openaire.exporter.context;
+
+import java.util.List;
+import java.util.Map;
+
+public class Category {
+
+	private String id;
+
+	private String label;
+
+	private boolean claim;
+
+	private Map<String, List<Param>> params;
+
+	private List<Concept> concepts;
+
+	public String getId() {
+		return id;
+	}
+
+	public String getLabel() {
+		return label;
+	}
+
+	public boolean isClaim() {
+		return claim;
+	}
+
+	public Map<String, List<Param>> getParams() {
+		return params;
+	}
+
+	public List<Concept> getConcepts() {
+		return concepts;
+	}
+
+	public Category setId(final String id) {
+		this.id = id;
+		return this;
+	}
+
+	public Category setLabel(final String label) {
+		this.label = label;
+		return this;
+	}
+
+	public Category setClaim(final boolean claim) {
+		this.claim = claim;
+		return this;
+	}
+
+	public Category setParams(final Map<String, List<Param>> params) {
+		this.params = params;
+		return this;
+	}
+
+	public Category setConcepts(final List<Concept> concepts) {
+		this.concepts = concepts;
+		return this;
+	}
+
+}
Index: modules/dnet-openaire-exporter/branches/beta/src/main/resources/ehcache.xml
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/resources/ehcache.xml	(revision 51423)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/resources/ehcache.xml	(revision 51424)
@@ -26,6 +26,17 @@
 	       transactionalMode="off">
 		<persistence strategy="localTempSwap" />
 	</cache>
+	
+	<cache name="context-cache"
+	       maxEntriesLocalHeap="100"
+	       maxEntriesLocalDisk="500"
+	       eternal="false"
+	       diskSpoolBufferSizeMB="1"
+	       timeToIdleSeconds="43200" timeToLiveSeconds="43200"
+	       memoryStoreEvictionPolicy="LFU"
+	       transactionalMode="off">
+		<persistence strategy="localTempSwap" />
+	</cache>
 
 	<cache name="datasources-mongo-cache"
 	       maxEntriesLocalHeap="1000"
Index: modules/dnet-openaire-exporter/branches/beta/src/main/resources/eu/dnetlib/openaire/exporter/xquery/findFunderContexts.xquery
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/resources/eu/dnetlib/openaire/exporter/xquery/findFunderContexts.xquery	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/resources/eu/dnetlib/openaire/exporter/xquery/findFunderContexts.xquery	(revision 51424)
@@ -0,0 +1,3 @@
+for $x in collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')
+where $x[./RESOURCE_PROFILE/BODY/CONFIGURATION/context/@type = 'funding']
+return $x
Index: modules/dnet-openaire-exporter/branches/beta/src/main/resources/eu/dnetlib/openaire/exporter/xquery/findCommunityContexts.xquery
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/resources/eu/dnetlib/openaire/exporter/xquery/findCommunityContexts.xquery	(nonexistent)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/resources/eu/dnetlib/openaire/exporter/xquery/findCommunityContexts.xquery	(revision 51424)
@@ -0,0 +1,3 @@
+for $x in collection('/db/DRIVER/ContextDSResources/ContextDSResourceType')
+where $x[./RESOURCE_PROFILE/BODY/CONFIGURATION/context/@type = 'community']
+return $x
Index: modules/dnet-openaire-exporter/branches/beta/src/main/resources/application.properties
===================================================================
--- modules/dnet-openaire-exporter/branches/beta/src/main/resources/application.properties	(revision 51423)
+++ modules/dnet-openaire-exporter/branches/beta/src/main/resources/application.properties	(revision 51424)
@@ -18,7 +18,7 @@
 openaire.exporter.requestTimeout    =   10
 
 # JDBC
-openaire.exporter.jdbc.url          =   jdbc:postgresql://localhost:5432/dnet_openaire
+openaire.exporter.jdbc.url          =   jdbc:postgresql://localhost:5432/dnet_openaireplus_beta
 openaire.exporter.jdbc.user         =   dnetapi
 openaire.exporter.jdbc.pwd          =   dnetPwd
 openaire.exporter.jdbc.minIdle      =   1
@@ -45,6 +45,8 @@
 openaire.exporter.findSolrIndexUrl          =   /eu/dnetlib/openaire/exporter/xquery/findSolrIndexUrl.xquery
 openaire.exporter.findIndexDsInfo           =   /eu/dnetlib/openaire/exporter/xquery/findIndexDsInfo.xquery
 openaire.exporter.findObjectStore           =   /eu/dnetlib/openaire/exporter/xquery/findObjectStore.xquery
+openaire.exporter.findFunderContexts        =   /eu/dnetlib/openaire/exporter/xquery/findFunderContexts.xquery
+openaire.exporter.findCommunityContexts     =   /eu/dnetlib/openaire/exporter/xquery/findCommunityContexts.xquery
 
 # REST API CONFIGURATION
 openaire.exporter.swagger.apiTitle          =   OpenAIRE aggregator REST API
