This is an automated email from the ASF dual-hosted git repository.

weibin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-graphar.git


The following commit(s) were added to refs/heads/main by this push:
     new e265e0e3 feat(java-info): Refactor the java-info module base on the 
format protocol files (#595)
e265e0e3 is described below

commit e265e0e38e69dc57c94be04d8482d6f7fa1630e2
Author: John <sp...@apache.org>
AuthorDate: Thu Sep 19 10:04:50 2024 +0800

    feat(java-info): Refactor the java-info module base on the format protocol 
files (#595)
---
 maven-projects/info/pom.xml                        |   6 +
 .../java/org/apache/graphar/info/AdjacentList.java |  40 +--
 .../java/org/apache/graphar/info/EdgeInfo.java     | 278 +++++++--------------
 .../java/org/apache/graphar/info/GraphInfo.java    | 221 ++++++----------
 .../java/org/apache/graphar/info/Property.java     |  42 ++--
 .../org/apache/graphar/info/PropertyGroup.java     | 117 ++++++---
 .../java/org/apache/graphar/info/VertexInfo.java   | 150 ++++-------
 .../FileType.java => loader/GraphLoader.java}      |  26 +-
 .../graphar/info/loader/LocalYamlGraphLoader.java  |  81 ++++++
 .../{type/FileType.java => saver/GraphSaver.java}  |  26 +-
 .../graphar/info/saver/LocalYamlGraphSaver.java    |  69 +++++
 .../org/apache/graphar/info/type/AdjListType.java  |  50 ----
 .../org/apache/graphar/info/type/DataType.java     |  69 -----
 .../apache/graphar/info/yaml/AdjacentListYaml.java |  23 +-
 .../org/apache/graphar/info/yaml/EdgeYaml.java     |  23 +-
 .../apache/graphar/info/yaml/EnumTransferUtil.java | 130 ++++++++++
 .../org/apache/graphar/info/yaml/GraphYaml.java    |   3 +-
 .../graphar/info/yaml/PropertyGroupYaml.java       |   9 +-
 .../org/apache/graphar/info/yaml/PropertyYaml.java |  10 +-
 .../org/apache/graphar/info/yaml/VertexYaml.java   |  13 +-
 .../org/apache/graphar/info/GraphLoaderTest.java   |  61 +++++
 .../org/apache/graphar/info/GraphSaverTest.java    |  54 ++++
 .../java/org/apache/graphar/info/TestUtil.java     | 143 +++++++++++
 23 files changed, 951 insertions(+), 693 deletions(-)

diff --git a/maven-projects/info/pom.xml b/maven-projects/info/pom.xml
index e9b0a607..bcb89d55 100644
--- a/maven-projects/info/pom.xml
+++ b/maven-projects/info/pom.xml
@@ -42,9 +42,15 @@
         <maven.compiler.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <proto-info.version>0.13.0.dev-SNAPSHOT</proto-info.version>
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.apache.graphar</groupId>
+            <artifactId>proto</artifactId>
+            <version>${proto-info.version}</version>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/AdjacentList.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/AdjacentList.java
index 091cc80c..161eac27 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/AdjacentList.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/AdjacentList.java
@@ -19,38 +19,42 @@
 
 package org.apache.graphar.info;
 
-import org.apache.graphar.info.type.AdjListType;
-import org.apache.graphar.info.type.FileType;
-import org.apache.graphar.info.yaml.AdjacentListYaml;
+import org.apache.graphar.proto.AdjListType;
+import org.apache.graphar.proto.FileType;
 
 public class AdjacentList {
-    private final AdjListType type;
-    private final FileType fileType;
-    private final String prefix;
+    private final org.apache.graphar.proto.AdjacentList protoAdjacentList;
 
     public AdjacentList(AdjListType type, FileType fileType, String prefix) {
-        this.type = type;
-        this.fileType = fileType;
-        this.prefix = prefix;
+        protoAdjacentList =
+                org.apache.graphar.proto.AdjacentList.newBuilder()
+                        .setType(type)
+                        .setFileType(fileType)
+                        .setPrefix(prefix)
+                        .build();
     }
 
-    AdjacentList(AdjacentListYaml yamlParser) {
-        this.type =
-                AdjListType.fromOrderedAndAlignedBy(
-                        yamlParser.isOrdered(), yamlParser.isAligned_by());
-        this.fileType = FileType.valueOf(yamlParser.getFile_type());
-        this.prefix = yamlParser.getPrefix();
+    private AdjacentList(org.apache.graphar.proto.AdjacentList 
protoAdjacentList) {
+        this.protoAdjacentList = protoAdjacentList;
+    }
+
+    public static AdjacentList ofProto(org.apache.graphar.proto.AdjacentList 
protoAdjacentList) {
+        return new AdjacentList(protoAdjacentList);
     }
 
     public AdjListType getType() {
-        return type;
+        return protoAdjacentList.getType();
     }
 
     public FileType getFileType() {
-        return fileType;
+        return protoAdjacentList.getFileType();
     }
 
     public String getPrefix() {
-        return prefix;
+        return protoAdjacentList.getPrefix();
+    }
+
+    org.apache.graphar.proto.AdjacentList getProto() {
+        return protoAdjacentList;
     }
 }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/EdgeInfo.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/EdgeInfo.java
index ff974c63..556f2672 100644
--- a/maven-projects/info/src/main/java/org/apache/graphar/info/EdgeInfo.java
+++ b/maven-projects/info/src/main/java/org/apache/graphar/info/EdgeInfo.java
@@ -19,37 +19,23 @@
 
 package org.apache.graphar.info;
 
-import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.apache.graphar.info.type.AdjListType;
-import org.apache.graphar.info.type.DataType;
 import org.apache.graphar.info.yaml.EdgeYaml;
 import org.apache.graphar.info.yaml.GraphYaml;
+import org.apache.graphar.proto.AdjListType;
+import org.apache.graphar.proto.DataType;
 import org.apache.graphar.util.GeneralParams;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.yaml.snakeyaml.LoaderOptions;
 import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.constructor.Constructor;
 
 public class EdgeInfo {
-    private final EdgeTriplet edgeTriplet;
-    private final long chunkSize;
-    private final long srcChunkSize;
-    private final long dstChunkSize;
-    private final boolean directed;
-    private final String prefix;
-    private final Map<AdjListType, AdjacentList> adjacentLists;
-    private final PropertyGroups propertyGroups;
-    private final String version;
+    private final org.apache.graphar.proto.EdgeInfo protoEdgeInfo;
+    private final Map<AdjListType, AdjacentList> cachedAdjacentLists;
+    private final PropertyGroups cachedPropertyGroups;
 
     public EdgeInfo(
             String srcLabel,
@@ -61,135 +47,100 @@ public class EdgeInfo {
             boolean directed,
             String prefix,
             List<AdjacentList> adjacentListsAsList,
-            List<PropertyGroup> propertyGroupsAsList,
-            String version) {
-        this.edgeTriplet = new EdgeTriplet(srcLabel, edgeLabel, dstLabel);
-        this.chunkSize = chunkSize;
-        this.srcChunkSize = srcChunkSize;
-        this.dstChunkSize = dstChunkSize;
-        this.directed = directed;
-        this.prefix = prefix;
-        this.adjacentLists =
+            List<PropertyGroup> propertyGroupsAsList) {
+        this.cachedAdjacentLists =
                 adjacentListsAsList.stream()
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         AdjacentList::getType, 
Function.identity()));
-        this.propertyGroups = new PropertyGroups(propertyGroupsAsList);
-        this.version = version;
-    }
-
-    private EdgeInfo(EdgeYaml yamlParser) {
-        this(
-                yamlParser.getSrc_type(),
-                yamlParser.getEdge_type(),
-                yamlParser.getDst_type(),
-                yamlParser.getChunk_size(),
-                yamlParser.getSrc_chunk_size(),
-                yamlParser.getDst_chunk_size(),
-                yamlParser.isDirected(),
-                yamlParser.getPrefix(),
-                yamlParser.getAdj_lists().stream()
-                        .map(AdjacentList::new)
-                        .collect(Collectors.toUnmodifiableList()),
-                yamlParser.getProperty_groups().stream()
-                        .map(PropertyGroup::new)
-                        .collect(Collectors.toUnmodifiableList()),
-                yamlParser.getVersion());
+        this.cachedPropertyGroups = new PropertyGroups(propertyGroupsAsList);
+        this.protoEdgeInfo =
+                org.apache.graphar.proto.EdgeInfo.newBuilder()
+                        .setSourceVertexType(srcLabel)
+                        .setType(edgeLabel)
+                        .setDestinationVertexChunkSize(dstChunkSize)
+                        .setChunkSize(chunkSize)
+                        .setSourceVertexChunkSize(srcChunkSize)
+                        .setDestinationVertexType(dstLabel)
+                        .setIsDirected(directed)
+                        .setPrefix(prefix)
+                        .addAllAdjacentList(
+                                adjacentListsAsList.stream()
+                                        .map(AdjacentList::getProto)
+                                        
.collect(Collectors.toUnmodifiableList()))
+                        .addAllProperties(
+                                propertyGroupsAsList.stream()
+                                        .map(PropertyGroup::getProto)
+                                        
.collect(Collectors.toUnmodifiableList()))
+                        .build();
+    }
+
+    public EdgeInfo(org.apache.graphar.proto.EdgeInfo protoEdgeInfo) {
+        this.protoEdgeInfo = protoEdgeInfo;
+        this.cachedAdjacentLists =
+                protoEdgeInfo.getAdjacentListList().stream()
+                        .map(AdjacentList::ofProto)
+                        .collect(
+                                Collectors.toUnmodifiableMap(
+                                        AdjacentList::getType, 
Function.identity()));
+        this.cachedPropertyGroups = 
PropertyGroups.ofProto(protoEdgeInfo.getPropertiesList());
     }
 
     private EdgeInfo(
-            EdgeTriplet edgeTriplet,
-            long chunkSize,
-            long srcChunkSize,
-            long dstChunkSize,
-            boolean directed,
-            String prefix,
-            Map<AdjListType, AdjacentList> adjacentLists,
-            PropertyGroups propertyGroups,
-            String version) {
-        this.edgeTriplet = edgeTriplet;
-        this.chunkSize = chunkSize;
-        this.srcChunkSize = srcChunkSize;
-        this.dstChunkSize = dstChunkSize;
-        this.directed = directed;
-        this.prefix = prefix;
-        this.adjacentLists = adjacentLists;
-        this.propertyGroups = propertyGroups;
-        this.version = version;
-    }
-
-    public static EdgeInfo load(String edgeInfoPath) throws IOException {
-        return load(edgeInfoPath, new Configuration());
-    }
-
-    public static EdgeInfo load(String edgeInfoPath, Configuration conf) 
throws IOException {
-        if (conf == null) {
-            throw new IllegalArgumentException("Configuration is null");
-        }
-        return load(edgeInfoPath, FileSystem.get(conf));
+            org.apache.graphar.proto.EdgeInfo protoEdgeInfo,
+            Map<AdjListType, AdjacentList> cachedAdjacentLists,
+            PropertyGroups cachedPropertyGroups) {
+        this.protoEdgeInfo = protoEdgeInfo;
+        this.cachedAdjacentLists = cachedAdjacentLists;
+        this.cachedPropertyGroups = cachedPropertyGroups;
     }
 
-    public static EdgeInfo load(String edgeInfoPath, FileSystem fileSystem) 
throws IOException {
-        if (fileSystem == null) {
-            throw new IllegalArgumentException("FileSystem is null");
-        }
-        FSDataInputStream inputStream = fileSystem.open(new 
Path(edgeInfoPath));
-        Yaml edgeInfoYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new 
LoaderOptions()));
-        EdgeYaml edgeInfoYaml = edgeInfoYamlLoader.load(inputStream);
-        return new EdgeInfo(edgeInfoYaml);
+    org.apache.graphar.proto.EdgeInfo getProto() {
+        return protoEdgeInfo;
+    }
+
+    public static String concat(String srcLabel, String edgeLabel, String 
dstLabel) {
+        return srcLabel
+                + GeneralParams.regularSeparator
+                + edgeLabel
+                + GeneralParams.regularSeparator
+                + dstLabel;
     }
 
     public Optional<EdgeInfo> addAdjacentListAsNew(AdjacentList adjacentList) {
-        if (adjacentList == null || 
adjacentLists.containsKey(adjacentList.getType())) {
+        if (adjacentList == null || 
cachedAdjacentLists.containsKey(adjacentList.getType())) {
             return Optional.empty();
         }
         Map<AdjListType, AdjacentList> newAdjacentLists =
                 Stream.concat(
-                                adjacentLists.entrySet().stream(),
+                                cachedAdjacentLists.entrySet().stream(),
                                 Map.of(adjacentList.getType(), 
adjacentList).entrySet().stream())
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         Map.Entry::getKey, 
Map.Entry::getValue));
-        return Optional.of(
-                new EdgeInfo(
-                        edgeTriplet,
-                        chunkSize,
-                        srcChunkSize,
-                        dstChunkSize,
-                        directed,
-                        prefix,
-                        newAdjacentLists,
-                        propertyGroups,
-                        version));
+        return Optional.of(new EdgeInfo(protoEdgeInfo, newAdjacentLists, 
cachedPropertyGroups));
     }
 
     public Optional<EdgeInfo> addPropertyGroupAsNew(PropertyGroup 
propertyGroup) {
-        return propertyGroups
+        // do not need check property group exist, because PropertyGroups will 
check it
+        return cachedPropertyGroups
                 .addPropertyGroupAsNew(propertyGroup)
                 .map(
                         newPropertyGroups ->
                                 new EdgeInfo(
-                                        edgeTriplet,
-                                        chunkSize,
-                                        srcChunkSize,
-                                        dstChunkSize,
-                                        directed,
-                                        prefix,
-                                        adjacentLists,
-                                        newPropertyGroups,
-                                        version));
+                                        protoEdgeInfo, cachedAdjacentLists, 
newPropertyGroups));
     }
 
     public boolean hasAdjListType(AdjListType adjListType) {
-        return adjacentLists.containsKey(adjListType);
+        return cachedAdjacentLists.containsKey(adjListType);
     }
 
     public boolean hasProperty(String propertyName) {
-        return propertyGroups.hasProperty(propertyName);
+        return cachedPropertyGroups.hasProperty(propertyName);
     }
 
     public boolean hasPropertyGroup(PropertyGroup propertyGroup) {
-        return propertyGroups.hasPropertyGroup(propertyGroup);
+        return cachedPropertyGroups.hasPropertyGroup(propertyGroup);
     }
 
     public AdjacentList getAdjacentList(AdjListType adjListType) {
@@ -197,15 +148,15 @@ public class EdgeInfo {
         // other methods which get adjacent list in this class should call 
this method first,
         // so we don't check AdjListType in other methods.
         checkAdjListTypeExist(adjListType);
-        return adjacentLists.get(adjListType);
+        return cachedAdjacentLists.get(adjListType);
     }
 
     public int getPropertyGroupNum() {
-        return propertyGroups.getPropertyGroupNum();
+        return cachedPropertyGroups.getPropertyGroupNum();
     }
 
     public PropertyGroup getPropertyGroup(String property) {
-        return propertyGroups.getPropertyGroup(property);
+        return cachedPropertyGroups.getPropertyGroup(property);
     }
 
     public String getPropertyGroupPrefix(PropertyGroup propertyGroup) {
@@ -243,35 +194,15 @@ public class EdgeInfo {
     }
 
     public DataType getPropertyType(String propertyName) {
-        return propertyGroups.getPropertyType(propertyName);
+        return cachedPropertyGroups.getPropertyType(propertyName);
     }
 
     public boolean isPrimaryKey(String propertyName) {
-        return propertyGroups.isPrimaryKey(propertyName);
+        return cachedPropertyGroups.isPrimaryKey(propertyName);
     }
 
     public boolean isNullableKey(String propertyName) {
-        return propertyGroups.isNullableKey(propertyName);
-    }
-
-    public void save(String filePath) throws IOException {
-        save(filePath, new Configuration());
-    }
-
-    public void save(String filePath, Configuration conf) throws IOException {
-        if (conf == null) {
-            throw new IllegalArgumentException("Configuration is null");
-        }
-        save(filePath, FileSystem.get(conf));
-    }
-
-    public void save(String fileName, FileSystem fileSystem) throws 
IOException {
-        if (fileSystem == null) {
-            throw new IllegalArgumentException("FileSystem is null");
-        }
-        FSDataOutputStream outputStream = fileSystem.create(new 
Path(fileName));
-        outputStream.writeBytes(dump());
-        outputStream.close();
+        return cachedPropertyGroups.isNullableKey(propertyName);
     }
 
     public String dump() {
@@ -281,63 +212,63 @@ public class EdgeInfo {
     }
 
     public String getConcat() {
-        return edgeTriplet.getConcat();
+        return concat(getSrcLabel(), getEdgeLabel(), getDstLabel());
     }
 
     public String getSrcLabel() {
-        return edgeTriplet.getSrcLabel();
+        return protoEdgeInfo.getSourceVertexType();
     }
 
     public String getEdgeLabel() {
-        return edgeTriplet.getEdgeLabel();
+        return protoEdgeInfo.getType();
     }
 
     public String getDstLabel() {
-        return edgeTriplet.getDstLabel();
+        return protoEdgeInfo.getDestinationVertexType();
     }
 
     public long getChunkSize() {
-        return chunkSize;
+        return protoEdgeInfo.getChunkSize();
     }
 
     public long getSrcChunkSize() {
-        return srcChunkSize;
+        return protoEdgeInfo.getSourceVertexChunkSize();
     }
 
     public long getDstChunkSize() {
-        return dstChunkSize;
+        return protoEdgeInfo.getDestinationVertexChunkSize();
     }
 
     public boolean isDirected() {
-        return directed;
+        return protoEdgeInfo.getIsDirected();
     }
 
     public String getPrefix() {
-        return prefix;
+        return protoEdgeInfo.getPrefix();
     }
 
-    public Map<AdjListType, AdjacentList> getAdjacentLists() {
-        return adjacentLists;
+    public String getEdgePath() {
+        return getPrefix() + "/" + getConcat() + ".edge.yaml";
     }
 
-    public List<PropertyGroup> getPropertyGroups() {
-        return propertyGroups.getPropertyGroupList();
+    public Map<AdjListType, AdjacentList> getAdjacentLists() {
+        return cachedAdjacentLists;
     }
 
-    public String getVersion() {
-        return version;
+    public List<PropertyGroup> getPropertyGroups() {
+        return cachedPropertyGroups.getPropertyGroupList();
     }
 
     private void checkAdjListTypeExist(AdjListType adjListType) {
         if (adjListType == null) {
             throw new IllegalArgumentException("The adjacency list type is 
null");
         }
-        if (!adjacentLists.containsKey(adjListType)) {
+        if (!cachedAdjacentLists.containsKey(adjListType)) {
             throw new IllegalArgumentException(
                     "The adjacency list type "
                             + adjListType
                             + " does not exist in the edge info "
-                            + this.edgeTriplet.getConcat());
+                            + getConcat());
         }
     }
 
@@ -353,41 +284,4 @@ public class EdgeInfo {
                             + getConcat());
         }
     }
-
-    private static class EdgeTriplet {
-        private final String srcLabel;
-        private final String edgeLabel;
-        private final String dstLabel;
-
-        public EdgeTriplet(String srcLabel, String edgeLabel, String dstLabel) 
{
-            this.srcLabel = srcLabel;
-            this.edgeLabel = edgeLabel;
-            this.dstLabel = dstLabel;
-        }
-
-        public String getConcat() {
-            return srcLabel
-                    + GeneralParams.regularSeparator
-                    + edgeLabel
-                    + GeneralParams.regularSeparator
-                    + dstLabel;
-        }
-
-        @Override
-        public String toString() {
-            return getConcat();
-        }
-
-        public String getSrcLabel() {
-            return srcLabel;
-        }
-
-        public String getEdgeLabel() {
-            return edgeLabel;
-        }
-
-        public String getDstLabel() {
-            return dstLabel;
-        }
-    }
 }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/GraphInfo.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/GraphInfo.java
index c8d00d61..b2177080 100644
--- a/maven-projects/info/src/main/java/org/apache/graphar/info/GraphInfo.java
+++ b/maven-projects/info/src/main/java/org/apache/graphar/info/GraphInfo.java
@@ -19,8 +19,6 @@
 
 package org.apache.graphar.info;
 
-import java.io.IOException;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -29,114 +27,56 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.graphar.info.yaml.GraphYaml;
 import org.apache.graphar.util.GeneralParams;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.yaml.snakeyaml.LoaderOptions;
 import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.constructor.Constructor;
 
 public class GraphInfo {
-    private final String name;
-    private final List<VertexInfo> vertexInfos;
-    private final List<EdgeInfo> edgeInfos;
-    private final String prefix;
-    private final Map<String, VertexInfo> vertexLabel2VertexInfo;
-    private final Map<String, EdgeInfo> edgeConcat2EdgeInfo;
-    private final String version;
+    private final org.apache.graphar.proto.GraphInfo protoGraphInfo;
+    private final List<VertexInfo> cachedVertexInfoList;
+    private final List<EdgeInfo> cachedEdgeInfoList;
+    private final Map<String, VertexInfo> cachedVertexInfoMap;
+    private final Map<String, EdgeInfo> cachedEdgeInfoMap;
 
     public GraphInfo(
-            String name,
-            List<VertexInfo> vertexInfos,
-            List<EdgeInfo> edgeInfos,
-            String prefix,
-            String version) {
-        this.name = name;
-        this.vertexInfos = List.copyOf(vertexInfos);
-        this.edgeInfos = List.copyOf(edgeInfos);
-        this.prefix = prefix;
-        this.version = version;
-        this.vertexLabel2VertexInfo =
+            String name, List<VertexInfo> vertexInfos, List<EdgeInfo> 
edgeInfos, String prefix) {
+        this.cachedVertexInfoList = List.copyOf(vertexInfos);
+        this.cachedEdgeInfoList = List.copyOf(edgeInfos);
+        this.cachedVertexInfoMap =
                 vertexInfos.stream()
                         .collect(
                                 Collectors.toUnmodifiableMap(
-                                        VertexInfo::getLabel, 
Function.identity()));
-        this.edgeConcat2EdgeInfo =
+                                        VertexInfo::getType, 
Function.identity()));
+        this.cachedEdgeInfoMap =
                 edgeInfos.stream()
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         EdgeInfo::getConcat, 
Function.identity()));
-    }
-
-    private GraphInfo(GraphYaml graphYaml, Configuration conf) throws 
IOException {
-        this(
-                graphYaml.getName(),
-                vertexFileNames2VertexInfos(graphYaml.getVertices(), conf),
-                edgeFileNames2EdgeInfos(graphYaml.getEdges(), conf),
-                graphYaml.getPrefix(),
-                graphYaml.getVersion());
+        this.protoGraphInfo =
+                org.apache.graphar.proto.GraphInfo.newBuilder()
+                        .setName(name)
+                        .addAllVertices(
+                                vertexInfos.stream()
+                                        .map(VertexInfo::getVertexPath)
+                                        .collect(Collectors.toList()))
+                        .addAllEdges(
+                                edgeInfos.stream()
+                                        .map(EdgeInfo::getEdgePath)
+                                        .collect(Collectors.toList()))
+                        .setPrefix(prefix)
+                        .build();
     }
 
     private GraphInfo(
-            String name,
-            List<VertexInfo> vertexInfos,
-            List<EdgeInfo> edgeInfos,
-            String prefix,
-            Map<String, VertexInfo> vertexLabel2VertexInfo,
-            Map<String, EdgeInfo> edgeConcat2EdgeInfo,
-            String version) {
-        this.name = name;
-        this.vertexInfos = vertexInfos;
-        this.edgeInfos = edgeInfos;
-        this.prefix = prefix;
-        this.vertexLabel2VertexInfo = vertexLabel2VertexInfo;
-        this.edgeConcat2EdgeInfo = edgeConcat2EdgeInfo;
-        this.version = version;
-    }
-
-    public static GraphInfo load(String graphPath) throws IOException {
-        return load(graphPath, new Configuration());
-    }
-
-    public static GraphInfo load(String graphPath, FileSystem fileSystem) 
throws IOException {
-        if (fileSystem == null) {
-            throw new IllegalArgumentException("FileSystem is null");
-        }
-        return load(graphPath, fileSystem.getConf());
-    }
-
-    public static GraphInfo load(String graphPath, Configuration conf) throws 
IOException {
-        if (conf == null) {
-            throw new IllegalArgumentException("Configuration is null");
-        }
-        Path path = new Path(graphPath);
-        FileSystem fileSystem = path.getFileSystem(conf);
-        FSDataInputStream inputStream = fileSystem.open(path);
-        Yaml graphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new 
LoaderOptions()));
-        GraphYaml graphYaml = graphYamlLoader.load(inputStream);
-        return new GraphInfo(graphYaml, conf);
-    }
-
-    public void save(String filePath) throws IOException {
-        save(filePath, new Configuration());
-    }
+            org.apache.graphar.proto.GraphInfo protoGraphInfo,
+            List<VertexInfo> cachedVertexInfoList,
+            List<EdgeInfo> cachedEdgeInfoList,
+            Map<String, VertexInfo> cachedVertexInfoMap,
+            Map<String, EdgeInfo> cachedEdgeInfoMap) {
 
-    public void save(String filePath, Configuration conf) throws IOException {
-        if (conf == null) {
-            throw new IllegalArgumentException("Configuration is null");
-        }
-        save(filePath, FileSystem.get(conf));
-    }
-
-    public void save(String fileName, FileSystem fileSystem) throws 
IOException {
-        if (fileSystem == null) {
-            throw new IllegalArgumentException("FileSystem is null");
-        }
-        FSDataOutputStream outputStream = fileSystem.create(new 
Path(fileName));
-        outputStream.writeBytes(dump());
-        outputStream.close();
+        this.protoGraphInfo = protoGraphInfo;
+        this.cachedVertexInfoList = cachedVertexInfoList;
+        this.cachedEdgeInfoList = cachedEdgeInfoList;
+        this.cachedVertexInfoMap = cachedVertexInfoMap;
+        this.cachedEdgeInfoMap = cachedEdgeInfoMap;
     }
 
     public String dump() {
@@ -146,28 +86,30 @@ public class GraphInfo {
     }
 
     public Optional<GraphInfo> addVertexAsNew(VertexInfo vertexInfo) {
-        if (vertexInfo == null || hasVertexInfo(vertexInfo.getLabel())) {
+        if (vertexInfo == null || hasVertexInfo(vertexInfo.getType())) {
             return Optional.empty();
         }
-        List<VertexInfo> newVertexInfos =
-                Stream.concat(vertexInfos.stream(), Stream.of(vertexInfo))
+        final org.apache.graphar.proto.GraphInfo newProtoGraphInfo =
+                org.apache.graphar.proto.GraphInfo.newBuilder(protoGraphInfo)
+                        .addVertices(vertexInfo.getVertexPath())
+                        .build();
+        final List<VertexInfo> newVertexInfoList =
+                Stream.concat(cachedVertexInfoList.stream(), 
Stream.of(vertexInfo))
                         .collect(Collectors.toList());
-        Map<String, VertexInfo> newVertexLabel2VertexInfo =
+        final Map<String, VertexInfo> newVertexInfoMap =
                 Stream.concat(
-                                vertexLabel2VertexInfo.entrySet().stream(),
-                                Stream.of(Map.entry(vertexInfo.getLabel(), 
vertexInfo)))
+                                cachedVertexInfoMap.entrySet().stream(),
+                                Stream.of(Map.entry(vertexInfo.getType(), 
vertexInfo)))
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         Map.Entry::getKey, 
Map.Entry::getValue));
         return Optional.of(
                 new GraphInfo(
-                        name,
-                        newVertexInfos,
-                        edgeInfos,
-                        prefix,
-                        newVertexLabel2VertexInfo,
-                        edgeConcat2EdgeInfo,
-                        version));
+                        newProtoGraphInfo,
+                        newVertexInfoList,
+                        cachedEdgeInfoList,
+                        newVertexInfoMap,
+                        cachedEdgeInfoMap));
     }
 
     public Optional<GraphInfo> addEdgeAsNew(EdgeInfo edgeInfo) {
@@ -176,88 +118,69 @@ public class GraphInfo {
                         edgeInfo.getSrcLabel(), edgeInfo.getEdgeLabel(), 
edgeInfo.getDstLabel())) {
             return Optional.empty();
         }
-        List<EdgeInfo> newEdgeInfos =
-                Stream.concat(edgeInfos.stream(), 
Stream.of(edgeInfo)).collect(Collectors.toList());
-        Map<String, EdgeInfo> newEdgeConcat2EdgeInfo =
+        final org.apache.graphar.proto.GraphInfo newProtoGraphInfo =
+                org.apache.graphar.proto.GraphInfo.newBuilder(protoGraphInfo)
+                        .addEdges(edgeInfo.getEdgePath())
+                        .build();
+        final List<EdgeInfo> newEdgeInfos =
+                Stream.concat(cachedEdgeInfoList.stream(), Stream.of(edgeInfo))
+                        .collect(Collectors.toList());
+        final Map<String, EdgeInfo> newEdgeConcat2EdgeInfo =
                 Stream.concat(
-                                edgeConcat2EdgeInfo.entrySet().stream(),
+                                cachedEdgeInfoMap.entrySet().stream(),
                                 Stream.of(Map.entry(edgeInfo.getConcat(), 
edgeInfo)))
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         Map.Entry::getKey, 
Map.Entry::getValue));
         return Optional.of(
                 new GraphInfo(
-                        name,
-                        vertexInfos,
+                        newProtoGraphInfo,
+                        cachedVertexInfoList,
                         newEdgeInfos,
-                        prefix,
-                        vertexLabel2VertexInfo,
-                        newEdgeConcat2EdgeInfo,
-                        version));
+                        cachedVertexInfoMap,
+                        newEdgeConcat2EdgeInfo));
     }
 
     public boolean hasVertexInfo(String label) {
-        return vertexLabel2VertexInfo.containsKey(label);
+        return cachedVertexInfoMap.containsKey(label);
     }
 
     public boolean hasEdgeInfo(String srcLabel, String edgeLabel, String 
dstLabel) {
-        return edgeConcat2EdgeInfo.containsKey(srcLabel + dstLabel + 
edgeLabel);
+        return cachedEdgeInfoMap.containsKey(EdgeInfo.concat(srcLabel, 
edgeLabel, dstLabel));
     }
 
     public VertexInfo getVertexInfo(String label) {
         checkVertexExist(label);
-        return vertexLabel2VertexInfo.get(label);
+        return cachedVertexInfoMap.get(label);
     }
 
     public EdgeInfo getEdgeInfo(String srcLabel, String edgeLabel, String 
dstLabel) {
         checkEdgeExist(srcLabel, edgeLabel, dstLabel);
-        return edgeConcat2EdgeInfo.get(srcLabel + edgeLabel + dstLabel);
+        return cachedEdgeInfoMap.get(EdgeInfo.concat(srcLabel, edgeLabel, 
dstLabel));
     }
 
     public int getVertexInfoNum() {
-        return vertexInfos.size();
+        return cachedVertexInfoList.size();
     }
 
     public int getEdgeInfoNum() {
-        return edgeInfos.size();
+        return cachedEdgeInfoList.size();
     }
 
     public String getName() {
-        return name;
+        return protoGraphInfo.getName();
     }
 
     public List<VertexInfo> getVertexInfos() {
-        return vertexInfos;
+        return cachedVertexInfoList;
     }
 
     public List<EdgeInfo> getEdgeInfos() {
-        return edgeInfos;
+        return cachedEdgeInfoList;
     }
 
     public String getPrefix() {
-        return prefix;
-    }
-
-    public String getVersion() {
-        return version;
-    }
-
-    private static List<VertexInfo> vertexFileNames2VertexInfos(
-            List<String> vertexFileNames, Configuration conf) throws 
IOException {
-        ArrayList<VertexInfo> tempVertices = new 
ArrayList<>(vertexFileNames.size());
-        for (String vertexFileName : vertexFileNames) {
-            tempVertices.add(VertexInfo.load(vertexFileName, conf));
-        }
-        return List.copyOf(tempVertices);
-    }
-
-    private static List<EdgeInfo> edgeFileNames2EdgeInfos(
-            List<String> edgeFileNames, Configuration conf) throws IOException 
{
-        ArrayList<EdgeInfo> tempEdges = new ArrayList<>(edgeFileNames.size());
-        for (String edgeFileName : edgeFileNames) {
-            tempEdges.add(EdgeInfo.load(edgeFileName, conf));
-        }
-        return List.copyOf(tempEdges);
+        return protoGraphInfo.getPrefix();
     }
 
     private void checkVertexExist(String label) {
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
index 1221ebc1..09ce2361 100644
--- a/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
+++ b/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
@@ -19,42 +19,46 @@
 
 package org.apache.graphar.info;
 
-import org.apache.graphar.info.type.DataType;
-import org.apache.graphar.info.yaml.PropertyYaml;
+import org.apache.graphar.proto.DataType;
 
 public class Property {
-    private final String name;
-    private final DataType dataType;
-    private final boolean primary;
-    private final boolean nullable;
+    private final org.apache.graphar.proto.Property protoProperty;
 
     public Property(String name, DataType dataType, boolean primary, boolean 
nullable) {
-        this.name = name;
-        this.dataType = dataType;
-        this.primary = primary;
-        this.nullable = nullable;
+        protoProperty =
+                org.apache.graphar.proto.Property.newBuilder()
+                        .setName(name)
+                        .setType(dataType)
+                        .setIsPrimaryKey(primary)
+                        .setIsNullable(nullable)
+                        .build();
     }
 
-    Property(PropertyYaml yamlParser) {
-        this.name = yamlParser.getName();
-        this.dataType = DataType.fromString(yamlParser.getData_type());
-        this.primary = yamlParser.getIs_primary();
-        this.nullable = yamlParser.getIs_nullable();
+    private Property(org.apache.graphar.proto.Property protoProperty) {
+        this.protoProperty = protoProperty;
+    }
+
+    public static Property ofProto(org.apache.graphar.proto.Property 
protoProperty) {
+        return new Property(protoProperty);
     }
 
     public String getName() {
-        return name;
+        return protoProperty.getName();
     }
 
     public DataType getDataType() {
-        return dataType;
+        return protoProperty.getType();
     }
 
     public boolean isPrimary() {
-        return primary;
+        return protoProperty.getIsPrimaryKey();
     }
 
     public boolean isNullable() {
-        return nullable;
+        return protoProperty.getIsNullable();
+    }
+
+    org.apache.graphar.proto.Property getProto() {
+        return protoProperty;
     }
 }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/PropertyGroup.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/PropertyGroup.java
index 1d922c99..87b8d5bd 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/PropertyGroup.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/PropertyGroup.java
@@ -27,80 +27,109 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.apache.graphar.info.type.DataType;
-import org.apache.graphar.info.type.FileType;
-import org.apache.graphar.info.yaml.PropertyGroupYaml;
+import org.apache.graphar.proto.DataType;
+import org.apache.graphar.proto.FileType;
 import org.apache.graphar.util.GeneralParams;
 
 public class PropertyGroup implements Iterable<Property> {
-    private final List<Property> propertyList;
-    private final Map<String, Property> propertyMap;
-    private final FileType fileType;
-    private final String prefix;
-
-    public PropertyGroup(List<Property> propertyMap, FileType fileType, String 
prefix) {
-        this.propertyList = List.copyOf(propertyMap);
-        this.propertyMap =
-                propertyMap.stream()
+    private final org.apache.graphar.proto.PropertyGroup protoPropertyGroup;
+    private final List<Property> cachedPropertyList;
+    private final Map<String, Property> cachedPropertyMap;
+
+    public PropertyGroup(List<Property> propertyList, FileType fileType, 
String prefix) {
+        this.cachedPropertyList = List.copyOf(propertyList);
+        this.cachedPropertyMap =
+                cachedPropertyList.stream()
+                        .collect(
+                                Collectors.toUnmodifiableMap(
+                                        Property::getName, 
Function.identity()));
+        this.protoPropertyGroup =
+                org.apache.graphar.proto.PropertyGroup.newBuilder()
+                        .addAllProperties(
+                                cachedPropertyList.stream()
+                                        .map(Property::getProto)
+                                        .collect(Collectors.toList()))
+                        .setFileType(fileType)
+                        .setPrefix(prefix)
+                        .build();
+    }
+
+    private PropertyGroup(org.apache.graphar.proto.PropertyGroup 
protoPropertyGroup) {
+        this.protoPropertyGroup = protoPropertyGroup;
+        this.cachedPropertyList =
+                protoPropertyGroup.getPropertiesList().stream()
+                        .map(Property::ofProto)
+                        .collect(Collectors.toUnmodifiableList());
+        this.cachedPropertyMap =
+                cachedPropertyList.stream()
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         Property::getName, 
Function.identity()));
-        this.fileType = fileType;
-        this.prefix = prefix;
     }
 
-    PropertyGroup(PropertyGroupYaml yamlParser) {
-        this(
-                yamlParser.getProperties().stream()
-                        .map(Property::new)
-                        .collect(Collectors.toUnmodifiableList()),
-                FileType.fromString(yamlParser.getFile_type()),
-                yamlParser.getPrefix());
+    public static PropertyGroup ofProto(org.apache.graphar.proto.PropertyGroup 
protoPropertyGroup) {
+        return new PropertyGroup(protoPropertyGroup);
     }
 
     public Optional<PropertyGroup> addPropertyAsNew(Property property) {
-        if (property == null || !propertyMap.containsKey(property.getName())) {
+        if (property == null || 
cachedPropertyMap.containsKey(property.getName())) {
             return Optional.empty();
         }
-        List<Property> newPropertyMap =
-                Stream.concat(propertyMap.values().stream(), 
Stream.of(property))
+        List<Property> newPropertyList =
+                Stream.concat(
+                                protoPropertyGroup.getPropertiesList().stream()
+                                        .map(Property::ofProto),
+                                Stream.of(property))
                         .collect(Collectors.toUnmodifiableList());
-        return Optional.of(new PropertyGroup(newPropertyMap, fileType, 
prefix));
+        return Optional.of(
+                new PropertyGroup(
+                        newPropertyList,
+                        protoPropertyGroup.getFileType(),
+                        protoPropertyGroup.getPrefix()));
     }
 
     @Override
     public Iterator<Property> iterator() {
-        return propertyList.iterator();
+        return cachedPropertyList.iterator();
     }
 
     @Override
     public String toString() {
-        return propertyList.stream()
+        return cachedPropertyList.stream()
                 .map(Property::getName)
                 .collect(Collectors.joining(GeneralParams.regularSeparator));
     }
 
     public int size() {
-        return propertyList.size();
+        return cachedPropertyList.size();
     }
 
     public List<Property> getPropertyList() {
-        return propertyList;
+        return cachedPropertyList;
     }
 
-    public Map<String, Property> getPropertyMap() {
-        return propertyMap;
+    public Map<String, Property> getCachedPropertyMap() {
+        return cachedPropertyMap;
     }
 
     public FileType getFileType() {
-        return fileType;
+        return protoPropertyGroup.getFileType();
     }
 
     public String getPrefix() {
-        return prefix;
+        return protoPropertyGroup.getPrefix();
+    }
+
+    org.apache.graphar.proto.PropertyGroup getProto() {
+        return protoPropertyGroup;
     }
 }
 
+/**
+ * PropertyGroups is a helper class to manage a list of PropertyGroup objects, 
which can be used by
+ * {@link org.apache.graphar.info.VertexInfo} and {@link 
org.apache.graphar.info.EdgeInfo}
+ * conveniently. but should not be exposed to outer side of the package.
+ */
 class PropertyGroups {
     private final List<PropertyGroup> propertyGroupList;
     private final Map<String, PropertyGroup> propertyGroupMap;
@@ -110,7 +139,9 @@ class PropertyGroups {
         this.propertyGroupList = List.copyOf(propertyGroupList);
         this.properties =
                 propertyGroupList.stream()
-                        .flatMap(propertyGroup -> 
propertyGroup.getPropertyMap().values().stream())
+                        .flatMap(
+                                propertyGroup ->
+                                        
propertyGroup.getCachedPropertyMap().values().stream())
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         Property::getName, 
Function.identity()));
@@ -132,6 +163,14 @@ class PropertyGroups {
         this.properties = properties;
     }
 
+    static PropertyGroups ofProto(
+            List<org.apache.graphar.proto.PropertyGroup> protoPropertyGroups) {
+        return new PropertyGroups(
+                protoPropertyGroups.stream()
+                        .map(PropertyGroup::ofProto)
+                        .collect(Collectors.toList()));
+    }
+
     Optional<PropertyGroups> addPropertyGroupAsNew(PropertyGroup 
propertyGroup) {
         if (propertyGroup == null || propertyGroup.size() == 0 || 
hasPropertyGroup(propertyGroup)) {
             return Optional.empty();
@@ -144,22 +183,20 @@ class PropertyGroups {
         List<PropertyGroup> newPropertyGroupsAsList =
                 Stream.concat(propertyGroupList.stream(), 
Stream.of(propertyGroup))
                         .collect(Collectors.toUnmodifiableList());
-        Map<String, PropertyGroup> tempPropertyGroupAsMap = new 
HashMap<>(propertyGroupMap);
+        Map<String, PropertyGroup> tempPropertyGroupMap = new 
HashMap<>(propertyGroupMap);
         for (Property property : propertyGroup) {
-            tempPropertyGroupAsMap.put(property.getName(), propertyGroup);
+            tempPropertyGroupMap.put(property.getName(), propertyGroup);
         }
         Map<String, Property> newProperties =
                 Stream.concat(
                                 properties.values().stream(),
-                                
propertyGroup.getPropertyMap().values().stream())
+                                
propertyGroup.getCachedPropertyMap().values().stream())
                         .collect(
                                 Collectors.toUnmodifiableMap(
                                         Property::getName, 
Function.identity()));
         return Optional.of(
                 new PropertyGroups(
-                        newPropertyGroupsAsList,
-                        Map.copyOf(tempPropertyGroupAsMap),
-                        newProperties));
+                        newPropertyGroupsAsList, 
Map.copyOf(tempPropertyGroupMap), newProperties));
     }
 
     boolean hasProperty(String propertyName) {
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/VertexInfo.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/VertexInfo.java
index c03bab5d..d3247562 100644
--- a/maven-projects/info/src/main/java/org/apache/graphar/info/VertexInfo.java
+++ b/maven-projects/info/src/main/java/org/apache/graphar/info/VertexInfo.java
@@ -19,119 +19,81 @@
 
 package org.apache.graphar.info;
 
-import java.io.IOException;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
-import org.apache.graphar.info.type.DataType;
 import org.apache.graphar.info.yaml.GraphYaml;
 import org.apache.graphar.info.yaml.VertexYaml;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.yaml.snakeyaml.LoaderOptions;
+import org.apache.graphar.proto.DataType;
 import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.constructor.Constructor;
 
 public class VertexInfo {
-    private final String label;
-    private final long chunkSize;
-    private final PropertyGroups propertyGroups;
-    private final String prefix;
-    private final String version;
+    private final org.apache.graphar.proto.VertexInfo protoVertexInfo;
+    private final PropertyGroups cachedPropertyGroups;
 
     public VertexInfo(
-            String label,
-            long chunkSize,
-            List<PropertyGroup> propertyGroups,
-            String prefix,
-            String version) {
-        this.label = label;
-        this.chunkSize = chunkSize;
-        this.propertyGroups = new PropertyGroups(propertyGroups);
-        this.prefix = prefix;
-        this.version = version;
-    }
-
-    private VertexInfo(VertexYaml parser) {
-        this(
-                parser.getType(),
-                parser.getChunk_size(),
-                parser.getProperty_groups().stream()
-                        .map(PropertyGroup::new)
-                        .collect(Collectors.toUnmodifiableList()),
-                parser.getPrefix(),
-                parser.getVersion());
-    }
-
-    private VertexInfo(
-            String label,
-            long chunkSize,
-            PropertyGroups propertyGroups,
-            String prefix,
-            String version) {
-        this.label = label;
-        this.chunkSize = chunkSize;
-        this.propertyGroups = propertyGroups;
-        this.prefix = prefix;
-        this.version = version;
-    }
-
-    public static VertexInfo load(String vertexInfoPath) throws IOException {
-        return load(vertexInfoPath, new Configuration());
-    }
-
-    public static VertexInfo load(String vertexInfoPath, Configuration conf) 
throws IOException {
-        if (conf == null) {
-            throw new IllegalArgumentException("Configuration is null");
-        }
-        return load(vertexInfoPath, FileSystem.get(conf));
+            String type, long chunkSize, List<PropertyGroup> propertyGroups, 
String prefix) {
+        this.cachedPropertyGroups = new PropertyGroups(propertyGroups);
+        this.protoVertexInfo =
+                org.apache.graphar.proto.VertexInfo.newBuilder()
+                        .setType(type)
+                        .setChunkSize(chunkSize)
+                        .addAllProperties(
+                                propertyGroups.stream()
+                                        .map(PropertyGroup::getProto)
+                                        .collect(Collectors.toList()))
+                        .setPrefix(prefix)
+                        .build();
     }
 
-    public static VertexInfo load(String vertexInfoPath, FileSystem 
fileSystem) throws IOException {
-        if (fileSystem == null) {
-            throw new IllegalArgumentException("FileSystem is null");
-        }
-        FSDataInputStream inputStream = fileSystem.open(new 
Path(vertexInfoPath));
-        Yaml vertexInfoYamlLoader =
-                new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
-        VertexYaml vertexInfoYaml = vertexInfoYamlLoader.load(inputStream);
-        return new VertexInfo(vertexInfoYaml);
+    private VertexInfo(org.apache.graphar.proto.VertexInfo protoVertexInfo) {
+        this.protoVertexInfo = protoVertexInfo;
+        this.cachedPropertyGroups = 
PropertyGroups.ofProto(protoVertexInfo.getPropertiesList());
+    }
+
+    public static VertexInfo ofProto(org.apache.graphar.proto.VertexInfo 
protoVertexInfo) {
+        return new VertexInfo(protoVertexInfo);
+    }
+
+    org.apache.graphar.proto.VertexInfo getProto() {
+        return protoVertexInfo;
     }
 
     public Optional<VertexInfo> addPropertyGroupAsNew(PropertyGroup 
propertyGroup) {
-        return propertyGroups
+        // do not need check property group exist, because PropertyGroups will 
check it
+        return cachedPropertyGroups
                 .addPropertyGroupAsNew(propertyGroup)
                 .map(
                         newPropertyGroups ->
                                 new VertexInfo(
-                                        label, chunkSize, newPropertyGroups, 
prefix, version));
+                                        protoVertexInfo.getType(),
+                                        protoVertexInfo.getChunkSize(),
+                                        
newPropertyGroups.getPropertyGroupList(),
+                                        protoVertexInfo.getPrefix()));
     }
 
     public int propertyGroupNum() {
-        return propertyGroups.getPropertyGroupNum();
+        return cachedPropertyGroups.getPropertyGroupNum();
     }
 
     public DataType getPropertyType(String propertyName) {
-        return propertyGroups.getPropertyType(propertyName);
+        return cachedPropertyGroups.getPropertyType(propertyName);
     }
 
     public boolean hasProperty(String propertyName) {
-        return propertyGroups.hasProperty(propertyName);
+        return cachedPropertyGroups.hasProperty(propertyName);
     }
 
     public boolean isPrimaryKey(String propertyName) {
-        return propertyGroups.isPrimaryKey(propertyName);
+        return cachedPropertyGroups.isPrimaryKey(propertyName);
     }
 
     public boolean isNullableKey(String propertyName) {
-        return propertyGroups.isNullableKey(propertyName);
+        return cachedPropertyGroups.isNullableKey(propertyName);
     }
 
     public boolean hasPropertyGroup(PropertyGroup propertyGroup) {
-        return propertyGroups.hasPropertyGroup(propertyGroup);
+        return cachedPropertyGroups.hasPropertyGroup(propertyGroup);
     }
 
     public String getPropertyGroupPrefix(PropertyGroup propertyGroup) {
@@ -148,50 +110,30 @@ public class VertexInfo {
         return getPrefix() + "/vertex_count";
     }
 
-    public void save(String filePath) throws IOException {
-        save(filePath, new Configuration());
-    }
-
-    public void save(String filePath, Configuration conf) throws IOException {
-        if (conf == null) {
-            throw new IllegalArgumentException("Configuration is null");
-        }
-        save(filePath, FileSystem.get(conf));
-    }
-
-    public void save(String fileName, FileSystem fileSystem) throws 
IOException {
-        if (fileSystem == null) {
-            throw new IllegalArgumentException("FileSystem is null");
-        }
-        FSDataOutputStream outputStream = fileSystem.create(new 
Path(fileName));
-        outputStream.writeBytes(dump());
-        outputStream.close();
-    }
-
     public String dump() {
         Yaml yaml = new Yaml(GraphYaml.getDumperOptions());
         VertexYaml vertexYaml = new VertexYaml(this);
         return yaml.dump(vertexYaml);
     }
 
-    public String getLabel() {
-        return label;
+    public String getType() {
+        return protoVertexInfo.getType();
     }
 
     public long getChunkSize() {
-        return chunkSize;
+        return protoVertexInfo.getChunkSize();
     }
 
     public List<PropertyGroup> getPropertyGroups() {
-        return propertyGroups.getPropertyGroupList();
+        return cachedPropertyGroups.getPropertyGroupList();
     }
 
     public String getPrefix() {
-        return prefix;
+        return protoVertexInfo.getPrefix();
     }
 
-    public String getVersion() {
-        return version;
+    public String getVertexPath() {
+        return getPrefix() + "/" + getType() + ".vertex.yaml";
     }
 
     private void checkPropertyGroupExist(PropertyGroup propertyGroup) {
@@ -203,7 +145,7 @@ public class VertexInfo {
                     "Property group "
                             + propertyGroup
                             + " does not exist in the vertex "
-                            + getLabel());
+                            + getType());
         }
     }
 }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphLoader.java
similarity index 60%
copy from 
maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
copy to 
maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphLoader.java
index b45038b8..b21238c1 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphLoader.java
@@ -17,26 +17,12 @@
  * under the License.
  */
 
-package org.apache.graphar.info.type;
+package org.apache.graphar.info.loader;
 
-public enum FileType {
-    CSV,
-    PARQUET,
-    ORC;
+import java.io.IOException;
+import org.apache.graphar.info.GraphInfo;
 
-    public static FileType fromString(String fileType) {
-        if (fileType == null) {
-            return null;
-        }
-        switch (fileType) {
-            case "csv":
-                return CSV;
-            case "parquet":
-                return PARQUET;
-            case "orc":
-                return ORC;
-            default:
-                throw new IllegalArgumentException("Unknown file type: " + 
fileType);
-        }
-    }
+@FunctionalInterface
+public interface GraphLoader {
+    public GraphInfo load(String graphYamlPath) throws IOException;
 }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/LocalYamlGraphLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/LocalYamlGraphLoader.java
new file mode 100644
index 00000000..f2936fb4
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/LocalYamlGraphLoader.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+package org.apache.graphar.info.loader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.graphar.info.EdgeInfo;
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.VertexInfo;
+import org.apache.graphar.info.yaml.EdgeYaml;
+import org.apache.graphar.info.yaml.GraphYaml;
+import org.apache.graphar.info.yaml.VertexYaml;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public class LocalYamlGraphLoader implements GraphLoader {
+    private static FileSystem fileSystem = null;
+
+    public LocalYamlGraphLoader() {}
+
+    @Override
+    public GraphInfo load(String graphYamlPath) throws IOException {
+        if (fileSystem == null) {
+            fileSystem = FileSystem.get(new Configuration());
+        }
+        // load graph itself
+        final Path path = new Path(graphYamlPath);
+        final FSDataInputStream inputStream = fileSystem.open(path);
+        final Yaml yamlLoader = new Yaml(new Constructor(GraphYaml.class, new 
LoaderOptions()));
+        final GraphYaml graphYaml = yamlLoader.load(inputStream);
+        // load vertices
+        final String ABSOLUTE_PREFIX = path.getParent().toString();
+        List<VertexInfo> vertexInfos = new 
ArrayList<>(graphYaml.getVertices().size());
+        for (String vertexYamlName : graphYaml.getVertices()) {
+            vertexInfos.add(loadVertex(ABSOLUTE_PREFIX + "/" + 
vertexYamlName));
+        }
+        // load edges
+        List<EdgeInfo> edgeInfos = new 
ArrayList<>(graphYaml.getEdges().size());
+        for (String edgeYamlName : graphYaml.getEdges()) {
+            edgeInfos.add(loadEdge(ABSOLUTE_PREFIX + "/" + edgeYamlName));
+        }
+        return new GraphInfo(graphYaml.getName(), vertexInfos, edgeInfos, 
graphYaml.getPrefix());
+    }
+
+    private VertexInfo loadVertex(String path) throws IOException {
+        FSDataInputStream inputStream = fileSystem.open(new Path(path));
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = vertexYamlLoader.load(inputStream);
+        return vertexYaml.toVertexInfo();
+    }
+
+    private EdgeInfo loadEdge(String path) throws IOException {
+        FSDataInputStream inputStream = fileSystem.open(new Path(path));
+        Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new 
LoaderOptions()));
+        EdgeYaml edgeYaml = edgeYamlLoader.load(inputStream);
+        return edgeYaml.toEdgeInfo();
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphSaver.java
similarity index 60%
rename from 
maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
rename to 
maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphSaver.java
index b45038b8..5ee1d916 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphSaver.java
@@ -17,26 +17,12 @@
  * under the License.
  */
 
-package org.apache.graphar.info.type;
+package org.apache.graphar.info.saver;
 
-public enum FileType {
-    CSV,
-    PARQUET,
-    ORC;
+import java.io.IOException;
+import org.apache.graphar.info.GraphInfo;
 
-    public static FileType fromString(String fileType) {
-        if (fileType == null) {
-            return null;
-        }
-        switch (fileType) {
-            case "csv":
-                return CSV;
-            case "parquet":
-                return PARQUET;
-            case "orc":
-                return ORC;
-            default:
-                throw new IllegalArgumentException("Unknown file type: " + 
fileType);
-        }
-    }
+@FunctionalInterface
+public interface GraphSaver {
+    void save(String path, GraphInfo graphInfo) throws IOException;
 }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/saver/LocalYamlGraphSaver.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/LocalYamlGraphSaver.java
new file mode 100644
index 00000000..500268d1
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/LocalYamlGraphSaver.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package org.apache.graphar.info.saver;
+
+import java.io.IOException;
+import org.apache.graphar.info.EdgeInfo;
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.VertexInfo;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+
+public class LocalYamlGraphSaver implements GraphSaver {
+    private static final FileSystem fileSystem;
+
+    static {
+        try {
+            fileSystem = FileSystem.get(new Configuration());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void save(String path, GraphInfo graphInfo) throws IOException {
+        try (FSDataOutputStream outputStream =
+                fileSystem.create(new Path(path + "/" + graphInfo.getName() + 
".graph.yaml"))) {
+            outputStream.writeBytes(graphInfo.dump());
+            for (VertexInfo vertexInfo : graphInfo.getVertexInfos()) {
+                saveVertex(path, vertexInfo);
+            }
+            for (EdgeInfo edgeInfo : graphInfo.getEdgeInfos()) {
+                saveEdge(path, edgeInfo);
+            }
+        }
+    }
+
+    private void saveVertex(String path, VertexInfo vertexInfo) throws 
IOException {
+        try (FSDataOutputStream outputStream =
+                fileSystem.create(new Path(path + "/" + vertexInfo.getType() + 
".vertex.yaml"))) {
+            outputStream.writeBytes(vertexInfo.dump());
+        }
+    }
+
+    private void saveEdge(String path, EdgeInfo edgeInfo) throws IOException {
+        try (FSDataOutputStream outputStream =
+                fileSystem.create(new Path(path + "/" + edgeInfo.getConcat() + 
".edge.yaml"))) {
+            outputStream.writeBytes(edgeInfo.dump());
+        }
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/AdjListType.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/type/AdjListType.java
deleted file mode 100644
index a077d870..00000000
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/AdjListType.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.graphar.info.type;
-
-public enum AdjListType {
-    /** collection of edges by source, but unordered, can represent COO format 
*/
-    unordered_by_source,
-    /** collection of edges by destination, but unordered, can represent COO */
-    unordered_by_dest,
-    /** collection of edges by source, ordered by source, can represent CSR 
format */
-    ordered_by_source,
-    /** collection of edges by destination, ordered by destination, can 
represent CSC format */
-    ordered_by_dest;
-
-    public static AdjListType fromOrderedAndAlignedBy(boolean ordered, String 
alignedBy) {
-        switch (alignedBy) {
-            case "src":
-                return ordered ? ordered_by_source : unordered_by_source;
-            case "dst":
-                return ordered ? ordered_by_dest : unordered_by_dest;
-            default:
-                throw new IllegalArgumentException("Invalid alignedBy: " + 
alignedBy);
-        }
-    }
-
-    public boolean isOrdered() {
-        return this == ordered_by_source || this == ordered_by_dest;
-    }
-
-    public String getAlignedBy() {
-        return this == ordered_by_source || this == unordered_by_source ? 
"src" : "dst";
-    }
-}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/DataType.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/type/DataType.java
deleted file mode 100644
index 83c31aec..00000000
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/DataType.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.graphar.info.type;
-
-public enum DataType {
-    /** Boolean */
-    BOOL,
-
-    /** Signed 32-bit integer */
-    INT32,
-
-    /** Signed 64-bit integer */
-    INT64,
-
-    /** 4-byte floating point value */
-    FLOAT,
-
-    /** 8-byte floating point value */
-    DOUBLE,
-
-    /** UTF8 variable-length string */
-    STRING,
-
-    /** List of same type */
-    LIST;
-
-    public static DataType fromString(String s) {
-        switch (s) {
-            case "bool":
-                return BOOL;
-            case "int32":
-                return INT32;
-            case "int64":
-                return INT64;
-            case "float":
-                return FLOAT;
-            case "double":
-                return DOUBLE;
-            case "string":
-                return STRING;
-            case "list":
-                return LIST;
-            default:
-                throw new IllegalArgumentException("Unknown data type: " + s);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return name().toLowerCase();
-    }
-}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/AdjacentListYaml.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/AdjacentListYaml.java
index 90d3a1cb..b65da68d 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/AdjacentListYaml.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/AdjacentListYaml.java
@@ -19,6 +19,9 @@
 
 package org.apache.graphar.info.yaml;
 
+import org.apache.graphar.info.AdjacentList;
+import org.apache.graphar.proto.AdjListType;
+
 public class AdjacentListYaml {
     private boolean ordered;
     private String aligned_by;
@@ -33,12 +36,26 @@ public class AdjacentListYaml {
     }
 
     public AdjacentListYaml(org.apache.graphar.info.AdjacentList adjacentList) 
{
-        this.ordered = adjacentList.getType().isOrdered();
-        this.aligned_by = adjacentList.getType().getAlignedBy();
-        this.file_type = adjacentList.getFileType().toString();
+        final var adjListType = adjacentList.getType();
+        this.ordered =
+                adjListType == AdjListType.ORDERED_BY_SOURCE
+                        || adjListType == AdjListType.ORDERED_BY_DESTINATION;
+        this.aligned_by =
+                adjListType == AdjListType.ORDERED_BY_SOURCE
+                                || adjListType == 
AdjListType.UNORDERED_BY_SOURCE
+                        ? "src"
+                        : "dst";
+        this.file_type = 
EnumTransferUtil.fileType2String(adjacentList.getFileType());
         this.prefix = adjacentList.getPrefix();
     }
 
+    public AdjacentList toAdjacentList() {
+        return new AdjacentList(
+                EnumTransferUtil.orderedAndAlignedBy2AdjListType(ordered, 
aligned_by),
+                EnumTransferUtil.string2FileType(file_type),
+                prefix);
+    }
+
     public boolean isOrdered() {
         return ordered;
     }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EdgeYaml.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EdgeYaml.java
index e955306b..ff31aae4 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EdgeYaml.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EdgeYaml.java
@@ -48,12 +48,12 @@ public class EdgeYaml {
         this.prefix = "";
         this.adj_lists = new ArrayList<>();
         this.property_groups = new ArrayList<>();
-        this.version = "";
+        this.version = "v1";
     }
 
     public EdgeYaml(EdgeInfo edgeInfo) {
         this.src_type = edgeInfo.getSrcLabel();
-        this.edge_type = edgeInfo.getEdgeLabel();
+        this.edge_type = edgeInfo.getSrcLabel();
         this.dst_type = edgeInfo.getDstLabel();
         this.chunk_size = edgeInfo.getChunkSize();
         this.src_chunk_size = edgeInfo.getSrcChunkSize();
@@ -68,7 +68,24 @@ public class EdgeYaml {
                 edgeInfo.getPropertyGroups().stream()
                         .map(PropertyGroupYaml::new)
                         .collect(Collectors.toList());
-        this.version = edgeInfo.getVersion();
+    }
+
+    public EdgeInfo toEdgeInfo() {
+        return new EdgeInfo(
+                src_type,
+                edge_type,
+                dst_type,
+                chunk_size,
+                src_chunk_size,
+                dst_chunk_size,
+                directed,
+                prefix,
+                adj_lists.stream()
+                        .map(AdjacentListYaml::toAdjacentList)
+                        .collect(Collectors.toUnmodifiableList()),
+                property_groups.stream()
+                        .map(PropertyGroupYaml::toPropertyGroup)
+                        .collect(Collectors.toList()));
     }
 
     public String getSrc_type() {
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EnumTransferUtil.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EnumTransferUtil.java
new file mode 100644
index 00000000..2c484da8
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/EnumTransferUtil.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package org.apache.graphar.info.yaml;
+
+import org.apache.graphar.proto.AdjListType;
+import org.apache.graphar.proto.FileType;
+
+public class EnumTransferUtil {
+    static String fileType2String(FileType fileType) {
+        switch (fileType) {
+            case CSV:
+                return "csv";
+            case PARQUET:
+                return "parquet";
+            case ORC:
+                return "orc";
+            case JSON:
+                return "json";
+            case AVRO:
+                return "avro";
+            case HDF5:
+                return "hdf5";
+            default:
+                throw new IllegalArgumentException("Invalid fileType: " + 
fileType);
+        }
+    }
+
+    static FileType string2FileType(String fileType) {
+        switch (fileType) {
+            case "csv":
+                return FileType.CSV;
+            case "parquet":
+                return FileType.PARQUET;
+            case "orc":
+                return FileType.ORC;
+            case "json":
+                return FileType.JSON;
+            case "avro":
+                return FileType.AVRO;
+            case "hdf5":
+                return FileType.HDF5;
+            default:
+                throw new IllegalArgumentException("Invalid fileType: " + 
fileType);
+        }
+    }
+
+    static String dataType2String(org.apache.graphar.proto.DataType dataType) {
+        switch (dataType) {
+            case BOOL:
+                return "bool";
+            case INT32:
+                return "int32";
+            case INT64:
+                return "int64";
+            case FLOAT:
+                return "float";
+            case DOUBLE:
+                return "double";
+            case STRING:
+                return "string";
+            case LIST:
+                return "list";
+            case DATE:
+                return "date";
+            case TIMESTAMP:
+                return "timestamp";
+            case TIME:
+                return "time";
+            default:
+                throw new IllegalArgumentException("Invalid dataType: " + 
dataType);
+        }
+    }
+
+    static org.apache.graphar.proto.DataType string2DataType(String dataType) {
+        switch (dataType) {
+            case "bool":
+                return org.apache.graphar.proto.DataType.BOOL;
+            case "int32":
+                return org.apache.graphar.proto.DataType.INT32;
+            case "int64":
+                return org.apache.graphar.proto.DataType.INT64;
+            case "float":
+                return org.apache.graphar.proto.DataType.FLOAT;
+            case "double":
+                return org.apache.graphar.proto.DataType.DOUBLE;
+            case "string":
+                return org.apache.graphar.proto.DataType.STRING;
+            case "list":
+                return org.apache.graphar.proto.DataType.LIST;
+            case "date":
+                return org.apache.graphar.proto.DataType.DATE;
+            case "timestamp":
+                return org.apache.graphar.proto.DataType.TIMESTAMP;
+            case "time":
+                return org.apache.graphar.proto.DataType.TIME;
+            default:
+                throw new IllegalArgumentException("Invalid dataType: " + 
dataType);
+        }
+    }
+
+    public static AdjListType orderedAndAlignedBy2AdjListType(boolean ordered, 
String alignedBy) {
+        switch (alignedBy) {
+            case "src":
+                return ordered ? AdjListType.ORDERED_BY_SOURCE : 
AdjListType.UNORDERED_BY_SOURCE;
+            case "dst":
+                return ordered
+                        ? AdjListType.ORDERED_BY_DESTINATION
+                        : AdjListType.UNORDERED_BY_DESTINATION;
+            default:
+                throw new IllegalArgumentException("Invalid alignedBy: " + 
alignedBy);
+        }
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
index faec9bc4..4b52ea4e 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
@@ -54,13 +54,12 @@ public class GraphYaml {
         this.prefix = graphInfo.getPrefix();
         this.vertices =
                 graphInfo.getVertexInfos().stream()
-                        .map(vertexInfo -> vertexInfo.getLabel() + 
".vertex.yaml")
+                        .map(vertexInfo -> vertexInfo.getType() + 
".vertex.yaml")
                         .collect(Collectors.toList());
         this.edges =
                 graphInfo.getEdgeInfos().stream()
                         .map(edgeInfo -> edgeInfo.getConcat() + ".edge.yaml")
                         .collect(Collectors.toList());
-        this.version = graphInfo.getVersion();
     }
 
     public static DumperOptions getDumperOptions() {
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYaml.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYaml.java
index 202d6ed0..1e992539 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYaml.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYaml.java
@@ -40,10 +40,17 @@ public class PropertyGroupYaml {
                 propertyGroup.getPropertyList().stream()
                         .map(PropertyYaml::new)
                         .collect(Collectors.toList());
-        this.file_type = propertyGroup.getFileType().toString();
+        this.file_type = 
EnumTransferUtil.fileType2String(propertyGroup.getFileType());
         this.prefix = propertyGroup.getPrefix();
     }
 
+    PropertyGroup toPropertyGroup() {
+        return new PropertyGroup(
+                
properties.stream().map(PropertyYaml::toProperty).collect(Collectors.toList()),
+                EnumTransferUtil.string2FileType(file_type),
+                prefix);
+    }
+
     public List<PropertyYaml> getProperties() {
         return properties;
     }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
index bd06b577..89fa87a0 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
@@ -37,11 +37,19 @@ public class PropertyYaml {
 
     public PropertyYaml(Property property) {
         this.name = property.getName();
-        this.data_type = property.getDataType().toString();
+        this.data_type = 
EnumTransferUtil.dataType2String(property.getDataType());
         this.is_primary = property.isPrimary();
         this.is_nullable = Optional.of(property.isNullable());
     }
 
+    Property toProperty() {
+        return new Property(
+                name,
+                EnumTransferUtil.string2DataType(data_type),
+                is_primary,
+                is_nullable.orElseGet(() -> !is_primary));
+    }
+
     public String getName() {
         return name;
     }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/VertexYaml.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/VertexYaml.java
index a759724f..6449c716 100644
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/VertexYaml.java
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/VertexYaml.java
@@ -40,14 +40,23 @@ public class VertexYaml {
     }
 
     public VertexYaml(VertexInfo vertexInfo) {
-        this.type = vertexInfo.getLabel();
+        this.type = vertexInfo.getType();
         this.chunk_size = vertexInfo.getChunkSize();
         this.property_groups =
                 vertexInfo.getPropertyGroups().stream()
                         .map(PropertyGroupYaml::new)
                         .collect(Collectors.toList());
         this.prefix = vertexInfo.getPrefix();
-        this.version = vertexInfo.getVersion();
+    }
+
+    public VertexInfo toVertexInfo() {
+        return new VertexInfo(
+                type,
+                chunk_size,
+                property_groups.stream()
+                        .map(PropertyGroupYaml::toPropertyGroup)
+                        .collect(Collectors.toList()),
+                prefix);
     }
 
     public String getType() {
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphLoaderTest.java
 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphLoaderTest.java
new file mode 100644
index 00000000..00272042
--- /dev/null
+++ 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphLoaderTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package org.apache.graphar.info;
+
+import java.io.IOException;
+import org.apache.graphar.info.loader.GraphLoader;
+import org.apache.graphar.info.loader.LocalYamlGraphLoader;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class GraphLoaderTest {
+
+    @BeforeClass
+    public static void init() {
+        TestUtil.checkTestData();
+    }
+
+    @AfterClass
+    public static void clean() {}
+
+    @Test
+    public void testLoad() {
+        final GraphLoader graphLoader = new LocalYamlGraphLoader();
+        final String GRAPH_PATH = TestUtil.getLdbcSampleGraphPath();
+        try {
+            final GraphInfo graphInfo = graphLoader.load(GRAPH_PATH);
+            Assert.assertNotNull(graphInfo);
+            Assert.assertNotNull(graphInfo.getEdgeInfos());
+            Assert.assertEquals(1, graphInfo.getEdgeInfos().size());
+            for (EdgeInfo edgeInfo : graphInfo.getEdgeInfos()) {
+                Assert.assertNotNull(edgeInfo.getConcat());
+            }
+            Assert.assertNotNull(graphInfo.getVertexInfos());
+            Assert.assertEquals(1, graphInfo.getVertexInfos().size());
+            for (VertexInfo vertexInfo : graphInfo.getVertexInfos()) {
+                Assert.assertNotNull(vertexInfo.getType());
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphSaverTest.java 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphSaverTest.java
new file mode 100644
index 00000000..3fe219e2
--- /dev/null
+++ 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphSaverTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package org.apache.graphar.info;
+
+import java.io.File;
+import org.apache.graphar.info.saver.GraphSaver;
+import org.apache.graphar.info.saver.LocalYamlGraphSaver;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GraphSaverTest {
+
+    @Test
+    public void testSave() {
+        final String LDBC_SAMPLE_SAVE_DIR = TestUtil.SAVE_DIR + 
"/ldbc_sample/";
+        final GraphSaver graphSaver = new LocalYamlGraphSaver();
+        final GraphInfo graphInfo = TestUtil.getLdbcSampleDataSet();
+        try {
+            graphSaver.save(LDBC_SAMPLE_SAVE_DIR, graphInfo);
+            Assert.assertTrue(
+                    new File(LDBC_SAMPLE_SAVE_DIR + "/" + graphInfo.getName() 
+ ".graph.yaml")
+                            .exists());
+            for (VertexInfo vertexInfo : graphInfo.getVertexInfos()) {
+                Assert.assertTrue(
+                        new File(LDBC_SAMPLE_SAVE_DIR + "/" + 
vertexInfo.getType() + ".vertex.yaml")
+                                .exists());
+            }
+            for (EdgeInfo edgeInfo : graphInfo.getEdgeInfos()) {
+                Assert.assertTrue(
+                        new File(LDBC_SAMPLE_SAVE_DIR + "/" + 
edgeInfo.getConcat() + ".edge.yaml")
+                                .exists());
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/TestUtil.java 
b/maven-projects/info/src/test/java/org/apache/graphar/info/TestUtil.java
new file mode 100644
index 00000000..3660b905
--- /dev/null
+++ b/maven-projects/info/src/test/java/org/apache/graphar/info/TestUtil.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package org.apache.graphar.info;
+
+import java.util.List;
+import org.apache.graphar.proto.AdjListType;
+import org.apache.graphar.proto.DataType;
+import org.apache.graphar.proto.FileType;
+import org.junit.Assume;
+
+public class TestUtil {
+    private static String GAR_TEST_DATA = null;
+
+    static final String SAVE_DIR = "/tmp/graphar/test/";
+
+    private static String LDBC_SAMPLE_GRAPH_PATH = 
"/ldbc_sample/csv/ldbc_sample.graph.yml";
+
+    public static String getTestData() {
+        return GAR_TEST_DATA;
+    }
+
+    public static String getLdbcSampleGraphPath() {
+        return getTestData() + "/" + LDBC_SAMPLE_GRAPH_PATH;
+    }
+
+    public static GraphInfo getLdbcSampleDataSet() {
+        // create vertex info of yaml:
+        // type: person
+        // chunk_size: 100
+        // prefix: vertex/person/
+        // property_groups:
+        //  - properties:
+        //      - name: id
+        //        data_type: int64
+        //        is_primary: true
+        //        is_nullable: false
+        //    prefix: id/
+        //    file_type: csv
+        //  - properties:
+        //      - name: firstName
+        //        data_type: string
+        //        is_primary: false
+        //      - name: lastName
+        //        data_type: string
+        //        is_primary: false
+        //      - name: gender
+        //        data_type: string
+        //        is_primary: false
+        //        is_nullable: true
+        //    prefix: firstName_lastName_gender/
+        //    file_type: csv
+        // version: gar/v1
+
+        Property id = new Property("id", DataType.INT64, true, false);
+        Property firstName = new Property("firstName", DataType.STRING, false, 
false);
+        Property lastName = new Property("lastName", DataType.STRING, false, 
false);
+        Property gender = new Property("gender", DataType.STRING, false, true);
+        PropertyGroup pg1 = new PropertyGroup(List.of(id), FileType.CSV, 
"id/");
+        PropertyGroup pg2 =
+                new PropertyGroup(
+                        List.of(firstName, lastName, gender), FileType.CSV, 
"firstName_lastName");
+        VertexInfo person = new VertexInfo("person", 100, List.of(pg1, pg2), 
"vertex/person/");
+
+        // create edge info of yaml:
+        // src_type: person
+        // edge_type: knows
+        // dst_type: person
+        // chunk_size: 1024
+        // src_chunk_size: 100
+        // dst_chunk_size: 100
+        // directed: false
+        // prefix: edge/person_knows_person/
+        // adj_lists:
+        //  - ordered: true
+        //    aligned_by: src
+        //    prefix: ordered_by_source/
+        //    file_type: csv
+        //  - ordered: true
+        //    aligned_by: dst
+        //    prefix: ordered_by_dest/
+        //    file_type: csv
+        // property_groups:
+        //  - prefix: creationDate/
+        //    file_type: csv
+        //    properties:
+        //      - name: creationDate
+        //        data_type: string
+        //        is_primary: false
+        // version: gar/v1
+        AdjacentList orderedBySource =
+                new AdjacentList(AdjListType.ORDERED_BY_SOURCE, FileType.CSV, 
"ordered_by_source/");
+        AdjacentList orderedByDest =
+                new AdjacentList(
+                        AdjListType.ORDERED_BY_DESTINATION, FileType.CSV, 
"ordered_by_dest/");
+        Property creationDate = new Property("creationDate", DataType.STRING, 
false, false);
+        PropertyGroup pg3 = new PropertyGroup(List.of(creationDate), 
FileType.CSV, "creationDate/");
+        EdgeInfo knows =
+                new EdgeInfo(
+                        "person",
+                        "knows",
+                        "person",
+                        1024,
+                        100,
+                        100,
+                        false,
+                        "edge/person_knows_person/",
+                        List.of(orderedBySource, orderedByDest),
+                        List.of(pg3));
+
+        // create graph info of yaml:
+        // name: ldbc_sample
+        // vertices:
+        //  - person.vertex.yml
+        // edges:
+        //  - person_knows_person.edge.yml
+        // version: gar/v1
+        return new GraphInfo("ldbc_sample", List.of(person), List.of(knows), 
"");
+    }
+
+    public static void checkTestData() {
+        if (GAR_TEST_DATA == null) {
+            GAR_TEST_DATA = System.getenv("GAR_TEST_DATA");
+        }
+        Assume.assumeTrue("GAR_TEST_DATA is not set", GAR_TEST_DATA != null);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@graphar.apache.org
For additional commands, e-mail: commits-h...@graphar.apache.org


Reply via email to