You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2018/06/09 13:42:09 UTC
[1/2] lucene-solr:branch_7x: SOLR-12455: Refactor JSON serialization
code into SolrJ package
Repository: lucene-solr
Updated Branches:
refs/heads/branch_7x 56559f089 -> fef87d718
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/java/org/apache/solr/common/util/WriteableValue.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/WriteableValue.java b/solr/solrj/src/java/org/apache/solr/common/util/WriteableValue.java
new file mode 100644
index 0000000..82e7d00
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/util/WriteableValue.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+
+import org.apache.solr.common.util.JavaBinCodec.ObjectResolver;
+
+public abstract class WriteableValue implements ObjectResolver {
+ public abstract void write(String name, TextWriter writer) throws IOException;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/test/org/apache/solr/client/solrj/cloud/autoscaling/TestPolicy.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/cloud/autoscaling/TestPolicy.java b/solr/solrj/src/test/org/apache/solr/client/solrj/cloud/autoscaling/TestPolicy.java
index 60c84b7..30506c2 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/cloud/autoscaling/TestPolicy.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/cloud/autoscaling/TestPolicy.java
@@ -52,6 +52,7 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.CollectionParams.CollectionAction;
import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.JsonTextWriter;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.ObjectCache;
import org.apache.solr.common.util.Pair;
@@ -2525,7 +2526,7 @@ public void testUtilizeNodeFailure2() throws Exception {
StringWriter writer = new StringWriter();
NamedList<Object> val = new NamedList<>();
val.add("violations", violations);
- JSONWriter.write (writer, true, JSONWriter.JSON_NL_MAP, val);
+ JSONWriter.write (writer, true, JsonTextWriter.JSON_NL_MAP, val);
assertEquals(2l,
Utils.getObjectByPath(Utils.fromJSONString(writer.toString()), true,"violations[0]/violation/replica/NRT"));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java b/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java
new file mode 100644
index 0000000..5b240fe
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/common/util/TestFastWriter.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.lucene.util.LuceneTestCase;
+
+
+class MemWriter extends FastWriter {
+ public List<char[]> buffers = new LinkedList<>();
+
+ Random r;
+ public MemWriter(char[] tempBuffer, Random r) {
+ super(null, tempBuffer, 0);
+ this.r = r;
+ }
+
+ @Override
+ public void flush(char[] arr, int offset, int len) throws IOException {
+ if (arr == buf && offset==0 && len==buf.length) {
+ buffers.add(buf); // steal the buffer
+ buf = new char[r.nextInt(9000)+1];
+ } else if (len > 0) {
+ char[] newBuf = new char[len];
+ System.arraycopy(arr, offset, newBuf, 0, len);
+ buffers.add(newBuf);
+ }
+ }
+
+ @Override
+ public void flush(String str, int offset, int len) throws IOException {
+ if (len == 0) return;
+ buffers.add( str.substring(offset, offset+len).toCharArray() );
+ }
+}
+
+
+
+public class TestFastWriter extends LuceneTestCase {
+
+ Random rand;
+ char[] arr;
+ String s;
+
+ public void testRandomWrites() throws Exception {
+ rand = random();
+
+ arr = new char[20000];
+ for (int i=0; i<arr.length; i++) {
+ arr[i] = (char)rand.nextInt();
+ }
+ s = new String(arr);
+
+ for (int i=0; i<1000; i++) {
+ doRandomWrites();
+ }
+ }
+
+
+ public void doRandomWrites() throws Exception {
+ int bufSize = ( rand.nextBoolean() ? rand.nextInt(10) : rand.nextInt(20000) )+1;
+ MemWriter out = new MemWriter(new char[bufSize], rand);
+
+ int hash = 0;
+ long written = 0;
+ int iter = rand.nextInt(20)+1;
+ for (int i=0; i<iter; i++) {
+ int which = rand.nextInt(3);
+
+
+ int off = rand.nextInt(arr.length);
+ int len = off < arr.length ? rand.nextInt(arr.length - off) : 0;
+
+
+
+ if (which == 0) {
+ out.write(arr, off, len);
+ } else if (which == 1) {
+ out.write(s, off, len);
+ } else {
+ len = 1;
+ out.write(arr[off]);
+ }
+
+ hash = incHash(hash, arr, off, len);
+ written += len;
+ }
+
+ out.close();
+
+ int hash2 = 0;
+ for (char[] buffer : out.buffers) {
+ hash2 = incHash(hash2, buffer, 0, buffer.length);
+ }
+
+ assertEquals(hash, hash2);
+ }
+
+
+ public int incHash(int hash, char[] arr, int off, int len) {
+ for (int i=off; i<off+len; i++) {
+ hash = hash * 31 + arr[i];
+ }
+ return hash;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/test/org/apache/solr/common/util/TestSolrJsonWriter.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/common/util/TestSolrJsonWriter.java b/solr/solrj/src/test/org/apache/solr/common/util/TestSolrJsonWriter.java
new file mode 100644
index 0000000..3dd2cdd
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/common/util/TestSolrJsonWriter.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.IteratorWriter;
+import org.apache.solr.common.MapWriter;
+
+public class TestSolrJsonWriter extends SolrTestCaseJ4 {
+ public void test() throws IOException {
+ StringWriter writer = new StringWriter();
+
+ Map<String, Object> map = new HashMap<>();
+ map.put("k1","v1");
+ map.put("k2",1);
+ map.put("k3",false);
+ map.put("k4",Utils.makeMap("k41", "v41", "k42","v42"));
+ map.put("k5", (MapWriter) ew -> {
+ ew.put("k61","v61");
+ ew.put("k62","v62");
+ ew.put("k63", (IteratorWriter) iw -> iw.add("v631")
+ .add("v632"));
+ });
+
+ new SolrJSONWriter(writer)
+ .setIndent(true)
+ .writeObj(map)
+ .close();
+ Object o = Utils.fromJSONString(writer.toString());
+ assertEquals("v1", Utils.getObjectByPath(o, true, "k1"));
+ assertEquals(1l, Utils.getObjectByPath(o, true, "k2"));
+ assertEquals(Boolean.FALSE, Utils.getObjectByPath(o, true, "k3"));
+ assertEquals("v41", Utils.getObjectByPath(o, true, "k4/k41"));
+ assertEquals("v42", Utils.getObjectByPath(o, true, "k4/k42"));
+ assertEquals("v61", Utils.getObjectByPath(o, true, "k5/k61"));
+ assertEquals("v62", Utils.getObjectByPath(o, true, "k5/k62"));
+ assertEquals("v631", Utils.getObjectByPath(o, true, "k5/k63[0]"));
+ assertEquals("v632", Utils.getObjectByPath(o, true, "k5/k63[1]"));
+ }
+}
[2/2] lucene-solr:branch_7x: SOLR-12455: Refactor JSON serialization
code into SolrJ package
Posted by no...@apache.org.
SOLR-12455: Refactor JSON serialization code into SolrJ package
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/fef87d71
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/fef87d71
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/fef87d71
Branch: refs/heads/branch_7x
Commit: fef87d7181208643849b00b94f582b34748ffbb4
Parents: 56559f0
Author: Noble Paul <no...@apache.org>
Authored: Sat Jun 9 23:40:55 2018 +1000
Committer: Noble Paul <no...@apache.org>
Committed: Sat Jun 9 23:41:49 2018 +1000
----------------------------------------------------------------------
solr/CHANGES.txt | 2 +
.../apache/solr/response/CSVResponseWriter.java | 2 +-
.../solr/response/JSONResponseWriter.java | 5 +-
.../org/apache/solr/response/JSONWriter.java | 471 +----------------
.../apache/solr/response/PHPResponseWriter.java | 4 +-
.../response/PHPSerializedResponseWriter.java | 2 +-
.../solr/response/QueryResponseWriterUtil.java | 2 +-
.../solr/response/RubyResponseWriter.java | 4 +-
.../solr/response/SmileResponseWriter.java | 4 +-
.../solr/response/TextResponseWriter.java | 211 +-------
.../apache/solr/response/WriteableValue.java | 25 -
.../transform/RawValueTransformerFactory.java | 9 +-
.../response/transform/WriteableGeoJSON.java | 6 +-
.../java/org/apache/solr/util/FastWriter.java | 157 ------
.../apache/solr/response/JSONWriterTest.java | 53 +-
.../org/apache/solr/util/TestFastWriter.java | 124 -----
.../org/apache/solr/common/util/FastWriter.java | 157 ++++++
.../apache/solr/common/util/JsonTextWriter.java | 499 +++++++++++++++++++
.../apache/solr/common/util/SolrJSONWriter.java | 114 +++++
.../org/apache/solr/common/util/TextWriter.java | 231 +++++++++
.../apache/solr/common/util/WriteableValue.java | 25 +
.../solrj/cloud/autoscaling/TestPolicy.java | 3 +-
.../apache/solr/common/util/TestFastWriter.java | 125 +++++
.../solr/common/util/TestSolrJsonWriter.java | 60 +++
24 files changed, 1298 insertions(+), 997 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index f4a14ca..69bf911 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -50,6 +50,8 @@ Optimizations
* SOLR-12350: Do not use docValues as stored for _str (copy)fields in _default configset (janhoy)
+* SOLR-12455: Refactor JSON serialization code into SolrJ package (noble)
+
Other Changes
----------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java b/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
index 326220c..e894c77 100644
--- a/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
@@ -36,6 +36,7 @@ import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.FastWriter;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.internal.csv.CSVPrinter;
import org.apache.solr.internal.csv.CSVStrategy;
@@ -45,7 +46,6 @@ import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.apache.solr.search.DocList;
import org.apache.solr.search.ReturnFields;
-import org.apache.solr.util.FastWriter;
/**
*
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java b/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
index f69dc36..a52aef6 100644
--- a/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
@@ -24,6 +24,7 @@ import java.util.Map;
import org.apache.solr.common.PushWriter;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.JsonTextWriter;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.request.SolrQueryRequest;
@@ -50,10 +51,10 @@ public class JSONResponseWriter implements QueryResponseWriter {
public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
final SolrParams params = req.getParams();
final String wrapperFunction = params.get(JSONWriter.JSON_WRAPPER_FUNCTION);
- final String namedListStyle = params.get(JSONWriter.JSON_NL_STYLE, JSONWriter.JSON_NL_FLAT).intern();
+ final String namedListStyle = params.get(JsonTextWriter.JSON_NL_STYLE, JsonTextWriter.JSON_NL_FLAT).intern();
final JSONWriter w;
- if (namedListStyle.equals(JSONWriter.JSON_NL_ARROFNTV)) {
+ if (namedListStyle.equals(JsonTextWriter.JSON_NL_ARROFNTV)) {
w = new ArrayOfNameTypeValueJSONWriter(
writer, req, rsp, wrapperFunction, namedListStyle, true);
} else {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/JSONWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/JSONWriter.java b/solr/core/src/java/org/apache/solr/response/JSONWriter.java
index fb615cc..77aee3d 100644
--- a/solr/core/src/java/org/apache/solr/response/JSONWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/JSONWriter.java
@@ -19,30 +19,17 @@ package org.apache.solr.response;
import java.io.IOException;
import java.io.Writer;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.solr.common.IteratorWriter;
-import org.apache.solr.common.MapWriter;
import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.common.util.JsonTextWriter;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.ReturnFields;
-public class JSONWriter extends TextResponseWriter {
- public static final String JSON_NL_MAP="map";
- public static final String JSON_NL_FLAT="flat";
- public static final String JSON_NL_ARROFARR="arrarr";
- public static final String JSON_NL_ARROFMAP="arrmap";
- public static final String JSON_NL_ARROFNTV="arrntv";
- static final String JSON_NL_STYLE="json.nl";
+public class JSONWriter extends TextResponseWriter implements JsonTextWriter {
static final int JSON_NL_STYLE_COUNT = 5; // for use by JSONWriterTest
static final String JSON_WRAPPER_FUNCTION="json.wrf";
- private static char[] hexdigits = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
final protected String namedListStyle;
protected String wrapperFunction;
@@ -73,236 +60,21 @@ public class JSONWriter extends TextResponseWriter {
}
- protected static void unicodeEscape(Appendable out, int ch) throws IOException {
- out.append('\\');
- out.append('u');
- out.append(hexdigits[(ch>>>12) ]);
- out.append(hexdigits[(ch>>>8) & 0xf]);
- out.append(hexdigits[(ch>>>4) & 0xf]);
- out.append(hexdigits[(ch) & 0xf]);
+ @Override
+ public String getNamedListStyle() {
+ return namedListStyle;
}
+
public void writeResponse() throws IOException {
if(wrapperFunction!=null) {
- writer.write(wrapperFunction + "(");
+ _writeStr(wrapperFunction + "(");
}
writeNamedList(null, rsp.getValues());
if(wrapperFunction!=null) {
- writer.write(')');
- }
- writer.write('\n'); // ending with a newline looks much better from the command line
- }
-
- protected void writeKey(String fname, boolean needsEscaping) throws IOException {
- writeStr(null, fname, needsEscaping);
- writer.write(':');
- }
-
- /** Represents a NamedList directly as a JSON Object (essentially a Map)
- * Map null to "" and name mangle any repeated keys to avoid repeats in the
- * output.
- */
- protected void writeNamedListAsMapMangled(String name, NamedList val) throws IOException {
- int sz = val.size();
- writeMapOpener(sz);
- incLevel();
-
- // In JSON objects (maps) we can't have null keys or duplicates...
- // map null to "" and append a qualifier to duplicates.
- //
- // a=123,a=456 will be mapped to {a=1,a__1=456}
- // Disad: this is ambiguous since a real key could be called a__1
- //
- // Another possible mapping could aggregate multiple keys to an array:
- // a=123,a=456 maps to a=[123,456]
- // Disad: this is ambiguous with a real single value that happens to be an array
- //
- // Both of these mappings have ambiguities.
- HashMap<String,Integer> repeats = new HashMap<>(4);
-
- boolean first=true;
- for (int i=0; i<sz; i++) {
- String key = val.getName(i);
- if (key==null) key="";
-
- if (first) {
- first=false;
- repeats.put(key,0);
- } else {
- writeMapSeparator();
-
- Integer repeatCount = repeats.get(key);
- if (repeatCount==null) {
- repeats.put(key,0);
- } else {
- String newKey = key;
- int newCount = repeatCount;
- do { // avoid generated key clashing with a real key
- newKey = key + ' ' + (++newCount);
- repeatCount = repeats.get(newKey);
- } while (repeatCount != null);
-
- repeats.put(key,newCount);
- key = newKey;
- }
- }
-
- indent();
- writeKey(key, true);
- writeVal(key,val.getVal(i));
- }
-
- decLevel();
- writeMapCloser();
- }
-
- /** Represents a NamedList directly as a JSON Object (essentially a Map)
- * repeating any keys if they are repeated in the NamedList.
- * null key is mapped to "".
- */
- // NamedList("a"=1,"bar"="foo",null=3,null=null) => {"a":1,"bar":"foo","":3,"":null}
- protected void writeNamedListAsMapWithDups(String name, NamedList val) throws IOException {
- int sz = val.size();
- writeMapOpener(sz);
- incLevel();
-
- for (int i=0; i<sz; i++) {
- if (i!=0) {
- writeMapSeparator();
- }
-
- String key = val.getName(i);
- if (key==null) key="";
- indent();
- writeKey(key, true);
- writeVal(key,val.getVal(i));
- }
-
- decLevel();
- writeMapCloser();
- }
-
- // Represents a NamedList directly as an array of JSON objects...
- // NamedList("a"=1,"b"=2,null=3,null=null) => [{"a":1},{"b":2},3,null]
- protected void writeNamedListAsArrMap(String name, NamedList val) throws IOException {
- int sz = val.size();
- indent();
- writeArrayOpener(sz);
- incLevel();
-
- boolean first=true;
- for (int i=0; i<sz; i++) {
- String key = val.getName(i);
-
- if (first) {
- first=false;
- } else {
- writeArraySeparator();
- }
-
- indent();
-
- if (key==null) {
- writeVal(null,val.getVal(i));
- } else {
- writeMapOpener(1);
- writeKey(key, true);
- writeVal(key,val.getVal(i));
- writeMapCloser();
- }
-
- }
-
- decLevel();
- writeArrayCloser();
- }
-
- // Represents a NamedList directly as an array of JSON objects...
- // NamedList("a"=1,"b"=2,null=3,null=null) => [["a",1],["b",2],[null,3],[null,null]]
- protected void writeNamedListAsArrArr(String name, NamedList val) throws IOException {
- int sz = val.size();
- indent();
- writeArrayOpener(sz);
- incLevel();
-
- boolean first=true;
- for (int i=0; i<sz; i++) {
- String key = val.getName(i);
-
- if (first) {
- first=false;
- } else {
- writeArraySeparator();
- }
-
- indent();
-
- /*** if key is null, just write value???
- if (key==null) {
- writeVal(null,val.getVal(i));
- } else {
- ***/
-
- writeArrayOpener(1);
- incLevel();
- if (key==null) {
- writeNull(null);
- } else {
- writeStr(null, key, true);
- }
- writeArraySeparator();
- writeVal(key,val.getVal(i));
- decLevel();
- writeArrayCloser();
- }
-
- decLevel();
- writeArrayCloser();
- }
-
- // Represents a NamedList directly as an array with keys/values
- // interleaved.
- // NamedList("a"=1,"b"=2,null=3,null=null) => ["a",1,"b",2,null,3,null,null]
- protected void writeNamedListAsFlat(String name, NamedList val) throws IOException {
- int sz = val.size();
- writeArrayOpener(sz*2);
- incLevel();
-
- for (int i=0; i<sz; i++) {
- if (i!=0) {
- writeArraySeparator();
- }
- String key = val.getName(i);
- indent();
- if (key==null) {
- writeNull(null);
- } else {
- writeStr(null, key, true);
- }
- writeArraySeparator();
- writeVal(key, val.getVal(i));
- }
-
- decLevel();
- writeArrayCloser();
- }
-
- @Override
- public void writeNamedList(String name, NamedList val) throws IOException {
- if (val instanceof SimpleOrderedMap) {
- writeNamedListAsMapWithDups(name,val);
- } else if (namedListStyle==JSON_NL_FLAT) {
- writeNamedListAsFlat(name,val);
- } else if (namedListStyle==JSON_NL_MAP){
- writeNamedListAsMapWithDups(name,val);
- } else if (namedListStyle==JSON_NL_ARROFARR) {
- writeNamedListAsArrArr(name,val);
- } else if (namedListStyle==JSON_NL_ARROFMAP) {
- writeNamedListAsArrMap(name,val);
- } else if (namedListStyle==JSON_NL_ARROFNTV) {
- throw new UnsupportedOperationException(namedListStyle
- + " namedListStyle must only be used with "+ArrayOfNameTypeValueJSONWriter.class.getSimpleName());
+ _writeChar(')');
}
+ _writeChar('\n'); // ending with a newline looks much better from the command line
}
@Override
@@ -396,229 +168,14 @@ public class JSONWriter extends TextResponseWriter {
writeMapCloser();
}
- public void writeMapOpener(int size) throws IOException, IllegalArgumentException {
- writer.write('{');
- }
-
- public void writeMapSeparator() throws IOException {
- writer.write(',');
- }
-
- public void writeMapCloser() throws IOException {
- writer.write('}');
- }
-
- public void writeArrayOpener(int size) throws IOException, IllegalArgumentException {
- writer.write('[');
- }
-
- public void writeArraySeparator() throws IOException {
- writer.write(',');
- }
-
- public void writeArrayCloser() throws IOException {
- writer.write(']');
- }
-
- @Override
- public void writeStr(String name, String val, boolean needsEscaping) throws IOException {
- // it might be more efficient to use a stringbuilder or write substrings
- // if writing chars to the stream is slow.
- if (needsEscaping) {
-
-
- /* http://www.ietf.org/internet-drafts/draft-crockford-jsonorg-json-04.txt
- All Unicode characters may be placed within
- the quotation marks except for the characters which must be
- escaped: quotation mark, reverse solidus, and the control
- characters (U+0000 through U+001F).
- */
- writer.write('"');
-
- for (int i=0; i<val.length(); i++) {
- char ch = val.charAt(i);
- if ((ch > '#' && ch != '\\' && ch < '\u2028') || ch == ' ') { // fast path
- writer.write(ch);
- continue;
- }
- switch(ch) {
- case '"':
- case '\\':
- writer.write('\\');
- writer.write(ch);
- break;
- case '\r': writer.write('\\'); writer.write('r'); break;
- case '\n': writer.write('\\'); writer.write('n'); break;
- case '\t': writer.write('\\'); writer.write('t'); break;
- case '\b': writer.write('\\'); writer.write('b'); break;
- case '\f': writer.write('\\'); writer.write('f'); break;
- case '\u2028': // fallthrough
- case '\u2029':
- unicodeEscape(writer,ch);
- break;
- // case '/':
- default: {
- if (ch <= 0x1F) {
- unicodeEscape(writer,ch);
- } else {
- writer.write(ch);
- }
- }
- }
- }
-
- writer.write('"');
- } else {
- writer.write('"');
- writer.write(val);
- writer.write('"');
- }
- }
-
- @Override
- public void writeIterator(IteratorWriter val) throws IOException {
- writeArrayOpener(-1);
- incLevel();
- val.writeIter(new IteratorWriter.ItemWriter() {
- boolean first = true;
-
- @Override
- public IteratorWriter.ItemWriter add(Object o) throws IOException {
- if (!first) {
- JSONWriter.this.indent();
- JSONWriter.this.writeArraySeparator();
- }
- JSONWriter.this.writeVal(null, o);
- first = false;
- return this;
- }
- });
- decLevel();
- writeArrayCloser();
- }
-
- @Override
- public void writeMap(MapWriter val)
- throws IOException {
- writeMapOpener(-1);
- incLevel();
-
- val.writeMap(new MapWriter.EntryWriter() {
- boolean isFirst = true;
-
- @Override
- public MapWriter.EntryWriter put(String k, Object v) throws IOException {
- if (isFirst) {
- isFirst = false;
- } else {
- JSONWriter.this.writeMapSeparator();
- }
- if (doIndent) JSONWriter.this.indent();
- JSONWriter.this.writeKey(k, true);
- JSONWriter.this.writeVal(k, v);
- return this;
- }
- });
- decLevel();
- writeMapCloser();
- }
-
- @Override
- public void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal) throws IOException {
- if (!excludeOuter) {
- writeMapOpener(val.size());
- incLevel();
- isFirstVal=true;
- }
-
- boolean doIndent = excludeOuter || val.size() > 1;
-
- for (Map.Entry entry : (Set<Map.Entry>)val.entrySet()) {
- Object e = entry.getKey();
- String k = e==null ? "" : e.toString();
- Object v = entry.getValue();
-
- if (isFirstVal) {
- isFirstVal=false;
- } else {
- writeMapSeparator();
- }
-
- if (doIndent) indent();
- writeKey(k,true);
- writeVal(k,v);
- }
-
- if (!excludeOuter) {
- decLevel();
- writeMapCloser();
- }
- }
-
- @Override
- public void writeArray(String name, List l) throws IOException {
- writeArrayOpener(l.size());
- writeJsonIter(l.iterator());
- writeArrayCloser();
- }
-
- @Override
- public void writeArray(String name, Iterator val) throws IOException {
- writeArrayOpener(-1); // no trivial way to determine array size
- writeJsonIter(val);
- writeArrayCloser();
- }
-
- private void writeJsonIter(Iterator val) throws IOException {
- incLevel();
- boolean first=true;
- while( val.hasNext() ) {
- if( !first ) indent();
- writeVal(null, val.next());
- if( val.hasNext() ) {
- writeArraySeparator();
- }
- first=false;
- }
- decLevel();
- }
-
- //
- // Primitive types
- //
- @Override
- public void writeNull(String name) throws IOException {
- writer.write("null");
- }
-
- @Override
- public void writeInt(String name, String val) throws IOException {
- writer.write(val);
- }
-
- @Override
- public void writeLong(String name, String val) throws IOException {
- writer.write(val);
- }
-
- @Override
- public void writeBool(String name, String val) throws IOException {
- writer.write(val);
- }
-
- @Override
- public void writeFloat(String name, String val) throws IOException {
- writer.write(val);
- }
-
@Override
- public void writeDouble(String name, String val) throws IOException {
- writer.write(val);
+ public void _writeChar(char c) throws IOException {
+ writer.write(c);
}
@Override
- public void writeDate(String name, String val) throws IOException {
- writeStr(name, val, false);
+ public void _writeStr(String s) throws IOException {
+ writer.write(s);
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/PHPResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/PHPResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PHPResponseWriter.java
index a419fbb..ad12128 100644
--- a/solr/core/src/java/org/apache/solr/response/PHPResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/PHPResponseWriter.java
@@ -16,8 +16,8 @@
*/
package org.apache.solr.response;
-import java.io.Writer;
import java.io.IOException;
+import java.io.Writer;
import java.util.List;
import org.apache.solr.common.util.NamedList;
@@ -93,7 +93,7 @@ class PHPWriter extends JSONWriter {
}
@Override
- protected void writeKey(String fname, boolean needsEscaping) throws IOException {
+ public void writeKey(String fname, boolean needsEscaping) throws IOException {
writeStr(null, fname, needsEscaping);
writer.write('=');
writer.write('>');
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
index c660aae..05208be 100644
--- a/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
@@ -225,7 +225,7 @@ class PHPSerializedWriter extends JSONWriter {
}
@Override
- protected void writeKey(String fname, boolean needsEscaping) throws IOException {
+ public void writeKey(String fname, boolean needsEscaping) throws IOException {
writeStr(null, fname, needsEscaping);
}
void writeKey(int val, boolean needsEscaping) throws IOException {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/QueryResponseWriterUtil.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/QueryResponseWriterUtil.java b/solr/core/src/java/org/apache/solr/response/QueryResponseWriterUtil.java
index ed47e84..4146384 100644
--- a/solr/core/src/java/org/apache/solr/response/QueryResponseWriterUtil.java
+++ b/solr/core/src/java/org/apache/solr/response/QueryResponseWriterUtil.java
@@ -24,8 +24,8 @@ import java.io.Writer;
import java.nio.charset.StandardCharsets;
import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.common.util.FastWriter;
import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.util.FastWriter;
/**
* Static utility methods relating to {@link QueryResponseWriter}s
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/RubyResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/RubyResponseWriter.java b/solr/core/src/java/org/apache/solr/response/RubyResponseWriter.java
index 30e6f9f..6b73a7c 100644
--- a/solr/core/src/java/org/apache/solr/response/RubyResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/RubyResponseWriter.java
@@ -16,8 +16,8 @@
*/
package org.apache.solr.response;
-import java.io.Writer;
import java.io.IOException;
+import java.io.Writer;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
@@ -63,7 +63,7 @@ class RubyWriter extends NaNFloatWriter {
}
@Override
- protected void writeKey(String fname, boolean needsEscaping) throws IOException {
+ public void writeKey(String fname, boolean needsEscaping) throws IOException {
writeStr(null, fname, needsEscaping);
writer.write('=');
writer.write('>');
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/SmileResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/SmileResponseWriter.java b/solr/core/src/java/org/apache/solr/response/SmileResponseWriter.java
index 0bd0658..0ca6fa6 100644
--- a/solr/core/src/java/org/apache/solr/response/SmileResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/SmileResponseWriter.java
@@ -67,7 +67,7 @@ public class SmileResponseWriter extends BinaryResponseWriter {
}
@Override
- protected void writeNumber(String name, Number val) throws IOException {
+ public void writeNumber(String name, Number val) throws IOException {
if (val instanceof Integer) {
gen.writeNumber(val.intValue());
} else if (val instanceof Long) {
@@ -156,7 +156,7 @@ public class SmileResponseWriter extends BinaryResponseWriter {
}
@Override
- protected void writeKey(String fname, boolean needsEscaping) throws IOException {
+ public void writeKey(String fname, boolean needsEscaping) throws IOException {
gen.writeFieldName(fname);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
index 98c181a..250b37d 100644
--- a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
@@ -18,52 +18,29 @@ package org.apache.solr.response;
import java.io.IOException;
import java.io.Writer;
-import java.nio.file.Path;
-import java.util.Arrays;
import java.util.Calendar;
-import java.util.Date;
import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.util.BytesRef;
-import org.apache.solr.common.EnumFieldValue;
-import org.apache.solr.common.IteratorWriter;
-import org.apache.solr.common.MapSerializable;
-import org.apache.solr.common.MapWriter;
-import org.apache.solr.common.PushWriter;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.util.Base64;
-import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.FastWriter;
+import org.apache.solr.common.util.TextWriter;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.DocList;
import org.apache.solr.search.ReturnFields;
-import org.apache.solr.util.FastWriter;
/** Base class for text-oriented response writers.
*
*
*/
-public abstract class TextResponseWriter implements PushWriter {
+public abstract class TextResponseWriter implements TextWriter {
- // indent up to 40 spaces
- static final char[] indentChars = new char[81];
- static {
- Arrays.fill(indentChars,' ');
- indentChars[0] = '\n'; // start with a newline
- }
-
-
protected final FastWriter writer;
protected final IndexSchema schema;
protected final SolrQueryRequest req;
@@ -105,18 +82,15 @@ public abstract class TextResponseWriter implements PushWriter {
if(writer != null) writer.flushBuffer();
}
+ @Override
+ public boolean doIndent() {
+ return doIndent;
+ }
+
/** returns the Writer that the response is being written to */
public Writer getWriter() { return writer; }
- public void indent() throws IOException {
- if (doIndent) indent(level);
- }
-
- public void indent(int lev) throws IOException {
- writer.write(indentChars, 0, Math.min((lev<<1)+1, indentChars.length));
- }
-
//
// Functions to manipulate the current logical nesting level.
// Any indentation will be partially based on level.
@@ -125,13 +99,12 @@ public abstract class TextResponseWriter implements PushWriter {
public int level() { return level; }
public int incLevel() { return ++level; }
public int decLevel() { return --level; }
- public void setIndent(boolean doIndent) {
+ public TextResponseWriter setIndent(boolean doIndent) {
this.doIndent = doIndent;
+ return this;
}
- public abstract void writeNamedList(String name, NamedList val) throws IOException;
-
public final void writeVal(String name, Object val) throws IOException {
// if there get to be enough types, perhaps hashing on the type
@@ -141,10 +114,10 @@ public abstract class TextResponseWriter implements PushWriter {
// go in order of most common to least common, however some of the more general types like Map belong towards the end
if (val == null) {
writeNull(name);
- } else if (val instanceof String) {
- writeStr(name, val.toString(), true);
- // micro-optimization... using toString() avoids a cast first
- } else if (val instanceof IndexableField) {
+ return;
+ }
+
+ if(val instanceof IndexableField) {
IndexableField f = (IndexableField)val;
SchemaField sf = schema.getFieldOrNull( f.name() );
if( sf != null ) {
@@ -153,14 +126,6 @@ public abstract class TextResponseWriter implements PushWriter {
else {
writeStr(name, f.stringValue(), true);
}
- } else if (val instanceof Number) {
- writeNumber(name, (Number) val);
- } else if (val instanceof Boolean) {
- writeBool(name, (Boolean) val);
- } else if (val instanceof AtomicBoolean) {
- writeBool(name, ((AtomicBoolean) val).get());
- } else if (val instanceof Date) {
- writeDate(name, (Date) val);
} else if (val instanceof Document) {
SolrDocument doc = DocsStreamer.convertLuceneDocToSolrDoc((Document) val, schema, returnFields);
writeSolrDocument(name, doc, returnFields, 0);
@@ -180,79 +145,13 @@ public abstract class TextResponseWriter implements PushWriter {
// restricts the fields to write...?
} else if (val instanceof SolrDocumentList) {
writeSolrDocumentList(name, (SolrDocumentList)val, returnFields);
- } else if (val instanceof NamedList) {
- writeNamedList(name, (NamedList)val);
- } else if (val instanceof Path) {
- writeStr(name, ((Path) val).toAbsolutePath().toString(), true);
- } else if (val instanceof IteratorWriter) {
- writeIterator((IteratorWriter) val);
- } else if (val instanceof MapWriter) {
- writeMap((MapWriter) val);
- } else if (val instanceof MapSerializable) {
- //todo find a better way to reuse the map more efficiently
- writeMap(name, ((MapSerializable) val).toMap(new LinkedHashMap<>()), false, true);
- } else if (val instanceof Map) {
- writeMap(name, (Map)val, false, true);
- } else if (val instanceof Iterator) { // very generic; keep towards the end
- writeArray(name, (Iterator) val);
- } else if (val instanceof Iterable) { // very generic; keep towards the end
- writeArray(name,((Iterable)val).iterator());
- } else if (val instanceof Object[]) {
- writeArray(name,(Object[])val);
- } else if (val instanceof byte[]) {
- byte[] arr = (byte[])val;
- writeByteArr(name, arr, 0, arr.length);
} else if (val instanceof BytesRef) {
BytesRef arr = (BytesRef)val;
writeByteArr(name, arr.bytes, arr.offset, arr.length);
- } else if (val instanceof EnumFieldValue) {
- writeStr(name, val.toString(), true);
- } else if (val instanceof WriteableValue) {
- ((WriteableValue)val).write(name, this);
} else {
- // default... for debugging only. Would be nice to "assert false" ?
- writeStr(name, val.getClass().getName() + ':' + val.toString(), true);
+ TextWriter.super.writeVal(name, val);
}
}
- @Override
- public void writeMap(MapWriter mw) throws IOException {
- //todo
- }
-
- @Override
- public void writeIterator(IteratorWriter iw) throws IOException {
- /*todo*/
- }
-
- protected void writeBool(String name , Boolean val) throws IOException {
- writeBool(name, val.toString());
- }
-
- protected void writeNumber(String name, Number val) throws IOException {
- if (val instanceof Integer) {
- writeInt(name, val.toString());
- } else if (val instanceof Long) {
- writeLong(name, val.toString());
- } else if (val instanceof Float) {
- // we pass the float instead of using toString() because
- // it may need special formatting. same for double.
- writeFloat(name, val.floatValue());
- } else if (val instanceof Double) {
- writeDouble(name, val.doubleValue());
- } else if (val instanceof Short) {
- writeInt(name, val.toString());
- } else if (val instanceof Byte) {
- writeInt(name, val.toString());
- } else if (val instanceof AtomicInteger) {
- writeInt(name, ((AtomicInteger) val).get());
- } else if (val instanceof AtomicLong) {
- writeLong(name, ((AtomicLong) val).get());
- } else {
- // default... for debugging only
- writeStr(name, val.getClass().getName() + ':' + val.toString(), true);
- }
- }
-
// names are passed when writing primitives like writeInt to allow many different
// types of formats, including those where the name may come after the value (like
// some XML formats).
@@ -287,84 +186,4 @@ public abstract class TextResponseWriter implements PushWriter {
}
writeEndDocumentList();
}
-
-
- public abstract void writeStr(String name, String val, boolean needsEscaping) throws IOException;
-
- public abstract void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal) throws IOException;
-
- public void writeArray(String name, Object[] val) throws IOException {
- writeArray(name, Arrays.asList(val));
- }
-
- public void writeArray(String name, List l) throws IOException {
- writeArray(name, l.iterator());
- }
-
- public abstract void writeArray(String name, Iterator val) throws IOException;
-
- public abstract void writeNull(String name) throws IOException;
-
- /** if this form of the method is called, val is the Java string form of an int */
- public abstract void writeInt(String name, String val) throws IOException;
-
- public void writeInt(String name, int val) throws IOException {
- writeInt(name,Integer.toString(val));
- }
-
- /** if this form of the method is called, val is the Java string form of a long */
- public abstract void writeLong(String name, String val) throws IOException;
-
- public void writeLong(String name, long val) throws IOException {
- writeLong(name,Long.toString(val));
- }
-
- /** if this form of the method is called, val is the Java string form of a boolean */
- public abstract void writeBool(String name, String val) throws IOException;
-
- public void writeBool(String name, boolean val) throws IOException {
- writeBool(name,Boolean.toString(val));
- }
-
- /** if this form of the method is called, val is the Java string form of a float */
- public abstract void writeFloat(String name, String val) throws IOException;
-
- public void writeFloat(String name, float val) throws IOException {
- String s = Float.toString(val);
- // If it's not a normal number, write the value as a string instead.
- // The following test also handles NaN since comparisons are always false.
- if (val > Float.NEGATIVE_INFINITY && val < Float.POSITIVE_INFINITY) {
- writeFloat(name,s);
- } else {
- writeStr(name,s,false);
- }
- }
-
-
- /** if this form of the method is called, val is the Java string form of a double */
- public abstract void writeDouble(String name, String val) throws IOException;
-
- public void writeDouble(String name, double val) throws IOException {
- String s = Double.toString(val);
- // If it's not a normal number, write the value as a string instead.
- // The following test also handles NaN since comparisons are always false.
- if (val > Double.NEGATIVE_INFINITY && val < Double.POSITIVE_INFINITY) {
- writeDouble(name,s);
- } else {
- writeStr(name,s,false);
- }
- }
-
-
- public void writeDate(String name, Date val) throws IOException {
- writeDate(name, val.toInstant().toString());
- }
-
-
- /** if this form of the method is called, val is the Solr ISO8601 based date format */
- public abstract void writeDate(String name, String val) throws IOException;
-
- public void writeByteArr(String name, byte[] buf, int offset, int len) throws IOException {
- writeStr(name, Base64.byteArrayToBase64(buf, offset, len), false);
- }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/WriteableValue.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/WriteableValue.java b/solr/core/src/java/org/apache/solr/response/WriteableValue.java
deleted file mode 100644
index 15b9093..0000000
--- a/solr/core/src/java/org/apache/solr/response/WriteableValue.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.response;
-
-import java.io.IOException;
-
-import org.apache.solr.common.util.JavaBinCodec.ObjectResolver;
-
-public abstract class WriteableValue implements ObjectResolver {
- public abstract void write(String name, TextResponseWriter writer) throws IOException;
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java b/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
index aaf9861..25fe56c 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/RawValueTransformerFactory.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import com.google.common.base.Strings;
import org.apache.lucene.index.IndexableField;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.CommonParams;
@@ -27,12 +28,10 @@ import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.JavaBinCodec;
import org.apache.solr.common.util.JavaBinCodec.ObjectResolver;
import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.TextWriter;
+import org.apache.solr.common.util.WriteableValue;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.QueryResponseWriter;
-import org.apache.solr.response.TextResponseWriter;
-import org.apache.solr.response.WriteableValue;
-
-import com.google.common.base.Strings;
/**
* @since solr 5.2
@@ -158,7 +157,7 @@ public class RawValueTransformerFactory extends TransformerFactory
}
@Override
- public void write(String name, TextResponseWriter writer) throws IOException {
+ public void write(String name, TextWriter writer) throws IOException {
String str = null;
if(val instanceof IndexableField) { // delays holding it in memory
str = ((IndexableField)val).stringValue();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/response/transform/WriteableGeoJSON.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/transform/WriteableGeoJSON.java b/solr/core/src/java/org/apache/solr/response/transform/WriteableGeoJSON.java
index 40acebf..f89f5c8 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/WriteableGeoJSON.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/WriteableGeoJSON.java
@@ -19,8 +19,8 @@ package org.apache.solr.response.transform;
import java.io.IOException;
import org.apache.solr.common.util.JavaBinCodec;
-import org.apache.solr.response.TextResponseWriter;
-import org.apache.solr.response.WriteableValue;
+import org.apache.solr.common.util.TextWriter;
+import org.apache.solr.common.util.WriteableValue;
import org.locationtech.spatial4j.io.ShapeWriter;
import org.locationtech.spatial4j.shape.Shape;
@@ -44,7 +44,7 @@ public class WriteableGeoJSON extends WriteableValue {
}
@Override
- public void write(String name, TextResponseWriter writer) throws IOException {
+ public void write(String name, TextWriter writer) throws IOException {
jsonWriter.write(writer.getWriter(), shape);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/java/org/apache/solr/util/FastWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/FastWriter.java b/solr/core/src/java/org/apache/solr/util/FastWriter.java
deleted file mode 100644
index 7b9b687..0000000
--- a/solr/core/src/java/org/apache/solr/util/FastWriter.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.util;
-
-import java.io.Writer;
-import java.io.IOException;
-
-/** Single threaded BufferedWriter
- * Internal Solr use only, subject to change.
- */
-public class FastWriter extends Writer {
- // use default BUFSIZE of BufferedWriter so if we wrap that
- // it won't cause double buffering.
- private static final int BUFSIZE = 8192;
- protected final Writer sink;
- protected char[] buf;
- protected int pos;
-
- public FastWriter(Writer w) {
- this(w, new char[BUFSIZE], 0);
- }
-
- public FastWriter(Writer sink, char[] tempBuffer, int start) {
- this.sink = sink;
- this.buf = tempBuffer;
- this.pos = start;
- }
-
- public static FastWriter wrap(Writer sink) {
- return (sink instanceof FastWriter) ? (FastWriter)sink : new FastWriter(sink);
- }
-
- @Override
- public void write(int c) throws IOException {
- write((char)c);
- }
-
- public void write(char c) throws IOException {
- if (pos >= buf.length) {
- flush(buf,0,pos);
- pos=0;
- }
- buf[pos++] = c;
- }
-
- @Override
- public FastWriter append(char c) throws IOException {
- if (pos >= buf.length) {
- flush(buf,0,pos);
- pos=0;
- }
- buf[pos++] = c;
- return this;
- }
-
- @Override
- public void write(char arr[], int off, int len) throws IOException {
- for(;;) {
- int space = buf.length - pos;
-
- if (len <= space) {
- System.arraycopy(arr, off, buf, pos, len);
- pos += len;
- return;
- } else if (len > buf.length) {
- if (pos>0) {
- flush(buf,0,pos); // flush
- pos=0;
- }
- // don't buffer, just write to sink
- flush(arr, off, len);
- return;
- }
-
- // buffer is too big to fit in the free space, but
- // not big enough to warrant writing on its own.
- // write whatever we can fit, then flush and iterate.
-
- System.arraycopy(arr, off, buf, pos, space);
- flush(buf, 0, buf.length);
- pos = 0;
- off += space;
- len -= space;
- }
- }
-
- @Override
- public void write(String str, int off, int len) throws IOException {
- for(;;) {
- int space = buf.length - pos;
-
- if (len <= space) {
- str.getChars(off, off+len, buf, pos);
- pos += len;
- return;
- } else if (len > buf.length) {
- if (pos>0) {
- flush(buf,0,pos); // flush
- pos=0;
- }
- // don't buffer, just write to sink
- flush(str, off, len);
- return;
- }
-
- // buffer is too big to fit in the free space, but
- // not big enough to warrant writing on its own.
- // write whatever we can fit, then flush and iterate.
-
- str.getChars(off, off+space, buf, pos);
- flush(buf, 0, buf.length);
- pos = 0;
- off += space;
- len -= space;
- }
- }
-
- @Override
- public void flush() throws IOException {
- flush(buf, 0, pos);
- pos=0;
- if (sink != null) sink.flush();
- }
-
- public void flush(char[] buf, int offset, int len) throws IOException {
- sink.write(buf, offset, len);
- }
-
- public void flush(String str, int offset, int len) throws IOException {
- sink.write(str, offset, len);
- }
-
- @Override
- public void close() throws IOException {
- flush();
- if (sink != null) sink.close();
- }
-
- public void flushBuffer() throws IOException {
- flush(buf, 0, pos);
- pos=0;
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/test/org/apache/solr/response/JSONWriterTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/response/JSONWriterTest.java b/solr/core/src/test/org/apache/solr/response/JSONWriterTest.java
index 68cebd2..8a6cb71 100644
--- a/solr/core/src/test/org/apache/solr/response/JSONWriterTest.java
+++ b/solr/core/src/test/org/apache/solr/response/JSONWriterTest.java
@@ -30,9 +30,10 @@ import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.util.JsonTextWriter;
import org.apache.solr.common.util.NamedList;
-import org.apache.solr.search.ReturnFields;
import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.search.ReturnFields;
import org.apache.solr.search.SolrReturnFields;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -80,11 +81,11 @@ public class JSONWriterTest extends SolrTestCaseJ4 {
@Test
public void testJSON() throws IOException {
final String[] namedListStyles = new String[] {
- JSONWriter.JSON_NL_FLAT,
- JSONWriter.JSON_NL_MAP,
- JSONWriter.JSON_NL_ARROFARR,
- JSONWriter.JSON_NL_ARROFMAP,
- JSONWriter.JSON_NL_ARROFNTV,
+ JsonTextWriter.JSON_NL_FLAT,
+ JsonTextWriter.JSON_NL_MAP,
+ JsonTextWriter.JSON_NL_ARROFARR,
+ JsonTextWriter.JSON_NL_ARROFMAP,
+ JsonTextWriter.JSON_NL_ARROFNTV,
};
for (final String namedListStyle : namedListStyles) {
implTestJSON(namedListStyle);
@@ -202,17 +203,23 @@ public class JSONWriterTest extends SolrTestCaseJ4 {
methodsExpectedNotOverriden.add("writeMapOpener");
methodsExpectedNotOverriden.add("writeMapSeparator");
methodsExpectedNotOverriden.add("writeMapCloser");
- methodsExpectedNotOverriden.add("public void org.apache.solr.response.JSONWriter.writeArray(java.lang.String,java.util.List) throws java.io.IOException");
+ methodsExpectedNotOverriden.add("public default void org.apache.solr.common.util.JsonTextWriter.writeArray(java.lang.String,java.util.List) throws java.io.IOException");
methodsExpectedNotOverriden.add("writeArrayOpener");
methodsExpectedNotOverriden.add("writeArraySeparator");
methodsExpectedNotOverriden.add("writeArrayCloser");
- methodsExpectedNotOverriden.add("public void org.apache.solr.response.JSONWriter.writeMap(org.apache.solr.common.MapWriter) throws java.io.IOException");
- methodsExpectedNotOverriden.add("public void org.apache.solr.response.JSONWriter.writeIterator(org.apache.solr.common.IteratorWriter) throws java.io.IOException");
+ methodsExpectedNotOverriden.add("public default void org.apache.solr.common.util.JsonTextWriter.writeMap(org.apache.solr.common.MapWriter) throws java.io.IOException");
+ methodsExpectedNotOverriden.add("public default void org.apache.solr.common.util.JsonTextWriter.writeIterator(org.apache.solr.common.IteratorWriter) throws java.io.IOException");
+ methodsExpectedNotOverriden.add("public default void org.apache.solr.common.util.JsonTextWriter.writeJsonIter(java.util.Iterator) throws java.io.IOException");
final Class<?> subClass = ArrayOfNameTypeValueJSONWriter.class;
final Class<?> superClass = subClass.getSuperclass();
- for (final Method superClassMethod : superClass.getDeclaredMethods()) {
+ List<Method> allSuperClassMethods = new ArrayList<>();
+ for (Method method : superClass.getDeclaredMethods()) allSuperClassMethods.add(method);
+ for (Method method : JsonTextWriter.class.getDeclaredMethods()) allSuperClassMethods.add(method);
+
+
+ for (final Method superClassMethod : allSuperClassMethods) {
final String methodName = superClassMethod.getName();
final String methodFullName = superClassMethod.toString();
if (!methodName.startsWith("write")) continue;
@@ -226,10 +233,7 @@ public class JSONWriterTest extends SolrTestCaseJ4 {
&& !methodsExpectedNotOverriden.contains(methodFullName);
try {
- final Method subClassMethod = subClass.getDeclaredMethod(
- superClassMethod.getName(),
- superClassMethod.getParameterTypes());
-
+ final Method subClassMethod = getDeclaredMethodInClasses(superClassMethod, subClass);
if (expectOverriden) {
assertEquals("getReturnType() difference",
superClassMethod.getReturnType(),
@@ -260,9 +264,7 @@ public class JSONWriterTest extends SolrTestCaseJ4 {
// only own private method of its own
if (subClassMethod.getName().equals("ifNeededWriteTypeAndValueKey")) continue;
try {
- final Method superClassMethod = superClass.getDeclaredMethod(
- subClassMethod.getName(),
- subClassMethod.getParameterTypes());
+ final Method superClassMethod = getDeclaredMethodInClasses( subClassMethod,superClass, JsonTextWriter.class);
assertEquals("getReturnType() difference",
subClassMethod.getReturnType(),
@@ -272,7 +274,22 @@ public class JSONWriterTest extends SolrTestCaseJ4 {
}
}
}
-
+
+ private Method getDeclaredMethodInClasses(Method subClassMethod, Class<?>... classes) throws NoSuchMethodException {
+ for (int i = 0; i < classes.length; i++) {
+ Class<?> klass = classes[i];
+ try {
+ return klass.getDeclaredMethod(
+ subClassMethod.getName(),
+ subClassMethod.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ if(i==classes.length-1) throw e;
+ }
+ }
+ throw new NoSuchMethodException(subClassMethod.toString());
+
+ }
+
@Test
public void testConstantsUnchanged() {
assertEquals("json.nl", JSONWriter.JSON_NL_STYLE);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/core/src/test/org/apache/solr/util/TestFastWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/util/TestFastWriter.java b/solr/core/src/test/org/apache/solr/util/TestFastWriter.java
deleted file mode 100644
index 5857666..0000000
--- a/solr/core/src/test/org/apache/solr/util/TestFastWriter.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.util;
-
-import org.apache.lucene.util.LuceneTestCase;
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-
-
-class MemWriter extends FastWriter {
- public List<char[]> buffers = new LinkedList<>();
-
- Random r;
- public MemWriter(char[] tempBuffer, Random r) {
- super(null, tempBuffer, 0);
- this.r = r;
- }
-
- @Override
- public void flush(char[] arr, int offset, int len) throws IOException {
- if (arr == buf && offset==0 && len==buf.length) {
- buffers.add(buf); // steal the buffer
- buf = new char[r.nextInt(9000)+1];
- } else if (len > 0) {
- char[] newBuf = new char[len];
- System.arraycopy(arr, offset, newBuf, 0, len);
- buffers.add(newBuf);
- }
- }
-
- @Override
- public void flush(String str, int offset, int len) throws IOException {
- if (len == 0) return;
- buffers.add( str.substring(offset, offset+len).toCharArray() );
- }
-}
-
-
-
-public class TestFastWriter extends LuceneTestCase {
-
- Random rand;
- char[] arr;
- String s;
-
- public void testRandomWrites() throws Exception {
- rand = random();
-
- arr = new char[20000];
- for (int i=0; i<arr.length; i++) {
- arr[i] = (char)rand.nextInt();
- }
- s = new String(arr);
-
- for (int i=0; i<1000; i++) {
- doRandomWrites();
- }
- }
-
-
- public void doRandomWrites() throws Exception {
- int bufSize = ( rand.nextBoolean() ? rand.nextInt(10) : rand.nextInt(20000) )+1;
- MemWriter out = new MemWriter(new char[bufSize], rand);
-
- int hash = 0;
- long written = 0;
- int iter = rand.nextInt(20)+1;
- for (int i=0; i<iter; i++) {
- int which = rand.nextInt(3);
-
-
- int off = rand.nextInt(arr.length);
- int len = off < arr.length ? rand.nextInt(arr.length - off) : 0;
-
-
-
- if (which == 0) {
- out.write(arr, off, len);
- } else if (which == 1) {
- out.write(s, off, len);
- } else {
- len = 1;
- out.write(arr[off]);
- }
-
- hash = incHash(hash, arr, off, len);
- written += len;
- }
-
- out.close();
-
- int hash2 = 0;
- for (char[] buffer : out.buffers) {
- hash2 = incHash(hash2, buffer, 0, buffer.length);
- }
-
- assertEquals(hash, hash2);
- }
-
-
- public int incHash(int hash, char[] arr, int off, int len) {
- for (int i=off; i<off+len; i++) {
- hash = hash * 31 + arr[i];
- }
- return hash;
- }
-}
-
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/java/org/apache/solr/common/util/FastWriter.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/FastWriter.java b/solr/solrj/src/java/org/apache/solr/common/util/FastWriter.java
new file mode 100644
index 0000000..2575624
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/util/FastWriter.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/** Single threaded BufferedWriter
+ * Internal Solr use only, subject to change.
+ */
+public class FastWriter extends Writer {
+ // use default BUFSIZE of BufferedWriter so if we wrap that
+ // it won't cause double buffering.
+ private static final int BUFSIZE = 8192;
+ protected final Writer sink;
+ protected char[] buf;
+ protected int pos;
+
+ public FastWriter(Writer w) {
+ this(w, new char[BUFSIZE], 0);
+ }
+
+ public FastWriter(Writer sink, char[] tempBuffer, int start) {
+ this.sink = sink;
+ this.buf = tempBuffer;
+ this.pos = start;
+ }
+
+ public static FastWriter wrap(Writer sink) {
+ return (sink instanceof FastWriter) ? (FastWriter)sink : new FastWriter(sink);
+ }
+
+ @Override
+ public void write(int c) throws IOException {
+ write((char)c);
+ }
+
+ public void write(char c) throws IOException {
+ if (pos >= buf.length) {
+ flush(buf,0,pos);
+ pos=0;
+ }
+ buf[pos++] = c;
+ }
+
+ @Override
+ public FastWriter append(char c) throws IOException {
+ if (pos >= buf.length) {
+ flush(buf,0,pos);
+ pos=0;
+ }
+ buf[pos++] = c;
+ return this;
+ }
+
+ @Override
+ public void write(char arr[], int off, int len) throws IOException {
+ for(;;) {
+ int space = buf.length - pos;
+
+ if (len <= space) {
+ System.arraycopy(arr, off, buf, pos, len);
+ pos += len;
+ return;
+ } else if (len > buf.length) {
+ if (pos>0) {
+ flush(buf,0,pos); // flush
+ pos=0;
+ }
+ // don't buffer, just write to sink
+ flush(arr, off, len);
+ return;
+ }
+
+ // buffer is too big to fit in the free space, but
+ // not big enough to warrant writing on its own.
+ // write whatever we can fit, then flush and iterate.
+
+ System.arraycopy(arr, off, buf, pos, space);
+ flush(buf, 0, buf.length);
+ pos = 0;
+ off += space;
+ len -= space;
+ }
+ }
+
+ @Override
+ public void write(String str, int off, int len) throws IOException {
+ for(;;) {
+ int space = buf.length - pos;
+
+ if (len <= space) {
+ str.getChars(off, off+len, buf, pos);
+ pos += len;
+ return;
+ } else if (len > buf.length) {
+ if (pos>0) {
+ flush(buf,0,pos); // flush
+ pos=0;
+ }
+ // don't buffer, just write to sink
+ flush(str, off, len);
+ return;
+ }
+
+ // buffer is too big to fit in the free space, but
+ // not big enough to warrant writing on its own.
+ // write whatever we can fit, then flush and iterate.
+
+ str.getChars(off, off+space, buf, pos);
+ flush(buf, 0, buf.length);
+ pos = 0;
+ off += space;
+ len -= space;
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ flush(buf, 0, pos);
+ pos=0;
+ if (sink != null) sink.flush();
+ }
+
+ public void flush(char[] buf, int offset, int len) throws IOException {
+ sink.write(buf, offset, len);
+ }
+
+ public void flush(String str, int offset, int len) throws IOException {
+ sink.write(str, offset, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ flush();
+ if (sink != null) sink.close();
+ }
+
+ public void flushBuffer() throws IOException {
+ flush(buf, 0, pos);
+ pos=0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/java/org/apache/solr/common/util/JsonTextWriter.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/JsonTextWriter.java b/solr/solrj/src/java/org/apache/solr/common/util/JsonTextWriter.java
new file mode 100644
index 0000000..e176bd1
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/util/JsonTextWriter.java
@@ -0,0 +1,499 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.solr.common.IteratorWriter;
+import org.apache.solr.common.MapWriter;
+
+public interface JsonTextWriter extends TextWriter {
+ char[] hexdigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ String JSON_NL_MAP = "map";
+ String JSON_NL_FLAT = "flat";
+ String JSON_NL_ARROFARR = "arrarr";
+ String JSON_NL_ARROFMAP = "arrmap";
+ String JSON_NL_ARROFNTV = "arrntv";
+ String JSON_NL_STYLE = "json.nl";
+
+ String getNamedListStyle();
+
+ void _writeChar(char c) throws IOException;
+
+ void _writeStr(String s) throws IOException;
+
+ default void writeMapOpener(int size) throws IOException, IllegalArgumentException {
+ _writeChar('{');
+ }
+
+ default void writeMapSeparator() throws IOException {
+ _writeChar(',');
+ }
+
+ default void writeMapCloser() throws IOException {
+ _writeChar('}');
+ }
+
+ default void writeArrayOpener(int size) throws IOException, IllegalArgumentException {
+ _writeChar('[');
+ }
+
+ default void writeArraySeparator() throws IOException {
+ _writeChar(',');
+ }
+
+ default void writeArrayCloser() throws IOException {
+ _writeChar(']');
+ }
+
+ default void writeStr(String name, String val, boolean needsEscaping) throws IOException {
+ // it might be more efficient to use a stringbuilder or write substrings
+ // if writing chars to the stream is slow.
+ if (needsEscaping) {
+
+
+ /* http://www.ietf.org/internet-drafts/draft-crockford-jsonorg-json-04.txt
+ All Unicode characters may be placed within
+ the quotation marks except for the characters which must be
+ escaped: quotation mark, reverse solidus, and the control
+ characters (U+0000 through U+001F).
+ */
+ _writeChar('"');
+
+ for (int i = 0; i < val.length(); i++) {
+ char ch = val.charAt(i);
+ if ((ch > '#' && ch != '\\' && ch < '\u2028') || ch == ' ') { // fast path
+ _writeChar(ch);
+ continue;
+ }
+ switch (ch) {
+ case '"':
+ case '\\':
+ _writeChar('\\');
+ _writeChar(ch);
+ break;
+ case '\r':
+ _writeChar('\\');
+ _writeChar('r');
+ break;
+ case '\n':
+ _writeChar('\\');
+ _writeChar('n');
+ break;
+ case '\t':
+ _writeChar('\\');
+ _writeChar('t');
+ break;
+ case '\b':
+ _writeChar('\\');
+ _writeChar('b');
+ break;
+ case '\f':
+ _writeChar('\\');
+ _writeChar('f');
+ break;
+ case '\u2028': // fallthrough
+ case '\u2029':
+ unicodeEscape(getWriter(), ch);
+ break;
+ // case '/':
+ default: {
+ if (ch <= 0x1F) {
+ unicodeEscape(getWriter(), ch);
+ } else {
+ _writeChar(ch);
+ }
+ }
+ }
+ }
+
+ _writeChar('"');
+ } else {
+ _writeChar('"');
+ _writeStr(val);
+ _writeChar('"');
+ }
+ }
+
+ default void writeIterator(IteratorWriter val) throws IOException {
+ writeArrayOpener(-1);
+ incLevel();
+ val.writeIter(new IteratorWriter.ItemWriter() {
+ boolean first = true;
+
+ @Override
+ public IteratorWriter.ItemWriter add(Object o) throws IOException {
+ if (!first) {
+ JsonTextWriter.this.indent();
+ JsonTextWriter.this.writeArraySeparator();
+ }
+ JsonTextWriter.this.writeVal(null, o);
+ first = false;
+ return this;
+ }
+ });
+ decLevel();
+ writeArrayCloser();
+ }
+
+ default void writeMap(MapWriter val)
+ throws IOException {
+ writeMapOpener(-1);
+ incLevel();
+
+ val.writeMap(new MapWriter.EntryWriter() {
+ boolean isFirst = true;
+
+ @Override
+ public MapWriter.EntryWriter put(String k, Object v) throws IOException {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ JsonTextWriter.this.writeMapSeparator();
+ }
+ JsonTextWriter.this.indent();
+ JsonTextWriter.this.writeKey(k, true);
+ writeVal(k, v);
+ return this;
+ }
+ });
+ decLevel();
+ writeMapCloser();
+ }
+
+ default void writeKey(String fname, boolean needsEscaping) throws IOException {
+ writeStr(null, fname, needsEscaping);
+ _writeChar(':');
+ }
+
+ default void writeJsonIter(Iterator val) throws IOException {
+ incLevel();
+ boolean first = true;
+ while (val.hasNext()) {
+ if (!first) indent();
+ writeVal(null, val.next());
+ if (val.hasNext()) {
+ writeArraySeparator();
+ }
+ first = false;
+ }
+ decLevel();
+ }
+
+ //
+ // Primitive types
+ //
+ default void writeNull(String name) throws IOException {
+ _writeStr("null");
+ }
+
+
+ default void writeInt(String name, String val) throws IOException {
+ _writeStr(val);
+ }
+
+ default void writeLong(String name, String val) throws IOException {
+ _writeStr(val);
+ }
+
+ default void writeBool(String name, String val) throws IOException {
+ _writeStr(val);
+ }
+
+ default void writeFloat(String name, String val) throws IOException {
+ _writeStr(val);
+ }
+
+ default void writeDouble(String name, String val) throws IOException {
+ _writeStr(val);
+ }
+
+ default void writeDate(String name, String val) throws IOException {
+ writeStr(name, val, false);
+ }
+
+
+ default void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal) throws IOException {
+ if (!excludeOuter) {
+ writeMapOpener(val.size());
+ incLevel();
+ isFirstVal = true;
+ }
+
+ boolean doIndent = excludeOuter || val.size() > 1;
+
+ for (Map.Entry entry : (Set<Map.Entry>) val.entrySet()) {
+ Object e = entry.getKey();
+ String k = e == null ? "" : e.toString();
+ Object v = entry.getValue();
+
+ if (isFirstVal) {
+ isFirstVal = false;
+ } else {
+ writeMapSeparator();
+ }
+
+ if (doIndent) indent();
+ writeKey(k, true);
+ writeVal(k, v);
+ }
+
+ if (!excludeOuter) {
+ decLevel();
+ writeMapCloser();
+ }
+ }
+
+
+ default void writeArray(String name, List l) throws IOException {
+ writeArrayOpener(l.size());
+ writeJsonIter(l.iterator());
+ writeArrayCloser();
+ }
+
+ default void writeArray(String name, Iterator val) throws IOException {
+ writeArrayOpener(-1); // no trivial way to determine array size
+ writeJsonIter(val);
+ writeArrayCloser();
+ }
+
+ default void unicodeEscape(Appendable out, int ch) throws IOException {
+ out.append('\\');
+ out.append('u');
+ out.append(hexdigits[(ch >>> 12)]);
+ out.append(hexdigits[(ch >>> 8) & 0xf]);
+ out.append(hexdigits[(ch >>> 4) & 0xf]);
+ out.append(hexdigits[(ch) & 0xf]);
+ }
+
+ default void writeNamedList(String name, NamedList val) throws IOException {
+ String namedListStyle = getNamedListStyle();
+ if (val instanceof SimpleOrderedMap) {
+ writeNamedListAsMapWithDups(name, val);
+ } else if (namedListStyle == JSON_NL_FLAT) {
+ writeNamedListAsFlat(name, val);
+ } else if (namedListStyle == JSON_NL_MAP) {
+ writeNamedListAsMapWithDups(name, val);
+ } else if (namedListStyle == JSON_NL_ARROFARR) {
+ writeNamedListAsArrArr(name, val);
+ } else if (namedListStyle == JSON_NL_ARROFMAP) {
+ writeNamedListAsArrMap(name, val);
+ } else if (namedListStyle == JSON_NL_ARROFNTV) {
+ throw new UnsupportedOperationException(namedListStyle
+ + " namedListStyle must only be used with ArrayOfNameTypeValueJSONWriter");
+ }
+ }
+
+ /**
+ * Represents a NamedList directly as a JSON Object (essentially a Map)
+ * Map null to "" and name mangle any repeated keys to avoid repeats in the
+ * output.
+ */
+ default void writeNamedListAsMapMangled(String name, NamedList val) throws IOException {
+ int sz = val.size();
+ writeMapOpener(sz);
+ incLevel();
+
+ // In JSON objects (maps) we can't have null keys or duplicates...
+ // map null to "" and append a qualifier to duplicates.
+ //
+ // a=123,a=456 will be mapped to {a=1,a__1=456}
+ // Disad: this is ambiguous since a real key could be called a__1
+ //
+ // Another possible mapping could aggregate multiple keys to an array:
+ // a=123,a=456 maps to a=[123,456]
+ // Disad: this is ambiguous with a real single value that happens to be an array
+ //
+ // Both of these mappings have ambiguities.
+ HashMap<String, Integer> repeats = new HashMap<>(4);
+
+ boolean first = true;
+ for (int i = 0; i < sz; i++) {
+ String key = val.getName(i);
+ if (key == null) key = "";
+
+ if (first) {
+ first = false;
+ repeats.put(key, 0);
+ } else {
+ writeMapSeparator();
+
+ Integer repeatCount = repeats.get(key);
+ if (repeatCount == null) {
+ repeats.put(key, 0);
+ } else {
+ String newKey = key;
+ int newCount = repeatCount;
+ do { // avoid generated key clashing with a real key
+ newKey = key + ' ' + (++newCount);
+ repeatCount = repeats.get(newKey);
+ } while (repeatCount != null);
+
+ repeats.put(key, newCount);
+ key = newKey;
+ }
+ }
+
+ indent();
+ writeKey(key, true);
+ writeVal(key, val.getVal(i));
+ }
+
+ decLevel();
+ writeMapCloser();
+ }
+
+ /**
+ * Represents a NamedList directly as a JSON Object (essentially a Map)
+ * repeating any keys if they are repeated in the NamedList.
+ * null key is mapped to "".
+ */
+ // NamedList("a"=1,"bar"="foo",null=3,null=null) => {"a":1,"bar":"foo","":3,"":null}
+ default void writeNamedListAsMapWithDups(String name, NamedList val) throws IOException {
+ int sz = val.size();
+ writeMapOpener(sz);
+ incLevel();
+
+ for (int i = 0; i < sz; i++) {
+ if (i != 0) {
+ writeMapSeparator();
+ }
+
+ String key = val.getName(i);
+ if (key == null) key = "";
+ indent();
+ writeKey(key, true);
+ writeVal(key, val.getVal(i));
+ }
+
+ decLevel();
+ writeMapCloser();
+ }
+
+ // Represents a NamedList directly as an array of JSON objects...
+ // NamedList("a"=1,"b"=2,null=3,null=null) => [{"a":1},{"b":2},3,null]
+ default void writeNamedListAsArrMap(String name, NamedList val) throws IOException {
+ int sz = val.size();
+ indent();
+ writeArrayOpener(sz);
+ incLevel();
+
+ boolean first = true;
+ for (int i = 0; i < sz; i++) {
+ String key = val.getName(i);
+
+ if (first) {
+ first = false;
+ } else {
+ writeArraySeparator();
+ }
+
+ indent();
+
+ if (key == null) {
+ writeVal(null, val.getVal(i));
+ } else {
+ writeMapOpener(1);
+ writeKey(key, true);
+ writeVal(key, val.getVal(i));
+ writeMapCloser();
+ }
+
+ }
+
+ decLevel();
+ writeArrayCloser();
+ }
+
+ // Represents a NamedList directly as an array of JSON objects...
+ // NamedList("a"=1,"b"=2,null=3,null=null) => [["a",1],["b",2],[null,3],[null,null]]
+ default void writeNamedListAsArrArr(String name, NamedList val) throws IOException {
+ int sz = val.size();
+ indent();
+ writeArrayOpener(sz);
+ incLevel();
+
+ boolean first = true;
+ for (int i = 0; i < sz; i++) {
+ String key = val.getName(i);
+
+ if (first) {
+ first = false;
+ } else {
+ writeArraySeparator();
+ }
+
+ indent();
+
+ /*** if key is null, just write value???
+ if (key==null) {
+ writeVal(null,val.getVal(i));
+ } else {
+ ***/
+
+ writeArrayOpener(1);
+ incLevel();
+ if (key == null) {
+ writeNull(null);
+ } else {
+ writeStr(null, key, true);
+ }
+ writeArraySeparator();
+ writeVal(key, val.getVal(i));
+ decLevel();
+ writeArrayCloser();
+ }
+
+ decLevel();
+ writeArrayCloser();
+ }
+
+ // Represents a NamedList directly as an array with keys/values
+ // interleaved.
+ // NamedList("a"=1,"b"=2,null=3,null=null) => ["a",1,"b",2,null,3,null,null]
+ default void writeNamedListAsFlat(String name, NamedList val) throws IOException {
+ int sz = val.size();
+ writeArrayOpener(sz * 2);
+ incLevel();
+
+ for (int i = 0; i < sz; i++) {
+ if (i != 0) {
+ writeArraySeparator();
+ }
+ String key = val.getName(i);
+ indent();
+ if (key == null) {
+ writeNull(null);
+ } else {
+ writeStr(null, key, true);
+ }
+ writeArraySeparator();
+ writeVal(key, val.getVal(i));
+ }
+
+ decLevel();
+ writeArrayCloser();
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/java/org/apache/solr/common/util/SolrJSONWriter.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/SolrJSONWriter.java b/solr/solrj/src/java/org/apache/solr/common/util/SolrJSONWriter.java
new file mode 100644
index 0000000..5eeefd4
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/util/SolrJSONWriter.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+
+/**
+ * Use this to serialize an object into Json. This only supports standard Objects
+ * and not the server-side Objects
+ */
+public class SolrJSONWriter implements JsonTextWriter {
+ // indent up to 40 spaces
+ static final char[] indentChars = new char[81];
+
+ static {
+ Arrays.fill(indentChars, ' ');
+ indentChars[0] = '\n'; // start with a newline
+ }
+
+ final protected String namedListStyle;
+ final FastWriter writer;
+ protected int level;
+ protected boolean doIndent;
+
+ public SolrJSONWriter(Writer writer) {
+ this(writer, JSON_NL_MAP);
+ }
+
+ public SolrJSONWriter(Writer writer, String namedListStyle) {
+ this.writer = writer == null ? null : FastWriter.wrap(writer);
+ this.namedListStyle = namedListStyle;
+ }
+
+ public SolrJSONWriter writeObj(Object o) throws IOException {
+ writeVal(null, o);
+ return this;
+ }
+
+ /**
+ * done with all writing
+ */
+ public void close() throws IOException {
+ if (writer != null) writer.flushBuffer();
+ }
+
+
+ @Override
+ public String getNamedListStyle() {
+ return namedListStyle;
+ }
+
+ @Override
+ public void _writeChar(char c) throws IOException {
+ writer.write(c);
+ }
+
+ @Override
+ public void _writeStr(String s) throws IOException {
+ writer.write(s);
+ }
+
+
+ public void setLevel(int level) {
+ this.level = level;
+ }
+
+ public int level() {
+ return level;
+ }
+
+ @Override
+ public int incLevel() {
+ return ++level;
+ }
+
+ @Override
+ public int decLevel() {
+ return --level;
+ }
+
+ @Override
+ public SolrJSONWriter setIndent(boolean doIndent) {
+ this.doIndent = doIndent;
+ return this;
+ }
+
+ @Override
+ public boolean doIndent() {
+ return doIndent;
+ }
+
+ @Override
+ public Writer getWriter() {
+ return writer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fef87d71/solr/solrj/src/java/org/apache/solr/common/util/TextWriter.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/TextWriter.java b/solr/solrj/src/java/org/apache/solr/common/util/TextWriter.java
new file mode 100644
index 0000000..b8dbeb2
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/util/TextWriter.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.common.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.solr.common.EnumFieldValue;
+import org.apache.solr.common.IteratorWriter;
+import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
+import org.apache.solr.common.PushWriter;
+
+//Base interface for all text based writers
+public interface TextWriter extends PushWriter {
+
+ default void writeVal(String name, Object val) throws IOException {
+
+ // if there get to be enough types, perhaps hashing on the type
+ // to get a handler might be faster (but types must be exact to do that...)
+ // (see a patch on LUCENE-3041 for inspiration)
+
+ // go in order of most common to least common, however some of the more general types like Map belong towards the end
+ if (val == null) {
+ writeNull(name);
+ } else if (val instanceof String) {
+ writeStr(name, val.toString(), true);
+ // micro-optimization... using toString() avoids a cast first
+ } else if (val instanceof Number) {
+ writeNumber(name, (Number) val);
+ } else if (val instanceof Boolean) {
+ writeBool(name, (Boolean) val);
+ } else if (val instanceof AtomicBoolean) {
+ writeBool(name, ((AtomicBoolean) val).get());
+ } else if (val instanceof Date) {
+ writeDate(name, (Date) val);
+ } else if (val instanceof NamedList) {
+ writeNamedList(name, (NamedList)val);
+ } else if (val instanceof Path) {
+ writeStr(name, ((Path) val).toAbsolutePath().toString(), true);
+ } else if (val instanceof IteratorWriter) {
+ writeIterator((IteratorWriter) val);
+ } else if (val instanceof MapWriter) {
+ writeMap((MapWriter) val);
+ } else if (val instanceof MapSerializable) {
+ //todo find a better way to reuse the map more efficiently
+ writeMap(name, ((MapSerializable) val).toMap(new LinkedHashMap<>()), false, true);
+ } else if (val instanceof Map) {
+ writeMap(name, (Map)val, false, true);
+ } else if (val instanceof Iterator) { // very generic; keep towards the end
+ writeArray(name, (Iterator) val);
+ } else if (val instanceof Iterable) { // very generic; keep towards the end
+ writeArray(name,((Iterable)val).iterator());
+ } else if (val instanceof Object[]) {
+ writeArray(name,(Object[])val);
+ } else if (val instanceof byte[]) {
+ byte[] arr = (byte[])val;
+ writeByteArr(name, arr, 0, arr.length);
+ } else if (val instanceof EnumFieldValue) {
+ writeStr(name, val.toString(), true);
+ } else if (val instanceof WriteableValue) {
+ ((WriteableValue)val).write(name, this);
+ } else {
+ // default... for debugging only. Would be nice to "assert false" ?
+ writeStr(name, val.getClass().getName() + ':' + val.toString(), true);
+ }
+ }
+
+ void writeStr(String name, String val, boolean needsEscaping) throws IOException;
+
+ void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal) throws IOException;
+
+ void writeArray(String name, Iterator val) throws IOException;
+
+ void writeNull(String name) throws IOException;
+
+
+ /** if this form of the method is called, val is the Java string form of an int */
+ void writeInt(String name, String val) throws IOException;
+
+
+ /** if this form of the method is called, val is the Java string form of a long */
+ void writeLong(String name, String val) throws IOException;
+
+ /** if this form of the method is called, val is the Java string form of a boolean */
+ void writeBool(String name, String val) throws IOException;
+
+ /** if this form of the method is called, val is the Java string form of a float */
+ void writeFloat(String name, String val) throws IOException;
+
+
+ /** if this form of the method is called, val is the Java string form of a double */
+ void writeDouble(String name, String val) throws IOException;
+
+
+ /** if this form of the method is called, val is the Solr ISO8601 based date format */
+ void writeDate(String name, String val) throws IOException;
+
+ void writeNamedList(String name, NamedList val) throws IOException;
+
+ Writer getWriter();
+
+ default void writeNumber(String name, Number val) throws IOException {
+ if (val instanceof Integer) {
+ writeInt(name, val.toString());
+ } else if (val instanceof Long) {
+ writeLong(name, val.toString());
+ } else if (val instanceof Float) {
+ // we pass the float instead of using toString() because
+ // it may need special formatting. same for double.
+ writeFloat(name, val.floatValue());
+ } else if (val instanceof Double) {
+ writeDouble(name, val.doubleValue());
+ } else if (val instanceof Short) {
+ writeInt(name, val.toString());
+ } else if (val instanceof Byte) {
+ writeInt(name, val.toString());
+ } else if (val instanceof AtomicInteger) {
+ writeInt(name, ((AtomicInteger) val).get());
+ } else if (val instanceof AtomicLong) {
+ writeLong(name, ((AtomicLong) val).get());
+ } else {
+ // default... for debugging only
+ writeStr(name, val.getClass().getName() + ':' + val.toString(), true);
+ }
+ }
+
+ default void writeArray(String name, Object[] val) throws IOException {
+ writeArray(name, Arrays.asList(val));
+ }
+
+ default void writeArray(String name, List l) throws IOException {
+ writeArray(name, l.iterator());
+ }
+
+
+ default void writeDate(String name, Date val) throws IOException {
+ writeDate(name, val.toInstant().toString());
+ }
+
+ default void writeByteArr(String name, byte[] buf, int offset, int len) throws IOException {
+ writeStr(name, Base64.byteArrayToBase64(buf, offset, len), false);
+ }
+
+ default void writeInt(String name, int val) throws IOException {
+ writeInt(name,Integer.toString(val));
+ }
+
+ default void writeLong(String name, long val) throws IOException {
+ writeLong(name,Long.toString(val));
+ }
+
+
+ default void writeBool(String name, boolean val) throws IOException {
+ writeBool(name,Boolean.toString(val));
+ }
+
+
+ default void writeFloat(String name, float val) throws IOException {
+ String s = Float.toString(val);
+ // If it's not a normal number, write the value as a string instead.
+ // The following test also handles NaN since comparisons are always false.
+ if (val > Float.NEGATIVE_INFINITY && val < Float.POSITIVE_INFINITY) {
+ writeFloat(name,s);
+ } else {
+ writeStr(name,s,false);
+ }
+ }
+
+
+ default void writeDouble(String name, double val) throws IOException {
+ String s = Double.toString(val);
+ // If it's not a normal number, write the value as a string instead.
+ // The following test also handles NaN since comparisons are always false.
+ if (val > Double.NEGATIVE_INFINITY && val < Double.POSITIVE_INFINITY) {
+ writeDouble(name,s);
+ } else {
+ writeStr(name,s,false);
+ }
+ }
+ default void writeBool(String name , Boolean val) throws IOException {
+ writeBool(name, val.toString());
+ }
+
+ @Override
+ default void writeMap(MapWriter mw) throws IOException {
+ //todo
+ }
+
+ @Override
+ default void writeIterator(IteratorWriter iw) throws IOException {
+ /*todo*/
+ }
+ default void indent() throws IOException {
+ if (doIndent()) indent(level());
+ }
+ int incLevel();
+ int decLevel();
+ TextWriter setIndent(boolean doIndent);
+ int level();
+ boolean doIndent();
+ default void indent(int lev) throws IOException {
+ getWriter().write(SolrJSONWriter.indentChars, 0, Math.min((lev<<1)+1, SolrJSONWriter.indentChars.length));
+ }
+
+}