package com.tinkerpop.gremlin.server;

import com.tinkerpop.blueprints.util.StreamFactory;
import com.tinkerpop.gremlin.server.util.ser.ToStringResultSerializer;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.stream.Stream;

/**
 * Serializes a single result from the ScripEngine.  Typically this will be an item from an iterator.  ResultSerializer
 * instances are instantiated to a cache via ServiceLoader and indexed based on the mime types they support.  If
 * a mime type is supported more than once the last ResultSerializer instance loaded for that mime type is assigned.
 * If a mime type is not found the default ToStringResultSerializer is used to return the results.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
public interface ResultSerializer {
    /**
     * Map of serializers to mime types.
     */
    static final Map<String, ResultSerializer> resultSerializers = new HashMap<String, ResultSerializer>(){{
        final ServiceLoader<ResultSerializer> serviceLoader = ServiceLoader.load(ResultSerializer.class);
        StreamFactory.stream(serviceLoader.iterator()).flatMap(serializer->
                Stream.of(serializer.mimeTypesSupported()).map(mimeType->Arrays.asList(mimeType, serializer))
        ).forEach(l -> put(l.get(0).toString(), (ResultSerializer) l.get(1)));
    }};

    /**
     * Default serializer.
     */
    static final ToStringResultSerializer TO_STRING_RESULT_SERIALIZER = new ToStringResultSerializer();

    /**
     * Serialize a result with a SUCCESS result code.
     */
    public default String serialize(final Object o, final Context context) {
        return this.serialize(o, ResultCode.SUCCESS, context);
    }

    /**
     * Serialize a result.
     * @param o the result
     * @param code the response code
     * @param context the context of the server and request
     * @return the result serialized to a String
     */
    public String serialize(final Object o, final ResultCode code, final Context context);

    /**
     * The list of mime types that the serializer supports.
     */
    public String[] mimeTypesSupported();

    /**
     * Choose a serializer based on the "accept" argument on the message, where "accept" is a mime type.
     */
    public static ResultSerializer select(final String accept) {
        return resultSerializers.getOrDefault(accept, TO_STRING_RESULT_SERIALIZER);
    }
}

@@ -341,19 +341,28 @@
 the 
+%7B@code 
 Scrip
+t
 Engine
+%7D
 .  T
@@ -402,20 +402,48 @@
 m an
- i
+%0A * %7B@link java.util.I
 terator
+%7D
 .  
+%7B@link 
 Resu
@@ -454,19 +454,17 @@
 rializer
-%0A *
+%7D
  instanc
@@ -497,16 +497,26 @@
 ache via
+%0A * %7B@link
  Service
@@ -521,16 +521,17 @@
 ceLoader
+%7D
  and ind
@@ -576,19 +576,16 @@
 ort.  If
-%0A *
  a mime 
@@ -615,13 +615,17 @@
 than
+%0A *
  once
+,
  the
@@ -630,16 +630,23 @@
 he last 
+%7B@link 
 ResultSe
@@ -653,16 +653,17 @@
 rializer
+%7D
  instanc
@@ -702,19 +702,16 @@
 ssigned.
-%0A *
  If a mi
@@ -724,16 +724,19 @@
 e is not
+%0A *
  found t
@@ -746,16 +746,23 @@
 default 
+%7B@link 
 ToString
@@ -777,16 +777,17 @@
 rializer
+%7D
  is used
@@ -960,16 +960,260 @@
 e types.
+ Initialize %7B@link ResultSerializer%7D instances with %7B@link ServiceLoader%7D%0A     * invoking %7B@link #mimeTypesSupported()%7D and mapping each mime type returned in that array back to the associated%0A     * %7B@link ResultSerializer%7D in the @%7Blink Map%7D,
 %0A     */
@@ -1891,23 +1891,42 @@
  with a 
+%7B@link ResultCode#
 SUCCESS
+%7D
  result 
@@ -2121,16 +2121,23 @@
 result.%0A
+     *%0A
      * @

Add javadoc for Gremlin Server.