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 2015/06/16 13:28:53 UTC

svn commit: r1685764 - in /lucene/dev/branches/branch_5x/solr: ./ core/src/java/org/apache/solr/client/solrj/embedded/ core/src/java/org/apache/solr/response/ core/src/java/org/apache/solr/response/transform/ core/src/test/org/apache/solr/request/ core...

Author: noble
Date: Tue Jun 16 11:28:53 2015
New Revision: 1685764

URL: http://svn.apache.org/r1685764
Log:
SOLR-7662: Refactored response writing to consolidate the logic in  one place

Added:
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/DocsStreamer.java   (with props)
Removed:
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/ResponseWriterUtil.java
Modified:
    lucene/dev/branches/branch_5x/solr/CHANGES.txt
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/XMLWriter.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/request/TestBinaryResponseWriter.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/response/TestCustomDocTransformer.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java

Modified: lucene/dev/branches/branch_5x/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/CHANGES.txt?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/solr/CHANGES.txt Tue Jun 16 11:28:53 2015
@@ -138,6 +138,8 @@ Other Changes
 * SOLR-7680: Use POST instead of GET when finding versions for mismatches with
   CloudInspectUtil for tests (Ramkumar Aiyengar)
 
+* SOLR-7662: Refactored response writing to consolidate the logic in  one place (Noble Paul)
+
 ==================  5.2.1 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release
@@ -603,6 +605,8 @@ Other Changes
 * SOLR-7183: Fix Locale blacklisting for Minikdc based tests. (Ishan Chattopadhyaya, hossman
   via Anshum Gupta)
 
+* SOLR-7662: Refactored response writing to consolidate the logic in  one place (Noble Paul)
+
 ==================  5.1.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java Tue Jun 16 11:28:53 2015
@@ -222,7 +222,7 @@ public class EmbeddedSolrServer extends
               super.writeSolrDocumentList(docs);
             }
 
-          }.marshal(rsp.getValues(), out);
+          }.setWritableDocFields(resolver). marshal(rsp.getValues(), out);
 
           InputStream in = new ByteArrayInputStream(out.toByteArray());
           return (NamedList<Object>) new JavaBinCodec(resolver).unmarshal(in);

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java Tue Jun 16 11:28:53 2015
@@ -16,21 +16,25 @@
  */
 package org.apache.solr.response;
 
-import java.io.*;
-import java.util.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
-import org.apache.lucene.util.BytesRef;
 import org.apache.solr.client.solrj.impl.BinaryResponseParser;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.util.JavaBinCodec;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.transform.DocTransformer;
-import org.apache.solr.response.transform.TransformContext;
-import org.apache.solr.schema.*;
+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.search.SolrIndexSearcher;
@@ -41,15 +45,13 @@ import org.slf4j.LoggerFactory;
 
 public class BinaryResponseWriter implements BinaryQueryResponseWriter {
   private static final Logger LOG = LoggerFactory.getLogger(BinaryResponseWriter.class);
-  public static final Set<Class> KNOWN_TYPES = new HashSet<>();
 
   @Override
   public void write(OutputStream out, SolrQueryRequest req, SolrQueryResponse response) throws IOException {
     Resolver resolver = new Resolver(req, response.getReturnFields());
     Boolean omitHeader = req.getParams().getBool(CommonParams.OMIT_HEADER);
     if (omitHeader != null && omitHeader) response.getValues().remove("responseHeader");
-    JavaBinCodec codec = new JavaBinCodec(resolver);
-    codec.marshal(response.getValues(), out);
+    new JavaBinCodec(resolver).setWritableDocFields(resolver).marshal(response.getValues(), out);
   }
 
   @Override
@@ -67,16 +69,12 @@ public class BinaryResponseWriter implem
     /* NOOP */
   }
 
-  public static class Resolver implements JavaBinCodec.ObjectResolver {
+  public static class Resolver implements JavaBinCodec.ObjectResolver , JavaBinCodec.WritableDocFields {
     protected final SolrQueryRequest solrQueryRequest;
     protected IndexSchema schema;
     protected SolrIndexSearcher searcher;
     protected final ReturnFields returnFields;
 
-    // transmit field values using FieldType.toObject()
-    // rather than the String from FieldType.toExternal()
-    boolean useFieldObjects = true;
-
     public Resolver(SolrQueryRequest req, ReturnFields returnFields) {
       solrQueryRequest = req;
       this.returnFields = returnFields;
@@ -95,73 +93,35 @@ public class BinaryResponseWriter implem
         return null; // null means we completely handled it
       }
       if( o instanceof IndexableField ) {
-        if(schema == null) schema = solrQueryRequest.getSchema(); 
-        
+        if(schema == null) schema = solrQueryRequest.getSchema();
+
         IndexableField f = (IndexableField)o;
         SchemaField sf = schema.getFieldOrNull(f.name());
         try {
-          o = getValue(sf, f);
-        } 
-        catch (Exception e) {
+          o = DocsStreamer.getValue(sf, f);
+        } catch (Exception e) {
           LOG.warn("Error reading a field : " + o, e);
         }
       }
-      if (o instanceof SolrDocument) {
-        // Remove any fields that were not requested.
-        // This typically happens when distributed search adds 
-        // extra fields to an internal request
-        SolrDocument doc = (SolrDocument)o;
-        Iterator<Map.Entry<String, Object>> i = doc.iterator();
-        while ( i.hasNext() ) {
-          String fname = i.next().getKey();
-          if ( !returnFields.wantsField( fname ) ) {
-            i.remove();
-          }
-        }
-        return doc;
-      }
       return o;
     }
 
-    protected void writeResultsBody( ResultContext res, JavaBinCodec codec ) throws IOException 
-    {
-      DocList ids = res.docs;
-      int sz = ids.size();
-      codec.writeTag(JavaBinCodec.ARR, sz);
-      if(searcher == null) searcher = solrQueryRequest.getSearcher();
-      if(schema == null) schema = solrQueryRequest.getSchema();
-
-      DocTransformer transformer = returnFields.getTransformer();
-      TransformContext context = new TransformContext();
-      context.query = res.query;
-      context.wantsScores = returnFields.wantsScore() && ids.hasScores();
-      context.req = solrQueryRequest;
-      context.searcher = searcher;
-      if( transformer != null ) {
-        transformer.setContext( context );
-      }
-      
-      Set<String> fnames = returnFields.getLuceneFieldNames();
-      boolean onlyPseudoFields = (fnames == null && !returnFields.wantsAllFields() && !returnFields.hasPatternMatching())
-          || (fnames != null && fnames.size() == 1 && SolrReturnFields.SCORE.equals(fnames.iterator().next()));
-      context.iterator = ids.iterator();
-      for (int i = 0; i < sz; i++) {
-        int id = context.iterator.nextDoc();
-        SolrDocument sdoc;
-        if (onlyPseudoFields) {
-          // no need to get stored fields of the document, see SOLR-5968
-          sdoc = new SolrDocument();
-        } else {
-          Document doc = searcher.doc(id, fnames);
-          sdoc = getDoc(doc);
-        }
-        if( transformer != null ) {
-          transformer.transform(sdoc, id);
-        }
-        codec.writeSolrDocument(sdoc);
-      }
-      if( transformer != null ) {
-        transformer.setContext( null );
+    @Override
+    public boolean isWritable(String name) {
+      return returnFields.wantsField(name);
+    }
+
+    @Override
+    public boolean wantsAllFields() {
+      return returnFields.wantsAllFields();
+    }
+
+    protected void writeResultsBody( ResultContext res, JavaBinCodec codec ) throws IOException {
+      codec.writeTag(JavaBinCodec.ARR, res.docs.size());
+      DocsStreamer docStreamer = new DocsStreamer(res.docs,res.query, solrQueryRequest, returnFields);
+      while (docStreamer.hasNext()) {
+        SolrDocument doc = docStreamer.next();
+        codec.writeSolrDocument(doc);
       }
     }
     
@@ -178,7 +138,7 @@ public class BinaryResponseWriter implem
       }
       l.add(maxScore);
       codec.writeArray(l);
-      
+
       // this is a seprate function so that streaming responses can use just that part
       writeResultsBody( ctx, codec );
     }
@@ -193,7 +153,7 @@ public class BinaryResponseWriter implem
         SchemaField sf = schema.getFieldOrNull(fieldName);
         Object val = null;
         try {
-          val = getValue(sf,f);
+          val = DocsStreamer.getValue(sf,f);
         } catch (Exception e) {
           // There is a chance of the underlying field not really matching the
           // actual field type . So ,it can throw exception
@@ -212,30 +172,6 @@ public class BinaryResponseWriter implem
       }
       return solrDoc;
     }
-    
-    public Object getValue(SchemaField sf, IndexableField f) throws Exception {
-      FieldType ft = null;
-      if(sf != null) ft =sf.getType();
-      
-      if (ft == null) {  // handle fields not in the schema
-        BytesRef bytesRef = f.binaryValue();
-        if (bytesRef != null) {
-          if (bytesRef.offset == 0 && bytesRef.length == bytesRef.bytes.length) {
-            return bytesRef.bytes;
-          } else {
-            final byte[] bytes = new byte[bytesRef.length];
-            System.arraycopy(bytesRef.bytes, bytesRef.offset, bytes, 0, bytesRef.length);
-            return bytes;
-          }
-        } else return f.stringValue();
-      } else {
-        if (useFieldObjects && KNOWN_TYPES.contains(ft.getClass())) {
-          return ft.toObject(f);
-        } else {
-          return ft.toExternal(f);
-        }
-      }
-    }
   }
 
 
@@ -263,18 +199,5 @@ public class BinaryResponseWriter implem
     }
   }
 
-  static {
-    KNOWN_TYPES.add(BoolField.class);
-    KNOWN_TYPES.add(StrField.class);
-    KNOWN_TYPES.add(TextField.class);
-    KNOWN_TYPES.add(TrieField.class);
-    KNOWN_TYPES.add(TrieIntField.class);
-    KNOWN_TYPES.add(TrieLongField.class);
-    KNOWN_TYPES.add(TrieFloatField.class);
-    KNOWN_TYPES.add(TrieDoubleField.class);
-    KNOWN_TYPES.add(TrieDateField.class);
-    KNOWN_TYPES.add(BinaryField.class);
-    // We do not add UUIDField because UUID object is not a supported type in JavaBinCodec
-    // and if we write UUIDField.toObject, we wouldn't know how to handle it in the client side
-  }
+
 }

Added: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/DocsStreamer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/DocsStreamer.java?rev=1685764&view=auto
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/DocsStreamer.java (added)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/DocsStreamer.java Tue Jun 16 11:28:53 2015
@@ -0,0 +1,194 @@
+package org.apache.solr.response;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.transform.DocTransformer;
+import org.apache.solr.response.transform.TransformContext;
+import org.apache.solr.schema.BinaryField;
+import org.apache.solr.schema.BoolField;
+import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.schema.StrField;
+import org.apache.solr.schema.TextField;
+import org.apache.solr.schema.TrieDateField;
+import org.apache.solr.schema.TrieDoubleField;
+import org.apache.solr.schema.TrieField;
+import org.apache.solr.schema.TrieFloatField;
+import org.apache.solr.schema.TrieIntField;
+import org.apache.solr.schema.TrieLongField;
+import org.apache.solr.search.DocIterator;
+import org.apache.solr.search.DocList;
+import org.apache.solr.search.ReturnFields;
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.search.SolrReturnFields;
+
+/*
+ * This streams SolrDocuments from a DocList and applies transformer
+ */
+public class DocsStreamer implements Iterator<SolrDocument> {
+  private static final Set<Class> KNOWN_TYPES = new HashSet<>();
+  private final DocList docs;
+
+  private SolrIndexSearcher searcher;
+  private final IndexSchema schema;
+  private DocTransformer transformer;
+  private DocIterator docIterator;
+  private boolean onlyPseudoFields;
+  private Set<String> fnames;
+  private TransformContext context;
+  private int idx = -1;
+
+  public DocsStreamer(DocList docList, Query query, SolrQueryRequest req, ReturnFields returnFields) {
+    this.docs = docList;
+    this.schema = req.getSchema();
+    searcher = req.getSearcher();
+    transformer = returnFields.getTransformer();
+    docIterator = docList.iterator();
+    context = new TransformContext();
+    context.query = query;
+    context.wantsScores = returnFields.wantsScore() && docList.hasScores();
+    context.req = req;
+    context.searcher = searcher;
+    context.iterator = docIterator;
+    fnames = returnFields.getLuceneFieldNames();
+    onlyPseudoFields = (fnames == null && !returnFields.wantsAllFields() && !returnFields.hasPatternMatching())
+        || (fnames != null && fnames.size() == 1 && SolrReturnFields.SCORE.equals(fnames.iterator().next()));
+    if (transformer != null) transformer.setContext(context);
+  }
+
+  public boolean hasScores() {
+    return context.wantsScores;
+  }
+
+  public int currentIndex() {
+    return idx;
+  }
+
+  public boolean hasNext() {
+    return docIterator.hasNext();
+  }
+
+  public SolrDocument next() {
+    int id = docIterator.nextDoc();
+    idx++;
+    SolrDocument sdoc = null;
+
+    if (onlyPseudoFields) {
+      // no need to get stored fields of the document, see SOLR-5968
+      sdoc = new SolrDocument();
+    } else {
+      try {
+        Document doc = searcher.doc(id, fnames);
+        sdoc = getDoc(doc, schema);
+      } catch (IOException e) {
+        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error reading document with docId " + id, e);
+      }
+    }
+
+    if (transformer != null) {
+      try {
+        transformer.transform(sdoc, id);
+      } catch (IOException e) {
+        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error applying transformer", e);
+      }
+    }
+    return sdoc;
+
+  }
+
+  public static SolrDocument getDoc(Document doc, final IndexSchema schema) {
+    SolrDocument out = new SolrDocument();
+    for (IndexableField f : doc.getFields()) {
+      // Make sure multivalued fields are represented as lists
+      Object existing = out.get(f.name());
+      if (existing == null) {
+        SchemaField sf = schema.getFieldOrNull(f.name());
+        if (sf != null && sf.multiValued()) {
+          List<Object> vals = new ArrayList<>();
+          vals.add(f);
+          out.setField(f.name(), vals);
+        } else {
+          out.setField(f.name(), f);
+        }
+      } else {
+        out.addField(f.name(), f);
+      }
+    }
+    return out;
+  }
+
+  @Override
+  public void remove() { //do nothing
+  }
+
+  public static Object getValue(SchemaField sf, IndexableField f) {
+    FieldType ft = null;
+    if (sf != null) ft = sf.getType();
+
+    if (ft == null) {  // handle fields not in the schema
+      BytesRef bytesRef = f.binaryValue();
+      if (bytesRef != null) {
+        if (bytesRef.offset == 0 && bytesRef.length == bytesRef.bytes.length) {
+          return bytesRef.bytes;
+        } else {
+          final byte[] bytes = new byte[bytesRef.length];
+          System.arraycopy(bytesRef.bytes, bytesRef.offset, bytes, 0, bytesRef.length);
+          return bytes;
+        }
+      } else return f.stringValue();
+    } else {
+      if (KNOWN_TYPES.contains(ft.getClass())) {
+        return ft.toObject(f);
+      } else {
+        return ft.toExternal(f);
+      }
+    }
+  }
+
+
+  static {
+    KNOWN_TYPES.add(BoolField.class);
+    KNOWN_TYPES.add(StrField.class);
+    KNOWN_TYPES.add(TextField.class);
+    KNOWN_TYPES.add(TrieField.class);
+    KNOWN_TYPES.add(TrieIntField.class);
+    KNOWN_TYPES.add(TrieLongField.class);
+    KNOWN_TYPES.add(TrieFloatField.class);
+    KNOWN_TYPES.add(TrieDoubleField.class);
+    KNOWN_TYPES.add(TrieDateField.class);
+    KNOWN_TYPES.add(BinaryField.class);
+    // We do not add UUIDField because UUID object is not a supported type in JavaBinCodec
+    // and if we write UUIDField.toObject, we wouldn't know how to handle it in the client side
+  }
+
+}

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java Tue Jun 16 11:28:53 2015
@@ -332,10 +332,10 @@ class JSONWriter extends TextResponseWri
 
     boolean first=true;
     for (String fname : doc.getFieldNames()) {
-      if (!returnFields.wantsField(fname)) {
+      if (returnFields!= null && !returnFields.wantsField(fname)) {
         continue;
       }
-      
+
       if (first) {
         first=false;
       }
@@ -365,9 +365,8 @@ class JSONWriter extends TextResponseWri
       writeKey("_childDocuments_", true);
       writeArrayOpener(doc.getChildDocumentCount());
       List<SolrDocument> childDocs = doc.getChildDocuments();
-      ReturnFields rf = new SolrReturnFields();
       for(int i=0; i<childDocs.size(); i++) {
-        writeSolrDocument(null, childDocs.get(i), rf, i);
+        writeSolrDocument(null, childDocs.get(i), null, i);
       }
       writeArrayCloser();
     }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java Tue Jun 16 11:28:53 2015
@@ -118,7 +118,7 @@ class PHPSerializedWriter extends JSONWr
   }
   
   @Override
-  public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException 
+  public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException
   {
     writeKey(idx, false);
     
@@ -126,7 +126,7 @@ class PHPSerializedWriter extends JSONWr
     LinkedHashMap <String,Object> multi = new LinkedHashMap<>();
 
     for (String fname : doc.getFieldNames()) {
-      if(!returnFields.wantsField(fname)){
+      if (returnFields != null && !returnFields.wantsField(fname)) {
         continue;
       }
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java Tue Jun 16 11:28:53 2015
@@ -34,8 +34,6 @@ import org.apache.solr.schema.TrieDateFi
 import org.apache.solr.util.FastWriter;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.transform.DocTransformer;
-import org.apache.solr.response.transform.TransformContext;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.DocList;
@@ -157,17 +155,10 @@ public abstract class TextResponseWriter
     } else if (val instanceof Date) {
       writeDate(name,(Date)val);
     } else if (val instanceof Document) {
-      SolrDocument doc = toSolrDocument( (Document)val );
-      DocTransformer transformer = returnFields.getTransformer();
-      if( transformer != null ) {
-        TransformContext context = new TransformContext();
-        context.req = req;
-        transformer.setContext(context);
-        transformer.transform(doc, -1);
-      }
-      writeSolrDocument(name, doc, returnFields, 0 );
+      SolrDocument doc = DocsStreamer.getDoc((Document) val, schema);
+      writeSolrDocument(name, doc,returnFields, 0 );
     } else if (val instanceof SolrDocument) {
-      writeSolrDocument(name, (SolrDocument)val, returnFields, 0);
+      writeSolrDocument(name, (SolrDocument)val,returnFields, 0);
     } else if (val instanceof ResultContext) {
       // requires access to IndexReader
       writeDocuments(name, (ResultContext)val, returnFields);
@@ -217,7 +208,7 @@ public abstract class TextResponseWriter
 
   public abstract void writeStartDocumentList(String name, long start, int size, long numFound, Float maxScore) throws IOException;  
 
-  public abstract void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException;  
+  public abstract void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException;
   
   public abstract void writeEndDocumentList() throws IOException;
   
@@ -231,39 +222,14 @@ public abstract class TextResponseWriter
     writeEndDocumentList();
   }
 
-  public final SolrDocument toSolrDocument( Document doc ) 
-  {
-    return ResponseWriterUtil.toSolrDocument(doc, schema);
-  }
-  
   public final void writeDocuments(String name, ResultContext res, ReturnFields fields ) throws IOException {
     DocList ids = res.docs;
-    TransformContext context = new TransformContext();
-    context.query = res.query;
-    context.wantsScores = fields.wantsScore() && ids.hasScores();
-    context.req = req;
-    writeStartDocumentList(name, ids.offset(), ids.size(), ids.matches(), 
-        context.wantsScores ? new Float(ids.maxScore()) : null );
-    
-    DocTransformer transformer = fields.getTransformer();
-    context.searcher = req.getSearcher();
-    context.iterator = ids.iterator();
-    if( transformer != null ) {
-      transformer.setContext( context );
-    }
-    int sz = ids.size();
-    Set<String> fnames = fields.getLuceneFieldNames();
-    for (int i=0; i<sz; i++) {
-      int id = context.iterator.nextDoc();
-      Document doc = context.searcher.doc(id, fnames);
-      SolrDocument sdoc = toSolrDocument( doc );
-      if( transformer != null ) {
-        transformer.transform( sdoc, id);
-      }
-      writeSolrDocument( null, sdoc, returnFields, i );
-    }
-    if( transformer != null ) {
-      transformer.setContext( null );
+    DocsStreamer docsStreamer = new DocsStreamer(res.docs,res.query, req, fields);
+    writeStartDocumentList(name, ids.offset(), ids.size(), ids.matches(),
+        docsStreamer.hasScores() ? new Float(ids.maxScore()) : null);
+
+    while (docsStreamer.hasNext()) {
+      writeSolrDocument(null, docsStreamer.next(), returnFields, docsStreamer.currentIndex());
     }
     writeEndDocumentList();
   }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/XMLWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/XMLWriter.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/XMLWriter.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/XMLWriter.java Tue Jun 16 11:28:53 2015
@@ -191,10 +191,10 @@ public class XMLWriter extends TextRespo
     incLevel();
 
     for (String fname : doc.getFieldNames()) {
-      if (!returnFields.wantsField(fname)) {
+      if (returnFields!= null && !returnFields.wantsField(fname)) {
         continue;
       }
-      
+
       Object val = doc.getFieldValue(fname);
       if( "_explain_".equals( fname ) ) {
         System.out.println( val );

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java Tue Jun 16 11:28:53 2015
@@ -32,7 +32,7 @@ import org.apache.solr.common.SolrExcept
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.ResponseWriterUtil;
+import org.apache.solr.response.DocsStreamer;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
@@ -140,7 +140,7 @@ class ChildDocTransformer extends Transf
         while(i.hasNext()) {
           Integer childDocNum = i.next();
           Document childDoc = context.searcher.doc(childDocNum);
-          SolrDocument solrChildDoc = ResponseWriterUtil.toSolrDocument(childDoc, schema);
+          SolrDocument solrChildDoc = DocsStreamer.getDoc(childDoc, schema);
 
           // TODO: future enhancement...
           // support an fl local param in the transformer, which is used to build

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/response/transform/DocTransformer.java Tue Jun 16 11:28:53 2015
@@ -21,7 +21,6 @@ import java.io.IOException;
 
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.response.QueryResponseWriter;
-import org.apache.solr.response.ResponseWriterUtil;
 import org.apache.solr.search.SolrIndexSearcher;
 
 /**

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/request/TestBinaryResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/request/TestBinaryResponseWriter.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/request/TestBinaryResponseWriter.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/request/TestBinaryResponseWriter.java Tue Jun 16 11:28:53 2015
@@ -19,6 +19,7 @@ package org.apache.solr.request;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.Locale;
+import java.util.Map;
 import java.util.UUID;
 
 import org.apache.solr.common.SolrDocument;
@@ -89,7 +90,11 @@ public class TestBinaryResponseWriter ex
     assertNotNull("obj is null", o);
     assertTrue("obj is not doc", o instanceof SolrDocument);
 
-    SolrDocument out = (SolrDocument) o;
+    SolrDocument out = new SolrDocument();
+    for (Map.Entry<String, Object> e : in) {
+      if(r.isWritable(e.getKey())) out.put(e.getKey(),e.getValue());
+
+    }
     assertTrue("id not found", out.getFieldNames().contains("id"));
     assertTrue("ddd_s not found", out.getFieldNames().contains("ddd_s"));
     assertEquals("Wrong number of fields found", 

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/response/TestCustomDocTransformer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/response/TestCustomDocTransformer.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/response/TestCustomDocTransformer.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/response/TestCustomDocTransformer.java Tue Jun 16 11:28:53 2015
@@ -19,6 +19,8 @@ package org.apache.solr.response;
 
 import java.io.IOException;
 
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrInputDocument;
@@ -108,11 +110,21 @@ public class TestCustomDocTransformer ex
     public void transform(SolrDocument doc, int docid) throws IOException {
       str.setLength(0);
       for(String s : extra) {
-        String v = ResponseWriterUtil.getAsString(s, doc);
+        String v = getAsString(s, doc);
         str.append(v).append('#');
       }
       System.out.println( "HELLO: "+str );
       doc.setField(name, str.toString());
     }
   }
+  public static String getAsString(String field, SolrDocument doc) {
+    Object v = doc.getFirstValue(field);
+    if(v != null) {
+      if(v instanceof IndexableField) {
+        return ((IndexableField)v).stringValue();
+      }
+      return v.toString();
+    }
+    return null;
+  }
 }

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java?rev=1685764&r1=1685763&r2=1685764&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java (original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java Tue Jun 16 11:28:53 2015
@@ -79,16 +79,24 @@ public class JavaBinCodec {
 
 
   private static byte VERSION = 2;
-  private ObjectResolver resolver;
+  private final ObjectResolver resolver;
   protected FastOutputStream daos;
   private StringCache stringCache;
+  private WritableDocFields writableDocFields;
 
   public JavaBinCodec() {
+    resolver =null;
+    writableDocFields =null;
   }
 
   public JavaBinCodec(ObjectResolver resolver) {
     this(resolver, null);
   }
+  public JavaBinCodec setWritableDocFields(WritableDocFields writableDocFields){
+    this.writableDocFields = writableDocFields;
+    return this;
+
+  }
 
   public JavaBinCodec(ObjectResolver resolver, StringCache stringCache) {
     this.resolver = resolver;
@@ -272,18 +280,7 @@ public class JavaBinCodec {
     }
     if (val instanceof SolrDocument) {
       //this needs special treatment to know which fields are to be written
-      if (resolver == null) {
-        writeSolrDocument((SolrDocument) val);
-      } else {
-        Object retVal = resolver.resolve(val, this);
-        if (retVal != null) {
-          if (retVal instanceof SolrDocument) {
-            writeSolrDocument((SolrDocument) retVal);
-          } else {
-            writeVal(retVal);
-          }
-        }
-      }
+      writeSolrDocument((SolrDocument) val);
       return true;
     }
     if (val instanceof SolrInputDocument) {
@@ -344,14 +341,24 @@ public class JavaBinCodec {
 
   public void writeSolrDocument(SolrDocument doc) throws IOException {
     List<SolrDocument> children = doc.getChildDocuments();
-    int sz = doc.size() + (children==null ? 0 : children.size());
+    int fieldsCount = 0;
+    if(writableDocFields == null || writableDocFields.wantsAllFields()){
+      fieldsCount = doc.size();
+    } else {
+      for (Entry<String, Object> e : doc) {
+        if(writableDocFields.isWritable(e.getKey())) fieldsCount++;
+      }
+    }
+    int sz = fieldsCount + (children==null ? 0 : children.size());
     writeTag(SOLRDOC);
     writeTag(ORDERED_MAP, sz);
     for (Map.Entry<String, Object> entry : doc) {
       String name = entry.getKey();
-      writeExternString(name);
-      Object val = entry.getValue();
-      writeVal(val);
+      if(writableDocFields == null || writableDocFields.isWritable(name)) {
+        writeExternString(name);
+        Object val = entry.getValue();
+        writeVal(val);
+      }
     }
     if (children != null) {
       for (SolrDocument child : children) {
@@ -841,6 +848,12 @@ public class JavaBinCodec {
     public Object resolve(Object o, JavaBinCodec codec) throws IOException;
   }
 
+  public interface WritableDocFields {
+    public boolean isWritable(String name);
+    public boolean wantsAllFields();
+  }
+
+
   public static class StringCache {
     private final Cache<StringBytes, String> cache;