diff --git a/.gitignore b/.gitignore
index 64d448025de3..39e230a42e00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -157,6 +157,12 @@ flex/interactive/sdk/python/gs_interactive/rest.py
!flex/interactive/sdk/python/gs_interactive/client/generated/__init__.py
!flex/interactive/sdk/python/gs_interactive/models/long_text.py
+interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/models/
+interactive_engine/groot-http/.openapi-generator/
+interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/*.java
+interactive_engine/groot-http/src/main/java/org/
+interactive_engine/groot-http/src/main/resources/
+interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/V1Api.java
**/.cache/
diff --git a/charts/graphscope-store/templates/configmap.yaml b/charts/graphscope-store/templates/configmap.yaml
index c690d3f33809..54cb1b1359ae 100644
--- a/charts/graphscope-store/templates/configmap.yaml
+++ b/charts/graphscope-store/templates/configmap.yaml
@@ -171,6 +171,10 @@ data:
# export MALLOC_CONF=prof:true,lg_prof_interval:29,lg_prof_sample:19,prof_prefix=/tmp
export RUST_BACKTRACE=1
+ if [ "$ROLE" = "frontend" ]; then
+ echo "Starting groot-http Spring Boot service..."
+ java -jar ${GRAPHSCOPE_HOME}/groot/lib/groot-http-0.0.1-SNAPSHOT.jar > /var/log/graphscope/groot-http.log 2>&1 &
+ fi
${GRAPHSCOPE_HOME}/groot/bin/store_ctl.sh start ${ROLE} # || sleep infinity
portal_setup.sh: |-
#!/bin/bash
diff --git a/flex/interactive/sdk/generate_sdk.sh b/flex/interactive/sdk/generate_sdk.sh
index e38c33bc9920..fd45191d5cd0 100755
--- a/flex/interactive/sdk/generate_sdk.sh
+++ b/flex/interactive/sdk/generate_sdk.sh
@@ -81,6 +81,20 @@ function do_gen_python() {
eval $cmd
}
+function do_gen_spring() {
+ echo "Generating Spring API"
+ OUTPUT_PATH="${CUR_DIR}/../../../interactive_engine/groot-http"
+ GROOT_PACKAGE_NAME="com.alibaba.graphscope.groot"
+ GROOT_ARTIFACT_ID="groot-http"
+ additional_properties="apiPackage=${GROOT_PACKAGE_NAME}.service.api,modelPackage=${GROOT_PACKAGE_NAME}.service.models,artifactId=${GROOT_ARTIFACT_ID},groupId=${GROUP_ID},invokerPackage=${GROOT_PACKAGE_NAME}"
+ export JAVA_OPTS="-Dlog.level=${LOG_LEVEL}"
+ cmd="openapi-generator-cli generate -i ${OPENAPI_SPEC_PATH} -g spring -o ${OUTPUT_PATH}"
+ cmd=" ${cmd} --additional-properties=${additional_properties}"
+ echo "Running command: ${cmd}"
+
+ eval $cmd
+}
+
function do_gen() {
# expect only one argument
if [ $# -ne 1 ]; then
@@ -97,6 +111,9 @@ function do_gen() {
python)
do_gen_python
;;
+ spring)
+ do_gen_spring
+ ;;
*)
err "Unsupported language: $lang"
usage
diff --git a/flex/openapi/openapi_interactive.yaml b/flex/openapi/openapi_interactive.yaml
index bdbf4474907b..92b307d9a265 100644
--- a/flex/openapi/openapi_interactive.yaml
+++ b/flex/openapi/openapi_interactive.yaml
@@ -166,14 +166,228 @@ paths:
required: true
schema:
type: string
- description: The id of graph to delete
+ description: The id of graph to get schema
responses:
- '200':
+ 200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/GetGraphSchemaResponse'
+ 500:
+ $ref: "#/components/responses/500"
+ /v1/graph/{graph_id}/schema/vertex:
+ post:
+ tags:
+ - AdminService/GraphManagement
+ description: Create a vertex type
+ operationId: createVertexType
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateVertexType'
+ responses:
+ '200':
+ description: Successfully created the vertex type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/APIResponse'
+ '400':
+ $ref: "#/components/responses/400"
+ '500':
+ $ref: "#/components/responses/500"
+
+ delete:
+ tags:
+ - AdminService/GraphManagement
+ description: Delete a vertex type by name
+ operationId: deleteVertexTypeByName
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: type_name
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Successfully deleted the vertex type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/APIResponse'
+ '400':
+ $ref: "#/components/responses/400"
+ '500':
+ $ref: "#/components/responses/500"
+
+ put:
+ tags:
+ - AdminService/GraphManagement
+ description: Update a vertex type to add more properties
+ operationId: updateVertexType
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateVertexType'
+ responses:
+ '200':
+ description: Successfully updated the vertex type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/APIResponse'
+ '400':
+ $ref: "#/components/responses/400"
+ '500':
+ $ref: "#/components/responses/500"
+
+ /v1/graph/{graph_id}/schema/edge:
+ post:
+ tags:
+ - AdminService/GraphManagement
+ description: Create a edge type
+ operationId: createEdgeType
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateEdgeType'
+ responses:
+ '200':
+ description: Successful created the edge type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/APIResponse'
+ '400':
+ $ref: "#/components/responses/400"
+ '500':
+ $ref: "#/components/responses/500"
+
+ delete:
+ tags:
+ - AdminService/GraphManagement
+ description: Delete an edge type by name
+ operationId: deleteEdgeTypeByName
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: type_name
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: source_vertex_type
+ in: query
+ required: true
+ schema:
+ type: string
+ - name: destination_vertex_type
+ in: query
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Successfully deleted the edge type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/APIResponse'
+ '400':
+ $ref: "#/components/responses/400"
+ '500':
+ $ref: "#/components/responses/500"
+
+ put:
+ tags:
+ - AdminService/GraphManagement
+ description: Update an edge type to add more properties
+ operationId: updateEdgeType
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateEdgeType'
+ responses:
+ 200:
+ description: Successfully updated the edge type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/APIResponse'
+ 400:
+ $ref: "#/components/responses/400"
+ 500:
+ $ref: "#/components/responses/500"
+
+ /v1/graph/{graph_id}/snapshot/{snapshot_id}/status:
+ get:
+ tags:
+ - AdminService/GraphManagement
+ description: Get the status of a snapshot by id
+ operationId: get_snapshot_status
+ parameters:
+ - name: graph_id
+ in: path
+ required: true
+ schema:
+ type: string
+ - name: snapshot_id
+ in: path
+ required: true
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: the status of a snapshot_id of whether it is available
+ content:
+ application/json:
+ schema:
+ type: boolean
+ '400':
+ $ref: "#/components/responses/400"
+ '500':
+ $ref: "#/components/responses/500"
+
/v1/graph/{graph_id}/statistics:
get:
tags:
@@ -626,7 +840,7 @@ paths:
post:
tags:
- GraphService/VertexManagement
- summary: Add vertex to the graph
+ summary: Add vertex (and edge) to the graph
operationId: add_vertex
parameters:
- name: graph_id
@@ -635,7 +849,7 @@ paths:
schema:
type: string
description: |
- Add the provided vertex to the specified graph.
+ Add the provided vertex (and edge) to the specified graph.
requestBody:
required: true
content:
@@ -660,7 +874,6 @@ paths:
properties:
- name: "weight"
value: 0.2
-
responses:
'200':
description: Successfully created vertex
@@ -712,7 +925,7 @@ paths:
summary: Update vertex's property
operationId: update_vertex
description: |
- Remove the vertex from the specified graph.
+ Update the vertex with the provided properties to the specified graph.
parameters:
- name: graph_id
in : path
@@ -723,7 +936,9 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/VertexRequest'
+ type: array
+ items:
+ $ref: '#/components/schemas/VertexRequest'
example:
label: "person"
primary_key_value: 2
@@ -779,18 +994,15 @@ paths:
required: true
schema:
type: string
- - name: label
- in: query
- required: true
- description: The label name of querying vertex.
- schema:
- type: string
- - name: primary_key_value
- in: query
- required: true
- description: The value of the querying vertex's primary key
- schema:
- $ref: '#/components/schemas/AnyValue'
+ requestBody:
+ description: The label and primary key values of the vertex to be deleted.
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DeleteVertexRequest'
responses:
'200':
description: Successfully delete vertex
@@ -1005,7 +1217,9 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/EdgeRequest'
+ type: array
+ items:
+ $ref: '#/components/schemas/EdgeRequest'
example:
src_label: "person"
dst_label: "software"
@@ -1066,35 +1280,15 @@ paths:
required: true
schema:
type: string
- - name: src_label
- in: query
- required: true
- description: The label name of src vertex.
- schema:
- type: string
- example: person
- - name: src_primary_key_value
- in: query
- required: true
- description: The primary key value of src vertex.
- schema:
- $ref: '#/components/schemas/AnyValue'
- # type: object
- example: 1
- - name: dst_label
- in: query
- required: true
- description: The label name of dst vertex.
- schema:
- type: string
- example: software
- - name: dst_primary_key_value
- in: query
- required: true
- description: The primary key value of dst vertex.
- schema:
- $ref: '#/components/schemas/AnyValue'
- example: 3
+ requestBody:
+ description: The label and primary key values of the src and dst vertices, and the edge label.
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DeleteEdgeRequest'
responses:
'200':
description: Successfully delete edge
@@ -1131,6 +1325,7 @@ paths:
example:
code: 103
message: "Internal error"
+
/v1/graph/{graph_id}/query:
post:
tags:
@@ -1304,6 +1499,7 @@ paths:
example:
code: 103
message: "Internal error"
+
components:
schemas:
AnyValue: {}
@@ -1320,91 +1516,137 @@ components:
$ref: '#/components/schemas/AnyValue'
PrimitiveType:
x-body-name: primitive_type
+ allOf:
+ - $ref: '#/components/schemas/BaseGSDataType'
+ - type: object
+ required:
+ - primitive_type
+ properties:
+ primitive_type:
+ type: string
+ enum: [DT_SIGNED_INT32, DT_UNSIGNED_INT32, DT_SIGNED_INT64, DT_UNSIGNED_INT64,
+ DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_STRING]
+ # The DT_STRING is added for backward compatibility, it should be replaced by StringType
+ example: DT_SIGNED_INT32
+ BaseStringType:
+ x-body-name: base_string_type
type: object
- required:
- - primitive_type
+ required:
+ - string_type
properties:
- primitive_type:
+ string_type:
type: string
- enum: [DT_SIGNED_INT32, DT_UNSIGNED_INT32, DT_SIGNED_INT64, DT_UNSIGNED_INT64,
- DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_STRING]
- # The DT_STRING is added for backward compatibility, it should be replaced by StringType
- example: DT_SIGNED_INT32
+ discriminator:
+ propertyName: string_type
LongText:
x-body-name: long_text
- type: object
- additionalProperties: false
- required:
- - long_text
- properties:
- long_text:
- type: string
- nullable: true
+ allOf:
+ - $ref: '#/components/schemas/BaseStringType'
+ - type: object
+ additionalProperties: false
+ required:
+ - long_text
+ properties:
+ long_text:
+ type: string
+ nullable: true
FixedChar:
x-body-name: fixed_char
- type: object
- additionalProperties: false
- required:
- - char
- properties:
- char:
- type: object
+ allOf:
+ - $ref: '#/components/schemas/BaseStringType'
+ - type: object
+ additionalProperties: false
required:
- - fixed_length
+ - char
properties:
- fixed_length:
- type: integer
+ char:
+ type: object
+ required:
+ - fixed_length
+ properties:
+ fixed_length:
+ type: integer
VarChar:
x-body-name: var_char
- type: object
- additionalProperties: false
- required:
- - var_char
- properties:
- var_char:
- type: object
+ allOf:
+ - $ref: '#/components/schemas/BaseStringType'
+ - type: object
+ additionalProperties: false
required:
- - max_length
+ - var_char
properties:
- max_length:
- type: integer
+ var_char:
+ type: object
+ required:
+ - max_length
+ properties:
+ max_length:
+ type: integer
StringType:
x-body-name: string_type
- type: object
- required:
- - string
- properties:
- string:
- oneOf:
- - $ref: '#/components/schemas/LongText'
- - $ref: '#/components/schemas/FixedChar'
- - $ref: '#/components/schemas/VarChar'
- TimeStampType:
- x-body-name: time_stamp_type
+ allOf:
+ - $ref: '#/components/schemas/BaseGSDataType'
+ - type: object
+ required:
+ - string
+ properties:
+ string:
+ oneOf:
+ - $ref: '#/components/schemas/LongText'
+ - $ref: '#/components/schemas/FixedChar'
+ - $ref: '#/components/schemas/VarChar'
+ BaseTemporalType:
+ x-body-name: base_temporal_type
type: object
required:
- - timestamp
+ - temporal_type
properties:
- timestamp:
+ temporal_type:
type: string
+ discriminator:
+ propertyName: temporal_type
+ TimeStampType:
+ x-body-name: time_stamp_type
+ allOf:
+ - $ref: '#/components/schemas/BaseTemporalType'
+ - type: object
+ required:
+ - timestamp
+ properties:
+ timestamp:
+ type: string
DateType:
x-body-name: date_type
- type: object
- required:
- - date32
- properties:
- date32:
- type: string
+ allOf:
+ - $ref: '#/components/schemas/BaseTemporalType'
+ - type: object
+ required:
+ - date32
+ properties:
+ date32:
+ type: string
TemporalType:
x-body-name: temporal_type
+ allOf:
+ - $ref: '#/components/schemas/BaseGSDataType'
+ - type: object
+ required:
+ - temporal
+ properties:
+ temporal:
+ oneOf:
+ - $ref: '#/components/schemas/TimeStampType'
+ - $ref: '#/components/schemas/DateType'
+ BaseGSDataType:
+ x-body-name: base_gs_data_type
type: object
required:
- - temporal
+ - type_name
properties:
- temporal:
- oneOf:
- - $ref: '#/components/schemas/TimeStampType'
- - $ref: '#/components/schemas/DateType'
+ type_name:
+ type: string
+ discriminator:
+ propertyName: type_name
GSDataType:
x-body-name: gs_data_type
oneOf:
@@ -1444,18 +1686,33 @@ components:
type: object
required:
- label
- - primary_key_value
+ - primary_key_values
- properties
properties:
label:
type: string
example: person
- primary_key_value:
- $ref: '#/components/schemas/AnyValue'
+ primary_key_values:
+ type: array
+ items:
+ $ref: '#/components/schemas/Property'
properties:
type: array
items:
$ref: '#/components/schemas/Property'
+ DeleteVertexRequest:
+ x-body-name: delete_vertex_request
+ type: object
+ properties:
+ label:
+ type: string
+ description: The label name of the vertex.
+ example: person
+ primary_key_values:
+ type: array
+ description: Primary key values for the vertex.
+ items:
+ $ref: '#/components/schemas/Property'
VertexData:
x-body-name: vertex_data
type: object
@@ -1504,8 +1761,8 @@ components:
- src_label
- dst_label
- edge_label
- - src_primary_key_value
- - dst_primary_key_value
+ - src_primary_key_values
+ - dst_primary_key_values
properties:
src_label:
type: string
@@ -1516,14 +1773,44 @@ components:
edge_label:
type: string
example: created
- src_primary_key_value:
- $ref: '#/components/schemas/AnyValue'
- dst_primary_key_value:
- $ref: '#/components/schemas/AnyValue'
+ src_primary_key_values:
+ type: array
+ items:
+ $ref: '#/components/schemas/Property'
+ dst_primary_key_values:
+ type: array
+ items:
+ $ref: '#/components/schemas/Property'
properties:
type: array
items:
$ref: '#/components/schemas/Property'
+ DeleteEdgeRequest:
+ x-body-name: delete_edge_request
+ type: object
+ properties:
+ edge_label:
+ type: string
+ description: The label name of the edge.
+ example: created
+ src_label:
+ type: string
+ description: The label name of the source vertex.
+ example: person
+ dst_label:
+ type: string
+ description: The label name of the destination vertex.
+ example: software
+ src_primary_key_values:
+ type: array
+ description: Primary key values for the source vertex.
+ items:
+ $ref: '#/components/schemas/Property'
+ dst_primary_key_values:
+ type: array
+ description: Primary key values for the destination vertex.
+ items:
+ $ref: '#/components/schemas/Property'
QueryRequest:
x-body-name: query_request
type: object
diff --git a/interactive_engine/assembly/pom.xml b/interactive_engine/assembly/pom.xml
index 39b0aa02ea32..2ddf36a64810 100644
--- a/interactive_engine/assembly/pom.xml
+++ b/interactive_engine/assembly/pom.xml
@@ -64,6 +64,11 @@
groot-server
${project.version}
+
+ com.alibaba.graphscope
+ groot-http
+ ${project.version}
+
com.alibaba.graphscope
executor
diff --git a/interactive_engine/groot-http/.openapi-generator-ignore b/interactive_engine/groot-http/.openapi-generator-ignore
new file mode 100644
index 000000000000..e5386b6dd5a9
--- /dev/null
+++ b/interactive_engine/groot-http/.openapi-generator-ignore
@@ -0,0 +1,28 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
+
+pom.xml
+src/main/java/com/alibaba/graphscope/groot/service/impl
+src/main/java/com/alibaba/graphscope/groot/service/api/ApiUtil.java
+src/main/java/com/alibaba/graphscope/groot/service/api/V1ApiController.java
\ No newline at end of file
diff --git a/interactive_engine/groot-http/README.md b/interactive_engine/groot-http/README.md
new file mode 100644
index 000000000000..5cd22b6081a2
--- /dev/null
+++ b/interactive_engine/groot-http/README.md
@@ -0,0 +1,21 @@
+# OpenAPI generated server
+
+Spring Boot Server
+
+## Overview
+This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
+By using the [OpenAPI-Spec](https://openapis.org), you can easily generate a server stub.
+This is an example of building a OpenAPI-enabled server in Java using the SpringBoot framework.
+
+
+The underlying library integrating OpenAPI to Spring Boot is [springdoc](https://springdoc.org).
+Springdoc will generate an OpenAPI v3 specification based on the generated Controller and Model classes.
+The specification is available to download using the following url:
+http://localhost:8080/v3/api-docs/
+
+Start your server as a simple java application
+
+You can view the api documentation in swagger-ui by pointing to
+http://localhost:8080/swagger-ui.html
+
+Change default port value in application.properties
\ No newline at end of file
diff --git a/interactive_engine/groot-http/pom.xml b/interactive_engine/groot-http/pom.xml
new file mode 100644
index 000000000000..b2e34ae53386
--- /dev/null
+++ b/interactive_engine/groot-http/pom.xml
@@ -0,0 +1,119 @@
+
+
+ interactive-parent
+ com.alibaba.graphscope
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+ groot-http
+ jar
+ ${project.groupId}:${project.artifactId}
+
+ 1.8
+ ${java.version}
+ ${java.version}
+ UTF-8
+ 1.6.14
+ 5.3.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.data
+ spring-data-commons
+
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ ${springdoc.version}
+
+
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ org.openapitools
+ jackson-databind-nullable
+ 0.2.6
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ com.alibaba.graphscope
+ groot-client
+
+
+
+ src/main/java
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.0.0
+
+
+ generate-sources
+ generate-sources
+
+ exec
+
+
+ /bin/bash
+
+ ${project.basedir}/pre-generate.sh
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+ com.alibaba.graphscope.groot.OpenApiGeneratorApplication
+
+
+
+
+
diff --git a/interactive_engine/groot-http/pre-generate.sh b/interactive_engine/groot-http/pre-generate.sh
new file mode 100755
index 000000000000..25543c14e761
--- /dev/null
+++ b/interactive_engine/groot-http/pre-generate.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
+SDK_SCRIPT_PATH="${SCRIPT_DIR}/../../flex/interactive/sdk/generate_sdk.sh"
+LANGUAGE="spring"
+
+if [ ! -f "$SDK_SCRIPT_PATH" ]; then
+ echo "Error: SDK generation script not found at $SDK_SCRIPT_PATH"
+ exit 1
+fi
+
+echo "Generating Spring files using OpenAPI Generator..."
+bash "$SDK_SCRIPT_PATH" -g "$LANGUAGE"
+
+if [ $? -ne 0 ]; then
+ echo "Failed to generate Spring files"
+ exit 1
+else
+ echo "Successfully generated Spring files"
+fi
\ No newline at end of file
diff --git a/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/ApiUtil.java b/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/ApiUtil.java
new file mode 100644
index 000000000000..2e1dd6b8cf58
--- /dev/null
+++ b/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/ApiUtil.java
@@ -0,0 +1,39 @@
+package com.alibaba.graphscope.groot.service.api;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.context.request.NativeWebRequest;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+public class ApiUtil {
+ public static void setExampleResponse(
+ NativeWebRequest req, String contentType, String example) {
+ try {
+ HttpServletResponse res = req.getNativeResponse(HttpServletResponse.class);
+ res.setCharacterEncoding("UTF-8");
+ res.addHeader("Content-Type", contentType);
+ res.getWriter().print(example);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static ResponseEntity createErrorResponse(HttpStatus status, String message) {
+ return ResponseEntity.status(status).body(String.format("{\"error\": \"%s\"}", message));
+ }
+
+ public static ResponseEntity createSuccessResponse(String message, long snapshotId) {
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(
+ String.format(
+ "{\"message\": \"%s\", \"snapshot id\": %d}", message, snapshotId));
+ }
+
+ public static ResponseEntity createSuccessResponse(String message) {
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(String.format("{\"message\": \"%s\"}", message));
+ }
+}
diff --git a/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/V1ApiController.java b/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/V1ApiController.java
new file mode 100644
index 000000000000..3db37441e571
--- /dev/null
+++ b/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/api/V1ApiController.java
@@ -0,0 +1,335 @@
+package com.alibaba.graphscope.groot.service.api;
+
+import com.alibaba.graphscope.groot.service.impl.EdgeManagementService;
+import com.alibaba.graphscope.groot.service.impl.SchemaManagementService;
+import com.alibaba.graphscope.groot.service.impl.VertexManagementService;
+import com.alibaba.graphscope.groot.service.models.CreateEdgeType;
+import com.alibaba.graphscope.groot.service.models.CreateGraphRequest;
+import com.alibaba.graphscope.groot.service.models.CreateGraphResponse;
+import com.alibaba.graphscope.groot.service.models.CreateVertexType;
+import com.alibaba.graphscope.groot.service.models.DeleteEdgeRequest;
+import com.alibaba.graphscope.groot.service.models.DeleteVertexRequest;
+import com.alibaba.graphscope.groot.service.models.EdgeRequest;
+import com.alibaba.graphscope.groot.service.models.GetGraphSchemaResponse;
+import com.alibaba.graphscope.groot.service.models.VertexEdgeRequest;
+import com.alibaba.graphscope.groot.service.models.VertexRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+import javax.validation.Valid;
+
+@RestController
+@RequestMapping("${openapi.graphScopeInteractiveAPIV03.base-path:/v1/graph}")
+public class V1ApiController implements V1Api {
+
+ private final VertexManagementService vertexManagementService;
+ private final EdgeManagementService edgeManagementService;
+ private final SchemaManagementService schemaManagementService;
+
+ @Autowired
+ public V1ApiController(
+ VertexManagementService vertexService,
+ EdgeManagementService edgeService,
+ SchemaManagementService schemaManagementService) {
+ this.vertexManagementService = vertexService;
+ this.edgeManagementService = edgeService;
+ this.schemaManagementService = schemaManagementService;
+ }
+
+ @Override
+ @PostMapping(
+ value = "/{graph_id}/vertex",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity addVertex(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody @Valid VertexEdgeRequest vertexEdgeRequest) {
+ try {
+ long si;
+ if (vertexEdgeRequest.getEdgeRequest() == null) {
+ si = vertexManagementService.addVertices(vertexEdgeRequest.getVertexRequest());
+ } else {
+ si = vertexManagementService.addVerticesAndEdges(vertexEdgeRequest);
+ }
+ return ApiUtil.createSuccessResponse("Vertices and edges added successfully", si);
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to add vertices and edges: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @DeleteMapping(
+ value = "/{graph_id}/vertex",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity deleteVertex(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody(required = true) List deleteVertexRequest) {
+ try {
+ long si = vertexManagementService.deleteVertices(deleteVertexRequest);
+ return ApiUtil.createSuccessResponse("Vertices deleted successfully", si);
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to delete vertices: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PutMapping(
+ value = "/{graph_id}/vertex",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity updateVertex(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody(required = false) List vertexRequest) {
+ try {
+ long si = vertexManagementService.updateVertices(vertexRequest);
+ return ApiUtil.createSuccessResponse("Vertices updated successfully", si);
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to update vertices: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PostMapping(
+ value = "/{graph_id}/edge",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity addEdge(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody(required = true) List edgeRequest) {
+ try {
+ long si = edgeManagementService.addEdges(edgeRequest);
+ return ApiUtil.createSuccessResponse("Edges added successfully", si);
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR, "Failed to add edges: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @DeleteMapping(
+ value = "/{graph_id}/edge",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity deleteEdge(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody(required = true) List deleteEdgeRequest) {
+ try {
+ long si = edgeManagementService.deleteEdges(deleteEdgeRequest);
+ return ApiUtil.createSuccessResponse("Edges deleted successfully", si);
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR, "Failed to delete edges: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PutMapping(
+ value = "/{graph_id}/edge",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity updateEdge(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody(required = false) List edgeRequest) {
+ try {
+ long si = edgeManagementService.updateEdges(edgeRequest);
+ return ApiUtil.createSuccessResponse("Edges updated successfully", si);
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR, "Failed to update edges: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PostMapping(
+ value = "/{graph_id}/schema/vertex",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity createVertexType(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody @Validated CreateVertexType createVertexType) {
+ try {
+ schemaManagementService.createVertexType(createVertexType);
+ return ApiUtil.createSuccessResponse("Vertex type created successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to create vertex type: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @DeleteMapping(
+ value = "/{graph_id}/schema/vertex",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity deleteVertexTypeByName(
+ @PathVariable("graph_id") String graphId,
+ @RequestParam(value = "type_name", required = true) String typeName) {
+ try {
+ schemaManagementService.deleteVertexType(typeName);
+ return ApiUtil.createSuccessResponse("Vertex type deleted successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to delete vertex type" + e.getMessage());
+ }
+ }
+
+ @Override
+ @PutMapping(
+ value = "/{graph_id}/schema/vertex",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity updateVertexType(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody @Validated CreateVertexType updateVertexType) {
+ try {
+ schemaManagementService.updateVertexType(updateVertexType);
+ return ApiUtil.createSuccessResponse("Vertex type updated successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to update vertex type: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PostMapping(
+ value = "/{graph_id}/schema/edge",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity createEdgeType(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody @Validated CreateEdgeType createEdgeType) {
+ try {
+ schemaManagementService.createEdgeType(createEdgeType);
+ return ApiUtil.createSuccessResponse("Edge type created successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to create edge type: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @DeleteMapping(
+ value = "/{graph_id}/schema/edge",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity deleteEdgeTypeByName(
+ @PathVariable("graph_id") String graphId,
+ @RequestParam(value = "type_name", required = true) String typeName,
+ @RequestParam(value = "source_vertex_type", required = true) String sourceVertexType,
+ @RequestParam(value = "destination_vertex_type", required = true)
+ String destinationVertexType) {
+ try {
+ schemaManagementService.deleteEdgeType(
+ typeName, sourceVertexType, destinationVertexType);
+ return ApiUtil.createSuccessResponse("Edge type deleted successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to delete edge type: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PutMapping(
+ value = "/{graph_id}/schema/edge",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity updateEdgeType(
+ @PathVariable("graph_id") String graphId,
+ @RequestBody @Validated CreateEdgeType updateEdgeType) {
+ try {
+ schemaManagementService.updateEdgeType(updateEdgeType);
+ return ApiUtil.createSuccessResponse("Edge type updated successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to update edge type: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PostMapping(
+ value = "",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity createGraph(
+ @RequestBody @Validated CreateGraphRequest createGraphRequest) {
+ try {
+ schemaManagementService.importSchema(createGraphRequest.getSchema());
+ CreateGraphResponse response = new CreateGraphResponse();
+ // a default graph id, since groot does not support multiple graphs
+ response.setGraphId("0");
+ return ResponseEntity.status(HttpStatus.OK).body(response);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
+ }
+ }
+
+ @Override
+ @GetMapping(value = "/{graph_id}/schema", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity getSchema(
+ @PathVariable("graph_id") String graphId) {
+ try {
+ GetGraphSchemaResponse response = schemaManagementService.getSchema();
+ return ResponseEntity.status(HttpStatus.OK).body(response);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
+ }
+ }
+
+ @Override
+ @DeleteMapping(value = "/{graph_id}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity deleteGraph(@PathVariable("graph_id") String graphId) {
+ try {
+ schemaManagementService.dropSchema();
+ return ApiUtil.createSuccessResponse("Graph schema deleted successfully");
+ } catch (Exception e) {
+ return ApiUtil.createErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "Failed to delete graph schema: " + e.getMessage());
+ }
+ }
+
+ @Override
+ @PostMapping(
+ value = "/{graph_id}/snapshot/{snapshot_id}/status",
+ produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity getSnapshotStatus(
+ @PathVariable("graph_id") String graphId,
+ @PathVariable("snapshot_id") Integer snapshotId) {
+ try {
+ boolean res = schemaManagementService.remoteFlush(snapshotId);
+ return ResponseEntity.status(HttpStatus.OK).body(res);
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(false);
+ }
+ }
+}
diff --git a/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/impl/DtoConverter.java b/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/impl/DtoConverter.java
new file mode 100644
index 000000000000..a60cc927fefc
--- /dev/null
+++ b/interactive_engine/groot-http/src/main/java/com/alibaba/graphscope/groot/service/impl/DtoConverter.java
@@ -0,0 +1,201 @@
+package com.alibaba.graphscope.groot.service.impl;
+
+import com.alibaba.graphscope.groot.sdk.schema.Edge;
+import com.alibaba.graphscope.groot.sdk.schema.EdgeLabel;
+import com.alibaba.graphscope.groot.sdk.schema.EdgeLabel.EdgeRelation;
+import com.alibaba.graphscope.groot.sdk.schema.Vertex;
+import com.alibaba.graphscope.groot.sdk.schema.VertexLabel;
+import com.alibaba.graphscope.groot.service.models.BaseEdgeTypeVertexTypePairRelationsInner;
+import com.alibaba.graphscope.groot.service.models.DateType;
+import com.alibaba.graphscope.groot.service.models.DeleteEdgeRequest;
+import com.alibaba.graphscope.groot.service.models.DeleteVertexRequest;
+import com.alibaba.graphscope.groot.service.models.EdgeRequest;
+import com.alibaba.graphscope.groot.service.models.GSDataType;
+import com.alibaba.graphscope.groot.service.models.GetEdgeType;
+import com.alibaba.graphscope.groot.service.models.GetPropertyMeta;
+import com.alibaba.graphscope.groot.service.models.GetVertexType;
+import com.alibaba.graphscope.groot.service.models.PrimitiveType;
+import com.alibaba.graphscope.groot.service.models.Property;
+import com.alibaba.graphscope.groot.service.models.StringType;
+import com.alibaba.graphscope.groot.service.models.TemporalType;
+import com.alibaba.graphscope.groot.service.models.TemporalTypeAllOfTemporal;
+import com.alibaba.graphscope.groot.service.models.TimeStampType;
+import com.alibaba.graphscope.groot.service.models.VertexRequest;
+import com.alibaba.graphscope.proto.groot.DataTypePb;
+
+import org.openapitools.jackson.nullable.JsonNullable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class DtoConverter {
+ public static Vertex convertToVertex(VertexRequest vertexRequest) {
+ String label = vertexRequest.getLabel();
+ Map propertyMap = convertToPropertyMap(vertexRequest.getProperties());
+ Map primaryKeyValues =
+ convertToPropertyMap(vertexRequest.getPrimaryKeyValues());
+ propertyMap.putAll(primaryKeyValues);
+ return new Vertex(label, propertyMap);
+ }
+
+ public static Vertex convertToVertex(DeleteVertexRequest deleteVertexRequest) {
+ String label = deleteVertexRequest.getLabel();
+ Map primaryKeyValues =
+ convertToPropertyMap(deleteVertexRequest.getPrimaryKeyValues());
+ return new Vertex(label, primaryKeyValues);
+ }
+
+ public static Edge convertToEdge(EdgeRequest edgeRequest) {
+ String label = edgeRequest.getEdgeLabel();
+ String srcLabel = edgeRequest.getSrcLabel();
+ String dstLabel = edgeRequest.getDstLabel();
+ Map srcPkMap = convertToPropertyMap(edgeRequest.getSrcPrimaryKeyValues());
+ Map dstPkMap = convertToPropertyMap(edgeRequest.getDstPrimaryKeyValues());
+ Map propertyMap = convertToPropertyMap(edgeRequest.getProperties());
+ return new Edge(label, srcLabel, dstLabel, srcPkMap, dstPkMap, propertyMap);
+ }
+
+ public static Edge convertToEdge(DeleteEdgeRequest deleteEdgeRequest) {
+ String label = deleteEdgeRequest.getEdgeLabel();
+ String srcLabel = deleteEdgeRequest.getSrcLabel();
+ String dstLabel = deleteEdgeRequest.getDstLabel();
+ Map srcPkMap =
+ convertToPropertyMap(deleteEdgeRequest.getSrcPrimaryKeyValues());
+ Map dstPkMap =
+ convertToPropertyMap(deleteEdgeRequest.getDstPrimaryKeyValues());
+ return new Edge(label, srcLabel, dstLabel, srcPkMap, dstPkMap);
+ }
+
+ public static DataTypePb convertToDataTypePb(GSDataType dataType) {
+ if (dataType instanceof PrimitiveType) {
+ PrimitiveType primitiveType = (PrimitiveType) dataType;
+ switch (primitiveType.getPrimitiveType()) {
+ case SIGNED_INT32:
+ return DataTypePb.INT;
+ case UNSIGNED_INT32:
+ return DataTypePb.UINT;
+ case SIGNED_INT64:
+ return DataTypePb.LONG;
+ case UNSIGNED_INT64:
+ return DataTypePb.ULONG;
+ case BOOL:
+ return DataTypePb.BOOL;
+ case FLOAT:
+ return DataTypePb.FLOAT;
+ case DOUBLE:
+ return DataTypePb.DOUBLE;
+ case STRING:
+ return DataTypePb.STRING;
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported primitive type: " + primitiveType);
+ }
+ } else if (dataType instanceof StringType) {
+ return DataTypePb.STRING;
+ } else if (dataType instanceof TemporalType) {
+ TemporalType temporalType = (TemporalType) dataType;
+ TemporalTypeAllOfTemporal temporal = temporalType.getTemporal();
+ if (temporal instanceof DateType) {
+ return DataTypePb.DATE32;
+ } else if (temporal instanceof TimeStampType) {
+ return DataTypePb.TIMESTAMP_MS;
+ } else {
+ throw new IllegalArgumentException("Unsupported temporal type: " + temporalType);
+ }
+ }
+ throw new IllegalArgumentException("Unsupported data type: " + dataType);
+ }
+
+ public static GetVertexType convertToDtoVertexType(VertexLabel vertexLabel) {
+ GetVertexType vertexType = new GetVertexType();
+ vertexType.setTypeName(vertexLabel.getLabel());
+ vertexType.setTypeId(vertexLabel.getId());
+ vertexType.setProperties(convertToDtoProperties(vertexLabel.getProperties()));
+ vertexType.setPrimaryKeys(
+ vertexLabel.getProperties().stream()
+ .filter(p -> p.isPrimaryKey())
+ .map(p -> p.getName())
+ .collect(Collectors.toList()));
+ return vertexType;
+ }
+
+ public static GetEdgeType convertToDtoEdgeType(EdgeLabel edgeLabel) {
+ GetEdgeType edgeType = new GetEdgeType();
+ edgeType.setTypeName(edgeLabel.getLabel());
+ edgeType.setTypeId(edgeLabel.getId());
+ edgeType.setProperties(convertToDtoProperties(edgeLabel.getProperties()));
+ for (EdgeRelation edgeRelation : edgeLabel.getRelations()) {
+ BaseEdgeTypeVertexTypePairRelationsInner pair =
+ new BaseEdgeTypeVertexTypePairRelationsInner();
+ pair.setSourceVertex(edgeRelation.getSrcLabel());
+ pair.setDestinationVertex(edgeRelation.getDstLabel());
+ edgeType.addVertexTypePairRelationsItem(pair);
+ }
+ return edgeType;
+ }
+
+ private static Map convertToPropertyMap(List properties) {
+ Map propertyMap = new HashMap<>();
+ for (Property property : properties) {
+ String value = extractValue(property.getValue());
+ propertyMap.put(property.getName(), value);
+ }
+ return propertyMap;
+ }
+
+ private static List convertToDtoProperties(
+ List properties) {
+ List propertyMetas = new ArrayList<>();
+ for (com.alibaba.graphscope.groot.sdk.schema.Property property : properties) {
+ GetPropertyMeta propertyMeta = new GetPropertyMeta();
+ propertyMeta.setPropertyName(property.getName());
+ propertyMeta.setPropertyId(property.getId());
+ propertyMeta.setPropertyType(convertToDtoDataType(property.getDataType()));
+ propertyMetas.add(propertyMeta);
+ }
+ return propertyMetas;
+ }
+
+ private static GSDataType convertToDtoDataType(DataTypePb dataType) {
+ switch (dataType) {
+ case INT:
+ return new PrimitiveType(
+ PrimitiveType.PrimitiveTypeEnum.SIGNED_INT32, "PrimitiveType");
+ case UINT:
+ return new PrimitiveType(
+ PrimitiveType.PrimitiveTypeEnum.UNSIGNED_INT32, "PrimitiveType");
+ case LONG:
+ return new PrimitiveType(
+ PrimitiveType.PrimitiveTypeEnum.SIGNED_INT64, "PrimitiveType");
+ case ULONG:
+ return new PrimitiveType(
+ PrimitiveType.PrimitiveTypeEnum.UNSIGNED_INT64, "PrimitiveType");
+ case BOOL:
+ return new PrimitiveType(PrimitiveType.PrimitiveTypeEnum.BOOL, "PrimitiveType");
+ case FLOAT:
+ return new PrimitiveType(PrimitiveType.PrimitiveTypeEnum.FLOAT, "PrimitiveType");
+ case DOUBLE:
+ return new PrimitiveType(PrimitiveType.PrimitiveTypeEnum.DOUBLE, "PrimitiveType");
+ case STRING:
+ return new PrimitiveType(PrimitiveType.PrimitiveTypeEnum.STRING, "PrimitiveType");
+ case DATE32:
+ TemporalTypeAllOfTemporal date = new DateType("YYYY-MM-DD".toString(), "DateType");
+ return new TemporalType(date, "TemporalType");
+ case TIMESTAMP_MS:
+ // TODO: confirm the format of timestamp? should be int64 milliseconds since
+ // 1970-01-01 00:00:00.000000?
+ TemporalTypeAllOfTemporal timestamp =
+ new TimeStampType("YYYY-MM-DD HH:MM:SS".toString(), "TimeStampType");
+ return new TemporalType(timestamp, "TemporalType");
+ default:
+ throw new IllegalArgumentException("Unsupported data type: " + dataType);
+ }
+ }
+
+ private static String extractValue(JsonNullable
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring-boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring-boot.version}
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ ${spring-boot.version}
+ import
+ pom
+
@@ -885,6 +908,11 @@
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+