/**
* FlatJSONResponseWriter
* Copyright 2017 by Michael Peter Christen
* First released 30.03.2017 at http://yacy.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21.txt
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.cora.federate.solr.responsewriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexableField;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.ResultContext;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TextField;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocList;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.util.DateFormatUtil;
import org.json.simple.JSONArray;
import net.yacy.cora.federate.solr.SolrType;
import net.yacy.cora.util.JSONObject;
public class FlatJSONResponseWriter implements QueryResponseWriter {
private static final char lb = '\n';
private boolean elasticsearchBulkRequest;
public FlatJSONResponseWriter(boolean elasticsearchBulkRequest) {
this.elasticsearchBulkRequest = elasticsearchBulkRequest;
}
@Override
public String getContentType(SolrQueryRequest arg0, SolrQueryResponse arg1) {
return "application/json; charset=UTF-8";
}
@Override
public void init(@SuppressWarnings("rawtypes") NamedList arg0) {
}
@Override
public void write(final Writer writer, final SolrQueryRequest request, final SolrQueryResponse rsp) throws IOException {
NamedList<?> values = rsp.getValues();
DocList response = ((ResultContext) values.get("response")).docs;
writeDocs(writer, request, response);
}
private static final void writeDocs(final Writer writer, final SolrQueryRequest request, final DocList response) throws IOException {
boolean includeScore = false;
final int sz = response.size();
SolrIndexSearcher searcher = request.getSearcher();
DocIterator iterator = response.iterator();
includeScore = includeScore && response.hasScores();
IndexSchema schema = request.getSchema();
for (int i = 0; i < sz; i++) {
int id = iterator.nextDoc();
Document doc = searcher.doc(id);
writeDoc(writer, schema, null, doc.getFields(), (includeScore ? iterator.score() : 0.0f), includeScore);
}
}
private static final void writeDoc(final Writer writer, final IndexSchema schema, final String name, final List<IndexableField> fields, final float score, final boolean includeScore) throws IOException {
JSONObject json = new JSONObject(true);
int sz = fields.size();
int fidx1 = 0, fidx2 = 0;
while (fidx1 < sz) {
IndexableField value = fields.get(fidx1);
String fieldName = value.name();
fidx2 = fidx1 + 1;
while (fidx2 < sz && fieldName.equals(fields.get(fidx2).name())) {
fidx2++;
}
SchemaField sf = schema == null ? null : schema.getFieldOrNull(fieldName);
if (sf == null) {
sf = new SchemaField(fieldName, new TextField());
}
FieldType type = sf.getType();
if (fidx1 + 1 == fidx2) {
if (sf.multiValued()) {
JSONArray a = new JSONArray();
json.put(fieldName, a);
JSONObject j = new JSONObject();
String sv = value.stringValue();
setValue(j, type.getTypeName(), "x", sv); //sf.write(this, null, f1);
a.add(j.get("x"));
} else {
setValue(json, type.getTypeName(), value.name(), value.stringValue());
}
} else {
JSONArray a = new JSONArray();
json.put(fieldName, a);
for (int i = fidx1; i < fidx2; i++) {
String sv = fields.get(i).stringValue();
JSONObject j = new JSONObject();
setValue(j, type.getTypeName(), "x", sv); //sf.write(this, null, f1);
a.add(j.get("x"));
}
}
fidx1 = fidx2;
}
writer.write(json.toString());
writer.write(lb);
}
private static void setValue(final JSONObject json, final String typeName, final String name, final String value) {
if (typeName.equals(SolrType.text_general.printName()) ||
typeName.equals(SolrType.string.printName()) ||
typeName.equals(SolrType.text_en_splitting_tight.printName())) {
json.put(name, value);
} else if (typeName.equals(SolrType.bool.printName())) {
json.put(name, "F".equals(value) ? false : true);
} else if (typeName.equals(SolrType.num_integer.printName())) {
json.put(name, Long.parseLong(value));
} else if (typeName.equals(SolrType.num_long.printName())) {
json.put(name, Long.parseLong(value));
} else if (typeName.equals(SolrType.date.printName())) {
json.put(name, DateFormatUtil.formatExternal(new Date(Long.parseLong(value))));
} else if (typeName.equals(SolrType.num_float.printName())) {
json.put(name, Double.parseDouble(value));
} else if (typeName.equals(SolrType.num_double.printName())) {
json.put(name, Double.parseDouble(value));
}
}
public static final void writeDoc(final Writer writer, final SolrDocument doc) throws IOException {
JSONObject json = new JSONObject(true);
final Map<String, Object> fields = doc.getFieldValueMap();
for (String key: fields.keySet()) {
if (key == null) continue;
Object value = doc.get(key);
if (value == null) {
} else if (value instanceof Collection<?>) {
JSONArray a = new JSONArray();
json.put(key, a);
for (Object o: ((Collection<?>) value)) {
a.add(o);
}
} else {
json.put(key, value);
}
}
writer.write(json.toString());
writer.write(lb);
}
}