All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.arcadedb.server.http.handler.AbstractQueryHandler Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 2021-present Arcade Data Ltd ([email protected])
 *
 * 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.
 *
 * SPDX-FileCopyrightText: 2021-present Arcade Data Ltd ([email protected])
 * SPDX-License-Identifier: Apache-2.0
 */
package com.arcadedb.server.http.handler;

import com.arcadedb.database.Database;
import com.arcadedb.database.Document;
import com.arcadedb.database.Identifiable;
import com.arcadedb.database.RID;
import com.arcadedb.exception.RecordNotFoundException;
import com.arcadedb.graph.Edge;
import com.arcadedb.graph.Vertex;
import com.arcadedb.log.LogManager;
import com.arcadedb.query.sql.executor.Result;
import com.arcadedb.query.sql.executor.ResultSet;
import com.arcadedb.schema.DocumentType;
import com.arcadedb.schema.LocalEdgeType;
import com.arcadedb.schema.LocalVertexType;
import com.arcadedb.serializer.JsonGraphSerializer;
import com.arcadedb.serializer.JsonSerializer;
import com.arcadedb.serializer.json.JSONArray;
import com.arcadedb.serializer.json.JSONObject;
import com.arcadedb.server.http.HttpServer;

import java.util.*;
import java.util.logging.*;
import java.util.stream.*;

public abstract class AbstractQueryHandler extends DatabaseAbstractHandler {

  protected static final int DEFAULT_LIMIT = 20_000;

  public AbstractQueryHandler(final HttpServer httpServer) {
    super(httpServer);
  }

  protected void serializeResultSet(final Database database, final String serializer, final int limit, final JSONObject response,
      final ResultSet qResult) {
    if (qResult == null)
      return;

    switch (serializer) {
    case "graph": {
      // SERIALIZES THE GRAPH ELEMENTS IN VERTICES AND EDGES
      final JsonGraphSerializer serializerImpl = new JsonGraphSerializer().setExpandVertexEdges(false);
      serializerImpl.setUseCollectionSize(false).setUseCollectionSizeForEdges(true);

      final Set includedVertices = new HashSet<>();
      final Set includedEdges = new HashSet<>();
      final JSONArray vertices = new JSONArray();
      final JSONArray edges = new JSONArray();

      while (qResult.hasNext()) {
        final Result row = qResult.next();

        if (row.isVertex()) {
          final Vertex v = row.getVertex().get();
          if (includedVertices.add(v.getIdentity()))
            vertices.put(serializerImpl.serializeGraphElement(v));
        } else if (row.isEdge()) {
          final Edge e = row.getEdge().get();
          if (includedEdges.add(e.getIdentity()))
            edges.put(serializerImpl.serializeGraphElement(e));
        } else {
          analyzeResultContent(database, serializerImpl, includedVertices, includedEdges, vertices, edges, row, limit);
        }

        if (limit > 0 && vertices.length() + edges.length() >= limit)
          break;
      }

      response.put("result", new JSONObject().put("vertices", vertices).put("edges", edges));
      break;
    }

    case "studio": {
      // USE BY STUDIO TO RENDER GRAPH AND TABLE AT THE SAME TIME
      final JsonGraphSerializer serializerImpl = new JsonGraphSerializer().setExpandVertexEdges(false);
      serializerImpl.setUseCollectionSize(false).setUseCollectionSizeForEdges(true);

      final Set includedRecords = new HashSet<>();
      final Set includedVertices = new HashSet<>();
      final Set includedEdges = new HashSet<>();
      final JSONArray vertices = new JSONArray();
      final JSONArray edges = new JSONArray();
      final JSONArray records = new JSONArray();

      if (qResult != null) {
        while (qResult.hasNext()) {
          final Result row = qResult.next();

          boolean recordIncluded = true;
          if (!row.getIdentity().isEmpty()) {
            final RID rid = row.getIdentity().get();
            recordIncluded = includedRecords.add(rid);
            if (recordIncluded)
              records.put(serializerImpl.serializeResult(database, row));
          } else
            records.put(serializerImpl.serializeResult(database, row));

          if (row.isVertex()) {
            if (recordIncluded) {
              final Vertex v = row.getVertex().get();
              if (includedVertices.add(v.getIdentity()))
                vertices.put(serializerImpl.serializeGraphElement(v));
            }
          } else if (row.isEdge()) {
            final Edge e = row.getEdge().get();
            if (recordIncluded)
              if (includedEdges.add(e.getIdentity())) {
                edges.put(serializerImpl.serializeGraphElement(e));
                try {
                  if (includedVertices.add(e.getIn())) {
                    includedRecords.add(e.getIn());
                    vertices.put(serializerImpl.serializeGraphElement(e.getInVertex()));
                  }
                  if (includedVertices.add(e.getOut())) {
                    includedRecords.add(e.getOut());
                    vertices.put(serializerImpl.serializeGraphElement(e.getOutVertex()));
                  }
                } catch (RecordNotFoundException ex) {
                  LogManager.instance().log(this, Level.SEVERE, "Record %s not found during serialization", ex.getRID());
                }
              }
          } else {
            analyzeResultContent(database, serializerImpl, includedVertices, includedEdges, vertices, edges, row, limit);
          }

          if (limit > 0 && records.length() >= limit)
            break;
        }
      }

      // FILTER OUT NOT CONNECTED EDGES
      for (final Identifiable entry : includedVertices) {
        if (limit > 0 && vertices.length() + edges.length() >= limit)
          break;

        try {
          final Vertex vertex = entry.asVertex(true);

          final Iterable vEdgesOut = vertex.getEdges(Vertex.DIRECTION.OUT);
          for (final Edge e : vEdgesOut) {
            if (includedVertices.contains(e.getIn()) && !includedEdges.contains(e.getIdentity()))
              edges.put(serializerImpl.serializeGraphElement(e));
          }

          final Iterable vEdgesIn = vertex.getEdges(Vertex.DIRECTION.IN);
          for (final Edge e : vEdgesIn) {
            if (includedVertices.contains(e.getOut()) && !includedEdges.contains(e.getIdentity()))
              edges.put(serializerImpl.serializeGraphElement(e));
          }
        } catch (RecordNotFoundException e) {
          LogManager.instance().log(this, Level.SEVERE, "Vertex %s not found during serialization", e.getRID());
        }
      }

      response.put("result", new JSONObject().put("vertices", vertices).put("edges", edges).put("records", records));
      break;
    }

    case "record": {
      final JsonSerializer serializerImpl = new JsonSerializer().setIncludeVertexEdges(false).setUseCollectionSize(false)
          .setUseCollectionSizeForEdges(false);
      final JSONArray result = new JSONArray();
      while (qResult.hasNext()) {
        final Result r = qResult.next();
        result.put(serializerImpl.serializeResult(database, r));
        if (limit > 0 && result.length() >= limit)
          break;
      }
      response.put("result", result);
      break;
    }

    default: {
      final JsonSerializer serializerImpl = new JsonSerializer().setIncludeVertexEdges(true).setUseCollectionSize(false)
          .setUseCollectionSizeForEdges(false);
      final JSONArray result = new JSONArray(limit > 0 ?
          qResult.stream().limit(limit + 1).map(r -> serializerImpl.serializeResult(database, r)).collect(Collectors.toList()) :
          qResult.stream().map(r -> serializerImpl.serializeResult(database, r)).collect(Collectors.toList()));
      response.put("result", result);
    }
    }
  }

  protected void analyzeResultContent(final Database database, final JsonGraphSerializer serializerImpl,
      final Set includedVertices, final Set includedEdges, final JSONArray vertices, final JSONArray edges,
      final Result row, final int limit) {
    for (final String prop : row.getPropertyNames()) {
      final Object value = row.getProperty(prop);
      if (value == null)
        continue;

      if (limit > 0 && vertices.length() + edges.length() >= limit)
        break;

      if (prop.equals("@rid") && RID.is(value)) {
        analyzePropertyValue(database, serializerImpl, includedVertices, includedEdges, vertices, edges,
            new RID(database, value.toString()), limit);
      } else
        analyzePropertyValue(database, serializerImpl, includedVertices, includedEdges, vertices, edges, value, limit);
    }
  }

  protected void analyzePropertyValue(final Database database, final JsonGraphSerializer serializerImpl,
      final Set includedVertices, final Set includedEdges, final JSONArray vertices, final JSONArray edges,
      final Object value, final int limit) {
    if (value instanceof Identifiable) {

      final DocumentType type;
      if (value instanceof Document)
        type = ((Document) value).getType();
      else {
        final RID rid = ((Identifiable) value).getIdentity();
        type = database.getSchema().getTypeByBucketId(rid.getBucketId());
      }

      if (type instanceof LocalVertexType) {
        if (includedVertices.add(((Identifiable) value).getIdentity()))
          vertices.put(serializerImpl.serializeGraphElement(((Identifiable) value).asVertex(true)));
      } else if (type instanceof LocalEdgeType) {
        final Edge edge = ((Identifiable) value).asEdge(true);
        if (includedEdges.add(edge.getIdentity())) {
          edges.put(serializerImpl.serializeGraphElement(edge));
          try {
            if (includedVertices.add(edge.getIn())) {
              final Vertex inV = edge.getInVertex();
              vertices.put(serializerImpl.serializeGraphElement(inV));
            }
            if (includedVertices.add(edge.getOut())) {
              final Vertex outV = edge.getOutVertex();
              vertices.put(serializerImpl.serializeGraphElement(outV));
            }
          } catch (RecordNotFoundException e) {
            LogManager.instance().log(this, Level.SEVERE, "Error on loading connecting vertices for edge %s: vertex %s not found",
                edge.getIdentity(), e.getRID());
          }
        }
      }
    } else if (value instanceof Result) {
      analyzeResultContent(database, serializerImpl, includedVertices, includedEdges, vertices, edges, (Result) value, limit);
    } else if (value instanceof Collection) {
      for (final Iterator it = ((Collection) value).iterator(); it.hasNext(); ) {
        analyzePropertyValue(database, serializerImpl, includedVertices, includedEdges, vertices, edges, it.next(), limit);
      }
    }
  }

  protected Object mapParams(Map paramMap) {
    if (paramMap != null) {
      if (!paramMap.isEmpty() && paramMap.containsKey("0")) {
        // ORDINAL
        final Object[] array = new Object[paramMap.size()];
        for (int i = 0; i < array.length; ++i) {
          array[i] = paramMap.get("" + i);
        }
        return array;
      }
    } else
      paramMap = Collections.emptyMap();
    return paramMap;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy