/*
 *
 *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
 *  *
 *  *  Licensed 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.
 *  *
 *  * For more information: http://www.orientechnologies.com
 *
 */
package com.orientechnologies.orient.server.network.protocol.http;

import com.orientechnologies.common.collection.OMultiValue;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.serialization.serializer.OJSONWriter;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.impls.orient.OrientEdge;
import com.tinkerpop.blueprints.impls.orient.OrientGraphNoTx;
import com.tinkerpop.blueprints.impls.orient.OrientVertex;

import java.io.IOException;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Graph wrapper to format the response as graph.
 *
 * @author Luca Garulli
 */
public class OHttpGraphResponse extends OHttpResponse {
  public OHttpGraphResponse(final OHttpResponse iWrapped) {
    super(iWrapped.getOutputStream(), iWrapped.httpVersion, iWrapped.additionalHeaders, iWrapped.characterSet, iWrapped.serverInfo,
        iWrapped.sessionId, iWrapped.callbackFunction, iWrapped.keepAlive, iWrapped.connection);
  }

  public void writeRecords(final Object iRecords, final String iFetchPlan, String iFormat, final String accept,
      final Map<String, Object> iAdditionalProperties, final String mode) throws IOException {
    if (iRecords == null)
      return;

    if (!mode.equalsIgnoreCase("graph")) {
      super.writeRecords(iRecords, iFetchPlan, iFormat, accept, iAdditionalProperties, mode);
      return;
    }

    if (accept != null && accept.contains("text/csv"))
      throw new IllegalArgumentException("Graph mode cannot accept '" + accept + "'");

    final OrientGraphNoTx graph = new OrientGraphNoTx((ODatabaseDocumentTx) ODatabaseRecordThreadLocal.INSTANCE.get());

    // DIVIDE VERTICES FROM EDGES
    final Set<OrientVertex> vertices = new HashSet<OrientVertex>();
    final Set<OrientEdge> edges = new HashSet<OrientEdge>();

    final Iterator<Object> iIterator = OMultiValue.getMultiValueIterator(iRecords);
    while (iIterator.hasNext()) {
      Object entry = iIterator.next();
      if (entry == null || !(entry instanceof OIdentifiable))
        // IGNORE IT
        continue;

      if (entry instanceof ODocument)
        if (((ODocument) entry).getSchemaClass().isVertexType())
          vertices.add(graph.getVertex(entry));
        else if (((ODocument) entry).getSchemaClass().isEdgeType())
          edges.add(graph.getEdge(entry));
        else
          // IGNORE IT
          continue;
    }

    final StringWriter buffer = new StringWriter();
    final OJSONWriter json = new OJSONWriter(buffer, "");
    json.beginObject();
    json.beginObject("graph");

    // WRITE VERTICES
    json.beginCollection("vertices");
    for (OrientVertex vertex : vertices) {
      json.beginObject();

      json.writeAttribute("@rid", vertex.getIdentity());
      json.writeAttribute("@class", vertex.getRecord().getClassName());

      // ADD ALL THE VERTEX'S EDGES
      for (Edge e : vertex.getEdges(Direction.BOTH))
        edges.add((OrientEdge) e);

      // ADD ALL THE PROPERTIES
      for (String field : vertex.getPropertyKeys()) {
        final Object v = vertex.getProperty(field);
        if (v != null)
          json.writeAttribute(field, v);
      }
      json.endObject();
    }
    json.endCollection();

    // WRITE EDGES
    json.beginCollection("edges");
    for (OrientEdge edge : edges) {
      if (!vertices.contains(edge.getVertex(Direction.OUT)) || !vertices.contains(edge.getVertex(Direction.IN)))
        // ONE OF THE 2 VERTICES ARE NOT PART OF THE RESULT SET: DISCARD IT
        continue;

      json.beginObject();
      json.writeAttribute("@rid", edge.getIdentity());
      json.writeAttribute("@class", edge.getRecord().getClassName());

      json.writeAttribute("from", edge.getVertex(Direction.IN).getId());
      json.writeAttribute("to", edge.getVertex(Direction.OUT).getId());

      for (String field : edge.getPropertyKeys()) {
        final Object v = edge.getProperty(field);
        if (v != null)
          json.writeAttribute(field, v);
      }

      json.endObject();
    }
    json.endCollection();

    if (iAdditionalProperties != null) {
      for (Map.Entry<String, Object> entry : iAdditionalProperties.entrySet()) {

        final Object v = entry.getValue();
        if (OMultiValue.isMultiValue(v)) {
          json.beginCollection(-1, true, entry.getKey());
          formatMultiValue(OMultiValue.getMultiValueIterator(v), buffer, null);
          json.endCollection(-1, true);
        } else
          json.writeAttribute(entry.getKey(), v);

        if (Thread.currentThread().isInterrupted())
          break;

      }
    }

    json.endObject();
    json.endObject();

    send(OHttpUtils.STATUS_OK_CODE, "OK", OHttpUtils.CONTENT_JSON, buffer.toString(), null);
  }
}

@@ -4833,18 +4833,19 @@
 rection.
-IN
+OUT
 ).getId(
@@ -4897,35 +4897,34 @@
 ertex(Direction.
-OUT
+IN
 ).getId());%0A%0A   

Fix Graph HTTP result set (OHttpGraphResponse)