Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/FeedSpeedTest.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/FeedSpeedTest.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/FeedSpeedTest.java	(revision 60503)
@@ -0,0 +1,159 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.UUID;
+
+import com.mongodb.DBObject;
+import com.mongodb.client.MongoDatabase;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.RecordParserFactory;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@Ignore
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = ConfigurationTestConfig.class)
+public class FeedSpeedTest {
+
+	private static final int N_RECORDS = 68271;
+
+	@Autowired
+	private MongoDatabase db;
+
+	@Autowired
+	private MDStoreDao dao;
+
+	@Autowired
+	private RecordParserFactory recordParserfactory;
+
+	@Before
+	public void setup() throws MDStoreServiceException {
+		dao.createMDStore("speed_test", "testFormat", "testInterpretation", "testLayout");
+	}
+
+
+	@Test
+	public void testSpeedFromFolder() throws IOException {
+		Iterable<String> iterable = new Iterable<String>() {
+
+			private int counter = 0;
+			private double last = System.currentTimeMillis();
+
+			@Override
+			public Iterator<String> iterator() {
+				return new Iterator<String>() {
+
+					@Override
+					public boolean hasNext() {
+						return counter < N_RECORDS;
+					}
+
+					@Override
+					public String next() {
+						if (counter % 10000 == 0) {
+							System.out.println("10K records processed in " + (System.currentTimeMillis() - last) / 1000 + " seconds");
+							last = System.currentTimeMillis();
+						}
+
+						File f = new File(String.format("/var/lib/eagle/content/EDH/HD%06d.xml", counter++));
+						if (f.exists()) {
+							try {
+								FileInputStream fileInputStream = new FileInputStream(f);
+								String s = IOUtils.toString(fileInputStream);
+								fileInputStream.close();
+								return s;
+							} catch (Exception e) {
+								return null;
+							}
+						} else {
+							try {
+								FileInputStream fileInputStream = new FileInputStream(new File("/var/lib/eagle/content/EDH/HD000001.xml"));
+								String s = IOUtils.toString(fileInputStream);
+								fileInputStream.close();
+								return s;
+							} catch (Exception e) {
+								return null;
+							}
+						}
+					}
+
+					@Override
+					public void remove() {}
+				};
+			}
+		};
+
+		MongoMDStore mdStore =
+				new MongoMDStore(UUID.randomUUID().toString(), db.getCollection("speed_test", DBObject.class), recordParserfactory.newInstance(), true, db);
+		mdStore.feed(iterable, false);
+	}
+
+	//@Ignore
+	@Test
+	public void testFeedSpeedFromTemplate() throws MDStoreServiceException, IOException {
+		MongoMDStore mdStore =
+				new MongoMDStore(UUID.randomUUID().toString(), db.getCollection("speed_test", DBObject.class), recordParserfactory.newInstance(), false, db);
+		mdStore.feed(new Iterable<String>() {
+
+			private int counter = 0;
+			private double last = System.currentTimeMillis();
+			private String templateRecord = IOUtils.toString(new ClassPathResource("/eu/dnetlib/data/mdstore/modular/mongodb/templateRecord.xml")
+					.getInputStream());
+
+			@Override
+			public Iterator<String> iterator() {
+				return new Iterator<String>() {
+
+					@Override
+					public boolean hasNext() {
+						return counter < N_RECORDS;
+					}
+
+					@Override
+					public String next() {
+						if (counter % 10000 == 0) {
+							System.out.println("10K records processed in " + (System.currentTimeMillis() - last) / 1000 + " seconds");
+							last = System.currentTimeMillis();
+						}
+
+						File f = new File(String.format("/var/lib/eagle/content/EDH/HD%06d.xml", counter++));
+						if (f.exists()) {
+							try {
+								FileInputStream fileInputStream = new FileInputStream(f);
+								String s = IOUtils.toString(fileInputStream);
+								fileInputStream.close();
+								return s;
+							} catch (Exception e) {
+								return null;
+							}
+						} else {
+							counter++;
+							try {
+								FileInputStream fileInputStream = new FileInputStream(new File("/var/lib/eagle/content/EDH/HD000009.xml"));
+								String s = IOUtils.toString(fileInputStream);
+								fileInputStream.close();
+								return s;
+							} catch (Exception e) {
+								return null;
+							}
+						}
+					}
+
+					@Override
+					public void remove() {}
+				};
+			}
+		}, false);
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/pom.xml
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/pom.xml	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/pom.xml	(revision 60503)
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>eu.dnetlib</groupId>
+		<artifactId>dnet45-parent</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.dnetlib</groupId>
+	<artifactId>cnr-mongo-mdstore</artifactId>
+	<packaging>jar</packaging>
+	<version>6.0.7</version>
+	<scm>
+		<developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet45/modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7</developerConnection>
+	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-test</artifactId>
+			<version>${spring.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>${mockito.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-test-utils</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-modular-mdstore-service</artifactId>
+			<version>[6.0.5-SNAPSHOT,7.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-inspector</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mongodb</groupId>
+			<artifactId>mongo-java-driver</artifactId>
+			<version>${mongodb.driver.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>joda-time</groupId>
+			<artifactId>joda-time</artifactId>
+			<version>2.3</version>
+		</dependency>
+		<dependency>
+			<groupId>com.ximpleware</groupId>
+			<artifactId>vtd-xml</artifactId>
+			<version>[2.12, 3.0.0)</version>
+		</dependency>
+
+	</dependencies>
+</project>
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/inspector/MDStoreInspector.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/inspector/MDStoreInspector.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/inspector/MDStoreInspector.java	(revision 60503)
@@ -0,0 +1,229 @@
+package eu.dnetlib.data.mdstore.modular.inspector;
+
+import static eu.dnetlib.miscutils.collections.MappedCollection.listMap;
+
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang3.StringUtils;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.io.SAXReader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.MDStoreDescription;
+import eu.dnetlib.data.mdstore.modular.MDStoreFeeder;
+import eu.dnetlib.data.mdstore.modular.connector.MDStore;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreManagerInfo;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager;
+import eu.dnetlib.data.mdstore.modular.mongodb.MongoMDStore;
+import eu.dnetlib.enabling.inspector.AbstractInspectorController;
+import eu.dnetlib.enabling.resultset.ResultSetListener;
+import eu.dnetlib.miscutils.functional.xml.TryIndentXmlString;
+
+@Controller
+public class MDStoreInspector extends AbstractInspectorController {
+
+	private static final Log log = LogFactory.getLog(MDStoreInspector.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	@Resource(name = "mongodbMDStoreDao")
+	private MDStoreDao dao;
+
+	@Autowired
+	private MDStoreTransactionManager transactionManager;
+
+	@Resource
+	private MDStoreFeeder feeder;
+
+	@Value("${dhp.openaire.mdstore.inspector.url}")
+	private String hadoopMdstoreInspectorUrl;
+
+	@RequestMapping(value = "/inspector/mdstores.do")
+	public void mdstores(final Model model) throws MDStoreServiceException {
+		model.addAttribute("mdstores", dao.listMDStores());
+	}
+
+	@RequestMapping(value = "/inspector/mdstore.do", method = RequestMethod.GET)
+	public String mdstore(final Model model,
+			@RequestParam("id") final String id,
+			@RequestParam(value = "start", required = false) final Integer startParam,
+			@RequestParam(value = "regex", required = false) final String regex) throws MDStoreServiceException {
+		
+		if (StringUtils.isNotBlank(hadoopMdstoreInspectorUrl) && id.startsWith("md-")) {
+			final String url = String.format(hadoopMdstoreInspectorUrl, id);
+			log.info("Redirect to " + url);
+			return "redirect:" + url;
+		} 
+
+		int pageSize = 10;
+		int start = 0;
+
+		if (startParam != null) {
+			start = startParam;
+		}
+
+		MongoMDStore mdstore = (MongoMDStore) dao.getMDStore(id);
+
+		ResultSetListener rs = mdstore.deliver(null, null, regex);
+		Function<String, Map<String, String>> function = new Function<String, Map<String, String>>() {
+
+			private SAXReader reader = new SAXReader();
+
+			@Override
+			public Map<String, String> apply(final String input) {
+				try {
+
+					Document doc = reader.read(new StringReader(input));
+					final HashMap<String, String> result = new HashMap<String, String>();
+					result.put("docId", doc.valueOf("//*[local-name()='objIdentifier']"));
+					result.put("body", input.replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
+					result.put("mdId", id);
+					return result;
+				} catch (DocumentException e) {
+					throw new RuntimeException(e);
+				}
+
+			}
+		};
+		List<Map<String, String>> page = Lists.transform(listMap(rs.getResult(1 + start, start + pageSize), new TryIndentXmlString()), function);
+
+		model.addAttribute("id", id);
+		model.addAttribute("start", start);
+		model.addAttribute("regex", regex);
+		model.addAttribute("nextPage", start + pageSize);
+		model.addAttribute("prevPage", Math.max(0, start - pageSize));
+		model.addAttribute("size", rs.getSize());
+		model.addAttribute("page", page);
+
+		return "inspector/mdstore";
+	}
+
+	@RequestMapping(value = "/inspector/mdstore.do", method = RequestMethod.POST)
+	public String bulkReplace(final Model model,
+			@RequestParam("id") final String id,
+			@RequestParam("regex") final String regex,
+			@RequestParam("replace") final String replace,
+			@RequestParam(value = "checkReplace", required = false) final Boolean checkReplace) throws MDStoreServiceException {
+
+		log.debug("regex: " + regex);
+		log.debug("replace: " + replace);
+
+		MongoMDStore mdstore = (MongoMDStore) dao.getMDStore(id);
+
+		boolean replaceEnable = checkReplace != null && checkReplace == true;
+
+		if (replaceEnable) {
+			mdstore.replace(regex, replace);
+		} else {
+			model.addAttribute("regex", regex);
+		}
+
+		return "redirect:mdstore.do?id=" + id;
+	}
+
+	@RequestMapping(value = "/inspector/mdstoreEditResult.do")
+	public void mdstoreEditRecord(final Model model, @RequestParam("mdId") final String mdId, @RequestParam("docId") final String docId)
+			throws MDStoreServiceException {
+		MDStore mdstore = dao.getMDStore(mdId);
+		String record = mdstore.getRecord(docId);
+		log.debug("Displaying record for editing :" + record);
+		model.addAttribute("mdId", mdId);
+		TryIndentXmlString tryIndent = new TryIndentXmlString();
+		String escaped = tryIndent.evaluate(record);
+		model.addAttribute("body", escaped.replace("&", "&amp;"));
+	}
+
+	@RequestMapping(value = "/inspector/mdstoreSaveRecord.do")
+	public String mdstoreSaveRecord(final Model model, @RequestParam("mdId") final String mdId, @RequestParam("body") final String body)
+			throws MDStoreServiceException {
+		MDStore mdstore = dao.getMDStore(mdId);
+
+		mdstore.feed(Lists.newArrayList(body), true);
+
+		return "redirect:mdstore.do?id=" + mdId;
+
+	}
+
+	@RequestMapping(value = "/inspector/mdstoreDeleteRecord.do")
+	public String mdstoreDeleteRecord(final Model model, @RequestParam("mdId") final String mdId, @RequestParam("docId") final String docId)
+			throws MDStoreServiceException {
+		MDStore mdstore = dao.getMDStore(mdId);
+		log.info("deleting record " + docId);
+		mdstore.deleteRecord(docId);
+		return "redirect:mdstore.do?id=" + mdId;
+	}
+
+	@RequestMapping(value = "/inspector/mdstoresRefreshSizes.do")
+	public String mdstoresRefreshSizes(final Model model) throws MDStoreServiceException {
+
+		for (MDStoreDescription mdstore : dao.listMDStores()) {
+			feeder.touchSize(mdstore.getId(), dao.getMDStore(mdstore.getId()).getSize());
+		}
+
+		return "redirect:mdstores.do";
+	}
+
+	@RequestMapping(value = "/inspector/ensure.do")
+	public String mdstoreEnsureIndex(final Model model, @RequestParam("id") final String mdId) throws MDStoreServiceException {
+
+		MongoMDStore mdStore = (MongoMDStore) dao.getMDStore(mdId);
+
+		log.info("manual ensureIndex for mdId: " + mdId);
+		mdStore.ensureIndices();
+
+		return "redirect:mdstores.do";
+	}
+
+	@RequestMapping(value = "/inspector/infoTransaction.do")
+	public void mdstoreInfoTransaction(final Model model, @RequestParam("id") final String id) throws MDStoreServiceException {
+		MDStoreManagerInfo info = transactionManager.getInfoForCurrentMdStore(id);
+		model.addAttribute("info", info);
+	}
+
+	@RequestMapping(value = "/inspector/dropUsedCollection.do")
+	public String dropUsedCollection(final Model model, @RequestParam("mdId") final String mdId, @RequestParam("id") final String id)
+			throws MDStoreServiceException {
+		transactionManager.dropUsed(mdId, id);
+		return "redirect:mdstore.do?id=" + mdId;
+	}
+
+	@RequestMapping(value = "/inspector/invalidTransactionCollection.do")
+	public String invalidTransactionCollection(final Model model, @RequestParam("mdId") final String mdId, @RequestParam("id") final String id)
+			throws MDStoreServiceException {
+		transactionManager.dropTransaction(mdId, id);
+		return "redirect:mdstore.do?id=" + mdId;
+	}
+
+	@RequestMapping(value = "/inspector/refreshSizes.do")
+	public String refreshSizes(final Model model) throws MDStoreServiceException {
+
+		dao.refreshSizes();
+		return "redirect:mdstores.do";
+	}
+
+	@RequestMapping(value = "/inspector/doGarbage.do")
+	public String doGarbage(final Model model) throws MDStoreServiceException {
+
+		dao.startGarbage();
+		return "redirect:mdstores.do";
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoMDStore.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoMDStore.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoMDStore.java	(revision 60503)
@@ -0,0 +1,312 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.ListIndexesIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.IndexOptions;
+import eu.dnetlib.data.mdstore.DocumentNotFoundException;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.MDFormatDescription;
+import eu.dnetlib.data.mdstore.modular.RecordParser;
+import eu.dnetlib.data.mdstore.modular.connector.MDStore;
+import eu.dnetlib.enabling.resultset.ResultSetListener;
+import eu.dnetlib.enabling.resultset.client.ResultSetClient;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.bson.conversions.Bson;
+import org.springframework.beans.factory.annotation.Required;
+
+public class MongoMDStore implements MDStore {
+
+	private static final int BULK_SIZE = 500;
+	private static final Log log = LogFactory.getLog(MongoMDStore.class);
+
+	private final boolean discardRecords;
+	private String id;
+	private MongoDatabase mongoDatabase;
+	private MongoCollection<DBObject> collection;
+	private MongoCollection<DBObject> discardedCollection;
+	private List<MDFormatDescription> mdformats;
+
+	private RecordParser recordParser;
+
+	private static List<String> indices = Lists.newArrayList("id", "timestamp", "originalId");
+	private final IndexOptions options = new IndexOptions().background(true);
+
+	public MongoMDStore(final String id,
+			final MongoCollection<DBObject> collection,
+			final RecordParser recordParser,
+			final boolean discardRecords,
+			final MongoDatabase mongoDatabase) {
+		this.id = id;
+		this.mongoDatabase = mongoDatabase;
+		this.collection = collection;
+		this.discardedCollection = this.mongoDatabase.getCollection("discarded-" + StringUtils.substringBefore(id, "_"), DBObject.class);
+		this.recordParser = recordParser;
+		this.discardRecords = discardRecords;
+	}
+
+	@Override
+	public int feed(final Iterable<String> records, final boolean incremental, final List<MDFormatDescription> mdformats) {
+		this.mdformats = mdformats;
+		return feed(records, incremental);
+	}
+
+	@Override
+	public int feed(final Iterable<String> records, final boolean incremental) {
+		// TODO: remove incremental from MDStore API. It is used in MDStoreModular. Useless here.
+
+		ensureIndices();
+
+		final BlockingQueue<Object> queue = new ArrayBlockingQueue<>(100);
+		final Object sentinel = new Object();
+		int countStored = 0;
+		final Callable<Integer> writer = () -> {
+			final MongoBulkWritesManager bulkWritesManager =
+					new MongoBulkWritesManager(collection, discardedCollection, mdformats, BULK_SIZE, recordParser, discardRecords);
+			int count = 0;
+			while (true) {
+				try {
+					final Object record = queue.take();
+					if (record.equals(sentinel)) {
+						bulkWritesManager.flushBulks();
+						break;
+					}
+					count++;
+					bulkWritesManager.insert((String) record);
+				} catch (final InterruptedException e) {
+					log.fatal("got exception in background thread", e);
+					throw new IllegalStateException(e);
+				}
+			}
+			log.debug(String.format("extracted %s records from feeder queue", count));
+			return count;
+		};
+		final ExecutorService executorService = Executors.newSingleThreadExecutor();
+		Future<Integer> storedCountInt = executorService.submit(writer);
+
+		try {
+			log.info("feeding mdstore " + id);
+			if (records != null) {
+				for (final String record : records) {
+					queue.put(record);
+				}
+			}
+			queue.put(sentinel);
+			countStored = storedCountInt.get().intValue();
+		} catch (final InterruptedException | ExecutionException e) {
+			log.error("Error on feeding mdstore with id:" + id, e);
+			throw new IllegalStateException(e);
+		}
+		log.info("finished feeding mdstore " + id);
+		return countStored;
+	}
+
+	public void ensureIndices() {
+		for (final String key : indices) {
+			collection.createIndex(new BasicDBObject(key, 1), options);
+		}
+		if (mdformats != null) {
+			for (final MDFormatDescription description : mdformats) {
+				collection.createIndex(new BasicDBObject(description.getName(), 1), options);
+			}
+		}
+	}
+
+	public boolean isIndexed() {
+		final ListIndexesIterable<DBObject> found = collection.listIndexes(DBObject.class);
+		return Sets.newHashSet(Iterables.transform(found, dbo -> {
+			final Set<String> keyset = ((DBObject) dbo.get("key")).toMap().keySet();
+			return Iterables.getFirst(keyset, "");
+		})).containsAll(indices);
+	}
+
+	/**
+	 * Method searches for the given string grep into this collection and replaces it with the given replacement.
+	 *
+	 * @param grep
+	 *            the string to search
+	 * @param replace
+	 *            the replacement
+	 */
+	public void replace(final String grep, final String replace) {
+		final Pattern regex = Pattern.compile(grep, Pattern.MULTILINE);
+		BasicDBObject query = (BasicDBObject) QueryBuilder.start("body").regex(regex).get();
+		final FindIterable<DBObject> matches = collection.find(query, DBObject.class);
+		//final DBCursor matches = collection.find(QueryBuilder.start("body").regex(regex).get());
+		if (log.isDebugEnabled())
+			log.debug("FOUND: " + Lists.newArrayList(matches).size());
+
+		for (final DBObject match : matches) {
+			final DBObject o = new BasicDBObject(match.toMap());
+			o.put("body", regex.matcher((String) match.get("body")).replaceAll(replace));
+			collection.findOneAndReplace(new BasicDBObject("_id", o.get("_id")), o);
+		}
+	}
+
+	@Override
+	public ResultSetListener deliver(final String from, final String until, final String recordFilter) throws MDStoreServiceException {
+		return deliver(from, until, recordFilter, new SerializeMongoRecord());
+	}
+
+	@Override
+	public ResultSetListener deliverIds(final String from, final String until, final String recordFilter) throws MDStoreServiceException {
+		return deliver(from, until, recordFilter, new SerializeMongoRecordId());
+	}
+
+	public ResultSetListener deliver(final String from, final String until, final String recordFilter, final Function<DBObject, String> serializer)
+			throws MDStoreServiceException {
+		final Pattern filter = (recordFilter != null) && (recordFilter.length() > 0) ? Pattern.compile(recordFilter, Pattern.MULTILINE) : null;
+
+		return new MongoResultSetListener(collection, parseLong(from), parseLong(until), filter, serializer);	}
+
+	private Long parseLong(final String s) throws MDStoreServiceException {
+		if (StringUtils.isBlank(s)) {
+			return null;
+		}
+		try {
+			return Long.valueOf(s);
+		} catch (NumberFormatException e) {
+			throw new MDStoreServiceException("Invalid date, expected java.lang.Long, or null", e);
+		}
+	}
+
+	@Override
+	public Iterable<String> iterate() {
+		return () -> Iterators.transform(collection.find().iterator(), arg -> (String) arg.get("body"));
+	}
+
+	@Override
+	public void deleteRecord(final String recordId) {
+		collection.deleteOne(new BasicDBObject("id", recordId));
+	}
+
+	@Override
+	public String getRecord(final String recordId) throws DocumentNotFoundException {
+		final DBObject obj = collection.find(new BasicDBObject("id", recordId)).first();
+		if (obj == null || !obj.containsField("body")) throw new DocumentNotFoundException(String.format(
+				"The document with id '%s' does not exist in mdstore: '%s'", recordId, id));
+		final String body = (String) obj.get("body");
+		if (body.trim().length() == 0) throw new DocumentNotFoundException(String.format("The document with id '%s' does not exist in mdstore: '%s'",
+				recordId, id));
+		return new SerializeMongoRecord().apply(obj);
+	}
+
+	@Override
+	public List<String> deliver(final String mdId, final int pageSize, final int offset, final Map<String, String> queryParam) {
+		final QueryBuilder query = QueryBuilder.start();
+
+		for (String key : queryParam.keySet()) {
+			query.and(key).regex(Pattern.compile(queryParam.get(key), Pattern.LITERAL));
+		}
+
+		FindIterable<DBObject> dbObjects = offset > 0
+				? collection.find((Bson) query.get()).limit(pageSize).skip(offset)
+				: collection.find((Bson) query.get()).limit(pageSize);
+
+
+		queryParam.put("count", "" + collection.count((Bson) query.get()));
+
+		final List<String> result = new ArrayList<>();
+		for (final DBObject item : dbObjects) {
+			result.add(item.get("body").toString());
+		}
+
+		return result;
+	}
+
+	@Override
+	public void truncate() {
+		collection.drop();
+		discardedCollection.drop();
+	}
+
+	public DBObject getMDStoreMetadata() {
+		return mongoDatabase.getCollection("metadata", DBObject.class).find(new BasicDBObject("mdId", getId())).first();
+	}
+
+	@Override
+	public String getFormat() {
+		return (String) getMDStoreMetadata().get("format");
+	}
+
+	@Override
+	public String getInterpretation() {
+		return (String) getMDStoreMetadata().get("interpretation");
+	}
+
+	@Override
+	public String getLayout() {
+		return (String) getMDStoreMetadata().get("layout");
+	}
+
+	@Override
+	public String getId() {
+		return id;
+	}
+
+	public void setId(final String id) {
+		this.id = id;
+	}
+
+	public MongoCollection<DBObject> getCollection() {
+		return collection;
+	}
+
+	public void setCollection(final MongoCollection<DBObject> collection) {
+		this.collection = collection;
+	}
+
+	public RecordParser getRecordParser() {
+		return recordParser;
+	}
+
+	@Required
+	public void setRecordParser(final RecordParser recordParser) {
+		this.recordParser = recordParser;
+	}
+
+	@Override
+	public int getSize() {
+		return (int) collection.count();
+	}
+
+	public MongoCollection<DBObject> getDiscardedCollection() {
+		return discardedCollection;
+	}
+
+	public void setDiscardedCollection(final MongoCollection<DBObject> discardedCollection) {
+		this.discardedCollection = discardedCollection;
+	}
+
+	private class SerializeMongoRecord implements Function<DBObject, String> {
+
+		@Override
+		public String apply(final DBObject arg) {
+			return (String) arg.get("body");
+		}
+	}
+
+	private class SerializeMongoRecordId implements Function<DBObject, String> {
+
+		@Override
+		public String apply(final DBObject arg) {
+			return (String) arg.get("id");
+		}
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoResultSetListener.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoResultSetListener.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoResultSetListener.java	(revision 60503)
@@ -0,0 +1,126 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.MongoClient;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.model.Sorts;
+import eu.dnetlib.enabling.resultset.ResultSet;
+import eu.dnetlib.enabling.resultset.ResultSetAware;
+import eu.dnetlib.enabling.resultset.ResultSetListener;
+import eu.dnetlib.miscutils.maps.ConcurrentSizedMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.bson.BsonDocument;
+import org.bson.conversions.Bson;
+
+import static com.mongodb.client.model.Filters.*;
+
+public class MongoResultSetListener implements ResultSetListener, ResultSetAware {
+
+	private static final Log log = LogFactory.getLog(MongoResultSetListener.class);
+
+	private ConcurrentSizedMap<Integer, String> lastKeys = new ConcurrentSizedMap<>();
+	private Bson sortByIdAsc = Sorts.orderBy(Sorts.ascending("id"));
+
+	private Function<DBObject, String> serializer;
+	private MongoCollection<DBObject> collection;
+	private Bson query;
+
+	public MongoResultSetListener(final MongoCollection<DBObject> collection, final Long from, final Long until, final Pattern filter, final Function<DBObject, String> serializer) {
+		this.collection = collection;
+		this.serializer = serializer;
+		this.query = query(from, until, filter);
+		log.debug("Query on mongo: "+this.query.toBsonDocument(BsonDocument.class, MongoClient.getDefaultCodecRegistry()));
+	}
+
+	@Override
+	public List<String> getResult(final int fromPosition, final int toPosition) {
+
+		ArrayList<DBObject> page = null;
+
+		String lastKey = lastKeys.get(fromPosition);
+		if (lastKey != null) {
+			page = continueFrom(lastKey, (toPosition - fromPosition) + 1);
+		} else {
+			page = fetchNew(fromPosition - 1, (toPosition - fromPosition) + 1);
+		}
+
+		if (!page.isEmpty()) {
+			DBObject last = page.get(page.size() - 1);
+			lastKeys.put(toPosition + 1, (String) last.get("id"));
+		}
+
+		if (log.isDebugEnabled()) {
+			log.info(String.format("got %s records from %s to %s", page.size(), fromPosition, toPosition));
+		}
+
+		return Lists.newArrayList(Iterables.transform(page, serializer));
+	}
+
+	private ArrayList<DBObject> fetchNew(final int from, final int size) {
+		final FindIterable<DBObject> it = collection.find(query).batchSize(size);
+		return Lists.newArrayList(it.sort(sortByIdAsc).skip(from).limit(size));
+	}
+
+	private ArrayList<DBObject> continueFrom(final String lastKey, final int size) {
+		if (log.isDebugEnabled()) {
+			log.debug("trying to continue from previous key: " + lastKey);
+		}
+		final Bson q = and(query, gt("id", lastKey));
+		final FindIterable<DBObject> it = collection.find(q).batchSize(size).sort(sortByIdAsc).limit(size);
+		return Lists.newArrayList(it);
+	}
+
+	private Bson query(final Long from, final Long until, final Pattern pattern) {
+		final Bson dateFilter = dateQuery(from, until);
+		final Bson regexFilter = regexQuery(pattern);
+		if (dateFilter != null & regexFilter != null) {
+			return and(dateFilter, regexFilter);
+		} else if (dateFilter != null) {
+			return dateFilter;
+		} else if (regexFilter != null) {
+			return regexFilter;
+		}
+		return new BasicDBObject();
+	}
+
+	private Bson dateQuery(final Long from, final Long until) {
+		if (from != null & until != null) {
+			return and(gte("timestamp", from), lte("timestamp", until));
+		}
+		if (from != null) {
+			return gte("timestamp", from);
+		}
+		if (until != null) {
+			return lte("timestamp", until);
+		}
+		return null;
+	}
+
+	private Bson regexQuery(final Pattern pattern) {
+		if (pattern != null) {
+			return regex("body", pattern);
+		}
+		return null;
+	}
+
+	@Override
+	public int getSize() {
+		return (int) collection.count(query);
+	}
+
+	@Override
+	public void setResultSet(final ResultSet resultSet) {
+		resultSet.close();
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/resources/eu/dnetlib/data/mdstore/modular/mongodb/inputRecord.xml
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/resources/eu/dnetlib/data/mdstore/modular/mongodb/inputRecord.xml	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/resources/eu/dnetlib/data/mdstore/modular/mongodb/inputRecord.xml	(revision 60503)
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<record xmlns:dc="http://purl.org/dc/elements/1.1/"
+        xmlns:dr="http://www.driver-repository.eu/namespace/dr"
+        xmlns:dri="http://www.driver-repository.eu/namespace/dri"
+        xmlns:oaf="http://namespace.openaire.eu/oaf"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <header xmlns="http://namespace.openaire.eu/">
+        <dri:objIdentifier>od______2367::0001a50c6388e9bfcb791a924ec4b837</dri:objIdentifier>
+        <dri:recordIdentifier>oai:pumaoai.isti.cnr.it:cnr.imati/cnr.ian.pv/1999-PP-018</dri:recordIdentifier>
+        <dri:dateOfCollection/>
+        <dri:mdFormat/>
+        <dri:mdFormatInterpretation/>
+        <dri:repositoryId>
+            10d18b66-1d2a-4579-9adc-aa57b0821c7f_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU=
+        </dri:repositoryId>
+        <dr:objectIdentifier/>
+        <dr:dateOfCollection>2016-11-22T09:15:30.817Z</dr:dateOfCollection>
+        <dr:dateOfTransformation>2016-11-22T09:18:15.904Z</dr:dateOfTransformation>
+        <oaf:datasourceprefix>od______2367</oaf:datasourceprefix>
+    </header>
+    <metadata xmlns="http://namespace.openaire.eu/">
+        <dc:title>Anisotropic mechanisms for multiphasic unipolar electrograms. Simulation studies and experimental
+            recordings
+        </dc:title>
+        <dc:creator>Colli Franzone, Piero,</dc:creator>
+        <dc:creator>Guerri, Luciano,</dc:creator>
+        <dc:creator>Pennacchio, Micol,</dc:creator>
+        <dc:creator>Taccardi, Bruno</dc:creator>
+        <dc:date>1999-09-30</dc:date>
+        <dc:description>The origin of the multiple, complex morphologies observed in
+            unipolar epicardial electrograms, and their relationships with myocardial
+            architecture, have not been fully elucidated. To clarify this problem we
+            simulated electrograms (EGs) with a model representing the heart as an
+            anisotropic bidomain with unequal anisotropy ratio, ellipsoidal ventricular
+            geometry, transmural fiber rotation, epi-endocardial obliqueness of fiber
+            direction and a simplified conduction system. The electrograms were compared
+            with those directly recorded from the surface of isolated dog hearts immersed
+            in a conducting medium. The model accurately reproduced the recorded EG
+            morphologies for excitation wave fronts that reach the recording sites by
+            spreading either along or across fibers.The
+            origin of the multiple waves that constitute the QRS complex could be better
+            understood after splitting the current sources, the potential distributions and
+            the EGs into a field component (further subdivided into an axial and a conormal component) and a "reference"
+            component. The split model provides an explanation of the interaction between the three-dimensional geometry
+            and direction of
+            propagation of a spreading wave front, the architecture of the fibers through
+            which excitation is spreading, the potential distributions and the QRS wave
+            forms. Because epicardial potentials, electrograms and isochrone contours can be
+            computed noninvasively from body surface measurements, interpreting epicardial
+            EGs in terms of intramural events may have clinical relevance.
+        </dc:description>
+        <dc:identifier>http://puma.isti.cnr.it/dfdownloadnew.php?ident=cnr.imati/cnr.ian.pv/1999-PP-018</dc:identifier>
+        <dc:identifier>
+            http://puma.isti.cnr.it/rmydownload.php?filename=cnr.imati/cnr.ian.pv/1999-PP-018/1999-PP-018_0.ps
+        </dc:identifier>
+        <dc:language>eng</dc:language>
+        <dc:source>Preprint ercim.cnr.ian//1999-1151, 1999.</dc:source>
+        <dc:subject>Electrograms, bidomain model, reference potential, cardiac potential maps, anisotropic propagation,
+            source splitting
+        </dc:subject>
+        <dc:subject>info:eu-repo/classification/msc/78A70,65N30</dc:subject>
+        <dc:rights>info:eu-repo/semantics/openAccess</dc:rights>
+        <dc:type>info:eu-repo/semantics/preprint</dc:type>
+        <dr:CobjCategory>0016</dr:CobjCategory>
+        <dr:CobjIdentifier/>
+        <oaf:dateAccepted>1999-09-30</oaf:dateAccepted>
+        <oaf:collectedDatasourceid>opendoar____::2367</oaf:collectedDatasourceid>
+        <oaf:accessrights>OPEN</oaf:accessrights>
+        <oaf:hostedBy id="opendoar____::2367" name="PUblication MAnagement"/>
+        <oaf:collectedFrom id="opendoar____::2367" name="PUblication MAnagement"/>
+    </metadata>
+    <about xmlns:oai="http://www.openarchives.org/OAI/2.0/" xmlns="http://namespace.openaire.eu/">
+        <provenance xmlns="http://www.openarchives.org/OAI/2.0/provenance"
+                    xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/provenance http://www.openarchives.org/OAI/2.0/provenance.xsd">
+            <originDescription altered="true" harvestDate="2016-11-22T09:15:30.817Z">
+                <baseURL>http://pumaoai.isti.cnr.it/openoai2.php</baseURL>
+                <identifier>oai:pumaoai.isti.cnr.it:cnr.imati/cnr.ian.pv/1999-PP-018</identifier>
+                <datestamp>1999-10-08</datestamp>
+                <metadataNamespace>http://www.openarchives.org/OAI/2.0/oai_dc/</metadataNamespace>
+            </originDescription>
+        </provenance>
+        <oaf:datainfo>
+            <oaf:inferred>false</oaf:inferred>
+            <oaf:deletedbyinference>false</oaf:deletedbyinference>
+            <oaf:trust>0.9</oaf:trust>
+            <oaf:inferenceprovenance/>
+            <oaf:provenanceaction classid="sysimport:crosswalk:repository"
+                                  classname="sysimport:crosswalk:repository"
+                                  schemeid="dnet:provenanceActions" schemename="dnet:provenanceActions"/>
+        </oaf:datainfo>
+    </about>
+</record>
\ No newline at end of file
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/deploy.info
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/deploy.info	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/deploy.info	(revision 60503)
@@ -0,0 +1 @@
+{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet45/modules/cnr-mongo-mdstore/trunk/", "deploy_repository": "dnet45-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet45-snapshots", "name": "cnr-mongo-mdstore"}
\ No newline at end of file
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreTransactionManagerImpl.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreTransactionManagerImpl.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreTransactionManagerImpl.java	(revision 60503)
@@ -0,0 +1,742 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.MongoIterable;
+import com.mongodb.client.model.Filters;
+import com.mongodb.client.model.IndexOptions;
+import com.mongodb.client.model.UpdateOptions;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.connector.*;
+import eu.dnetlib.data.mdstore.modular.mongodb.utils.MDStoreUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.bson.conversions.Bson;
+import org.joda.time.DateTime;
+import org.joda.time.Days;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * The Class MDStoreTransactionManager.
+ */
+public class MDStoreTransactionManagerImpl implements MDStoreTransactionManager {
+
+	/** The Constant log. */
+	private static final Log log = LogFactory.getLog(MDStoreTransactionManagerImpl.class);
+
+	/**
+	 * The table name.
+	 */
+	private static String TABLE_NAME = "metadataManager";
+
+	/** The max number of concurrent transactions per mdstore. */
+	private int maxTransactions = 1;
+
+	/**
+	 * The db.
+	 */
+	private MongoDatabase db;
+
+	/**
+	 * The manager table.
+	 */
+	private MongoCollection<DBObject> managerTable;
+
+	/** The expired days. */
+	private int expiredDays;
+
+	private final IndexOptions options = new IndexOptions().background(true);
+
+	/**
+	 * Bootstrap manager.
+	 */
+	private void bootstrapManager() {
+		log.debug("Bootstrap Manager start");
+		final MongoCollection<DBObject> metadataColl = db.getCollection("metadata", DBObject.class);
+		final FindIterable<DBObject> values = metadataColl.find();
+		this.setManagerTable(db.getCollection(TABLE_NAME, DBObject.class));
+		for (DBObject object : values) {
+			final String id = (String) object.get("mdId");
+			String newId = id;
+			if (id.contains("_")) {
+				newId = StringUtils.substringBefore(id, "_");
+			}
+			final BasicDBObject input = new BasicDBObject();
+			input.put("mdId", id);
+			input.put("currentId", newId);
+			input.put("expiring", new String[] {});
+			input.put("transactions", new String[] {});
+			getManagerTable().insertOne(input);
+			log.debug(String.format("Added %s to Metadata Manager data structure", id));
+
+		}
+		final BasicDBObject ensureIndex = new BasicDBObject();
+		ensureIndex.put("mdId", 1);
+		log.debug("Create index in MetadaManager ");
+		this.getManagerTable().createIndex(ensureIndex, options);
+	}
+
+	/**
+	 * Gets the DBObject describing an mdstore. null if there is no mdstore with the given id.
+	 *
+	 * @param mdstoreID the mdStore identifier
+	 * @return DBObject or null
+	 */
+	private DBObject getMDStoreAsDBObject(final String mdstoreID) throws MDStoreServiceException {
+		final BasicDBObject query = new BasicDBObject();
+		query.put("mdId", mdstoreID);
+		final FindIterable<DBObject> it = this.getManagerTable().find(query);
+		return it.first();
+	}
+
+	/**
+	 * Verify consistency.
+	 *
+	 * @throws MDStoreServiceException
+	 *             the MD store service exception
+	 */
+	@Override
+	public void verifyConsistency() throws MDStoreServiceException {
+		if (this.getManagerTable() == null) {
+			if (!Lists.newArrayList(db.listCollectionNames()).contains(TABLE_NAME))
+				bootstrapManager();
+			else {
+				this.setManagerTable(db.getCollection(TABLE_NAME, DBObject.class));
+			}
+		}
+		if (this.getManagerTable() == null) throw new MDStoreServiceException("Something bad happen, unable to create managerTable");
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#createMDStore(java.lang.String)
+	 */
+	@Override
+	public void createMDStore(final String mdId) throws MDStoreServiceException {
+		log.debug("Creating new mdstore");
+		verifyConsistency();
+		String newId = mdId;
+		if (mdId.contains("_")) {
+			newId = StringUtils.substringBefore(mdId, "_");
+		}
+		final BasicDBObject instance = new BasicDBObject();
+		instance.put("mdId", mdId);
+		instance.put("currentId", newId);
+		instance.put("expiring", new String[] {});
+		getManagerTable().insertOne(instance);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#dropMDStore(java.lang.String)
+	 */
+	@Override
+	public void dropMDStore(final String mdId) throws MDStoreServiceException {
+		verifyConsistency();
+		log.debug("Droping MDStore: " + mdId);
+		final BasicDBObject query = new BasicDBObject();
+		query.put("mdId", mdId);
+		final DBObject dropped = this.getManagerTable().findOneAndDelete(query);
+		garbage();
+		final String collectionName = (String) dropped.get("currentId");
+		this.db.getCollection(collectionName).drop();
+		this.db.getCollection("discarded-" + collectionName).drop();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#getMDStoreCollection(java.lang.String)
+	 */
+	@Override
+	public String getMDStoreCollection(final String mdId) throws MDStoreServiceException {
+		verifyConsistency();
+		DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
+		if (mdstoreInfo != null)
+			return (String) mdstoreInfo.get("currentId");
+		else return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#startTransaction(java.lang.String, boolean)
+	 */
+	@Override
+	public String startTransaction(final String mdId, final boolean refresh) throws MDStoreServiceException {
+		verifyConsistency();
+		log.info("Start transaction for metadata store " + mdId);
+		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
+		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdId);
+		String idCreation = StringUtils.substringBefore(mdId, "_");
+		idCreation = idCreation + "::" + System.currentTimeMillis();
+
+		BasicDBList values;
+		if (mdstoreInfo.containsField("transactions")) {
+			values = (BasicDBList) mdstoreInfo.get("transactions");
+			if (values.size() > getMaxTransactions())
+				throw new MDStoreServiceException("Cannot create more than " + getMaxTransactions() + " transactions, found: " + values.size() + ", mdId:"
+						+ mdId);
+		} else {
+			values = new BasicDBList();
+		}
+		final BasicDBObject transactionMetadata = new BasicDBObject();
+		transactionMetadata.put("id", idCreation);
+		transactionMetadata.put("refresh", refresh);
+		transactionMetadata.put("date", new Date());
+		values.add(transactionMetadata);
+		mdstoreInfo.put("transactions", values);
+		this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
+		return idCreation;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#commit(java.lang.String, java.lang.String,
+	 *      eu.dnetlib.data.mdstore.modular.connector.MDStore)
+	 */
+	@Override
+	public boolean commit(final String transactionId, final String mdstoreId, final MDStore current) throws MDStoreServiceException {
+		verifyConsistency();
+		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdstoreId);
+		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdstoreId);
+		final BasicDBList transactions = (BasicDBList) mdstoreInfo.get("transactions");
+		final DBObject transaction = findTransaction(transactions, transactionId);
+		if (transaction == null) throw new MDStoreServiceException("Error, unable to find transaction with Id " + transactionId);
+		final boolean refresh = (Boolean) transaction.get("refresh");
+		transactions.remove(transaction);
+		final String oldId = (String) mdstoreInfo.get("currentId");
+		if (refresh) {
+			mdstoreInfo.put("currentId", transactionId);
+			final BasicDBList stillUsed = (BasicDBList) mdstoreInfo.get("expiring");
+			if (stillUsed.size() == 0) {
+				db.getCollection(oldId).drop();
+				db.getCollection("discarded-" + oldId).drop();
+			}
+			log.debug("Replaced collection ");
+		} else {
+			log.debug("commit incremental ");
+			updateIncremental(transactionId, oldId);
+			db.getCollection(transactionId).drop();
+			db.getCollection("discarded-" + transactionId).drop();
+		}
+		this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
+
+		log.info("Committed transaction for metadata store " + mdstoreId);
+		return true;
+	}
+
+	/**
+	 * Find transaction.
+	 *
+	 * @param transactions
+	 *            the transactions
+	 * @param transactionId
+	 *            the transaction id
+	 * @return the DB object
+	 */
+	private DBObject findTransaction(final BasicDBList transactions, final String transactionId) {
+		if (transactions.size() == 0) return null;
+		for (Object tx : transactions) {
+			final BasicDBObject transaction = (BasicDBObject) tx;
+			final String id = (String) transaction.get("id");
+			if (transactionId.equals(id)) return transaction;
+		}
+		return null;
+
+	}
+
+	/**
+	 * Gets the db.
+	 *
+	 * @return the db
+	 */
+	public MongoDatabase getDb() {
+		return db;
+	}
+
+	/**
+	 * Sets the db.
+	 *
+	 * @param db
+	 *            the db to set
+	 */
+	@Required
+	public void setDb(final MongoDatabase db) {
+		this.db = db;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#readMdStore(java.lang.String)
+	 */
+	@Override
+	public String readMdStore(final String mdStoreId) throws MDStoreServiceException {
+		verifyConsistency();
+		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdStoreId);
+		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdStoreId);
+		final String currentId = (String) mdstoreInfo.get("currentId");
+		final BasicDBList values = (BasicDBList) mdstoreInfo.get("expiring");
+		updateMdstoreUsed(values, currentId);
+		this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
+		return currentId;
+
+	}
+
+
+	/**
+	 * Update mdstore used.
+	 *
+	 * @param values
+	 *            the values
+	 * @param mdId
+	 *            the md id
+	 */
+	private void updateMdstoreUsed(final BasicDBList values, final String mdId) {
+		if (values.size() > 0) {
+			for (Object value : values) {
+				final DBObject obj = (DBObject) value;
+				final String id = (String) obj.get("id");
+				if (mdId.equals(id)) {
+					obj.put("lastRead", new Date());
+					return;
+				}
+			}
+		}
+		final BasicDBObject readStore = new BasicDBObject();
+		readStore.put("id", mdId);
+		readStore.put("lastRead", new Date());
+		values.add(readStore);
+	}
+
+	/**
+	 * Gets the manager table.
+	 *
+	 * @return the managerTable
+	 */
+	public MongoCollection<DBObject> getManagerTable() {
+		return managerTable;
+	}
+
+	/**
+	 * Sets the manager table.
+	 *
+	 * @param managerTable
+	 *            the managerTable to set
+	 */
+	public void setManagerTable(final MongoCollection<DBObject> managerTable) {
+		this.managerTable = managerTable;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#getInfoForCurrentMdStore(java.lang.String)
+	 */
+	@Override
+	public MDStoreManagerInfo getInfoForCurrentMdStore(final String mdStoreId) throws MDStoreServiceException {
+		verifyConsistency();
+		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdStoreId);
+		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdStoreId);
+		final MDStoreManagerInfo result = new MDStoreManagerInfo();
+		result.setCurrentId((String) mdstoreInfo.get("currentId"));
+		result.setMdId((String) mdstoreInfo.get("mdId"));
+		final BasicDBList values = (BasicDBList) mdstoreInfo.get("expiring");
+		for (Object v : values) {
+			final MDStoreExpiredInfo stillused = new MDStoreExpiredInfo();
+			final DBObject value = (DBObject) v;
+			stillused.setId((String) value.get("id"));
+			stillused.setLastRead((Date) value.get("lastRead"));
+			result.addExpiredItem(stillused);
+		}
+		final BasicDBList transactions = (BasicDBList) mdstoreInfo.get("transactions");
+		if (transactions != null) {
+			for (Object tx : transactions) {
+				final MDStoreTransactionInfo transaction = new MDStoreTransactionInfo();
+				final DBObject value = (DBObject) tx;
+				final String transactionId = (String) value.get("id");
+				transaction.setId(transactionId);
+				transaction.setDate((Date) value.get("date"));
+				transaction.setRefresh((Boolean) value.get("refresh"));
+				transaction.setSize(db.getCollection(transactionId).count());
+				result.addTransactionInfo(transaction);
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#dropUsed(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public Boolean dropUsed(final String mdId, final String idToDrop) throws MDStoreServiceException {
+		verifyConsistency();
+		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
+		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdId);
+		return dropStore(mdstoreInfo, idToDrop, "expiring");
+	}
+
+	private boolean dropStore(DBObject mdstoreInfo, final String idToDrop, String transactionListName) throws MDStoreServiceException {
+		final BasicDBList transactionList = (BasicDBList) mdstoreInfo.get(transactionListName);
+		for (int i = 0; i < transactionList.size(); i++) {
+			final DBObject value = (DBObject) transactionList.get(i);
+			final String currentUsedId = (String) value.get("id");
+			if (currentUsedId.equals(idToDrop)) {
+				db.getCollection(idToDrop).drop();
+				db.getCollection("discarded-" + idToDrop).drop();
+				transactionList.remove(value);
+				mdstoreInfo.put(transactionListName, transactionList);
+				this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", mdstoreInfo.get("_id")), mdstoreInfo);
+				return true;
+			}
+		}
+		throw new MDStoreServiceException("Error, unable to drop collection " + idToDrop);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#garbage()
+	 */
+	@Override
+	public void garbage() throws MDStoreServiceException {
+		verifyConsistency();
+		log.info("Start garbage collection of MdStore");
+		final FindIterable<DBObject> it = this.managerTable.find();
+		int totalDeleted = 0;
+		for (DBObject currentObject :  it){
+			if (log.isDebugEnabled()) {
+				log.debug("start to check id: " + currentObject.get("currentId"));
+			}
+			garbageExpiring(currentObject, (String) currentObject.get("currentId"));
+			garbageTransactions(currentObject, (String) currentObject.get("currentId"));
+			this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", currentObject.get("_id")), currentObject);
+		}
+
+		// DELETING Collection that are not in the metadataManager table
+		MongoIterable<String> collections = this.db.listCollectionNames();
+		for (String collection : collections) {
+			if ((collection.length() > 30) && (!collection.contains("discarded-"))) {
+				final DBObject item = getMetadataObjectForCollections(collection);
+
+				if (shouldDelete(collection, item)) {
+					if (log.isDebugEnabled()) {
+						log.debug("delete collection: " + collection + " from mongo");
+					}
+					db.getCollection(collection).drop();
+					db.getCollection("discarded-" + collection).drop();
+					if (log.isDebugEnabled()) {
+						log.debug("delete collection: discarded-" + collection + " from mongo");
+					}
+				}
+			}
+		}
+
+		log.info("Complete garbage collection of MdStore, total store deleted: " + totalDeleted);
+	}
+
+	private DBObject getMetadataObjectForCollections(final String collectionName) {
+		if (collectionName == null) return null;
+		final String postfix = "_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==";
+		final String tmp = collectionName.contains("discarded-") ? StringUtils.substringAfter(collectionName, "discarded-") : collectionName;
+		final String collectionNameCleaned = StringUtils.substringBefore(tmp, "::") + postfix;
+
+		//DBObject query = QueryBuilder.start("mdId").is(collectionNameCleaned).get();
+		Bson query = Filters.eq("mdId", collectionNameCleaned);
+		return this.managerTable.find(query).first();
+
+	}
+
+	private boolean shouldDelete(final String collectionName, final DBObject metadataManagerInstance) {
+		log.debug("should delete instance "+metadataManagerInstance);
+		if((metadataManagerInstance== null) || (metadataManagerInstance.get("currentId")== null)){
+			log.debug("the instance has not currentID");
+			return true;
+		}
+		String currentId = (String) metadataManagerInstance.get("currentId");
+		if (collectionName.equals(currentId)) return false;
+		BasicDBList expiringList = (BasicDBList) metadataManagerInstance.get("expiring");
+		if (findInList(expiringList, collectionName, "id")) return false;
+		BasicDBList transactionsList = (BasicDBList) metadataManagerInstance.get("transactions");
+		return !findInList(transactionsList, collectionName, "id");
+	}
+
+	private boolean findInList(final BasicDBList list, final String object, final String tagname) {
+		if (list == null) return false;
+		for (Object o : list) {
+			DBObject currentObject = (DBObject) o;
+			final String id = (String) currentObject.get(tagname);
+			if (id.equals(object)) return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Delete.
+	 *
+	 * @param list
+	 *            the list
+	 * @param toRemove
+	 *            the to remove
+	 */
+	private void delete(final BasicDBList list, final List<DBObject> toRemove) {
+
+		for (final DBObject obj : toRemove) {
+			if (log.isDebugEnabled()) {
+				log.debug("deleting " + obj);
+			}
+			list.remove(obj);
+		}
+	}
+
+	/**
+	 * Garbage transactions.
+	 *
+	 * @param currentObject
+	 *            the current object
+	 * @param currentId
+	 *            the current id
+	 */
+	private void garbageTransactions(final DBObject currentObject, final String currentId) {
+		if (log.isDebugEnabled()) {
+			log.debug("Start garbage transactions ");
+		}
+
+		final BasicDBList expiring = (BasicDBList) currentObject.get("transactions");
+		if ((expiring == null) || (expiring.size() <= getMaxTransactions())) return;
+
+		List<DBObject> expiringList = Lists.newArrayList();
+
+		for (Object o : expiring) {
+			final DBObject cobj = (DBObject) o;
+			if (cobj != null) {
+				expiringList.add((DBObject) o);
+			}
+
+		}
+
+		expiringList.sort(MDStoreUtils.getComparatorOnDate());
+
+		List<DBObject> toRemove = Lists.newArrayList();
+		int i = 0;
+
+		// We should remove the k item less recent
+		// where k = numberOftotalTransaction - maxNumberOfTransaction
+		// k = numberOfItemToRemove
+
+		while (((expiringList.size() - toRemove.size()) > getMaxTransactions()) || (i < expiringList.size())) {
+			DBObject currentObj = expiringList.get(i++);
+			String objectId = (String) currentObj.get("id");
+			if (!objectId.equals(currentId)) {
+				if (log.isDebugEnabled()) {
+					log.debug("delete collection: " + objectId + " from mongo");
+				}
+				db.getCollection(objectId).drop();
+				db.getCollection("discarded-" + objectId).drop();
+				if (log.isDebugEnabled()) {
+					log.debug("delete collection: discarded-" + objectId + " from mongo");
+				}
+				toRemove.add(currentObj);
+			} else {
+				if (log.isDebugEnabled()) {
+					log.debug("Cannot remove transaction " + objectId + " because is the currentId: " + currentId);
+				}
+			}
+		}
+
+		delete(expiring, toRemove);
+		log.info("Deleted " + toRemove.size() + " transactions, mdStore Id:" + currentObject.get("mdId"));
+	}
+
+	/**
+	 * Garbage expiring.
+	 *
+	 * @param currentObject
+	 *            the current object
+	 * @param currentId
+	 *            the current id
+	 */
+	private void garbageExpiring(final DBObject currentObject, final String currentId) {
+		if (log.isDebugEnabled()) {
+			log.debug("Start to search expiring mdstores for id: " + currentObject.get("mdId"));
+		}
+		final BasicDBList expiring = (BasicDBList) currentObject.get("expiring");
+		final List<DBObject> toRemove = Lists.newArrayList();
+		if (log.isDebugEnabled()) {
+			if (expiring == null) {
+				log.debug("expiring list is null");
+			} else {
+				log.debug("expiring list size is :" + expiring.size());
+			}
+		}
+		if ((expiring == null) || (expiring.size() == 0)) {
+			log.debug("Deleted  0  expired  collections, mdStore Id:" + currentObject.get("mdId"));
+			return;
+		}
+		for (Object anExpiring : expiring) {
+			final DBObject currentExpiredStore = (DBObject) anExpiring;
+			final String currentUsedId = (String) currentExpiredStore.get("id");
+			final Days d = getExpiringDays(currentExpiredStore, "lastRead");
+			if (log.isDebugEnabled()) {
+				log.debug("the store :" + currentId + " expired since " + d.getDays() + "days ");
+			}
+			// DELETE the collection where the last time they was read
+			// is more than 3 days ago
+			if (d.getDays() > getExpiredDays()) {
+				if (!currentUsedId.equals(currentId)) {
+					db.getCollection(currentUsedId).drop();
+					db.getCollection("discarded-" + currentUsedId).drop();
+					log.debug("deleted collection " + currentUsedId);
+				}
+				toRemove.add(currentExpiredStore);
+			}
+		}
+		delete(expiring, toRemove);
+		log.debug("Deleted expired " + toRemove.size() + "collections, mdStore Id:" + currentObject.get("mdId"));
+	}
+
+	/**
+	 * Gets the expiring days.
+	 *
+	 * @param value
+	 *            the value
+	 * @param paramName
+	 *            the param name
+	 * @return the expiring days
+	 */
+	private Days getExpiringDays(final DBObject value, final String paramName) {
+		final Date lastRead = (Date) value.get(paramName);
+		final DateTime last = new DateTime(lastRead);
+		final DateTime today = new DateTime();
+		final Days d = Days.daysBetween(last, today);
+		return d;
+	}
+
+	/**
+	 * Gets the expired days.
+	 *
+	 * @return the expiredDays
+	 */
+	public int getExpiredDays() {
+		if (this.expiredDays == 0) return 3;
+		return expiredDays;
+	}
+
+	/**
+	 * Sets the expired days.
+	 *
+	 * @param expiredDays
+	 *            the expiredDays to set
+	 */
+	public void setExpiredDays(final int expiredDays) {
+		this.expiredDays = expiredDays;
+	}
+
+	/**
+	 * Update incremental.
+	 *
+	 * @param transactionId
+	 *            the transaction id
+	 * @param currentId
+	 *            the current id
+	 */
+	private void updateIncremental(final String transactionId, final String currentId) {
+		final MongoCollection<DBObject> transaction = db.getCollection(transactionId, DBObject.class);
+		final MongoCollection<DBObject> mdstore = db.getCollection(currentId, DBObject.class);
+		final FindIterable<DBObject> it = transaction.find().noCursorTimeout(true);
+		for (DBObject currentObj : it) {
+			final String id = (String) currentObj.get("id");
+			BasicDBObject newObj = (BasicDBObject)((BasicDBObject) currentObj).copy();
+			//Must not have _id in the new object
+			newObj.remove("_id");
+			//setting to journaled write concern to be sure that when the write returns everything has been flushed to disk (https://docs.mongodb.org/manual/faq/developers/#when-does-mongodb-write-updates-to-disk)
+			//the explicit fsync command can't be run anymore: 'Command failed with error 13: 'fsync may only be run against the admin database.'
+			final MongoCollection<DBObject> mdstoreWrite = mdstore.withWriteConcern(WriteConcern.JOURNALED);
+			mdstoreWrite.replaceOne(new BasicDBObject("id", id), newObj, new UpdateOptions().upsert(true));
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager#dropTransaction(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public Boolean dropTransaction(final String mdId, final String idToDrop) throws MDStoreServiceException {
+		verifyConsistency();
+		final DBObject mdstoreInfo = getMDStoreAsDBObject(mdId);
+		if (mdstoreInfo == null) throw new MDStoreServiceException("Error, unable to find Mdstore with Id " + mdId);
+		return dropStore(mdstoreInfo, idToDrop, "transactions");
+	}
+
+	public void garbageTransactionsOnStart() throws MDStoreServiceException {
+		verifyConsistency();
+		FindIterable<DBObject> it = this.managerTable.find();
+
+		final List<String> currentMdStoreId = Lists.newArrayList();
+		for (DBObject currentObject : it){
+			currentMdStoreId.add((String) currentObject.get("currentId"));
+			final BasicDBList transactions = (BasicDBList) currentObject.get("transactions");
+			if ((transactions != null) && (transactions.size() > 0)) {
+				for (Object tx : transactions) {
+					final DBObject currentTransactions = (DBObject) tx;
+					final String id = (String) currentTransactions.get("id");
+					db.getCollection(id).drop();
+					db.getCollection("discarded-" + id).drop();
+					log.debug("deleted collection " + id);
+				}
+				currentObject.put("transactions", new BasicDBList());
+				this.getManagerTable().findOneAndReplace(new BasicDBObject("_id", currentObject.get("_id")), currentObject);
+			}
+		}
+
+		//DELETING ALL THE DISCARDED COLLECTION THAT DISCARDED COLLECTION OF THE CURRENT MDSTORE
+		final ArrayList<String> collectionsNames = Lists.newArrayList(db.listCollectionNames());
+
+		for (String item : collectionsNames) {
+			if (item.startsWith("discarded-")) {
+				final String currentCollection = StringUtils.substringAfter(item, "discarded-");
+				if (!currentMdStoreId.contains(currentCollection)) {
+					log.info("Deleting discarded collection :" + item);
+					this.db.getCollection(item).drop();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Gets the max transactions.
+	 *
+	 * @return the maxTransactions
+	 */
+	public int getMaxTransactions() {
+		return maxTransactions;
+	}
+
+	/**
+	 * Sets the max transactions.
+	 *
+	 * @param maxTransactions
+	 *            the maxTransactions to set
+	 */
+	public void setMaxTransactions(final int maxTransactions) {
+		this.maxTransactions = maxTransactions;
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoBulkWritesManager.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoBulkWritesManager.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoBulkWritesManager.java	(revision 60503)
@@ -0,0 +1,147 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.model.*;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.MDFormatDescription;
+import eu.dnetlib.data.mdstore.modular.RecordParser;
+import eu.dnetlib.data.mdstore.modular.mongodb.utils.IndexFieldRecordParser;
+import eu.dnetlib.data.mdstore.modular.mongodb.utils.IndexFieldRecordParserException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static eu.dnetlib.data.mdstore.modular.MDStoreConstants.*;
+
+public class MongoBulkWritesManager {
+
+	private static final Log log = LogFactory.getLog(MongoBulkWritesManager.class);
+	private final boolean discardRecords;
+	private final boolean indexRecords;
+	private final IndexFieldRecordParser indexFieldRecordParser = new IndexFieldRecordParser();
+	private final List<MDFormatDescription> mdref;
+	private RecordParser recordParser;
+	private MongoCollection<DBObject> validCollection;
+	private List<WriteModel<DBObject>> validBulkOperationList;
+	private BulkWriteOptions writeOptions;
+	private MongoCollection<DBObject> discardedCollection;
+	private List<WriteModel<DBObject>> discardedBulkOperationList;
+	private int bulkSize;
+
+	public MongoBulkWritesManager(final MongoCollection<DBObject> collection,
+			final MongoCollection<DBObject> discardedCollection,
+			final List<MDFormatDescription> mdref,
+			final int bulkSize,
+			final RecordParser parser,
+			final boolean discardRecords) {
+		this.validCollection = collection.withWriteConcern(WriteConcern.ACKNOWLEDGED);
+		this.validBulkOperationList = Lists.newArrayList();
+
+		this.discardedCollection = discardedCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED);
+		this.discardedBulkOperationList = Lists.newArrayList();
+
+		this.bulkSize = bulkSize;
+		this.recordParser = parser;
+		this.discardRecords = discardRecords;
+		this.mdref = mdref;
+
+		this.indexRecords = (this.mdref != null &&  !this.mdref.isEmpty());
+		this.writeOptions = new BulkWriteOptions().ordered(false);
+	}
+
+	public void insert(final String record) throws MDStoreServiceException {
+		Map<String, String> recordProperties = null;
+		try {
+			recordProperties = recordParser.parseRecord(record);
+
+		} catch (Throwable e) {
+			if (discardRecords) {
+				log.debug("unhandled exception: " + e.getMessage());
+				discardRecord(record);
+			}
+		}
+		Map<String, List<String>> indexRecordField = null;
+		try {
+			if (indexRecords) {
+				indexRecordField = indexFieldRecordParser.parseRecord(record, mdref);
+			}
+		} catch (IndexFieldRecordParserException e) {
+			// could not index record fields
+			throw new MDStoreServiceException("Are you using the correct type of store / index definition for the records in " + validCollection.getNamespace() + " ?", e);
+		}
+
+		log.debug("found props: " + recordProperties);
+		if (recordProperties.containsKey(ID)) {
+			final DBObject obj = buildDBObject(record, recordProperties, indexRecordField);
+			if (log.isDebugEnabled()) {
+				log.debug("Saving object" + obj);
+			}
+			validBulkOperationList.add(new ReplaceOneModel(new BasicDBObject(ID, obj.get(ID)), obj, new UpdateOptions().upsert(true)));
+			if (((validBulkOperationList.size() % bulkSize) == 0) && !validBulkOperationList.isEmpty()) {
+				validCollection.bulkWrite(validBulkOperationList, writeOptions);
+				validBulkOperationList.clear();
+			}
+		} else {
+			if (discardRecords) {
+				log.debug("parsed record seems invalid");
+				discardRecord(record);
+			}
+		}
+	}
+
+	private void discardRecord(final String record) {
+		discardedBulkOperationList.add(new InsertOneModel(new BasicDBObject(BODY, record)));
+
+		if (((discardedBulkOperationList.size() % bulkSize) == 0) && !discardedBulkOperationList.isEmpty()) {
+			discardedCollection.bulkWrite(discardedBulkOperationList, writeOptions);
+			discardedBulkOperationList.clear();
+		}
+	}
+
+	public void flushBulks() {
+		//setting to journaled write concern to be sure that when the write returns everything has been flushed to disk (https://docs.mongodb.org/manual/faq/developers/#when-does-mongodb-write-updates-to-disk)
+		//the explicit fsync command can't be run anymore: 'Command failed with error 13: 'fsync may only be run against the admin database.'
+		if (!validBulkOperationList.isEmpty()) {
+			validCollection = getCollectionWithWriteConcern(validCollection, WriteConcern.JOURNALED);
+			validCollection.bulkWrite(validBulkOperationList, writeOptions);
+		}
+		if (!discardedBulkOperationList.isEmpty()) {
+			discardedCollection = getCollectionWithWriteConcern(discardedCollection, WriteConcern.JOURNALED);
+			discardedCollection.bulkWrite(discardedBulkOperationList, writeOptions);
+		}
+		//setting write concern back to ACKNOWLEDGE to avoid the execution of future writes all in Journaled mode
+		validCollection = getCollectionWithWriteConcern(validCollection, WriteConcern.ACKNOWLEDGED);
+		discardedCollection = getCollectionWithWriteConcern(discardedCollection, WriteConcern.ACKNOWLEDGED);
+	}
+
+	protected DBObject buildDBObject(final String record, final Map<String, String> recordProperties, final Map<String, List<String>> indexFieldProperties) {
+		final DBObject obj = new BasicDBObject();
+		obj.put(ID, recordProperties.get(ID));
+		obj.put(ORIGINALID, recordProperties.get(ORIGINALID));
+		obj.put(BODY, record);
+		obj.put(TIMESTAMP, Long.valueOf(recordProperties.get(TIMESTAMP)));
+		if (indexFieldProperties != null)
+			obj.putAll(Maps.filterKeys(indexFieldProperties, new Predicate<String>() {
+				//ensure we do not override the mandatory fields above with some unexpected value
+				@Override
+				public boolean apply(@Nullable final String s) {
+					return !s.equalsIgnoreCase(ID) && !s.equalsIgnoreCase(ORIGINALID) && !s.equalsIgnoreCase(BODY) && !s.equalsIgnoreCase(TIMESTAMP);
+				}
+			}));
+		return obj;
+	}
+
+	private MongoCollection<DBObject> getCollectionWithWriteConcern(MongoCollection<DBObject> collection, WriteConcern writeConcern) {
+		return collection.withWriteConcern(writeConcern);
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreDaoImpl.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreDaoImpl.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreDaoImpl.java	(revision 60503)
@@ -0,0 +1,327 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
+import com.mongodb.BasicDBObject;
+import com.mongodb.BasicDBObjectBuilder;
+import com.mongodb.DBObject;
+import com.mongodb.client.AggregateIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.CreateCollectionOptions;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.MDStoreDescription;
+import eu.dnetlib.data.mdstore.modular.RecordParser;
+import eu.dnetlib.data.mdstore.modular.RecordParserFactory;
+import eu.dnetlib.data.mdstore.modular.connector.MDStore;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDBStatus;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager;
+import eu.dnetlib.data.mdstore.modular.mongodb.utils.MDStoreUtils;
+import eu.dnetlib.miscutils.collections.FilteredCollection;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.datetime.DateUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.bson.Document;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Factory bean for MongoMDStore instances.
+ *
+ * @author marko
+ */
+public class MDStoreDaoImpl implements MDStoreDao {
+
+	public static final String MD_ID = "mdId";
+	public static final String FORMAT = "format";
+	public static final String INTERPRETATION = "interpretation";
+	public static final String LAYOUT = "layout";
+	public static final String SIZE = "size";
+	public static final String METADATA_NAME = "metadata";
+	private static final Log log = LogFactory.getLog(MDStoreDaoImpl.class);
+	private MongoDatabase db;
+
+	private RecordParserFactory recordParserFactory;
+
+	private boolean discardRecords = true;
+
+	@Autowired
+	private MDStoreTransactionManager transactionManager;
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void createMDStore(final String mdId, final String format, final String interpretation, final String layout) throws MDStoreServiceException {
+		transactionManager.createMDStore(mdId);
+		final String internalId = transactionManager.getMDStoreCollection(mdId);
+
+		if (!Lists.newArrayList(getDb().listCollectionNames()).contains(internalId)) {
+			log.info(String.format("creating collection %s", internalId));
+			getDb().createCollection(internalId, new CreateCollectionOptions());
+		}
+		final MongoCollection<DBObject> coll = getDb().getCollection(METADATA_NAME, DBObject.class);
+		final BasicDBObject obj = new BasicDBObject();
+		obj.put(MD_ID, mdId);
+		obj.put(FORMAT, format);
+		obj.put(INTERPRETATION, interpretation);
+		obj.put(LAYOUT, layout);
+		obj.put(SIZE, 0);
+		coll.insertOne(obj);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void deleteMDStore(final String mdId) throws MDStoreServiceException {
+		final MongoCollection<DBObject> metadata = getDb().getCollection(METADATA_NAME, DBObject.class);
+		if (metadata == null) throw new MDStoreServiceException("cannot find metadata collection");
+		transactionManager.dropMDStore(mdId);
+		metadata.deleteOne(new BasicDBObject(MD_ID, mdId));
+		log.info("deleted mdId: " + mdId);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public MDStore getMDStore(final String mdId) throws MDStoreServiceException {
+		final String internalId = transactionManager.getMDStoreCollection(mdId);
+		return new MongoMDStore(mdId, getDb().getCollection(internalId, DBObject.class), getRecordParser(), isDiscardRecords(), getDb());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public MDStore readMDStore(final String mdId) throws MDStoreServiceException {
+		final String internalId = transactionManager.readMdStore(mdId);
+		return new MongoMDStore(mdId, getDb().getCollection(internalId, DBObject.class), getRecordParser(), isDiscardRecords(), getDb());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public MDStore startTransaction(final String mdId, final boolean refresh) throws MDStoreServiceException {
+		final String transactionId = transactionManager.startTransaction(mdId, refresh);
+		return new MongoMDStore(transactionId, getDb().getCollection(transactionId, DBObject.class), getRecordParser(), isDiscardRecords(),
+				getDb());
+	}
+
+	private RecordParser getRecordParser() {
+		final RecordParser parser = getRecordParserFactory().newInstance();
+		parser.setTimestamp(DateUtils.now());
+		return parser;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<MDStoreDescription> listMDStores() {
+		return MappedCollection.listMap(getDb().getCollection(METADATA_NAME, DBObject.class).find(), input -> {
+
+			final String mdId = (String) input.get(MD_ID);
+			log.debug("Getting info for " + mdId);
+			final String format = (String) input.get(FORMAT);
+			final String layout = (String) input.get(LAYOUT);
+			final String interpretation = (String) input.get(INTERPRETATION);
+			MongoMDStore currentMDStore = null;
+			final MDStoreDescription description = new MDStoreDescription();
+			try {
+				currentMDStore = (MongoMDStore) getMDStore(mdId);
+			} catch (final MDStoreServiceException e) {
+				log.error("Error on retrieving mdstore for getting info mdId " + mdId);
+			}
+
+			int size = 0;
+			if (input.containsField(SIZE)) {
+				log.debug("Size retrieved from metadata for mdId :" + mdId);
+				size = (Integer) input.get(SIZE);
+			} else {
+				if (currentMDStore != null) {
+					log.debug("Size not Found in metadata for mdId :" + mdId + " calling getCount ");
+					size = currentMDStore.getSize();
+					input.put("size", size);
+					getDb().getCollection(METADATA_NAME, DBObject.class).findOneAndReplace(new BasicDBObject(MD_ID, mdId), input);
+				}
+			}
+			if (currentMDStore != null) {
+				description.setIndexed(currentMDStore.isIndexed());
+			}
+			description.setId(mdId);
+			description.setFormat(format);
+			description.setLayout(layout);
+			description.setInterpretation(interpretation);
+			description.setSize(size);
+			return description;
+		});
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<String> listMDStores(final String format, final String layout, final String interpretation) {
+		return MappedCollection.listMap(
+				FilteredCollection.listFilter(getDb().getCollection(METADATA_NAME, DBObject.class).find(), MDStoreUtils.dboFilter(format, layout, interpretation)),
+				MDStoreUtils.mdId());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int getCachedSize(final String id) throws MDStoreServiceException {
+		log.debug("retrieve cached size for mdstore: " + id);
+		final DBObject desc = getDb().getCollection(METADATA_NAME, DBObject.class).find(new BasicDBObject(MD_ID, id)).first();
+		if (!desc.containsField(SIZE)) {
+			desc.put(SIZE, getMDStore(id).getSize());
+		}
+
+		final Object oSize = desc.get(SIZE);
+		return (Integer) oSize;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void refreshSizes() throws MDStoreServiceException {
+		for (final MDStoreDescription mdStoreId : listMDStores()) {
+			refreshSize(mdStoreId.getId());
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int refreshSize(final String mdStoreId) throws MDStoreServiceException {
+		final int size = (int) getDb().getCollection(transactionManager.getMDStoreCollection(mdStoreId)).count();
+		final MongoCollection<DBObject> metadata = getDb().getCollection(METADATA_NAME, DBObject.class);
+		metadata.updateOne(new BasicDBObject(MD_ID, mdStoreId), new BasicDBObject("$set", new BasicDBObject(SIZE, size)));
+		return size;
+	}
+
+	@Override
+	public int getSumOfSizes(final String format, final String layout, final String interpretation) throws MDStoreServiceException {
+		final MongoCollection<DBObject> metadata = getDb().getCollection(METADATA_NAME, DBObject.class);
+		BasicDBObject matchObj = (BasicDBObject) BasicDBObjectBuilder.start("$match",
+				BasicDBObjectBuilder.start("format", format).add("layout", layout).add("interpretation", interpretation).get()).get();
+		BasicDBObject groupObj = (BasicDBObject) BasicDBObjectBuilder.start("$group",
+				BasicDBObjectBuilder.start("_id", "").add("total", new BasicDBObject("$sum", "$" + SIZE)).get()).get();
+		BasicDBObject projectObj = new BasicDBObject("$project", new BasicDBObject("_id", 0).append("total", 1));
+		List<BasicDBObject> pipeline = Lists.newArrayList(matchObj, groupObj, projectObj);
+		AggregateIterable<DBObject> output = metadata.aggregate(pipeline, DBObject.class);
+		DBObject result = output.first();
+		if (result == null || !result.containsField("total")) {
+			log.debug("No total found");
+			return 0;
+		} else return (Integer) result.get("total");
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void commit(final String transactionId, final String mdId) throws MDStoreServiceException {
+		transactionManager.commit(transactionId, mdId, getMDStore(mdId));
+	}
+
+	/**
+	 * Getter for property 'db'.
+	 *
+	 * @return Value for property 'db'.
+	 */
+	public MongoDatabase getDb() {
+		return db;
+	}
+
+	/**
+	 * Setter for property 'db'.
+	 *
+	 * @param db
+	 *            Value to set for property 'db'.
+	 */
+	@Required
+	public void setDb(final MongoDatabase db) {
+		this.db = db;
+	}
+
+	/**
+	 * Getter for property 'recordParser'.
+	 *
+	 * @return Value for property 'recordParser'.
+	 */
+	public RecordParserFactory getRecordParserFactory() {
+		return recordParserFactory;
+	}
+
+
+	@Required
+	public void setRecordParserFactory(final RecordParserFactory recordParserFactory) {
+		this.recordParserFactory = recordParserFactory;
+	}
+
+	/**
+	 * Getter for property 'discardRecords'.
+	 *
+	 * @return Value for property 'discardRecords'.
+	 */
+	public boolean isDiscardRecords() {
+		return discardRecords;
+	}
+
+	/**
+	 * Setter for property 'discardRecords'.
+	 *
+	 * @param discardRecords
+	 *            Value to set for property 'discardRecords'.
+	 */
+	public void setDiscardRecords(final boolean discardRecords) {
+		this.discardRecords = discardRecords;
+	}
+
+	@Override
+	public MDStoreDBStatus getDBStatus() {
+		final int handledDatastructures = Ints.saturatedCast(getDb().getCollection(METADATA_NAME).count());
+		//final int usedDiskSpace = Ints.saturatedCast(getDb().getStats().getLong("storageSize") / (1024 * 1024)); // in MB
+		//{ dbStats: 1, scale: 1 }
+		BasicDBObject statsQuery = new BasicDBObject("dbStats", 1);
+		statsQuery.put("scale", 1024 * 1024); //storageSize in MB
+		final Document statsRes = getDb().runCommand(statsQuery);
+		log.debug("DBStatus --  " + statsRes.toJson());
+		int usedDiskSpace;
+		//trying to handle different versions of the mongo server: old version returns storage size as long, new version as double
+		//TODO: simplify this when dev, beta, production are aligned with our local, latest, mongo version
+		String usedDiskSpaceStr = statsRes.get("storageSize").toString();
+		try {
+			Long usedDiskSpaceLong = Long.parseLong(usedDiskSpaceStr);
+			usedDiskSpace = Ints.saturatedCast(usedDiskSpaceLong);
+		} catch (NumberFormatException nfe) {
+			Double usedDiskSpaceDbl = Double.parseDouble(usedDiskSpaceStr);
+			usedDiskSpace = usedDiskSpaceDbl.intValue();
+		}
+		final String date = DateUtils.now_ISO8601();
+		return new MDStoreDBStatus(handledDatastructures, usedDiskSpace, date);
+	}
+
+	@Override
+	public void startGarbage() throws MDStoreServiceException {
+		this.transactionManager.garbage();
+	}
+
+	@Override
+	public void invalidTransaction(final String transactionId, final String mdId) throws MDStoreServiceException {
+		transactionManager.dropTransaction(mdId, transactionId);
+
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/MetadataCheckJob.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/MetadataCheckJob.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/MetadataCheckJob.java	(revision 60503)
@@ -0,0 +1,159 @@
+package eu.dnetlib.data.mdstore.modular.mongodb.utils;
+
+import java.io.StringReader;
+import java.util.List;
+import javax.xml.ws.Endpoint;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.client.MongoCollection;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.mongodb.MDStoreDaoImpl;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
+import eu.dnetlib.enabling.locators.UniqueServiceLocator;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.io.SAXReader;
+import org.springframework.beans.factory.annotation.Required;
+
+public class MetadataCheckJob {
+
+	private static final Log log = LogFactory.getLog(MetadataCheckJob.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * service locator.
+	 */
+	private UniqueServiceLocator serviceLocator;
+
+	/**
+	 * {@link Endpoint}
+	 */
+	private Endpoint endpoint;
+
+	/**
+	 * {@link EndpointReferenceBuilder}
+	 */
+	private EndpointReferenceBuilder<Endpoint> eprBuilder;
+
+	/**
+	 * MDStore dao.
+	 */
+	private MDStoreDao dao;
+
+	private boolean runOnStart;
+
+	public void runOnStart() throws MDStoreServiceException {
+		if (isRunOnStart()) {
+			log.info("running mdStore metadata check on service start");
+			repairMetadata();
+		}
+	}
+
+	/**
+	 * Job execution method.
+	 *
+	 * @throws MDStoreServiceException in case of ISLookUpException or DocumentException
+	 */
+	public void repairMetadata() throws MDStoreServiceException {
+		MongoCollection<DBObject> metadata = ((MDStoreDaoImpl) getDao()).getDb().getCollection("metadata", DBObject.class);
+		if (metadata.count() != 0) {
+			log.debug("mdStore metadata doesn't need to be repaired");
+			return;
+		}
+		try {
+			List<String> mdStores =
+					serviceLocator.getService(ISLookUpService.class).quickSearchProfile(
+							"//RESOURCE_PROFILE[" +
+									".//RESOURCE_TYPE/@value='MDStoreDSResourceType' and " +
+									".//RESOURCE_URI/@value='" + getServiceAddress() + "']");
+
+			log.debug("repairing mdstore metadata");
+
+			if (mdStores != null) {
+				for (String MDStoreProfile : mdStores) {
+					final DBObject mdInfo = getMdInfo(MDStoreProfile);
+					metadata.findOneAndReplace(new BasicDBObject("mdId", mdInfo.get("mdId")), mdInfo);
+				}
+			}
+			log.debug("FINISHED repairing mdstore metadata");
+
+		} catch (ISLookUpException | DocumentException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * Helper method, gets an MDStore profile and returns a DBObject.
+	 *
+	 * @param MDStoreProfile as obtain from the IS
+	 * @return a DBObject representing the metadata informations
+	 * @throws DocumentException when parsing invalid xml
+	 */
+	private DBObject getMdInfo(final String MDStoreProfile) throws DocumentException {
+		Document doc = new SAXReader().read(new StringReader(MDStoreProfile));
+
+		DBObject dbo = new BasicDBObject();
+		dbo.put("mdId", doc.valueOf("//RESOURCE_IDENTIFIER/@value"));
+		dbo.put("format", doc.valueOf("//METADATA_FORMAT/text()"));
+		dbo.put("layout", doc.valueOf("//METADATA_FORMAT_LAYOUT/text()"));
+		dbo.put("interpretation", doc.valueOf("//METADATA_FORMAT_INTERPRETATION/text()"));
+		dbo.put("size", doc.valueOf("//NUMBER_OF_RECORDS/text()"));
+
+		return dbo;
+	}
+
+	private String getServiceAddress() {
+		return getEprBuilder().getAddress(getEndpoint()) + "?wsdl";
+	}
+
+	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
+		return eprBuilder;
+	}
+
+	@Required
+	public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
+		this.eprBuilder = eprBuilder;
+	}
+
+	public Endpoint getEndpoint() {
+		return endpoint;
+	}
+
+	@Required
+	public void setEndpoint(final Endpoint endpoint) {
+		this.endpoint = endpoint;
+	}
+
+	public MDStoreDao getDao() {
+		return dao;
+	}
+
+	@Required
+	public void setDao(final MDStoreDao dao) {
+		this.dao = dao;
+	}
+
+	public boolean isRunOnStart() {
+		return runOnStart;
+	}
+
+	@Required
+	public void setRunOnStart(final boolean runOnStart) {
+		this.runOnStart = runOnStart;
+	}
+
+	public UniqueServiceLocator getServiceLocator() {
+		return serviceLocator;
+	}
+	
+	@Required
+	public void setServiceLocator(UniqueServiceLocator serviceLocator) {
+		this.serviceLocator = serviceLocator;
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/MDStoreUtils.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/MDStoreUtils.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/MDStoreUtils.java	(revision 60503)
@@ -0,0 +1,33 @@
+package eu.dnetlib.data.mdstore.modular.mongodb.utils;
+
+import java.util.Comparator;
+import java.util.Date;
+
+import com.google.common.base.Function;
+import com.mongodb.DBObject;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class MDStoreUtils {
+
+	public static UnaryFunction<String, DBObject> mdId() {
+		return arg -> (String) arg.get("mdId");
+	}
+
+	public static UnaryFunction<Boolean, DBObject> dboFilter(final String format, final String layout, final String interpretation) {
+		return dbo -> dbo.get("format").toString().equals(format) && dbo.get("layout").toString().equals(layout)
+				&& dbo.get("interpretation").toString().equals(interpretation);
+	}
+
+	public static Function<DBObject, String> body() {
+		return dbo -> (String) dbo.get("body");
+	}
+
+	public static Comparator<DBObject> getComparatorOnDate() {
+		return (o1, o2) -> {
+			Date d1 = (Date) o1.get("date");
+			Date d2 = (Date) o2.get("date");
+			return d1.compareTo(d2);
+		};
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/IndexFieldRecordParserException.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/IndexFieldRecordParserException.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/IndexFieldRecordParserException.java	(revision 60503)
@@ -0,0 +1,25 @@
+package eu.dnetlib.data.mdstore.modular.mongodb.utils;
+
+/**
+ * Created by Alessia Bardi on 14/06/2017.
+ *
+ * @author Alessia Bardi
+ */
+public class IndexFieldRecordParserException extends Exception {
+
+	public IndexFieldRecordParserException() {
+		super();
+	}
+
+	public IndexFieldRecordParserException(final String message) {
+		super(message);
+	}
+
+	public IndexFieldRecordParserException(final String message, final Throwable cause) {
+		super(message, cause);
+	}
+
+	public IndexFieldRecordParserException(final Throwable cause) {
+		super(cause);
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/IndexFieldRecordParser.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/IndexFieldRecordParser.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/IndexFieldRecordParser.java	(revision 60503)
@@ -0,0 +1,55 @@
+package eu.dnetlib.data.mdstore.modular.mongodb.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.ximpleware.AutoPilot;
+import com.ximpleware.VTDGen;
+import com.ximpleware.VTDNav;
+import eu.dnetlib.data.mdstore.modular.MDFormatDescription;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Created by sandro on 11/29/16.
+ */
+public class IndexFieldRecordParser {
+
+    private static final Log log = LogFactory.getLog(IndexFieldRecordParser.class);
+
+    private static List<String> getTextValue(final AutoPilot ap, final VTDNav vn, final String xpath) throws Exception {
+        List<String> results = new ArrayList<>();
+        ap.selectXPath(xpath);
+        while (ap.evalXPath() != -1) {
+            int t = vn.getText();
+            if (t > -1) results.add(vn.toNormalizedString(t));
+        }
+        return results;
+    }
+
+    public Map<String, List<String>> parseRecord(final String record, final List<MDFormatDescription> mdformats) throws IndexFieldRecordParserException {
+        if (mdformats == null || mdformats.size() == 0)
+            return null;
+        final Map<String, List<String>> result = new HashMap<>();
+
+        try {
+            final VTDGen vg = new VTDGen();
+            vg.setDoc(record.getBytes());
+            vg.parse(true);
+            final VTDNav vn = vg.getNav();
+            final AutoPilot ap = new AutoPilot(vn);
+
+            for (MDFormatDescription description : mdformats) {
+                List<String> xpathResult = getTextValue(ap, vn, description.getXpath());
+                result.put(description.getName(), xpathResult);
+            }
+            return result;
+        } catch (Throwable e) {
+            throw new IndexFieldRecordParserException("Cannot index record", e);
+        }
+    }
+
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/EnsureIndexJob.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/EnsureIndexJob.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/data/mdstore/modular/mongodb/utils/EnsureIndexJob.java	(revision 60503)
@@ -0,0 +1,48 @@
+package eu.dnetlib.data.mdstore.modular.mongodb.utils;
+
+import eu.dnetlib.data.mdstore.modular.MDStoreDescription;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.mongodb.MongoMDStore;
+import eu.dnetlib.enabling.tools.AbstractSchedulable;
+
+public class EnsureIndexJob extends AbstractSchedulable {
+
+	private static final Log log = LogFactory.getLog(EnsureIndexJob.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private MDStoreDao dao;
+
+	@Override
+	protected void doExecute() {
+		log.info("performing mdstore index check");
+
+		try {
+			for (MDStoreDescription mdstore : getDao().listMDStores()) {
+				try {
+					log.info("ensureindex for mdStoreId:" + mdstore.getId());
+					((MongoMDStore) getDao().getMDStore(mdstore.getId())).ensureIndices();
+				} catch (Throwable e) {
+					log.warn("unable to reindex mdstore: " + mdstore.getId(), e);
+				}
+			}
+		} catch (MDStoreServiceException e) {
+			log.warn("unable to reindex mdstore ", e);
+		}
+
+		log.info("mdstore index check completed");
+	}
+
+	@Required
+	public void setDao(final MDStoreDao dao) {
+		this.dao = dao;
+	}
+
+	public MDStoreDao getDao() {
+		return dao;
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/mongodb/MongoOptionsFactory.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/mongodb/MongoOptionsFactory.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/mongodb/MongoOptionsFactory.java	(revision 60503)
@@ -0,0 +1,33 @@
+package eu.dnetlib.mongodb;
+
+import com.mongodb.MongoClientOptions;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.FactoryBean;
+
+public class MongoOptionsFactory implements FactoryBean<MongoClientOptions> {
+	private int connectionsPerHost;
+
+	@Override
+	public MongoClientOptions getObject() throws BeansException {
+		return MongoClientOptions.builder().connectionsPerHost(connectionsPerHost).build();
+	}
+
+	@Override
+	public Class<MongoClientOptions> getObjectType() {
+		return MongoClientOptions.class;
+	}
+
+	@Override
+	public boolean isSingleton() {
+		return false;
+	}
+
+	public int getConnectionsPerHost() {
+		return connectionsPerHost;
+	}
+
+	public void setConnectionsPerHost(int connectionsPerHost) {
+		this.connectionsPerHost = connectionsPerHost;
+	}
+
+}

Property changes on: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/java/eu/dnetlib/mongodb/MongoOptionsFactory.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/applicationContext-mongodb-mdstore.properties
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/applicationContext-mongodb-mdstore.properties	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/applicationContext-mongodb-mdstore.properties	(revision 60503)
@@ -0,0 +1,12 @@
+services.mdstore.mongodb.host=localhost
+services.mdstore.mongodb.port=27017
+services.mdstore.mongodb.db=mdstore
+services.mdstore.mongodb.connectionsPerHost=20
+
+services.mdstore.mongodb.ensureindex.cron=0 0 23 * * ?
+services.mdstore.mongodb.garbage.cron=0 0 23 1/1 * ? *
+services.mdstore.mongodb.ensureindex.enable=false
+services.mdstore.mongodb.checkmetadata.onstart=true
+services.mdstore.mongodb.checkmetadata.startdelay=30000
+
+dhp.openaire.mdstore.inspector.url = 
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/utils/applicationContext-mongo-mdstore-scheduler.xml
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/utils/applicationContext-mongo-mdstore-scheduler.xml	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/utils/applicationContext-mongo-mdstore-scheduler.xml	(revision 60503)
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:wsa="http://cxf.apache.org/ws/addressing"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://cxf.apache.org/transports/http/configuration"
+	xmlns:t="http://dnetlib.eu/springbeans/t" xmlns:template="http://dnetlib.eu/springbeans/template"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                                    http://cxf.apache.org/ws/addressing http://cxf.apache.org/schemas/ws-addr-conf.xsd
+                                    http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+                                    http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+                            http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd">
+
+	<!-- beans -->
+	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
+		depends-on="mdStoreService">
+		<property name="triggers">
+			<list>
+				<ref bean="mdStoreCheckTrigger"/>
+			</list>
+		</property>
+	</bean>
+
+	<bean id="mdStoreEnsureIndexScheduler"
+		class="eu.dnetlib.data.mdstore.modular.mongodb.utils.EnsureIndexJob"
+		p:cronExpression="${services.mdstore.mongodb.ensureindex.cron}" 
+		p:enabled="${services.mdstore.mongodb.ensureindex.enable}"
+		p:dao-ref="mongodbMDStoreDao" />
+		
+	<bean id="mdStoreCheckTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"
+		p:startDelay="${services.mdstore.mongodb.checkmetadata.startdelay}" p:repeat-count="0" p:repeatInterval="60000">
+		<property name="jobDetail">
+			<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
+				<property name="targetObject" ref="mdStoreCheckMetadataMBean" />
+				<property name="targetMethod" value="runOnStart" />
+				<property name="concurrent" value="false" />
+			</bean>
+		</property>
+	</bean>		
+		
+	<bean id="mdStoreCheckMetadataMBean"
+		class="eu.dnetlib.data.mdstore.modular.mongodb.utils.MetadataCheckJob" 
+		depends-on="mdStoreService"		
+		p:runOnStart="${services.mdstore.mongodb.checkmetadata.onstart}"
+		p:dao-ref="mongodbMDStoreDao" p:serviceLocator-ref="uniqueServiceLocator" 
+		p:endpoint-ref="mdStoreServiceEndpoint" p:eprBuilder-ref="jaxwsEndpointReferenceBuilder" />
+		
+	<bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter">
+		<property name="beans">
+			<map>
+				<entry key="mongodbMDStore:name=metadata" value-ref="mdStoreCheckMetadataMBean" />
+			</map>
+		</property>
+	</bean>
+				
+</beans>
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/applicationContext-mongodb-mdstore.xml
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/applicationContext-mongodb-mdstore.xml	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/mongodb/applicationContext-mongodb-mdstore.xml	(revision 60503)
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:p="http://www.springframework.org/schema/p" xmlns:t="http://dnetlib.eu/springbeans/t"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="mongodbMDStoreDao" class="eu.dnetlib.data.mdstore.modular.mongodb.MDStoreDaoImpl"
+		p:db-ref="mdstoreMongoDB" p:recordParserFactory-ref="recordParserFactory" 
+		p:discardRecords="${services.mdstore.discardrecords}"/>
+
+
+	<bean id="mongoClient" class="com.mongodb.MongoClient">
+		<constructor-arg index="0" type="com.mongodb.ServerAddress">
+			<bean class="com.mongodb.ServerAddress">
+				<constructor-arg index="0" value="${services.mdstore.mongodb.host}"/>
+				<constructor-arg index="1" value="${services.mdstore.mongodb.port}"/>
+			</bean>
+		</constructor-arg>
+		<constructor-arg index="1" type="com.mongodb.MongoClientOptions">
+			<bean class="eu.dnetlib.mongodb.MongoOptionsFactory"
+			      p:connectionsPerHost="${services.mdstore.mongodb.connectionsPerHost}"/>
+		</constructor-arg>
+	</bean>
+	
+	<bean id= "mongoMdStoreTransaction" init-method="garbageTransactionsOnStart"
+	      class="eu.dnetlib.data.mdstore.modular.mongodb.MDStoreTransactionManagerImpl"
+	      p:db-ref="mdstoreMongoDB" p:expiredDays="${services.mdstore.readlock.expire.days}"/>
+
+	<bean id="mdstoreMongoDB" factory-bean="mongoClient"
+	      factory-method="getDatabase">
+		<constructor-arg type="java.lang.String" value="${services.mdstore.mongodb.db}"/>
+	</bean>
+	
+	<bean t:id="transctionManagerGarabageCollectionJobSchedulerAccessor"
+		class="org.springframework.scheduling.quartz.SchedulerAccessorBean"
+		p:scheduler-ref="jobScheduler">
+		<property name="triggers">
+			<list>
+				<bean class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
+					<property name="jobDetail">
+						<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
+							p:targetObject-ref="mongoMdStoreTransaction" p:targetMethod="garbage" />
+					</property>
+					<property name="cronExpression" value="${services.mdstore.mongodb.garbage.cron}"/>
+				</bean>				
+			</list>
+		</property>
+	</bean>
+
+
+</beans>
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/inspector/webContext-mdstore-inspector.xml
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/inspector/webContext-mdstore-inspector.xml	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/data/mdstore/modular/inspector/webContext-mdstore-inspector.xml	(revision 60503)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+                http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
+
+	<bean id="mdstoreInspectorGroup"
+		class="eu.dnetlib.enabling.inspector.StaticEntryPointDescriptorGroup"
+		p:name="mdstore">
+		<property name="descriptors">
+			<list>
+				<bean class="eu.dnetlib.enabling.inspector.StaticEntryPointDescriptor"
+					p:name="mdstores" p:relativeUrl="mdstores.do" />
+			</list>
+		</property>
+	</bean>
+
+</beans>
+
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstores.st
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstores.st	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstores.st	(revision 60503)
@@ -0,0 +1,20 @@
+$inspector/master(it={
+
+<h2>MDStores</h2>
+<a href="doGarbage.do" >Start Garbage</a>
+<table>
+  <tr>
+    <th>Format</th>
+    <th>Layout</th>
+    <th>Interpretation</th>
+    <th>Size <a href="refreshSizes.do">[R]</a></th>
+    <th>ID</th>
+    <th>Indexed?</th>
+    <th>Ensure index</th>
+    <th>MDStore Transaction</th>
+  </tr>
+  $mdstores:{
+    <tr><td>$it.format$</td><td>$it.layout$</td><td>$it.interpretation$</td><td>$it.size$</td><td><a href="mdstore.do?id=$it.id$">$it.id$</a></td><td><span class="$if(it.indexed)$enabled$else$disabled$endif$">$it.indexed$</span></td><td><a href="ensure.do?id=$it.id$">GO</a></td><td><a href="infoTransaction.do?id=$it.id$">VIEW</a></td></tr>
+  }$
+</table>
+})$
\ No newline at end of file
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstore.st
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstore.st	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstore.st	(revision 60503)
@@ -0,0 +1,37 @@
+$inspector/master(it={
+
+<style type="text/css">
+ .mdstoreRecords li.record {
+   display: block;
+   border-top: 1px solid #ccc;
+ }
+ 
+ .mdstoreRecords ul.nav li {
+   display: inline;
+ }
+</style>
+
+<h2>MDStore details</h2>
+<p>
+
+<form action="mdstore.do?id=$id$" method="POST">
+GREP: <input name="regex" value="$regex$"/> REPLACEMENT: <input name="replace" value="$replace$"/>
+Replace? <input type="checkbox" name="checkReplace" $if(checkReplace)$checked="checked"$endif$/>
+<input type="submit" value="grep/repl"/>
+</form>
+</p>
+
+<p>Show from: $start$ (<a href="?id=$id$&start=$prevPage$&regex=$regex$">prev</a>) out of $size$ (<a href="?id=$id$&start=$nextPage$&regex=$regex$">next</a>)</p>
+
+<ul class="mdstoreRecords">
+$page:{r|
+  <li class="record">
+   <ul class="nav">
+     <li><a href="mdstoreEditResult.do?mdId=$r.mdId$&docId=$r.docId$">edit</a></li>
+     <li><a href="mdstoreDeleteRecord.do?mdId=$r.mdId$&docId=$r.docId$">delete</a></li>
+   </ul>
+	 <pre WRAP="off">$r.body$</pre>
+  </li>
+}$
+</ul>
+})$
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstoreEditResult.st
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstoreEditResult.st	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/mdstoreEditResult.st	(revision 60503)
@@ -0,0 +1,27 @@
+$inspector/master(it={
+
+<style type="text/css">
+ #recordbody {
+  height: 60em;
+  width: 100%;
+  border: 1px solid #B0B0FF;
+  padding: 4px;
+ }
+</style>
+
+<h2>Low level edit mdstore record:</h2>
+
+<ul>
+  <li><a href="javascript:document.forms[0].submit()">save</a></li>
+</ul>
+
+<p> It will <b>not</b> trigger a mdstore modification date. </p>
+<form action="mdstoreSaveRecord.do" method="POST" accept-charset="UTF-8">
+<input type="hidden" name="mdId" value="$mdId$"/>
+<textarea id="recordbody" name="body" WRAP="off">
+$body$
+</textarea>
+
+</form>
+
+})$
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/infoTransaction.st
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/infoTransaction.st	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/main/resources/eu/dnetlib/enabling/views/inspector/infoTransaction.st	(revision 60503)
@@ -0,0 +1,44 @@
+$inspector/master(it={
+
+<h2>MDStores Transaction Info</h2>
+
+<h3>MDStore Id : </h3>
+<a href="mdstore.do?id=$info.mdId$">$info.mdId$</a>
+
+<h3>Current collection id: </h3>
+<a href="mdstore.do?id=$info.mdId$">$info.currentId$</a>
+
+
+
+
+
+
+
+<h3> Read- Lock MDStore : </h3>
+<table>
+  <tr>
+    <th>Id</th>
+    <th>Last time read</th>    
+    <th>drop</th>    
+  </tr>  
+  $info.stillUsed:{
+   	<tr><td>$it.id$</td> <td>$it.lastRead$</td><td><a href="dropUsedCollection.do?mdId=$info.mdId$&id=$it.id$">drop </a></td> </tr>
+   }$ 
+</table>
+
+
+<h3> Transaction MDStore : </h3>
+<table>
+  <tr>
+    <th>Id</th>
+    <th>Date</th>    
+    <th>Size</th>
+    <th>drop</th>      
+  </tr>  
+  $info.transactions:{
+   	<tr><td>$it.id$</td> <td>$it.date$</td><td>$it.size$</td> <td><a href="invalidTransactionCollection.do?mdId=$info.mdId$&id=$it.id$">drop </a></td> </tr>
+   }$ 
+</table>
+
+
+})$
\ No newline at end of file
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoBulkWritesManagerTest.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoBulkWritesManagerTest.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MongoBulkWritesManagerTest.java	(revision 60503)
@@ -0,0 +1,49 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+import com.mongodb.DBObject;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.MongoCollection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.mockito.Mockito.when;
+
+/**
+ * Created by Alessia Bardi on 2019-04-12.
+ *
+ * @author Alessia Bardi
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class MongoBulkWritesManagerTest {
+
+	private MongoBulkWritesManager mng;
+
+	@Mock
+	MongoCollection<DBObject> coll;
+
+	@Before
+	public void setUp(){
+		MockitoAnnotations.initMocks(this);
+		when(coll.withWriteConcern(WriteConcern.ACKNOWLEDGED)).thenReturn(coll);
+		mng = new MongoBulkWritesManager(coll, coll, null, 10, null, false);
+	}
+
+	@Test
+	public void buildDBObjectTest(){
+		Map<String, String> props = Maps.newHashMap();
+		props.put("timestamp", "1555078665140");
+		props.put("id", "od______4301::5af4702a60ddf0615fd1dfd6ded104df");
+		props.put("originalId", "x");
+		props.put("body","<body/>");
+
+		DBObject obj = mng.buildDBObject("<x/>", props, null);
+		System.out.println(obj);
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreTransactionManagerTest.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreTransactionManagerTest.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreTransactionManagerTest.java	(revision 60503)
@@ -0,0 +1,149 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import com.mongodb.Mongo;
+import com.mongodb.client.MongoDatabase;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.connector.MDStore;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+// TODO: reimplement tests
+
+@Ignore
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = ConfigurationTestConfig.class)
+public class MDStoreTransactionManagerTest {
+
+	@Autowired
+	private MongoDatabase db;
+
+	@Autowired
+	private MDStoreTransactionManager manager;
+
+	@Autowired
+	private MDStoreDao dao;
+
+	@Test
+	public void testCreateandRetrieve() throws MDStoreServiceException {
+		UUID idCreation = UUID.randomUUID();
+		db.getCollection("metadataManager").drop();
+		((MDStoreTransactionManagerImpl) manager).setManagerTable(null);
+
+		String mdId = idCreation.toString() + "_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==";
+		manager.createMDStore(mdId);
+
+		Assert.assertNotNull(manager.startTransaction(mdId, true));
+		Assert.assertNotNull(manager.startTransaction(mdId, true));
+
+		String s = manager.getMDStoreCollection(mdId);
+		Assert.assertNotNull(s);
+		this.manager.dropMDStore(mdId);
+		s = manager.getMDStoreCollection(mdId);
+		Assert.assertNull(s);
+		db.getCollection("metadataManager").drop();
+		((MDStoreTransactionManagerImpl) manager).setManagerTable(null);
+	}
+
+	@Test
+	public void testReadMdStore() throws MDStoreServiceException {
+		UUID idCreation = UUID.randomUUID();
+		String mdId = idCreation.toString() + "_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==";
+		manager.createMDStore(mdId);
+		Assert.assertNotNull(manager.readMdStore(mdId));
+		Assert.assertNotNull(manager.startTransaction(mdId, true));
+		Assert.assertNotNull(manager.readMdStore(mdId));
+		db.getCollection("metadataManager").drop();
+		((MDStoreTransactionManagerImpl) manager).setManagerTable(null);
+		db.getCollection("metadataManager").drop();
+		((MDStoreTransactionManagerImpl) manager).setManagerTable(null);
+
+	}
+
+	@Test
+	public void testCommit() throws MDStoreServiceException {
+		UUID idCreation = UUID.randomUUID();
+		String mdId = idCreation.toString() + "_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==";
+		manager.createMDStore(mdId);
+		String idCurrent = manager.readMdStore(mdId);
+		String transaction = manager.startTransaction(mdId, true);
+		// Assert.assertTrue(manager.commit(transaction, mdId));
+		Assert.assertNotSame(idCurrent, manager.readMdStore(mdId));
+
+	}
+
+	@Ignore
+	@Test
+	public void testDateTime() throws MDStoreServiceException, UnknownHostException {
+		Mongo mongo = new Mongo("localhost", 27017);
+		DB dbinput = mongo.getDB("mdstore");
+		DBCollection inputCollection = dbinput.getCollection("70e07e9f-b3bf-4423-8777-b159819e0c6a");
+
+		Assert.assertNotNull(inputCollection.findOne().get("body"));
+		UUID idCreation = UUID.randomUUID();
+
+		String mdId = idCreation.toString() + "_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==";
+
+		manager.createMDStore(mdId);
+		dao.createMDStore(mdId, "a", "a", "a");
+
+		String transId = manager.startTransaction(mdId, true);
+
+		ArrayList<String> data = new ArrayList<String>();
+		DBCursor cursor = inputCollection.find();
+
+		for (int i = 0; i < 1000; i++) {
+			data.add((String) cursor.next().get("body"));
+		}
+		dao.getMDStore(transId).feed(data, true);
+		// manager.commit(transId, mdId);
+
+		cursor = inputCollection.find();
+		transId = manager.startTransaction(mdId, false);
+
+		data.clear();
+		for (int i = 0; i < 10; i++) {
+			data.add(cursor.next().get("body").toString().replace("oai:pumaoai.isti.cnr.it:", "SUUUCAAA"));
+		}
+
+		String currentId = manager.readMdStore(mdId);
+
+		final MDStore newMdstore = dao.getMDStore(currentId);
+
+		new Thread(() -> {
+			List<String> dataInput = null;
+			try {
+				dataInput = newMdstore.deliver("", "", null).getResult(0, 10);
+				for (int i = 0; i < 10; i++) {
+					try {
+						Thread.sleep(1000);
+					} catch (InterruptedException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					}
+					System.out.println(dataInput.get(i));
+				}
+			} catch (MDStoreServiceException e) {
+				e.printStackTrace();
+			}
+		}).start();
+
+		dao.getMDStore(transId).feed(data, true);
+		// manager.commit(transId, mdId);
+
+	}
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/IndexFieldParserTest.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/IndexFieldParserTest.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/IndexFieldParserTest.java	(revision 60503)
@@ -0,0 +1,51 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.MDFormatDescription;
+import eu.dnetlib.data.mdstore.modular.mongodb.utils.IndexFieldRecordParser;
+import eu.dnetlib.data.mdstore.modular.mongodb.utils.IndexFieldRecordParserException;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+/**
+ * Created by sandro on 11/29/16.
+ */
+public class IndexFieldParserTest {
+
+
+    @Test
+    public void parserTest() throws IOException, MDStoreServiceException, IndexFieldRecordParserException {
+        InputStream inputStream = this.getClass().getResourceAsStream("/eu/dnetlib/data/mdstore/modular/mongodb/inputRecord.xml");
+
+        final String inputRecord = IOUtils.toString(inputStream);
+
+        final IndexFieldRecordParser parser = new IndexFieldRecordParser();
+
+        final List<MDFormatDescription> mdref = new ArrayList<>();
+
+        mdref.add(new MDFormatDescription("id", "//*[local-name()='objIdentifier']"));
+        mdref.add(new MDFormatDescription("title", "//*[local-name()='title']"));
+        mdref.add(new MDFormatDescription("creator", "//*[local-name()='creator']"));
+
+        Map<String, List<String>> stringListMap = parser.parseRecord(inputRecord, mdref);
+
+
+        for (String key : stringListMap.keySet()) {
+            System.out.println("key = " + key);
+            for (String value : stringListMap.get(key)) {
+                System.out.println("\t" + value);
+            }
+
+        }
+
+
+    }
+
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreDaoImplTest.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreDaoImplTest.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/MDStoreDaoImplTest.java	(revision 60503)
@@ -0,0 +1,78 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import eu.dnetlib.data.mdstore.MDStoreServiceException;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDBStatus;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import static org.junit.Assert.assertEquals;
+
+@Ignore
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = ConfigurationTestConfig.class)
+public class MDStoreDaoImplTest {
+
+	@Autowired
+	private MDStoreDao dao;
+	@Autowired
+	private MongoDatabase db;
+	@Autowired
+	private MDStoreTransactionManager manager;
+
+	@After
+	public void tearDown() throws MDStoreServiceException {
+		dao.deleteMDStore("1");
+		dao.deleteMDStore("2");
+		dao.deleteMDStore("3");
+		dao.deleteMDStore("4");
+		dao.deleteMDStore("5");
+		dao.deleteMDStore("6");
+	}
+
+	@Before
+	public void setUp() throws Exception {
+		dao.createMDStore("1", "F", "I", "L");
+		dao.createMDStore("2", "F", "I", "L");
+		dao.createMDStore("3", "F", "I", "L");
+		dao.createMDStore("4", "F", "I", "L");
+		dao.createMDStore("5", "F1", "I", "L");
+		dao.createMDStore("6", "F1", "I", "L");
+
+		final MongoCollection<DBObject> metadata = db.getCollection(MDStoreDaoImpl.METADATA_NAME, DBObject.class);
+
+		metadata.findOneAndUpdate(new BasicDBObject(MDStoreDaoImpl.MD_ID, "1"), new BasicDBObject("$set", new BasicDBObject(MDStoreDaoImpl.SIZE, 10)));
+		metadata.findOneAndUpdate(new BasicDBObject(MDStoreDaoImpl.MD_ID, "2"), new BasicDBObject("$set", new BasicDBObject(MDStoreDaoImpl.SIZE, 10)));
+		metadata.findOneAndUpdate(new BasicDBObject(MDStoreDaoImpl.MD_ID, "3"), new BasicDBObject("$set", new BasicDBObject(MDStoreDaoImpl.SIZE, 10)));
+		metadata.findOneAndUpdate(new BasicDBObject(MDStoreDaoImpl.MD_ID, "4"), new BasicDBObject("$set", new BasicDBObject(MDStoreDaoImpl.SIZE, 10)));
+		metadata.findOneAndUpdate(new BasicDBObject(MDStoreDaoImpl.MD_ID, "5"), new BasicDBObject("$set", new BasicDBObject(MDStoreDaoImpl.SIZE, 10)));
+		metadata.findOneAndUpdate(new BasicDBObject(MDStoreDaoImpl.MD_ID, "6"), new BasicDBObject("$set", new BasicDBObject(MDStoreDaoImpl.SIZE, 10)));
+
+	}
+
+	@Test
+	public void test() throws MDStoreServiceException {
+		assertEquals(40, dao.getSumOfSizes("F", "L", "I"));
+		assertEquals(20, dao.getSumOfSizes("F1", "L", "I"));
+		assertEquals(0, dao.getSumOfSizes("F_0", "L", "I"));
+	}
+
+	@Test
+	public void getDBStatusTest() {
+		final MDStoreDBStatus dbStatus = dao.getDBStatus();
+		System.out.println(dbStatus);
+
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/ConfigurationTestConfig.java
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/ConfigurationTestConfig.java	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/java/eu/dnetlib/data/mdstore/modular/mongodb/ConfigurationTestConfig.java	(revision 60503)
@@ -0,0 +1,45 @@
+package eu.dnetlib.data.mdstore.modular.mongodb;
+
+import java.net.UnknownHostException;
+
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+import eu.dnetlib.data.mdstore.modular.RecordParserFactory;
+import eu.dnetlib.data.mdstore.modular.StreamingRecordParser;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreDao;
+import eu.dnetlib.data.mdstore.modular.connector.MDStoreTransactionManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ConfigurationTestConfig {
+
+	@Bean
+	public MongoDatabase db() throws UnknownHostException {
+		final MongoClient mongo = new MongoClient("localhost", 27017);
+		return mongo.getDatabase("mdstore_test");
+	}
+
+	@Bean
+	public MDStoreTransactionManager manager() throws UnknownHostException {
+		final MDStoreTransactionManagerImpl manager = new MDStoreTransactionManagerImpl();
+		manager.setDb(db());
+		return manager;
+	}
+
+	@Bean
+	public RecordParserFactory recordParserFactory() {
+		final RecordParserFactory rpfactory = new RecordParserFactory();
+		rpfactory.setParserType(StreamingRecordParser.class);
+		return rpfactory;
+	}
+
+	@Bean
+	public MDStoreDao mdstoreDao() throws UnknownHostException {
+		final MDStoreDaoImpl dao = new MDStoreDaoImpl();
+		dao.setDb(db());
+		dao.setRecordParserFactory(recordParserFactory());
+		return dao;
+	}
+
+}
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/resources/eu/dnetlib/data/mdstore/modular/mongodb/templateRecord.xml
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/resources/eu/dnetlib/data/mdstore/modular/mongodb/templateRecord.xml	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7/src/test/resources/eu/dnetlib/data/mdstore/modular/mongodb/templateRecord.xml	(revision 60503)
@@ -0,0 +1,42 @@
+<oai:record xmlns="http://namespace.openaire.eu/"
+  xmlns:dc="http://purl.org/dc/elements/1.1/"
+  xmlns:dr="http://www.driver-repository.eu/namespace/dr"
+  xmlns:dri="http://www.driver-repository.eu/namespace/dri"
+  xmlns:oai="http://www.openarchives.org/OAI/2.0/"
+  xmlns:prov="http://www.openarchives.org/OAI/2.0/provenance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <oai:header>
+    <dri:objIdentifier>{id}</dri:objIdentifier>
+    <dri:recordIdentifier>entityId:2533216</dri:recordIdentifier>
+    <dri:dateOfCollection>2015-01-09T12:15:02.177+01:00</dri:dateOfCollection>
+    <dri:repositoryId>8e17a4fe-b77d-406b-8c75-4cfa233092d2_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU=</dri:repositoryId>
+    <dri:datasourceprefix>DAI</dri:datasourceprefix>
+  </oai:header>
+  <oai:metadata>
+    <eagle:eagleObject xmlns:eagle="http://www.eagle-network.eu/eagle">
+      <eagle:recordSourceInfo
+        landingPage="http://arachne.uni-koeln.de/entity/2533216" providerName="Arachne">entityId:2533216</eagle:recordSourceInfo>
+      <eagle:editingInfo>
+        <eagle:dateEdited>0000-00-00</eagle:dateEdited>
+        <eagle:metadataEditor>unknown</eagle:metadataEditor>
+      </eagle:editingInfo>
+      <eagle:metadataIpr uri="http://creativecommons.org/licenses/by/3.0/">This file is licensed under the Creative Commons Attribution 3.0 Unported license.</eagle:metadataIpr>
+      <eagle:title lang="de">CMS-XII-d009c-3_168111,02.jpg</eagle:title>
+      <!-- objekt http://arachne.uni-koeln.de/entity/1160926 -->
+      <eagle:description lang="de">Foto von: Siegel CMS XII D009c</eagle:description>
+      <eagle:entityType>visual</eagle:entityType>
+      <eagle:visualRepresentation>
+        <eagle:representationType>image</eagle:representationType>
+        <eagle:url>http://arachne.uni-koeln.de/entity/2533216</eagle:url>
+        <eagle:thumbnail>http://arachne.dainst.org/data/image/thumbnail/2533216</eagle:thumbnail>
+        <eagle:visualRepresentationIpr uri="http://creativecommons.org/licenses/by/3.0/">This file is licensed under the Creative Commons Attribution 3.0 Unported license.</eagle:visualRepresentationIpr>
+        <eagle:format>jpg</eagle:format>
+        <!-- objekt http://arachne.uni-koeln.de/entity/1160926 -->
+        <eagle:hasArtifact>
+          <eagle:artifactTitle>Siegel CMS XII D009c</eagle:artifactTitle>
+          <eagle:objectType>Dreiseitiges Prisma Mallia Steatitgruppe</eagle:objectType>
+          <eagle:material>weicher Stein</eagle:material>
+        </eagle:hasArtifact>
+      </eagle:visualRepresentation>
+    </eagle:eagleObject>
+  </oai:metadata>
+</oai:record>
Index: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7
===================================================================
--- modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7	(nonexistent)
+++ modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7	(revision 60503)

Property changes on: modules/cnr-mongo-mdstore/tags/cnr-mongo-mdstore-6.0.7
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,7 ##
+.springBeans
+.project
+.classpath
+target
+testbin
+.settings
+*.iml
