package com.bagri.xquery.saxon;
import static com.bagri.core.Constants.bg_schema;
import static com.bagri.core.Constants.mt_json;
import static com.bagri.support.util.FileUtils.def_encoding;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import javax.xml.transform.stream.StreamSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bagri.core.api.SchemaRepository;
import com.bagri.core.api.BagriException;
import com.bagri.core.query.ExpressionContainer;
import com.bagri.core.server.api.DocumentManagement;
import com.bagri.core.server.api.QueryManagement;
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.Resource;
import net.sf.saxon.lib.ResourceCollection;
import net.sf.saxon.resource.JSONResource;
import net.sf.saxon.trans.XPathException;
public class ResourceCollectionImpl implements ResourceCollection {
private static final Logger logger = LoggerFactory.getLogger(ResourceCollectionImpl.class);
private String uri;
private SchemaRepository repo;
private ExpressionContainer query;
private Collection<Long> docIds = null;
private Iterator<Long> iter = null;
public ResourceCollectionImpl(String uri, Collection<Long> docIds) {
this.uri = uri;
this.docIds = new ArrayList<>(docIds);
this.iter = docIds.iterator();
}
public ResourceCollectionImpl(String uri, SchemaRepository repo, ExpressionContainer query) {
this.uri = uri;
this.repo = repo;
this.query = query;
}
private void loadData() { //throws XPathException {
try {
docIds = ((QueryManagement) repo.getQueryManagement()).getDocumentIds(query);
} catch (BagriException ex) {
logger.error("loadData.error;", ex);
//throw new XPathException(ex);
docIds = Collections.emptyList();
}
logger.trace("loadData; got {} document ids", docIds.size());
this.iter = docIds.iterator();
}
private boolean hasNext() {
if (docIds == null) {
loadData();
}
boolean result = iter.hasNext();
logger.trace("hasNext; returning: {}", result);
return result;
}
private Long next() { //throws XPathException {
logger.trace("next.enter");
if (docIds == null) {
loadData();
}
Long currentId = iter.next();
logger.trace("next.exit; returning: {}", currentId);
return currentId;
}
@Override
public String getCollectionURI() {
return uri;
}
@Override
public Iterator<String> getResourceURIs(XPathContext context) throws XPathException {
logger.trace("getResourceURIs.enter;");
return new UriIterator();
}
@Override
public Iterator<? extends Resource> getResources(XPathContext context) throws XPathException {
logger.trace("getResources.enter;");
return new ResourceIterator();
}
@Override
public boolean isStable(XPathContext context) {
return true;
}
@Override
public String toString() {
return "ResourceCollectionImpl [query=" + query + ", docIds=" + docIds + "]";
}
public class UriIterator implements Iterator<String> {
@Override
public boolean hasNext() {
return ResourceCollectionImpl.this.hasNext();
}
@Override
public String next() {
Long next = ResourceCollectionImpl.this.next();
if (next != null) {
return bg_schema + ":/" + next;
}
return null;
}
@Override
public void remove() {
throw new UnsupportedOperationException("method remove is not supported");
}
}
public class ResourceIterator implements Iterator<Resource> {
@Override
public boolean hasNext() {
return ResourceCollectionImpl.this.hasNext();
}
@Override
public Resource next() {
Long docKey = ResourceCollectionImpl.this.next();
if (docKey != null) {
String content;
try {
content = ((DocumentManagement) repo.getDocumentManagement()).getDocumentAsString(docKey, null);
if (content != null && !content.isEmpty()) {
logger.trace("next; got content: {}", content.length());
String xref = bg_schema + ":/" + docKey;
String type = ((DocumentManagement) repo.getDocumentManagement()).getDocumentContentType(docKey);
if (mt_json.equals(type)) {
try {
InputStream is = new ByteArrayInputStream(content.getBytes(def_encoding));
return new JSONResource(xref, is);
} catch (UnsupportedEncodingException ex) {
logger.error("next.error", ex);
return null;
}
}
StreamSource ss = new StreamSource(new StringReader(content));
ss.setSystemId(xref);
// an attempt to cache source here?
//mgr.storeDocumentSource(docId, ss);
return new ResourceImpl(ss);
}
logger.trace("next. got empty content'");
} catch (BagriException ex) {
logger.error("next.error", ex);
}
}
return null;
}
@Override
public void remove() {
throw new UnsupportedOperationException("method remove is not supported");
}
}
}