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 2020/07/13 01:32:11 UTC

[lucene-solr] branch branch_8x updated: SOLR-11262: XML writer implements writeMap and writeIterator (#1665)

This is an automated email from the ASF dual-hosted git repository.

noble pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/branch_8x by this push:
     new 84f1d0b  SOLR-11262: XML writer implements writeMap and writeIterator (#1665)
84f1d0b is described below

commit 84f1d0b4da5a1b7f019e8c02e9a9b2858508b185
Author: S N Munendra <mu...@apache.org>
AuthorDate: Mon Jul 13 06:51:14 2020 +0530

    SOLR-11262: XML writer implements writeMap and writeIterator (#1665)
---
 solr/CHANGES.txt                                   |  1 +
 .../java/org/apache/solr/response/XMLWriter.java   | 46 +++++++++++++++
 .../org/apache/solr/response/TestPushWriter.java   | 66 +++++++++++++++++-----
 .../org/apache/solr/common/util/TextWriter.java    | 13 ++++-
 4 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 4c85a585..9888831 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -25,6 +25,7 @@ Improvements
 
 * SOLR-14635: ThreadDumpHandler has been enhanced to show lock ownership (hossman)
 
+* SOLR-11262: Implement writeMap and writeIterator in XMLWriter (yonik, Munendra S N)
 
 Optimizations
 ---------------------
diff --git a/solr/core/src/java/org/apache/solr/response/XMLWriter.java b/solr/core/src/java/org/apache/solr/response/XMLWriter.java
index 4e1f0a1..35aa8f1 100644
--- a/solr/core/src/java/org/apache/solr/response/XMLWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/XMLWriter.java
@@ -23,6 +23,8 @@ import java.util.Iterator;
 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.SolrException;
 import org.apache.solr.common.params.CommonParams;
@@ -265,6 +267,28 @@ public class XMLWriter extends TextResponseWriter {
   }
 
   @Override
+  public void writeMap(String name, MapWriter val) throws IOException {
+    // As the size is not known. So, always both startTag and endTag is written
+    // irrespective of number of entries in MapWriter
+    startTag("lst", name, false);
+    incLevel();
+
+    val.writeMap(new MapWriter.EntryWriter() {
+      @Override
+      public MapWriter.EntryWriter put(CharSequence k, Object v) throws IOException {
+        writeVal( null == k ? null : k.toString(), v);
+        return this;
+      }
+    });
+
+    decLevel();
+    if (doIndent) {
+      indent();
+    }
+    writer.write("</lst>");
+  }
+
+  @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public void writeMap(String name, @SuppressWarnings({"rawtypes"})Map map, boolean excludeOuter, boolean isFirstVal) throws IOException {
     int sz = map.size();
@@ -312,6 +336,28 @@ public class XMLWriter extends TextResponseWriter {
     }
   }
 
+  @Override
+  public void writeIterator(String name, IteratorWriter val) throws IOException {
+    // As the size is not known. So, always both startTag and endTag is written
+    // irrespective of number of entries in IteratorWriter
+    startTag("arr", name, false );
+    incLevel();
+
+    val.writeIter(new IteratorWriter.ItemWriter() {
+      @Override
+      public IteratorWriter.ItemWriter add(Object o) throws IOException {
+        writeVal(null, o);
+        return this;
+      }
+    });
+
+    decLevel();
+    if (doIndent) {
+      indent();
+    }
+    writer.write("</arr>");
+  }
+
   //
   // Primitive types
   //
diff --git a/solr/core/src/test/org/apache/solr/response/TestPushWriter.java b/solr/core/src/test/org/apache/solr/response/TestPushWriter.java
index 3fb32f4..6281e0f 100644
--- a/solr/core/src/test/org/apache/solr/response/TestPushWriter.java
+++ b/solr/core/src/test/org/apache/solr/response/TestPushWriter.java
@@ -18,7 +18,6 @@
 package org.apache.solr.response;
 
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
@@ -32,8 +31,10 @@ import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.PushWriter;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.JavaBinCodec;
+import org.apache.solr.common.util.TextWriter;
 import org.apache.solr.common.util.Utils;
 import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.util.BaseTestHarness;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,29 +44,51 @@ public class TestPushWriter extends SolrTestCaseJ4 {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
 
+  @SuppressWarnings({"unchecked"})
   public void testStandardResponse() throws IOException {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    OutputStreamWriter osw = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
-    PushWriter pw = new JSONWriter(osw,
-        new LocalSolrQueryRequest(null, new ModifiableSolrParams()), new SolrQueryResponse());
-    writeData(pw);
-    osw.flush();
-    if (log.isInfoEnabled()) {
-      log.info("{}", new String(baos.toByteArray(), StandardCharsets.UTF_8));
+    Map<Object, Object> m;
+    try (OutputStreamWriter osw = new OutputStreamWriter(baos, StandardCharsets.UTF_8)) {
+      JSONWriter pw = new JSONWriter(osw,
+          new LocalSolrQueryRequest(null, new ModifiableSolrParams()), new SolrQueryResponse());
+      writeData(null, pw);
+      osw.flush();
+      if (log.isInfoEnabled()) {
+        log.info("{}", new String(baos.toByteArray(), StandardCharsets.UTF_8));
+      }
+      m = (Map<Object, Object>) Utils.fromJSON(baos.toByteArray());
+      checkValues(m);
     }
-    @SuppressWarnings({"rawtypes"})
-    Map m = (Map) Utils.fromJSON(baos.toByteArray());
-    checkValues(m);
+
     try (JavaBinCodec jbc = new JavaBinCodec(baos= new ByteArrayOutputStream(), null)) {
       writeData(jbc);
-      try (JavaBinCodec jbcUn = new JavaBinCodec()) {
-        m = (Map) jbcUn.unmarshal(new ByteArrayInputStream(baos.toByteArray()));
-      }
+      m = (Map<Object, Object>) Utils.fromJavabin(baos.toByteArray());
     }
     checkValues(m);
   }
 
-  protected void checkValues(@SuppressWarnings({"rawtypes"})Map m) {
+  public void testXmlWriter() throws Exception {
+    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        OutputStreamWriter osw = new OutputStreamWriter(baos, StandardCharsets.UTF_8)) {
+      XMLWriter xml = new XMLWriter(osw,
+          new LocalSolrQueryRequest(null, new ModifiableSolrParams()), new SolrQueryResponse());
+      writeData(null, xml);
+      osw.flush();
+      if (log.isInfoEnabled()) {
+        log.info("{}", new String(baos.toByteArray(), StandardCharsets.UTF_8));
+      }
+      String response = new String(baos.toByteArray(), StandardCharsets.UTF_8);
+      BaseTestHarness.validateXPath(response,
+          "/lst/lst[@name='responseHeader']/int[@name='status'][.=1]",
+          "/lst/lst[@name='response']/int[@name=numFound][.=10]",
+          "/lst/lst[@name='response']/arr[@name='docs'][0]/lst/int[@name='id'][.=1]",
+          "/lst/lst[@name='response']/arr[@name='docs'][1]/lst/int[@name='id'][.=2]",
+          "/lst/lst[@name='response']/arr[@name='docs'][2]/lst/int[@name='id'][.=3]"
+      );
+    }
+  }
+
+  protected void checkValues(Map<Object, Object> m) {
     assertEquals(0, ((Number)Utils.getObjectByPath(m, true, "responseHeader/status")).intValue());
     assertEquals(10, ((Number)Utils.getObjectByPath(m, true, "response/numFound")).intValue());
     assertEquals(1, ((Number)Utils.getObjectByPath(m, true, "response/docs[0]/id")).intValue());
@@ -85,4 +108,17 @@ public class TestPushWriter extends SolrTestCaseJ4 {
                 }); }); });
     pw.close();
   }
+
+  protected void writeData(String name, TextWriter pw) throws IOException {
+    pw.writeMap(name, m -> {
+      m.put("responseHeader", singletonMap("status", 0))
+          .put("response", (MapWriter) m1 -> {
+            m1.put("numFound", 10)
+                .put("docs", (IteratorWriter) w -> {
+                  w.add((MapWriter) m3 -> m3.put("id", 1))
+                      .add(singletonMap("id", 2))
+                      .add(singletonMap("id", 3));
+                }); }); });
+    pw.close();
+  }
 }
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
index bb39756..f6b2c9e 100644
--- a/solr/solrj/src/java/org/apache/solr/common/util/TextWriter.java
+++ b/solr/solrj/src/java/org/apache/solr/common/util/TextWriter.java
@@ -64,9 +64,9 @@ public interface TextWriter extends PushWriter {
     } else if (val instanceof Path) {
       writeStr(name, ((Path) val).toAbsolutePath().toString(), true);
     } else if (val instanceof IteratorWriter) {
-      writeIterator((IteratorWriter) val);
+      writeIterator(name, (IteratorWriter) val);
     } else if (val instanceof MapWriter) {
-      writeMap((MapWriter) val);
+      writeMap(name, (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);
@@ -212,10 +212,19 @@ public interface TextWriter extends PushWriter {
     //todo
   }
 
+  default void writeMap(String name, MapWriter mw) throws IOException {
+    writeMap(mw);
+  }
+
   @Override
   default void writeIterator(IteratorWriter iw) throws IOException {
     /*todo*/
   }
+
+  default void writeIterator(String name, IteratorWriter iw) throws IOException {
+    writeIterator(iw);
+  }
+
   default void indent() throws IOException {
     if (doIndent()) indent(level());
   }