[Spark-java-refactor] Implement file get, dump and save functions for info (#443)

Main changes:

- prefix and file get methods for info;
- dump and save methods for info;
- dump-related methods for yamlParser;
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/EdgeInfo.java b/spark/graphar/src/main/java/org/apache/graphar/info/EdgeInfo.java
index 307b0e5..1187b7d 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/EdgeInfo.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/EdgeInfo.java
@@ -19,10 +19,6 @@
 
 package org.apache.graphar.info;
 
-import org.apache.graphar.info.type.AdjListType;
-import org.apache.graphar.info.type.DataType;
-import org.apache.graphar.info.yaml.EdgeYamlParser;
-import org.apache.graphar.util.GeneralParams;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -30,9 +26,14 @@
 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.EdgeYamlParser;
+import org.apache.graphar.info.yaml.GraphYamlParser;
+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;
@@ -117,13 +118,22 @@
         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) {
-            conf = new Configuration();
+            throw new IllegalArgumentException("Configuration is null");
         }
-        Path path = new Path(edgeInfoPath);
-        FileSystem fileSystem = path.getFileSystem(conf);
-        FSDataInputStream inputStream = fileSystem.open(path);
+        return load(edgeInfoPath, FileSystem.get(conf));
+    }
+
+    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(EdgeYamlParser.class, new LoaderOptions()));
         EdgeYamlParser edgeInfoYaml = edgeInfoYamlLoader.load(inputStream);
@@ -184,6 +194,9 @@
     }
 
     public AdjacentList getAdjacentList(AdjListType adjListType) {
+        // AdjListType will be checked in this method,
+        // 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);
     }
@@ -196,98 +209,77 @@
         return propertyGroups.getPropertyGroup(property);
     }
 
-    // TODO(@Thespica): Implement file path get methods
+    public String getPropertyGroupPrefix(PropertyGroup propertyGroup) {
+        checkPropertyGroupExist(propertyGroup);
+        return getPrefix() + "/" + propertyGroup.getPrefix();
+    }
 
-    //    public String getVerticesNumFilePath(AdjListType adjListType) {
-    //    }
-    //
-    //    public String getEdgesNumFilePath(long vertexChunkIndex, AdjListType adjListType) {
-    //    }
-    //
-    //    public String getAdjListFilePath(long vertexChunkIndex, long edgeChunkIndex, AdjListType
-    // adjListType) {
-    //    }
-    //
-    //    public String getAdjListPathPrefix(AdjListType adjListType) {
-    //    }
-    //
-    //    /**
-    //     * Get the adjacency list offset chunk file path of vertex chunk
-    //     * the offset chunks is aligned with the vertex chunks
-    //     *
-    //     * @param vertexChunkIndex index of vertex chunk
-    //     * @param adjListType      The adjacency list type.
-    //     */
-    //    public String getAdjListOffsetFilePath(long vertexChunkIndex, AdjListType adjListType) {
-    //
-    //    }
-    //
-    //    /**
-    //     * Get the path prefix of the adjacency list offset chunk for the given
-    //     * adjacency list type.
-    //     *
-    //     * @param adjListType The adjacency list type.
-    //     * @return A Result object containing the path prefix, or a Status object
-    //     * indicating an error.
-    //     */
-    //    public String getOffsetPathPrefix(AdjListType adjListType) {
-    //
-    //    }
-    //
-    //    public String getPropertyFilePath(
-    //            PropertyGroup propertyGroup,
-    //            AdjListType adjListType, long vertexChunkIndex,
-    //            long edgeChunkIndex) {
-    //
-    //    }
-    //
-    //    /**
-    //     * Get the path prefix of the property group chunk for the given
-    //     * adjacency list type.
-    //     *
-    //     * @param propertyGroup property group.
-    //     * @param adjListType   The adjacency list type.
-    //     * @return A Result object containing the path prefix, or a Status object
-    //     * indicating an error.
-    //     */
-    //    public String getPropertyGroupPathPrefix(
-    //            PropertyGroup propertyGroup,
-    //            AdjListType adjListType) {
-    //
-    //    }
+    public String getPropertyGroupChunkPath(PropertyGroup propertyGroup, long chunkIndex) {
+        // PropertyGroup will be checked in getPropertyGroupPrefix
+        return getPropertyGroupPrefix(propertyGroup) + "/chunk" + chunkIndex;
+    }
 
-    DataType getPropertyType(String propertyName) {
+    public String getAdjacentListPrefix(AdjListType adjListType) {
+        return getPrefix() + "/" + getAdjacentList(adjListType).getPrefix() + "/adj_list";
+    }
+
+    public String getAdjacentListChunkPath(AdjListType adjListType, long vertexChunkIndex) {
+        return getAdjacentListPrefix(adjListType) + "/chunk" + vertexChunkIndex;
+    }
+
+    public String getOffsetPrefix(AdjListType adjListType) {
+        return getAdjacentListPrefix(adjListType) + "/offset";
+    }
+
+    public String getOffsetChunkPath(AdjListType adjListType, long vertexChunkIndex) {
+        return getOffsetPrefix(adjListType) + "/chunk" + vertexChunkIndex;
+    }
+
+    public String getVerticesNumFilePath(AdjListType adjListType) {
+        return getAdjacentListPrefix(adjListType) + "/vertex_count";
+    }
+
+    public String getEdgesNumFilePath(AdjListType adjListType, long vertexChunkIndex) {
+        return getAdjacentListPrefix(adjListType) + "/edge_count" + vertexChunkIndex;
+    }
+
+    public DataType getPropertyType(String propertyName) {
         return propertyGroups.getPropertyType(propertyName);
     }
 
-    boolean isPrimaryKey(String propertyName) {
+    public boolean isPrimaryKey(String propertyName) {
         return propertyGroups.isPrimaryKey(propertyName);
     }
 
-    boolean isNullableKey(String propertyName) {
+    public boolean isNullableKey(String propertyName) {
         return propertyGroups.isNullableKey(propertyName);
     }
 
-    // TODO(@Thespica): Implement save and dump methods
-    //    /**
-    //     * Saves the edge info to a YAML file.
-    //     *
-    //     * @param fileName The name of the file to save to.
-    //     * @return A Status object indicating success or failure.
-    //     */
-    //    void save(String fileName) {
-    //
-    //    }
-    //
-    //    /**
-    //     * Returns the edge info as a YAML formatted string.
-    //     *
-    //     * @return A Result object containing the YAML string, or a Status object
-    //     * indicating an error.
-    //     */
-    //    public String dump() {
-    //
-    //    }
+    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(GraphYamlParser.getDumperOptions());
+        EdgeYamlParser edgeYaml = new EdgeYamlParser(this);
+        return yaml.dump(edgeYaml);
+    }
 
     public String getConcat() {
         return edgeTriplet.getConcat();
@@ -338,6 +330,9 @@
     }
 
     private void checkAdjListTypeExist(AdjListType adjListType) {
+        if (adjListType == null) {
+            throw new IllegalArgumentException("The adjacency list type is null");
+        }
         if (!adjacentLists.containsKey(adjListType)) {
             throw new IllegalArgumentException(
                     "The adjacency list type "
@@ -347,6 +342,19 @@
         }
     }
 
+    private void checkPropertyGroupExist(PropertyGroup propertyGroup) {
+        if (propertyGroup == null) {
+            throw new IllegalArgumentException("Property group is null");
+        }
+        if (!hasPropertyGroup(propertyGroup)) {
+            throw new IllegalArgumentException(
+                    "Property group "
+                            + propertyGroup
+                            + " does not exist in the edge "
+                            + getConcat());
+        }
+    }
+
     private static class EdgeTriplet {
         private final String srcLabel;
         private final String edgeLabel;
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/GraphInfo.java b/spark/graphar/src/main/java/org/apache/graphar/info/GraphInfo.java
index 70f6f37..977112a 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/GraphInfo.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/GraphInfo.java
@@ -19,8 +19,6 @@
 
 package org.apache.graphar.info;
 
-import org.apache.graphar.info.yaml.GraphYamlParser;
-import org.apache.graphar.util.GeneralParams;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -29,8 +27,11 @@
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import org.apache.graphar.info.yaml.GraphYamlParser;
+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;
@@ -96,12 +97,19 @@
     }
 
     public static GraphInfo load(String graphPath) throws IOException {
-        return load(graphPath, null);
+        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 (graphPath == null) {
-            conf = new Configuration();
+        if (conf == null) {
+            throw new IllegalArgumentException("Configuration is null");
         }
         Path path = new Path(graphPath);
         FileSystem fileSystem = path.getFileSystem(conf);
@@ -112,16 +120,33 @@
         return new GraphInfo(graphYaml, conf);
     }
 
-    // TODO(@Thespica): Implement save and dump methods
-    //    public void save(String path) {
-    //
-    //    }
-    //
-    //    public String dump() {
-    //
-    //    }
+    public void save(String filePath) throws IOException {
+        save(filePath, new Configuration());
+    }
 
-    Optional<GraphInfo> addVertexAsNew(VertexInfo vertexInfo) {
+    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(GraphYamlParser.getDumperOptions());
+        GraphYamlParser graphYaml = new GraphYamlParser(this);
+        return yaml.dump(graphYaml);
+    }
+
+    public Optional<GraphInfo> addVertexAsNew(VertexInfo vertexInfo) {
         if (vertexInfo == null || hasVertexInfo(vertexInfo.getLabel())) {
             return Optional.empty();
         }
@@ -146,7 +171,7 @@
                         version));
     }
 
-    Optional<GraphInfo> addEdgeAsNew(EdgeInfo edgeInfo) {
+    public Optional<GraphInfo> addEdgeAsNew(EdgeInfo edgeInfo) {
         if (edgeInfo == null
                 || hasEdgeInfo(
                         edgeInfo.getSrcLabel(), edgeInfo.getEdgeLabel(), edgeInfo.getDstLabel())) {
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/PropertyGroup.java b/spark/graphar/src/main/java/org/apache/graphar/info/PropertyGroup.java
index 930366f..7391f1c 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/PropertyGroup.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/PropertyGroup.java
@@ -19,9 +19,6 @@
 
 package org.apache.graphar.info;
 
-import org.apache.graphar.info.type.DataType;
-import org.apache.graphar.info.type.FileType;
-import org.apache.graphar.info.yaml.PropertyGroupYamlParser;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -30,9 +27,10 @@
 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.PropertyGroupYamlParser;
 import org.apache.graphar.util.GeneralParams;
-import org.jetbrains.annotations.NotNull;
 
 public class PropertyGroup implements Iterable<Property> {
     private final List<Property> propertyList;
@@ -70,7 +68,6 @@
         return Optional.of(new PropertyGroup(newPropertyMap, fileType, prefix));
     }
 
-    @NotNull
     @Override
     public Iterator<Property> iterator() {
         return propertyList.iterator();
@@ -78,7 +75,9 @@
 
     @Override
     public String toString() {
-        return propertyList.stream().map(Property::getName).collect(Collectors.joining(GeneralParams.regularSeparator));
+        return propertyList.stream()
+                .map(Property::getName)
+                .collect(Collectors.joining(GeneralParams.regularSeparator));
     }
 
     public int size() {
@@ -207,12 +206,10 @@
         return properties;
     }
 
-    Property getProperty(String propertyName) {
-        checkPropertyExist(propertyName);
-        return properties.get(propertyName);
-    }
-
     private void checkPropertyExist(String propertyName) {
+        if (null == propertyName) {
+            throw new IllegalArgumentException("Property name is null");
+        }
         if (!hasProperty(propertyName)) {
             throw new IllegalArgumentException(
                     "Property " + propertyName + " does not exist in the property group " + this);
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/VertexInfo.java b/spark/graphar/src/main/java/org/apache/graphar/info/VertexInfo.java
index 5e53653..2ccadc6 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/VertexInfo.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/VertexInfo.java
@@ -19,15 +19,16 @@
 
 package org.apache.graphar.info;
 
-import org.apache.graphar.info.type.DataType;
-import org.apache.graphar.info.yaml.VertexYamlParser;
 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.GraphYamlParser;
+import org.apache.graphar.info.yaml.VertexYamlParser;
 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;
@@ -78,20 +79,29 @@
         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) {
-            conf = new Configuration();
+            throw new IllegalArgumentException("Configuration is null");
         }
-        Path path = new Path(vertexInfoPath);
-        FileSystem fileSystem = path.getFileSystem(conf);
-        FSDataInputStream inputStream = fileSystem.open(path);
+        return load(vertexInfoPath, FileSystem.get(conf));
+    }
+
+    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(VertexYamlParser.class, new LoaderOptions()));
         VertexYamlParser vertexInfoYaml = vertexInfoYamlLoader.load(inputStream);
         return new VertexInfo(vertexInfoYaml);
     }
 
-    Optional<VertexInfo> addPropertyGroupAsNew(PropertyGroup propertyGroup) {
+    public Optional<VertexInfo> addPropertyGroupAsNew(PropertyGroup propertyGroup) {
         return propertyGroups
                 .addPropertyGroupAsNew(propertyGroup)
                 .map(
@@ -100,59 +110,69 @@
                                         label, chunkSize, newPropertyGroups, prefix, version));
     }
 
-    int propertyGroupNum() {
+    public int propertyGroupNum() {
         return propertyGroups.getPropertyGroupNum();
     }
 
-    PropertyGroup getPropertyGroup(String propertyName) {
-        return propertyGroups.getPropertyGroup(propertyName);
-    }
-
-    DataType getPropertyType(String propertyName) {
+    public DataType getPropertyType(String propertyName) {
         return propertyGroups.getPropertyType(propertyName);
     }
 
-    boolean hasProperty(String propertyName) {
+    public boolean hasProperty(String propertyName) {
         return propertyGroups.hasProperty(propertyName);
     }
 
-    boolean isPrimaryKey(String propertyName) {
+    public boolean isPrimaryKey(String propertyName) {
         return propertyGroups.isPrimaryKey(propertyName);
     }
 
-    boolean isNullableKey(String propertyName) {
+    public boolean isNullableKey(String propertyName) {
         return propertyGroups.isNullableKey(propertyName);
     }
 
-    boolean hasPropertyGroup(PropertyGroup propertyGroup) {
+    public boolean hasPropertyGroup(PropertyGroup propertyGroup) {
         return propertyGroups.hasPropertyGroup(propertyGroup);
     }
 
-    // TODO(@Thespica): Implement file path get methods
-    //
-    //    String getFilePath(PropertyGroup propertyGroup,
-    //                                    long chunkIndex) {
-    //
-    //    }
-    //
-    //    String getPathPrefix(
-    //            PropertyGroup propertyGroup) {
-    //
-    //    }
-    //
-    //    String getVerticesNumFilePath() {
-    //
-    //    }
+    public String getPropertyGroupPrefix(PropertyGroup propertyGroup) {
+        checkPropertyGroupExist(propertyGroup);
+        return getPrefix() + "/" + propertyGroup.getPrefix();
+    }
 
-    // TODO(@Thespica): Implement save and dump methods
-    //
-    //    void save(String fileName) {
-    //
-    //    }
-    //
-    //    String Dump() {
-    //
-    //    }
+    public String getPropertyGroupChunkPath(PropertyGroup propertyGroup, long chunkIndex) {
+        // PropertyGroup will be checked in getPropertyGroupPrefix
+        return getPropertyGroupPrefix(propertyGroup) + "/chunk" + chunkIndex;
+    }
+
+    public String getVerticesNumFilePath() {
+        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(GraphYamlParser.getDumperOptions());
+        VertexYamlParser vertexYaml = new VertexYamlParser(this);
+        return yaml.dump(vertexYaml);
+    }
 
     public String getLabel() {
         return label;
@@ -173,4 +193,17 @@
     public String getVersion() {
         return version;
     }
+
+    private void checkPropertyGroupExist(PropertyGroup propertyGroup) {
+        if (propertyGroup == null) {
+            throw new IllegalArgumentException("Property group is null");
+        }
+        if (!hasPropertyGroup(propertyGroup)) {
+            throw new IllegalArgumentException(
+                    "Property group "
+                            + propertyGroup
+                            + " does not exist in the vertex "
+                            + getLabel());
+        }
+    }
 }
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/type/AdjListType.java b/spark/graphar/src/main/java/org/apache/graphar/info/type/AdjListType.java
index 0bdaeee..a077d87 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/type/AdjListType.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/type/AdjListType.java
@@ -39,4 +39,12 @@
                 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/spark/graphar/src/main/java/org/apache/graphar/info/yaml/AdjacentListYamlParser.java b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/AdjacentListYamlParser.java
index c06e377..a971c03 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/AdjacentListYamlParser.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/AdjacentListYamlParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.graphar.info.yaml;
 
+import org.apache.graphar.info.AdjacentList;
+
 public class AdjacentListYamlParser {
     private boolean ordered;
     private String aligned_by;
@@ -32,6 +34,13 @@
         this.prefix = "";
     }
 
+    public AdjacentListYamlParser(AdjacentList adjacentList) {
+        this.ordered = adjacentList.getType().isOrdered();
+        this.aligned_by = adjacentList.getType().getAlignedBy();
+        this.file_type = adjacentList.getFileType().toString();
+        this.prefix = adjacentList.getPrefix();
+    }
+
     public boolean isOrdered() {
         return ordered;
     }
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/EdgeYamlParser.java b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/EdgeYamlParser.java
index 4d2dbfc..0d8813c 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/EdgeYamlParser.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/EdgeYamlParser.java
@@ -21,6 +21,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.graphar.info.EdgeInfo;
 
 public class EdgeYamlParser {
     private String src_label;
@@ -49,6 +51,26 @@
         this.version = "";
     }
 
+    public EdgeYamlParser(EdgeInfo edgeInfo) {
+        this.src_label = edgeInfo.getSrcLabel();
+        this.edge_label = edgeInfo.getEdgeLabel();
+        this.dst_label = edgeInfo.getDstLabel();
+        this.chunk_size = edgeInfo.getChunkSize();
+        this.src_chunk_size = edgeInfo.getSrcChunkSize();
+        this.dst_chunk_size = edgeInfo.getDstChunkSize();
+        this.directed = edgeInfo.isDirected();
+        this.prefix = edgeInfo.getPrefix();
+        this.adjacent_lists =
+                edgeInfo.getAdjacentLists().values().stream()
+                        .map(AdjacentListYamlParser::new)
+                        .collect(Collectors.toList());
+        this.property_groups =
+                edgeInfo.getPropertyGroups().stream()
+                        .map(PropertyGroupYamlParser::new)
+                        .collect(Collectors.toList());
+        this.version = edgeInfo.getVersion();
+    }
+
     public String getSrc_label() {
         return src_label;
     }
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/GraphYamlParser.java b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/GraphYamlParser.java
index 5bff10c..85fe697 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/GraphYamlParser.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/GraphYamlParser.java
@@ -21,6 +21,9 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.graphar.info.GraphInfo;
+import org.yaml.snakeyaml.DumperOptions;
 
 public class GraphYamlParser {
     private String name;
@@ -28,6 +31,15 @@
     private List<String> vertices;
     private List<String> edges;
     private String version;
+    private static final DumperOptions dumperOption;
+
+    static {
+        dumperOption = new DumperOptions();
+        dumperOption.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+        dumperOption.setIndent(4);
+        dumperOption.setIndicatorIndent(2);
+        dumperOption.setPrettyFlow(true);
+    }
 
     public GraphYamlParser() {
         this.name = "";
@@ -37,6 +49,24 @@
         this.version = "";
     }
 
+    public GraphYamlParser(GraphInfo graphInfo) {
+        this.name = graphInfo.getName();
+        this.prefix = graphInfo.getPrefix();
+        this.vertices =
+                graphInfo.getVertexInfos().stream()
+                        .map(vertexInfo -> vertexInfo.getLabel() + ".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() {
+        return dumperOption;
+    }
+
     public String getName() {
         return name;
     }
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYamlParser.java b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYamlParser.java
index 7d12e4c..43609df 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYamlParser.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyGroupYamlParser.java
@@ -21,6 +21,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.graphar.info.PropertyGroup;
 
 public class PropertyGroupYamlParser {
     private List<PropertyYamlParser> properties;
@@ -33,6 +35,15 @@
         this.prefix = "";
     }
 
+    public PropertyGroupYamlParser(PropertyGroup propertyGroup) {
+        this.properties =
+                propertyGroup.getPropertyList().stream()
+                        .map(PropertyYamlParser::new)
+                        .collect(Collectors.toList());
+        this.file_type = propertyGroup.getFileType().toString();
+        this.prefix = propertyGroup.getPrefix();
+    }
+
     public List<PropertyYamlParser> getProperties() {
         return properties;
     }
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyYamlParser.java b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyYamlParser.java
index a43d784..c511ada 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyYamlParser.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/PropertyYamlParser.java
@@ -20,6 +20,7 @@
 package org.apache.graphar.info.yaml;
 
 import java.util.Optional;
+import org.apache.graphar.info.Property;
 
 public class PropertyYamlParser {
     private String name;
@@ -34,6 +35,13 @@
         this.is_nullable = Optional.empty();
     }
 
+    public PropertyYamlParser(Property property) {
+        this.name = property.getName();
+        this.data_type = property.getDataType().toString();
+        this.is_primary = property.isPrimary();
+        this.is_nullable = Optional.of(property.isNullable());
+    }
+
     public String getName() {
         return name;
     }
diff --git a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/VertexYamlParser.java b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/VertexYamlParser.java
index 6e2f2c9..01c0984 100644
--- a/spark/graphar/src/main/java/org/apache/graphar/info/yaml/VertexYamlParser.java
+++ b/spark/graphar/src/main/java/org/apache/graphar/info/yaml/VertexYamlParser.java
@@ -19,7 +19,10 @@
 
 package org.apache.graphar.info.yaml;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.graphar.info.VertexInfo;
 
 public class VertexYamlParser {
     private String label;
@@ -28,7 +31,24 @@
     private String prefix;
     private String version;
 
-    public VertexYamlParser() {}
+    public VertexYamlParser() {
+        this.label = "";
+        this.chunk_size = 0;
+        this.property_groups = new ArrayList<>();
+        this.prefix = "";
+        this.version = "";
+    }
+
+    public VertexYamlParser(VertexInfo vertexInfo) {
+        this.label = vertexInfo.getLabel();
+        this.chunk_size = vertexInfo.getChunkSize();
+        this.property_groups =
+                vertexInfo.getPropertyGroups().stream()
+                        .map(PropertyGroupYamlParser::new)
+                        .collect(Collectors.toList());
+        this.prefix = vertexInfo.getPrefix();
+        this.version = vertexInfo.getVersion();
+    }
 
     public String getLabel() {
         return label;