Index: SRUAggregator/trunk/aggregator.yml
===================================================================
--- SRUAggregator/trunk/aggregator.yml	(revision 6043)
+++ SRUAggregator/trunk/aggregator.yml	(revision 6049)
@@ -13,6 +13,7 @@
 
   # AGGREGATOR_FILE_PATH: /data/fcsAggregator/fcsAggregatorCorpora.json
+  # AGGREGATOR_FILE_PATH_BACKUP: /data/fcsAggregator/fcsAggregatorCorpora.backup.json
   AGGREGATOR_FILE_PATH: /Users/edima/fcsAggregatorCorpora.json
-
+  AGGREGATOR_FILE_PATH_BACKUP: /Users/edima/fcsAggregatorCorpora.backup.json
   SCAN_MAX_DEPTH: 1 # recommended 3
   SCAN_TASK_INITIAL_DELAY: 0
Index: SRUAggregator/trunk/pom.xml
===================================================================
--- SRUAggregator/trunk/pom.xml	(revision 6043)
+++ SRUAggregator/trunk/pom.xml	(revision 6049)
@@ -8,5 +8,5 @@
 	<groupId>eu.clarin.sru.fcs</groupId>
 	<artifactId>Aggregator2</artifactId>
-	<version>2.0.0-alpha-21</version>
+	<version>2.0.0-alpha-22</version>
 	<name>FCS Aggregator</name>
 
Index: SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/Aggregator.java
===================================================================
--- SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/Aggregator.java	(revision 6043)
+++ SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/Aggregator.java	(revision 6049)
@@ -88,14 +88,8 @@
  * @author edima
  *
- * TODO: Use weblicht with results
- *
- * TODO: disable popups easily
- * 
- * TODO: atomic replace of cached corpora (file)
- *
  * TODO: zoom into the results from a corpus, allow functionality only for
  * the view (search for next set of results)
  *
- * TODO: fix search bug after going to stats
+ * TODO: Use weblicht with results
  *
  * TODO: Export search results to personal workspace as csv, excel, tcf, plain
@@ -151,5 +145,4 @@
 		bootstrap.addBundle(new AssetsBundle("/assets", "/", "index.html", "static"));
 	}
-
 
 	@Override
@@ -221,10 +214,25 @@
 
 		File corporaCacheFile = new File(params.AGGREGATOR_FILE_PATH);
-		try {
-			Corpora corpora = new ObjectMapper().readValue(corporaCacheFile, Corpora.class);
-			scanCacheAtom.set(corpora);
-			log.info("corpus list read from file; number of root corpora: " + scanCacheAtom.get().getCorpora().size());
-		} catch (Exception e) {
-			log.error("Error while reading cached corpora:", e);
+		File corporaOldCacheFile = new File(params.AGGREGATOR_FILE_PATH_BACKUP);
+
+		// init corpora from file
+		{
+			Corpora corpora = null;
+			try {
+				corpora = new ObjectMapper().readValue(corporaCacheFile, Corpora.class);
+			} catch (Exception xc) {
+				log.error("Failed to load cached corpora from primary file:", xc);
+			}
+			if (corpora == null) {
+				try {
+					corpora = new ObjectMapper().readValue(corporaOldCacheFile, Corpora.class);
+				} catch (Exception e) {
+					log.error("Failed to load cached corpora from backup file:", e);
+				}
+			}
+			if (corpora != null) {
+				scanCacheAtom.set(corpora);
+				log.info("corpus list read from file; number of root corpora: " + scanCacheAtom.get().getCorpora().size());
+			}
 		}
 
@@ -236,5 +244,5 @@
 				params.CENTER_REGISTRY_URL, params.SCAN_MAX_DEPTH,
 				params.additionalCQLEndpoints,
-				null, scanCacheAtom, corporaCacheFile,
+				null, scanCacheAtom, corporaCacheFile, corporaOldCacheFile,
 				scanStatsAtom, searchStatsAtom);
 		scheduler.scheduleAtFixedRate(task, params.SCAN_TASK_INITIAL_DELAY,
Index: SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/AggregatorConfiguration.java
===================================================================
--- SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/AggregatorConfiguration.java	(revision 6043)
+++ SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/app/AggregatorConfiguration.java	(revision 6049)
@@ -25,4 +25,8 @@
 		@JsonProperty
 		String AGGREGATOR_FILE_PATH;
+
+		@NotEmpty
+		@JsonProperty
+		String AGGREGATOR_FILE_PATH_BACKUP;
 
 		@JsonProperty
Index: SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/scan/ScanCrawlTask.java
===================================================================
--- SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/scan/ScanCrawlTask.java	(revision 6043)
+++ SRUAggregator/trunk/src/main/java/eu/clarin/sru/fcs/aggregator/scan/ScanCrawlTask.java	(revision 6049)
@@ -24,4 +24,5 @@
 	private AtomicReference<Corpora> corporaAtom;
 	private File cachedCorpora;
+	private File oldCachedCorpora;
 	private AtomicReference<Statistics> scanStatisticsAtom;
 	private AtomicReference<Statistics> searchStatisticsAtom;
@@ -32,8 +33,9 @@
 			int cacheMaxDepth, List<URL> additionalCQLEndpoints,
 			EndpointFilter filter,
-			AtomicReference<Corpora> corporaAtom, File cachedCorpora,
+			AtomicReference<Corpora> corporaAtom,
+			File cachedCorpora, File oldCachedCorpora,
 			AtomicReference<Statistics> scanStatisticsAtom,
 			AtomicReference<Statistics> searchStatisticsAtom
-			) {
+	) {
 		this.sruClient = sruClient;
 		this.centerRegistryUrl = centerRegistryUrl;
@@ -43,4 +45,5 @@
 		this.corporaAtom = corporaAtom;
 		this.cachedCorpora = cachedCorpora;
+		this.oldCachedCorpora = oldCachedCorpora;
 		this.scanStatisticsAtom = scanStatisticsAtom;
 		this.searchStatisticsAtom = searchStatisticsAtom;
@@ -83,6 +86,5 @@
 				log.warn("ScanCrawlTask: Skipped writing to disk (no corpora). Finished.");
 			} else {
-				ObjectMapper mapper = new ObjectMapper();
-				mapper.writerWithDefaultPrettyPrinter().writeValue(cachedCorpora, corpora);
+				dump(corpora, cachedCorpora, oldCachedCorpora);
 				log.info("ScanCrawlTask: wrote to disk, finished");
 			}
@@ -94,3 +96,21 @@
 		}
 	}
+
+	private static void dump(Corpora corpora,
+			File cachedCorpora, File oldCachedCorpora) throws IOException {
+		if (cachedCorpora.exists()) {
+			try {
+				oldCachedCorpora.delete();
+			} catch (Throwable txc) {
+				//ignore
+			}
+			try {
+				cachedCorpora.renameTo(oldCachedCorpora);
+			} catch (Throwable txc) {
+				// ignore
+			}
+		}
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.writerWithDefaultPrettyPrinter().writeValue(cachedCorpora, corpora);
+	}
 }
Index: SRUAggregator/trunk/src/main/resources/assets/js/components.js
===================================================================
--- SRUAggregator/trunk/src/main/resources/assets/js/components.js	(revision 6043)
+++ SRUAggregator/trunk/src/main/resources/assets/js/components.js	(revision 6049)
@@ -122,9 +122,10 @@
 
 	refresh: function() {
+		console.log("popover refresh", this.props.title);
 		$(this.getDOMNode()).popover('destroy');
 
 		var content;
 		if (Array.isArray(this.props.children))
-			content = this.props.children.map(React.renderToString).join(" ");
+			content = this.props.children.map(React.renderToString).join("");
 		else 
 			content = React.renderToString(this.props.children);
@@ -136,5 +137,5 @@
 			placement: this.props.placement,
 			title: this.props.title,
-			trigger: 'click',
+			trigger: 'focus',
 			html: true,
 		});
Index: SRUAggregator/trunk/src/main/resources/assets/js/components.jsx
===================================================================
--- SRUAggregator/trunk/src/main/resources/assets/js/components.jsx	(revision 6043)
+++ SRUAggregator/trunk/src/main/resources/assets/js/components.jsx	(revision 6049)
@@ -126,5 +126,5 @@
 		var content;
 		if (Array.isArray(this.props.children))
-			content = this.props.children.map(React.renderToString).join(" ");
+			content = this.props.children.map(React.renderToString).join("");
 		else 
 			content = React.renderToString(this.props.children);
@@ -136,5 +136,5 @@
 			placement: this.props.placement,
 			title: this.props.title,
-			trigger: 'click',
+			trigger: 'focus',
 			html: true,
 		});
Index: SRUAggregator/trunk/src/main/resources/assets/js/main.js
===================================================================
--- SRUAggregator/trunk/src/main/resources/assets/js/main.js	(revision 6043)
+++ SRUAggregator/trunk/src/main/resources/assets/js/main.js	(revision 6049)
@@ -3,5 +3,5 @@
 "use strict";
 
-var VERSION = "VERSION 2.0.0.Î±21";
+var VERSION = "VERSION 2.0.0.Î±22";
 var URLROOT = "/Aggregator-testing";
 
Index: SRUAggregator/trunk/src/main/resources/assets/js/main.jsx
===================================================================
--- SRUAggregator/trunk/src/main/resources/assets/js/main.jsx	(revision 6043)
+++ SRUAggregator/trunk/src/main/resources/assets/js/main.jsx	(revision 6049)
@@ -3,5 +3,5 @@
 "use strict";
 
-var VERSION = "VERSION 2.0.0.Î±21";
+var VERSION = "VERSION 2.0.0.Î±22";
 var URLROOT = "/Aggregator-testing";
 
Index: SRUAggregator/trunk/src/main/resources/assets/js/search.js
===================================================================
--- SRUAggregator/trunk/src/main/resources/assets/js/search.js	(revision 6043)
+++ SRUAggregator/trunk/src/main/resources/assets/js/search.js	(revision 6049)
@@ -604,5 +604,5 @@
 	renderDiagnostic: function(d) {
 		return 	React.createElement("div", {className: "alert alert-warning"}, 
-					React.createElement("div", null, "Diagnostic: ", d.diagnostic.message)
+					React.createElement("div", null, "Diagnostic: ", d.message)
 				); 
 	},
Index: SRUAggregator/trunk/src/main/resources/assets/js/search.jsx
===================================================================
--- SRUAggregator/trunk/src/main/resources/assets/js/search.jsx	(revision 6043)
+++ SRUAggregator/trunk/src/main/resources/assets/js/search.jsx	(revision 6049)
@@ -604,5 +604,5 @@
 	renderDiagnostic: function(d) {
 		return 	<div className="alert alert-warning"> 
-					<div>Diagnostic: {d.diagnostic.message}</div>
+					<div>Diagnostic: {d.message}</div>
 				</div>; 
 	},
