package org.nanopub.extra.server;

import java.io.OutputStream;

import org.nanopub.MalformedNanopubException;
import org.nanopub.Nanopub;
import org.nanopub.NanopubUtils;
import org.nanopub.extra.index.IndexUtils;
import org.nanopub.extra.index.NanopubIndex;
import org.nanopub.extra.index.NanopubIndexImpl;
import org.openrdf.model.URI;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;

public class FetchIndexFromDb extends FetchIndex {

	public static final int maxParallelRequestsPerServer = 5;

	private String indexUri;
	private NanopubDb db;
	private OutputStream out;
	private RDFFormat format;
	private boolean writeIndex, writeContent;
	private int nanopubCount;
	private FetchIndex.Listener listener;

	public FetchIndexFromDb(String indexUri, NanopubDb db, OutputStream out, RDFFormat format, boolean writeIndex, boolean writeContent) {
		this.indexUri = indexUri;
		this.db = db;
		this.out = out;
		this.format = format;
		this.writeIndex = writeIndex;
		this.writeContent = writeContent;
		nanopubCount = 0;
	}

	public void run() {
		try {
			getIndex(indexUri);
		} catch (RDFHandlerException | MalformedNanopubException ex) {
			throw new RuntimeException(ex);
		}
	}

	private void getIndex(String indexUri) throws RDFHandlerException, MalformedNanopubException {
		Nanopub np = GetNanopub.get(indexUri, db);
		if (!IndexUtils.isIndex(np)) {
			throw new RuntimeException("NOT AN INDEX: " + np.getUri());
		}
		NanopubIndex npi = IndexUtils.castToIndex(np);
		if (writeIndex) {
			writeNanopub(npi);
		}
		if (writeContent) {
			for (URI elementUri : npi.getElements()) {
				writeNanopub(GetNanopub.get(elementUri.toString(), db));
			}
		}
		for (URI subIndexUri : npi.getSubIndexes()) {
			getIndex(subIndexUri.toString());
		}
		if (npi.getAppendedIndex() != null) {
			getIndex(npi.getAppendedIndex().toString());
		}
	}

	private void writeNanopub(Nanopub np) throws RDFHandlerException {
		nanopubCount++;
		if (listener != null && nanopubCount % 100 == 0) {
			listener.progress(nanopubCount);
		}
		NanopubUtils.writeToStream(np, out, format);
	}

	public int getNanopubCount() {
		return nanopubCount;
	}

	public void setProgressListener(Listener l) {
		listener = l;
	}

}

@@ -257,57 +257,8 @@
 ex;%0A
-import org.nanopub.extra.index.NanopubIndexImpl;%0A
 impo
@@ -1270,28 +1270,28 @@
 opub
+Index
  np
+i
  = 
-GetNanopub.get
+getIndex
 (ind
@@ -1308,157 +1308,33 @@
 ;%0A%09%09
-if (!IndexUtils.isIndex(np)) %7B%0A%09%09%09throw new RuntimeException(%22NOT AN INDEX: %22 + np.getUri());%0A%09%09%7D%0A%09%09NanopubIndex npi = IndexUtils.castToIndex(np);
+while (npi != null) %7B
 %0A%09%09
+%09
 if (
@@ -1347,16 +1347,17 @@
 ndex) %7B%0A
+%09
 %09%09%09write
@@ -1368,26 +1368,28 @@
 pub(npi);%0A%09%09
+%09
 %7D%0A
+%09
 %09%09if (writeC
@@ -1401,16 +1401,17 @@
 t) %7B%0A%09%09%09
+%09
 for (URI
@@ -1441,24 +1441,25 @@
 ements()) %7B%0A
+%09
 %09%09%09%09writeNan
@@ -1514,16 +1514,19 @@
 %0A%09%09%09
+%09
 %7D%0A
+%09
 %09%09%7D%0A%09%09
+%09
 for 
@@ -1566,24 +1566,25 @@
 xes()) %7B%0A%09%09%09
+%09
 getIndex(sub
@@ -1607,18 +1607,20 @@
 g());%0A%09%09
+%09
 %7D%0A
+%09
 %09%09if (np
@@ -1650,24 +1650,31 @@
  null) %7B%0A%09%09%09
+%09npi = 
 getIndex(npi
@@ -1703,22 +1703,349 @@
 String()
+, db
 );%0A%09%09
-%7D
+%09%7D else %7B%0A%09%09%09%09npi = null;%0A%09%09%09%7D%0A%09%09%7D%0A%09%7D%0A%0A%09private static NanopubIndex getIndex(String indexUri, NanopubDb db) throws MalformedNanopubException %7B%0A%09%09Nanopub np = GetNanopub.get(indexUri, db);%0A%09%09if (!IndexUtils.isIndex(np)) %7B%0A%09%09%09throw new RuntimeException(%22NOT AN INDEX: %22 + np.getUri());%0A%09%09%7D%0A%09%09return IndexUtils.castToIndex(np);
 %0A%09%7D%0A%0A%09pr

Fix problem with stack overflow for large indexes