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

xiaokang 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 ae20a93a feat(java,info): refactor GraphInfoLoader provide API, hide 
yaml dependencies, replace prefix to uri (#745)
ae20a93a is described below

commit ae20a93a6eb6bdb980e575448fd09de98a99d00f
Author: Xiaokang Yang <81174897+yang...@users.noreply.github.com>
AuthorDate: Mon Sep 8 14:33:23 2025 +0800

    feat(java,info): refactor GraphInfoLoader provide API, hide yaml 
dependencies, replace prefix to uri (#745)
    
    * refactor load graphInfo method
    
    * refactor save graphInfo method
    
    * format
    
    * update
    
    * Provide uris directly
    
    * resolve uri by path
    
    * format
    
    * update
    
    * reset saver
    
    * fix graph prefix
    
    * format
    
    * change prefix from string to uri
    
    * add loader impl and test
    
    * add uri parser test
    
    * add builder test
---
 maven-projects/info/pom.xml                        |  28 +++-
 .../java/org/apache/graphar/info/AdjacentList.java |  22 +--
 .../java/org/apache/graphar/info/EdgeInfo.java     | 177 +++++++++------------
 .../java/org/apache/graphar/info/GraphInfo.java    | 111 +++----------
 .../org/apache/graphar/info/PropertyGroup.java     |  27 ++--
 .../java/org/apache/graphar/info/VertexInfo.java   | 104 +++---------
 .../graphar/info/loader/BaseGraphInfoLoader.java   | 101 ++++++++++++
 .../graphar/info/loader/GraphInfoLoader.java       |  35 ++++
 .../graphar/info/loader/LocalYamlGraphLoader.java  |  89 -----------
 .../graphar/info/loader/ReaderGraphInfoLoader.java |  62 ++++++++
 .../graphar/info/loader/StreamGraphInfoLoader.java |  63 ++++++++
 .../graphar/info/loader/StringGraphInfoLoader.java |  61 +++++++
 .../impl/LocalFileSystemReaderGraphInfoLoader.java |  36 +++++
 .../impl/LocalFileSystemStreamGraphInfoLoader.java |  37 +++++
 .../impl/LocalFileSystemStringGraphInfoLoader.java |  41 +++++
 .../org/apache/graphar/info/yaml/EdgeYaml.java     |  19 ---
 .../graphar/info/yaml/PropertyGroupYaml.java       |   2 +-
 .../org/apache/graphar/info/yaml/VertexYaml.java   |  11 --
 .../java/org/apache/graphar/util/PathUtil.java     |  48 ------
 .../java/org/apache/graphar/info/EdgeInfoTest.java |  74 ++++++++-
 .../apache/graphar/info/GraphInfoLoaderTest.java   |  92 +++++++++++
 .../org/apache/graphar/info/GraphInfoTest.java     |  96 ++++++-----
 .../org/apache/graphar/info/GraphInfoUriTest.java  | 101 ++++++++++++
 .../org/apache/graphar/info/GraphLoaderTest.java   |  61 -------
 .../java/org/apache/graphar/info/TestUtil.java     | 119 +++++++++++++-
 25 files changed, 1047 insertions(+), 570 deletions(-)

diff --git a/maven-projects/info/pom.xml b/maven-projects/info/pom.xml
index 52c85867..475aca61 100644
--- a/maven-projects/info/pom.xml
+++ b/maven-projects/info/pom.xml
@@ -57,15 +57,33 @@
             <version>2.0</version>
             <scope>compile</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-common</artifactId>
-            <version>3.4.0</version>
-        </dependency>
     </dependencies>
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>3.5.0</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <relocations>
+                                <relocation>
+                                    <pattern>org.yaml.snakeyaml</pattern>
+                                    
<shadedPattern>org.apache.graphar.shaded.snakeyaml</shadedPattern>
+                                </relocation>
+                            </relocations>
+                            
<createDependencyReducedPom>true</createDependencyReducedPom>
+                            <minimizeJar>false</minimizeJar>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
             <plugin>
                 <groupId>com.diffplug.spotless</groupId>
                 <artifactId>spotless-maven-plugin</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 ddf285de..bfe20cd1 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,27 +19,23 @@
 
 package org.apache.graphar.info;
 
+import java.net.URI;
 import org.apache.graphar.info.type.AdjListType;
 import org.apache.graphar.info.type.FileType;
-import org.apache.graphar.info.yaml.AdjacentListYaml;
 
 public class AdjacentList {
     private final AdjListType type;
     private final FileType fileType;
-    private final String prefix;
+    private final URI baseUri;
 
-    public AdjacentList(AdjListType type, FileType fileType, String prefix) {
+    public AdjacentList(AdjListType type, FileType fileType, URI baseUri) {
         this.type = type;
         this.fileType = fileType;
-        this.prefix = prefix;
+        this.baseUri = baseUri;
     }
 
-    AdjacentList(AdjacentListYaml yamlParser) {
-        this.type =
-                AdjListType.fromOrderedAndAlignedBy(
-                        yamlParser.isOrdered(), yamlParser.getAligned_by());
-        this.fileType = FileType.fromString(yamlParser.getFile_type());
-        this.prefix = yamlParser.getPrefix();
+    public AdjacentList(AdjListType type, FileType fileType, String prefix) {
+        this(type, fileType, URI.create(prefix));
     }
 
     public AdjListType getType() {
@@ -51,6 +47,10 @@ public class AdjacentList {
     }
 
     public String getPrefix() {
-        return prefix;
+        return baseUri.toString();
+    }
+
+    public URI getBaseUri() {
+        return baseUri;
     }
 }
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 31588c6a..3df5a0c4 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,7 +19,7 @@
 
 package org.apache.graphar.info;
 
-import java.io.IOException;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -33,14 +33,7 @@ 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.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;
@@ -48,7 +41,7 @@ public class EdgeInfo {
     private final long srcChunkSize;
     private final long dstChunkSize;
     private final boolean directed;
-    private final String prefix;
+    private final URI baseUri;
     private final Map<AdjListType, AdjacentList> adjacentLists;
     private final PropertyGroups propertyGroups;
     private final VersionInfo version;
@@ -63,6 +56,7 @@ public class EdgeInfo {
         private long srcChunkSize;
         private long dstChunkSize;
         private boolean directed;
+        private URI baseUri;
         private String prefix;
         private Map<AdjListType, AdjacentList> adjacentLists;
         private PropertyGroups propertyGroups;
@@ -122,6 +116,11 @@ public class EdgeInfo {
             return this;
         }
 
+        public EdgeInfoBuilder baseUri(URI baseUri) {
+            this.baseUri = baseUri;
+            return this;
+        }
+
         public EdgeInfoBuilder prefix(String prefix) {
             this.prefix = prefix;
             return this;
@@ -216,6 +215,22 @@ public class EdgeInfo {
                 throw new IllegalArgumentException("AdjacentLists is empty");
             }
 
+            if (baseUri == null && prefix == null) {
+                throw new IllegalArgumentException("baseUri and prefix cannot 
be both null");
+            }
+
+            if (baseUri != null && prefix != null && 
!URI.create(prefix).equals(baseUri)) {
+                throw new IllegalArgumentException(
+                        "baseUri and prefix conflict: baseUri="
+                                + baseUri.toString()
+                                + " prefix="
+                                + prefix);
+            }
+
+            if (baseUri == null) {
+                baseUri = URI.create(prefix);
+            }
+
             return new EdgeInfo(this);
         }
     }
@@ -226,7 +241,7 @@ public class EdgeInfo {
         this.srcChunkSize = builder.srcChunkSize;
         this.dstChunkSize = builder.dstChunkSize;
         this.directed = builder.directed;
-        this.prefix = builder.prefix;
+        this.baseUri = builder.baseUri;
         this.adjacentLists = builder.adjacentLists;
         this.propertyGroups = builder.propertyGroups;
         this.version = builder.version;
@@ -240,7 +255,7 @@ public class EdgeInfo {
             long srcChunkSize,
             long dstChunkSize,
             boolean directed,
-            String prefix,
+            URI baseUri,
             String version,
             List<AdjacentList> adjacentListsAsList,
             List<PropertyGroup> propertyGroupsAsList) {
@@ -252,7 +267,7 @@ public class EdgeInfo {
                 srcChunkSize,
                 dstChunkSize,
                 directed,
-                prefix,
+                baseUri,
                 VersionParser.getVersion(version),
                 adjacentListsAsList,
                 propertyGroupsAsList);
@@ -267,6 +282,32 @@ public class EdgeInfo {
             long dstChunkSize,
             boolean directed,
             String prefix,
+            String version,
+            List<AdjacentList> adjacentListsAsList,
+            List<PropertyGroup> propertyGroupsAsList) {
+        this(
+                srcType,
+                edgeType,
+                dstType,
+                chunkSize,
+                srcChunkSize,
+                dstChunkSize,
+                directed,
+                URI.create(prefix),
+                version,
+                adjacentListsAsList,
+                propertyGroupsAsList);
+    }
+
+    public EdgeInfo(
+            String srcType,
+            String edgeType,
+            String dstType,
+            long chunkSize,
+            long srcChunkSize,
+            long dstChunkSize,
+            boolean directed,
+            URI baseUri,
             VersionInfo version,
             List<AdjacentList> adjacentListsAsList,
             List<PropertyGroup> propertyGroupsAsList) {
@@ -275,7 +316,7 @@ public class EdgeInfo {
         this.srcChunkSize = srcChunkSize;
         this.dstChunkSize = dstChunkSize;
         this.directed = directed;
-        this.prefix = prefix;
+        this.baseUri = baseUri;
         this.adjacentLists =
                 adjacentListsAsList.stream()
                         .collect(
@@ -285,32 +326,13 @@ public class EdgeInfo {
         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.getVersion(),
-                yamlParser.getAdj_lists().stream()
-                        .map(AdjacentList::new)
-                        .collect(Collectors.toUnmodifiableList()),
-                yamlParser.getProperty_groups().stream()
-                        .map(PropertyGroup::new)
-                        .collect(Collectors.toUnmodifiableList()));
-    }
-
     private EdgeInfo(
             EdgeTriplet edgeTriplet,
             long chunkSize,
             long srcChunkSize,
             long dstChunkSize,
             boolean directed,
-            String prefix,
+            URI baseUri,
             String version,
             Map<AdjListType, AdjacentList> adjacentLists,
             PropertyGroups propertyGroups) {
@@ -320,7 +342,7 @@ public class EdgeInfo {
                 srcChunkSize,
                 dstChunkSize,
                 directed,
-                prefix,
+                baseUri,
                 VersionParser.getVersion(version),
                 adjacentLists,
                 propertyGroups);
@@ -332,7 +354,7 @@ public class EdgeInfo {
             long srcChunkSize,
             long dstChunkSize,
             boolean directed,
-            String prefix,
+            URI baseUri,
             VersionInfo version,
             Map<AdjListType, AdjacentList> adjacentLists,
             PropertyGroups propertyGroups) {
@@ -341,33 +363,12 @@ public class EdgeInfo {
         this.srcChunkSize = srcChunkSize;
         this.dstChunkSize = dstChunkSize;
         this.directed = directed;
-        this.prefix = prefix;
+        this.baseUri = baseUri;
         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));
-    }
-
-    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);
-    }
-
     public static String concat(String srcLabel, String edgeLabel, String 
dstLabel) {
         return srcLabel
                 + GeneralParams.regularSeparator
@@ -394,7 +395,7 @@ public class EdgeInfo {
                         srcChunkSize,
                         dstChunkSize,
                         directed,
-                        prefix,
+                        baseUri,
                         version,
                         newAdjacentLists,
                         propertyGroups));
@@ -411,7 +412,7 @@ public class EdgeInfo {
                                         srcChunkSize,
                                         dstChunkSize,
                                         directed,
-                                        prefix,
+                                        baseUri,
                                         version,
                                         adjacentLists,
                                         newPropertyGroups));
@@ -445,38 +446,38 @@ public class EdgeInfo {
         return propertyGroups.getPropertyGroup(property);
     }
 
-    public String getPropertyGroupPrefix(PropertyGroup propertyGroup) {
+    public URI getPropertyGroupPrefix(PropertyGroup propertyGroup) {
         checkPropertyGroupExist(propertyGroup);
-        return getPrefix() + propertyGroup.getPrefix();
+        return getBaseUri().resolve(propertyGroup.getBaseUri());
     }
 
-    public String getPropertyGroupChunkPath(PropertyGroup propertyGroup, long 
chunkIndex) {
+    public URI getPropertyGroupChunkPath(PropertyGroup propertyGroup, long 
chunkIndex) {
         // PropertyGroup will be checked in getPropertyGroupPrefix
-        return getPropertyGroupPrefix(propertyGroup) + "chunk" + chunkIndex;
+        return getPropertyGroupPrefix(propertyGroup).resolve("chunk" + 
chunkIndex);
     }
 
-    public String getAdjacentListPrefix(AdjListType adjListType) {
-        return getPrefix() + getAdjacentList(adjListType).getPrefix() + 
"adj_list/";
+    public URI getAdjacentListPrefix(AdjListType adjListType) {
+        return 
getBaseUri().resolve(getAdjacentList(adjListType).getBaseUri()).resolve("adj_list/");
     }
 
-    public String getAdjacentListChunkPath(AdjListType adjListType, long 
vertexChunkIndex) {
-        return getAdjacentListPrefix(adjListType) + "chunk" + vertexChunkIndex;
+    public URI getAdjacentListChunkPath(AdjListType adjListType, long 
vertexChunkIndex) {
+        return getAdjacentListPrefix(adjListType).resolve("chunk" + 
vertexChunkIndex);
     }
 
-    public String getOffsetPrefix(AdjListType adjListType) {
-        return getAdjacentListPrefix(adjListType) + "offset/";
+    public URI getOffsetPrefix(AdjListType adjListType) {
+        return getAdjacentListPrefix(adjListType).resolve("offset/");
     }
 
-    public String getOffsetChunkPath(AdjListType adjListType, long 
vertexChunkIndex) {
-        return getOffsetPrefix(adjListType) + "chunk" + vertexChunkIndex;
+    public URI getOffsetChunkPath(AdjListType adjListType, long 
vertexChunkIndex) {
+        return getOffsetPrefix(adjListType).resolve("chunk" + 
vertexChunkIndex);
     }
 
-    public String getVerticesNumFilePath(AdjListType adjListType) {
-        return getAdjacentListPrefix(adjListType) + "vertex_count";
+    public URI getVerticesNumFilePath(AdjListType adjListType) {
+        return getAdjacentListPrefix(adjListType).resolve("vertex_count");
     }
 
-    public String getEdgesNumFilePath(AdjListType adjListType, long 
vertexChunkIndex) {
-        return getAdjacentListPrefix(adjListType) + "edge_count" + 
vertexChunkIndex;
+    public URI getEdgesNumFilePath(AdjListType adjListType, long 
vertexChunkIndex) {
+        return getAdjacentListPrefix(adjListType).resolve("edge_count" + 
vertexChunkIndex);
     }
 
     public DataType getPropertyType(String propertyName) {
@@ -491,26 +492,6 @@ public class EdgeInfo {
         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();
-    }
-
     public String dump() {
         Yaml yaml = new Yaml(GraphYaml.getRepresenter(), 
GraphYaml.getDumperOptions());
         EdgeYaml edgeYaml = new EdgeYaml(this);
@@ -550,11 +531,11 @@ public class EdgeInfo {
     }
 
     public String getPrefix() {
-        return prefix;
+        return baseUri.toString();
     }
 
-    public String getEdgePath() {
-        return getPrefix() + getConcat() + ".edge.yaml";
+    public URI getBaseUri() {
+        return baseUri;
     }
 
     public VersionInfo getVersion() {
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 ddad1a88..7ba3ee59 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,7 @@
 
 package org.apache.graphar.info;
 
-import java.io.IOException;
-import java.util.ArrayList;
+import java.net.URI;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -28,20 +27,13 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.graphar.info.yaml.GraphYaml;
-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 URI baseUri;
     private final Map<String, VertexInfo> vertexType2VertexInfo;
     private final Map<String, EdgeInfo> edgeConcat2EdgeInfo;
     private final VersionInfo version;
@@ -52,10 +44,19 @@ public class GraphInfo {
             List<EdgeInfo> edgeInfos,
             String prefix,
             String version) {
+        this(name, vertexInfos, edgeInfos, URI.create(prefix), version);
+    }
+
+    public GraphInfo(
+            String name,
+            List<VertexInfo> vertexInfos,
+            List<EdgeInfo> edgeInfos,
+            URI baseUri,
+            String version) {
         this.name = name;
         this.vertexInfos = List.copyOf(vertexInfos);
         this.edgeInfos = List.copyOf(edgeInfos);
-        this.prefix = prefix;
+        this.baseUri = baseUri;
         this.version = VersionParser.getVersion(version);
         this.vertexType2VertexInfo =
                 vertexInfos.stream()
@@ -69,20 +70,11 @@ public class GraphInfo {
                                         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());
-    }
-
     private GraphInfo(
             String name,
             List<VertexInfo> vertexInfos,
             List<EdgeInfo> edgeInfos,
-            String prefix,
+            URI baseUri,
             String version,
             Map<String, VertexInfo> vertexType2VertexInfo,
             Map<String, EdgeInfo> edgeConcat2EdgeInfo) {
@@ -90,7 +82,7 @@ public class GraphInfo {
                 name,
                 vertexInfos,
                 edgeInfos,
-                prefix,
+                baseUri,
                 VersionParser.getVersion(version),
                 vertexType2VertexInfo,
                 edgeConcat2EdgeInfo);
@@ -100,62 +92,19 @@ public class GraphInfo {
             String name,
             List<VertexInfo> vertexInfos,
             List<EdgeInfo> edgeInfos,
-            String prefix,
+            URI baseUri,
             VersionInfo version,
             Map<String, VertexInfo> vertexType2VertexInfo,
             Map<String, EdgeInfo> edgeConcat2EdgeInfo) {
         this.name = name;
         this.vertexInfos = vertexInfos;
         this.edgeInfos = edgeInfos;
-        this.prefix = prefix;
+        this.baseUri = baseUri;
         this.version = version;
         this.vertexType2VertexInfo = vertexType2VertexInfo;
         this.edgeConcat2EdgeInfo = edgeConcat2EdgeInfo;
     }
 
-    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());
-    }
-
-    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.getRepresenter(), 
GraphYaml.getDumperOptions());
         GraphYaml graphYaml = new GraphYaml(this);
@@ -181,7 +130,7 @@ public class GraphInfo {
                         name,
                         newVertexInfos,
                         edgeInfos,
-                        prefix,
+                        baseUri,
                         version,
                         newVertexType2VertexInfo,
                         edgeConcat2EdgeInfo));
@@ -207,7 +156,7 @@ public class GraphInfo {
                         name,
                         vertexInfos,
                         newEdgeInfos,
-                        prefix,
+                        baseUri,
                         version,
                         vertexType2VertexInfo,
                         newEdgeConcat2EdgeInfo));
@@ -252,29 +201,15 @@ public class GraphInfo {
     }
 
     public String getPrefix() {
-        return prefix;
+        return baseUri.toString();
     }
 
-    public VersionInfo getVersion() {
-        return version;
+    public URI getBaseUri() {
+        return baseUri;
     }
 
-    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);
+    public VersionInfo getVersion() {
+        return version;
     }
 
     private void checkVertexExist(String type) {
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 c00ce3f5..b1c94a69 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
@@ -19,6 +19,7 @@
 
 package org.apache.graphar.info;
 
+import java.net.URI;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -29,16 +30,19 @@ 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.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;
+    private final URI baseUri;
 
     public PropertyGroup(List<Property> propertyMap, FileType fileType, String 
prefix) {
+        this(propertyMap, fileType, URI.create(prefix));
+    }
+
+    public PropertyGroup(List<Property> propertyMap, FileType fileType, URI 
baseUri) {
         this.propertyList = List.copyOf(propertyMap);
         this.propertyMap =
                 propertyMap.stream()
@@ -46,16 +50,7 @@ public class PropertyGroup implements Iterable<Property> {
                                 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());
+        this.baseUri = baseUri;
     }
 
     public Optional<PropertyGroup> addPropertyAsNew(Property property) {
@@ -65,7 +60,7 @@ public class PropertyGroup implements Iterable<Property> {
         List<Property> newPropertyMap =
                 Stream.concat(propertyMap.values().stream(), 
Stream.of(property))
                         .collect(Collectors.toUnmodifiableList());
-        return Optional.of(new PropertyGroup(newPropertyMap, fileType, 
prefix));
+        return Optional.of(new PropertyGroup(newPropertyMap, fileType, 
baseUri));
     }
 
     @Override
@@ -97,7 +92,11 @@ public class PropertyGroup implements Iterable<Property> {
     }
 
     public String getPrefix() {
-        return prefix;
+        return baseUri.toString();
+    }
+
+    public URI getBaseUri() {
+        return baseUri;
     }
 }
 
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 45eb4f04..711315c1 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,27 +19,19 @@
 
 package org.apache.graphar.info;
 
-import java.io.IOException;
+import java.net.URI;
 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.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.constructor.Constructor;
 
 public class VertexInfo {
     private final String type;
     private final long chunkSize;
     private final PropertyGroups propertyGroups;
-    private final String prefix;
+    private final URI baseUri;
     private final VersionInfo version;
 
     public VertexInfo(
@@ -48,55 +40,31 @@ public class VertexInfo {
             List<PropertyGroup> propertyGroups,
             String prefix,
             String version) {
-        this(type, chunkSize, propertyGroups, prefix, 
VersionParser.getVersion(version));
+        this(type, chunkSize, propertyGroups, URI.create(prefix), version);
     }
 
     public VertexInfo(
             String type,
             long chunkSize,
             List<PropertyGroup> propertyGroups,
-            String prefix,
+            URI baseUri,
+            String version) {
+        this(type, chunkSize, propertyGroups, baseUri, 
VersionParser.getVersion(version));
+    }
+
+    public VertexInfo(
+            String type,
+            long chunkSize,
+            List<PropertyGroup> propertyGroups,
+            URI baseUri,
             VersionInfo version) {
         this.type = type;
         this.chunkSize = chunkSize;
         this.propertyGroups = new PropertyGroups(propertyGroups);
-        this.prefix = prefix;
+        this.baseUri = baseUri;
         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());
-    }
-
-    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));
-    }
-
-    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);
-    }
-
     public Optional<VertexInfo> addPropertyGroupAsNew(PropertyGroup 
propertyGroup) {
         return propertyGroups
                 .addPropertyGroupAsNew(propertyGroup)
@@ -104,7 +72,7 @@ public class VertexInfo {
                 .map(
                         newPropertyGroups ->
                                 new VertexInfo(
-                                        type, chunkSize, newPropertyGroups, 
prefix, version));
+                                        type, chunkSize, newPropertyGroups, 
baseUri, version));
     }
 
     public int propertyGroupNum() {
@@ -131,38 +99,18 @@ public class VertexInfo {
         return propertyGroups.hasPropertyGroup(propertyGroup);
     }
 
-    public String getPropertyGroupPrefix(PropertyGroup propertyGroup) {
+    public URI getPropertyGroupPrefix(PropertyGroup propertyGroup) {
         checkPropertyGroupExist(propertyGroup);
-        return getPrefix() + propertyGroup.getPrefix();
+        return getBaseUri().resolve(propertyGroup.getBaseUri());
     }
 
-    public String getPropertyGroupChunkPath(PropertyGroup propertyGroup, long 
chunkIndex) {
+    public URI 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());
+        return getPropertyGroupPrefix(propertyGroup).resolve("chunk" + 
chunkIndex);
     }
 
-    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 URI getVerticesNumFilePath() {
+        return getBaseUri().resolve("vertex_count");
     }
 
     public String dump() {
@@ -184,15 +132,15 @@ public class VertexInfo {
     }
 
     public String getPrefix() {
-        return prefix;
+        return baseUri.toString();
     }
 
-    public VersionInfo getVersion() {
-        return version;
+    public URI getBaseUri() {
+        return baseUri;
     }
 
-    public String getVertexPath() {
-        return getPrefix() + getType() + ".vertex.yaml";
+    public VersionInfo getVersion() {
+        return version;
     }
 
     private void checkPropertyGroupExist(PropertyGroup propertyGroup) {
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/BaseGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/BaseGraphInfoLoader.java
new file mode 100644
index 00000000..77b74f8b
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/BaseGraphInfoLoader.java
@@ -0,0 +1,101 @@
+/*
+ * 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.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.graphar.info.EdgeInfo;
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.VertexInfo;
+import org.apache.graphar.info.yaml.AdjacentListYaml;
+import org.apache.graphar.info.yaml.EdgeYaml;
+import org.apache.graphar.info.yaml.GraphYaml;
+import org.apache.graphar.info.yaml.PropertyGroupYaml;
+import org.apache.graphar.info.yaml.VertexYaml;
+
+public abstract class BaseGraphInfoLoader implements GraphInfoLoader {
+
+    public abstract GraphInfo loadGraphInfo(URI graphYamlUri) throws 
IOException;
+
+    public abstract VertexInfo loadVertexInfo(URI vertexYamlUri) throws 
IOException;
+
+    public abstract EdgeInfo loadEdgeInfo(URI edgeYamlUri) throws IOException;
+
+    public GraphInfo buildGraphInfoFromGraphYaml(URI baseUri, GraphYaml 
graphYaml)
+            throws IOException {
+
+        URI defaultBaseUri = baseUri.resolve(".");
+        if (graphYaml.getPrefix() != null && !graphYaml.getPrefix().isEmpty()) 
{
+            defaultBaseUri = baseUri.resolve(graphYaml.getPrefix());
+        }
+
+        // load vertices
+        List<VertexInfo> vertexInfos = new 
ArrayList<>(graphYaml.getVertices().size());
+        for (String vertexYamlPath : graphYaml.getVertices()) {
+            URI vertexInfoUri = baseUri.resolve(vertexYamlPath);
+            vertexInfos.add(loadVertexInfo(vertexInfoUri));
+        }
+        // load edges
+        List<EdgeInfo> edgeInfos = new 
ArrayList<>(graphYaml.getEdges().size());
+        for (String edgeYamlPath : graphYaml.getEdges()) {
+            URI edgeInfoUri = baseUri.resolve(edgeYamlPath);
+            edgeInfos.add(loadEdgeInfo(edgeInfoUri));
+        }
+        return new GraphInfo(
+                graphYaml.getName(),
+                vertexInfos,
+                edgeInfos,
+                defaultBaseUri,
+                graphYaml.getVersion());
+    }
+
+    public VertexInfo buildVertexInfoFromGraphYaml(VertexYaml vertexYaml) {
+        return new VertexInfo(
+                vertexYaml.getType(),
+                vertexYaml.getChunk_size(),
+                vertexYaml.getProperty_groups().stream()
+                        .map(PropertyGroupYaml::toPropertyGroup)
+                        .collect(Collectors.toList()),
+                vertexYaml.getPrefix(),
+                vertexYaml.getVersion());
+    }
+
+    public EdgeInfo buildEdgeInfoFromGraphYaml(EdgeYaml edgeYaml) {
+        return new EdgeInfo(
+                edgeYaml.getSrc_type(),
+                edgeYaml.getEdge_type(),
+                edgeYaml.getDst_type(),
+                edgeYaml.getChunk_size(),
+                edgeYaml.getSrc_chunk_size(),
+                edgeYaml.getDst_chunk_size(),
+                edgeYaml.isDirected(),
+                edgeYaml.getPrefix(),
+                edgeYaml.getVersion(),
+                edgeYaml.getAdj_lists().stream()
+                        .map(AdjacentListYaml::toAdjacentList)
+                        .collect(Collectors.toUnmodifiableList()),
+                edgeYaml.getProperty_groups().stream()
+                        .map(PropertyGroupYaml::toPropertyGroup)
+                        .collect(Collectors.toList()));
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphInfoLoader.java
new file mode 100644
index 00000000..0c5e6d14
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphInfoLoader.java
@@ -0,0 +1,35 @@
+/*
+ * 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.net.URI;
+import org.apache.graphar.info.EdgeInfo;
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.VertexInfo;
+
+public interface GraphInfoLoader {
+
+    GraphInfo loadGraphInfo(URI graphYamlUri) throws IOException;
+
+    VertexInfo loadVertexInfo(URI vertexYamlUri) throws IOException;
+
+    EdgeInfo loadEdgeInfo(URI edgeYamlUri) 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
deleted file mode 100644
index 936fa9ed..00000000
--- 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/LocalYamlGraphLoader.java
+++ /dev/null
@@ -1,89 +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.loader;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-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.graphar.util.PathUtil;
-import org.yaml.snakeyaml.LoaderOptions;
-import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.constructor.Constructor;
-
-public class LocalYamlGraphLoader implements GraphLoader {
-    public LocalYamlGraphLoader() {}
-
-    @Override
-    public GraphInfo load(String graphYamlPath) throws IOException {
-        final Path path = FileSystems.getDefault().getPath(graphYamlPath);
-        // load graph itself
-        final BufferedReader reader = Files.newBufferedReader(path);
-        final Yaml yamlLoader = new Yaml(new Constructor(GraphYaml.class, new 
LoaderOptions()));
-        final GraphYaml graphYaml = yamlLoader.load(reader);
-        reader.close();
-        String defaultPrefix = PathUtil.pathToDirectory(graphYamlPath);
-        String prefix = defaultPrefix;
-        if (graphYaml.getPrefix() != null && !graphYaml.getPrefix().isEmpty()) 
{
-            prefix = graphYaml.getPrefix();
-        }
-
-        // 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, prefix, 
graphYaml.getVersion());
-    }
-
-    private VertexInfo loadVertex(String path) throws IOException {
-        final Path vertexPath = FileSystems.getDefault().getPath(path);
-        final BufferedReader reader = Files.newBufferedReader(vertexPath);
-        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
-        VertexYaml vertexYaml = vertexYamlLoader.load(reader);
-        reader.close();
-        return vertexYaml.toVertexInfo();
-    }
-
-    private EdgeInfo loadEdge(String path) throws IOException {
-        final Path edgePath = FileSystems.getDefault().getPath(path);
-        final BufferedReader reader = Files.newBufferedReader(edgePath);
-        Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new 
LoaderOptions()));
-        EdgeYaml edgeYaml = edgeYamlLoader.load(reader);
-        reader.close();
-        return edgeYaml.toEdgeInfo();
-    }
-}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/ReaderGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/ReaderGraphInfoLoader.java
new file mode 100644
index 00000000..f83b826b
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/ReaderGraphInfoLoader.java
@@ -0,0 +1,62 @@
+/*
+ * 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.io.Reader;
+import java.net.URI;
+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.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public abstract class ReaderGraphInfoLoader extends BaseGraphInfoLoader {
+
+    public abstract Reader readYaml(URI uri) throws IOException;
+
+    @Override
+    public GraphInfo loadGraphInfo(URI graphYamlUri) throws IOException {
+        Reader yaml = readYaml(graphYamlUri);
+        Yaml GraphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new 
LoaderOptions()));
+        GraphYaml graphYaml = GraphYamlLoader.load(yaml);
+        return buildGraphInfoFromGraphYaml(graphYamlUri, graphYaml);
+    }
+
+    @Override
+    public VertexInfo loadVertexInfo(URI vertexYamlUri) throws IOException {
+        Reader yaml = readYaml(vertexYamlUri);
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = vertexYamlLoader.load(yaml);
+        return buildVertexInfoFromGraphYaml(vertexYaml);
+    }
+
+    @Override
+    public EdgeInfo loadEdgeInfo(URI edgeYamlUri) throws IOException {
+        Reader yaml = readYaml(edgeYamlUri);
+        Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new 
LoaderOptions()));
+        EdgeYaml edgeYaml = edgeYamlLoader.load(yaml);
+        return buildEdgeInfoFromGraphYaml(edgeYaml);
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/StreamGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/StreamGraphInfoLoader.java
new file mode 100644
index 00000000..5292c622
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/StreamGraphInfoLoader.java
@@ -0,0 +1,63 @@
+/*
+ * 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.io.InputStream;
+import java.net.URI;
+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.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public abstract class StreamGraphInfoLoader extends BaseGraphInfoLoader {
+
+    public abstract InputStream readYaml(URI uri) throws IOException;
+
+    @Override
+    public GraphInfo loadGraphInfo(URI graphYamluri) throws IOException {
+        // load graph itself
+        InputStream yaml = readYaml(graphYamluri);
+        Yaml GraphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new 
LoaderOptions()));
+        GraphYaml graphYaml = GraphYamlLoader.load(yaml);
+        return buildGraphInfoFromGraphYaml(graphYamluri, graphYaml);
+    }
+
+    @Override
+    public VertexInfo loadVertexInfo(URI vertexYamlUri) throws IOException {
+        InputStream yaml = readYaml(vertexYamlUri);
+        Yaml edgeYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml edgeYaml = edgeYamlLoader.load(yaml);
+        return buildVertexInfoFromGraphYaml(edgeYaml);
+    }
+
+    @Override
+    public EdgeInfo loadEdgeInfo(URI edgeYamlUri) throws IOException {
+        InputStream yaml = readYaml(edgeYamlUri);
+        Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new 
LoaderOptions()));
+        EdgeYaml edgeYaml = edgeYamlLoader.load(yaml);
+        return buildEdgeInfoFromGraphYaml(edgeYaml);
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/StringGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/StringGraphInfoLoader.java
new file mode 100644
index 00000000..cc82ab69
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/StringGraphInfoLoader.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.loader;
+
+import java.io.IOException;
+import java.net.URI;
+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.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public abstract class StringGraphInfoLoader extends BaseGraphInfoLoader {
+
+    public abstract String readYaml(URI uri) throws IOException;
+
+    @Override
+    public GraphInfo loadGraphInfo(URI graphYamlUri) throws IOException {
+        String yaml = readYaml(graphYamlUri);
+        Yaml GraphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new 
LoaderOptions()));
+        GraphYaml graphYaml = GraphYamlLoader.load(yaml);
+        return buildGraphInfoFromGraphYaml(graphYamlUri, graphYaml);
+    }
+
+    @Override
+    public VertexInfo loadVertexInfo(URI vertexYamlUri) throws IOException {
+        String yaml = readYaml(vertexYamlUri);
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = vertexYamlLoader.load(yaml);
+        return buildVertexInfoFromGraphYaml(vertexYaml);
+    }
+
+    @Override
+    public EdgeInfo loadEdgeInfo(URI edgeYamlUri) throws IOException {
+        String yaml = readYaml(edgeYamlUri);
+        Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new 
LoaderOptions()));
+        EdgeYaml edgeYaml = edgeYamlLoader.load(yaml);
+        return buildEdgeInfoFromGraphYaml(edgeYaml);
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemReaderGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemReaderGraphInfoLoader.java
new file mode 100644
index 00000000..b1580c06
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemReaderGraphInfoLoader.java
@@ -0,0 +1,36 @@
+/*
+ * 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.impl;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URI;
+import org.apache.graphar.info.loader.ReaderGraphInfoLoader;
+
+public class LocalFileSystemReaderGraphInfoLoader extends 
ReaderGraphInfoLoader {
+    @Override
+    public Reader readYaml(URI uri) throws IOException {
+        if (uri.getScheme() != null && !"file".equals(uri.getScheme())) {
+            throw new RuntimeException("Only file:// scheme is supported in 
Local File System");
+        }
+        String path = uri.getPath();
+        return 
java.nio.file.Files.newBufferedReader(java.nio.file.Paths.get(path));
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemStreamGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemStreamGraphInfoLoader.java
new file mode 100644
index 00000000..5a4d35ef
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemStreamGraphInfoLoader.java
@@ -0,0 +1,37 @@
+/*
+ * 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.impl;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import org.apache.graphar.info.loader.StreamGraphInfoLoader;
+
+public class LocalFileSystemStreamGraphInfoLoader extends 
StreamGraphInfoLoader {
+    @Override
+    public InputStream readYaml(URI uri) throws IOException {
+        if (uri.getScheme() != null && !"file".equals(uri.getScheme())) {
+            throw new RuntimeException("Only file:// scheme is supported in 
Local File System");
+        }
+        String path = uri.getPath();
+        return new FileInputStream(path);
+    }
+}
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemStringGraphInfoLoader.java
 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemStringGraphInfoLoader.java
new file mode 100644
index 00000000..24b3d078
--- /dev/null
+++ 
b/maven-projects/info/src/main/java/org/apache/graphar/info/loader/impl/LocalFileSystemStringGraphInfoLoader.java
@@ -0,0 +1,41 @@
+/*
+ * 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.impl;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URI;
+import org.apache.graphar.info.loader.StringGraphInfoLoader;
+
+public class LocalFileSystemStringGraphInfoLoader extends 
StringGraphInfoLoader {
+    @Override
+    public String readYaml(URI uri) throws IOException {
+        if (uri.getScheme() != null && !"file".equals(uri.getScheme())) {
+            throw new IllegalArgumentException(
+                    "Only file:// scheme is supported in Local File System");
+        }
+        String path = uri.getPath();
+        try (FileInputStream fis = new FileInputStream(path)) {
+            byte[] data = new byte[fis.available()];
+            fis.read(data);
+            return new String(data);
+        }
+    }
+}
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 5ef06d33..141802f0 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
@@ -77,25 +77,6 @@ public class EdgeYaml {
                         .collect(Collectors.toList());
     }
 
-    public EdgeInfo toEdgeInfo() {
-        return new EdgeInfo(
-                src_type,
-                edge_type,
-                dst_type,
-                chunk_size,
-                src_chunk_size,
-                dst_chunk_size,
-                directed,
-                prefix,
-                version,
-                adj_lists.stream()
-                        .map(AdjacentListYaml::toAdjacentList)
-                        .collect(Collectors.toUnmodifiableList()),
-                property_groups.stream()
-                        .map(PropertyGroupYaml::toPropertyGroup)
-                        .collect(Collectors.toList()));
-    }
-
     public String getSrc_type() {
         return src_type;
     }
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 457d4175..72393218 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
@@ -45,7 +45,7 @@ public class PropertyGroupYaml {
         this.prefix = propertyGroup.getPrefix();
     }
 
-    PropertyGroup toPropertyGroup() {
+    public PropertyGroup toPropertyGroup() {
         return new PropertyGroup(
                 
properties.stream().map(PropertyYaml::toProperty).collect(Collectors.toList()),
                 FileType.fromString(file_type),
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 512d8e8c..345e0369 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
@@ -56,17 +56,6 @@ public class VertexYaml {
                         .orElse(null);
     }
 
-    public VertexInfo toVertexInfo() {
-        return new VertexInfo(
-                type,
-                chunk_size,
-                property_groups.stream()
-                        .map(PropertyGroupYaml::toPropertyGroup)
-                        .collect(Collectors.toList()),
-                prefix,
-                version);
-    }
-
     public String getType() {
         return type;
     }
diff --git 
a/maven-projects/info/src/main/java/org/apache/graphar/util/PathUtil.java 
b/maven-projects/info/src/main/java/org/apache/graphar/util/PathUtil.java
deleted file mode 100644
index 7b68c543..00000000
--- a/maven-projects/info/src/main/java/org/apache/graphar/util/PathUtil.java
+++ /dev/null
@@ -1,48 +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.util;
-
-public class PathUtil {
-    public static String pathToDirectory(String path) {
-        if (path.startsWith("s3://")) {
-            int t = path.indexOf('?');
-            if (t != -1) {
-                String prefix = path.substring(0, t);
-                String suffix = path.substring(t);
-                int lastSlashIdx = prefix.lastIndexOf('/');
-                if (lastSlashIdx != -1) {
-                    return prefix.substring(0, lastSlashIdx + 1) + suffix;
-                }
-            } else {
-                int lastSlashIdx = path.lastIndexOf('/');
-                if (lastSlashIdx != -1) {
-                    return path.substring(0, lastSlashIdx + 1);
-                }
-                return path;
-            }
-        } else {
-            int lastSlashIdx = path.lastIndexOf('/');
-            if (lastSlashIdx != -1) {
-                return path.substring(0, lastSlashIdx + 1);
-            }
-        }
-        return path;
-    }
-}
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/EdgeInfoTest.java 
b/maven-projects/info/src/test/java/org/apache/graphar/info/EdgeInfoTest.java
index 10e6125b..caf25bb5 100644
--- 
a/maven-projects/info/src/test/java/org/apache/graphar/info/EdgeInfoTest.java
+++ 
b/maven-projects/info/src/test/java/org/apache/graphar/info/EdgeInfoTest.java
@@ -19,13 +19,14 @@
 
 package org.apache.graphar.info;
 
+import java.net.URI;
 import java.util.List;
 import org.junit.Assert;
 import org.junit.Test;
 
 public class EdgeInfoTest {
 
-    private EdgeInfo.EdgeInfoBuilder e =
+    private final EdgeInfo.EdgeInfoBuilder e =
             EdgeInfo.builder()
                     .srcType("person")
                     .edgeType("knows")
@@ -33,9 +34,72 @@ public class EdgeInfoTest {
                     .srcChunkSize(100)
                     .dstChunkSize(100)
                     .directed(false)
-                    .prefix("edge/person_knows_person/")
+                    .baseUri(URI.create("edge/person_knows_person/"))
                     .version("gar/v1");
 
+    @Test
+    public void testBuildWithPrefix() {
+        EdgeInfo edgeInfo =
+                EdgeInfo.builder()
+                        .srcType("person")
+                        .edgeType("knows")
+                        .dstType("person")
+                        .propertyGroups(new 
PropertyGroups(List.of(TestUtil.pg3)))
+                        .adjacentLists(List.of(TestUtil.orderedBySource))
+                        .chunkSize(1024)
+                        .srcChunkSize(100)
+                        .dstChunkSize(100)
+                        .directed(false)
+                        .prefix("edge/person_knows_person/")
+                        .version("gar/v1")
+                        .build();
+        Assert.assertEquals(URI.create("edge/person_knows_person/"), 
edgeInfo.getBaseUri());
+    }
+
+    @Test
+    public void testUriAndPrefixConflict() {
+        try {
+            EdgeInfo.builder()
+                    .srcType("person")
+                    .edgeType("knows")
+                    .dstType("person")
+                    .propertyGroups(new PropertyGroups(List.of(TestUtil.pg3)))
+                    .adjacentLists(List.of(TestUtil.orderedBySource))
+                    .chunkSize(1024)
+                    .srcChunkSize(100)
+                    .dstChunkSize(100)
+                    .directed(false)
+                    .prefix("edge/person_knows_person/")
+                    .baseUri(URI.create("/person_knows_person/"))
+                    .version("gar/v1")
+                    .build();
+        } catch (IllegalArgumentException e) {
+            Assert.assertEquals(
+                    "baseUri and prefix conflict: 
baseUri=/person_knows_person/ prefix=edge/person_knows_person/",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void testMissingUriAndPrefix() {
+        try {
+            EdgeInfo.builder()
+                    .srcType("person")
+                    .edgeType("knows")
+                    .dstType("person")
+                    .propertyGroups(new PropertyGroups(List.of(TestUtil.pg3)))
+                    .adjacentLists(List.of(TestUtil.orderedBySource))
+                    .chunkSize(1024)
+                    .srcChunkSize(100)
+                    .dstChunkSize(100)
+                    .directed(false)
+                    .version("gar/v1")
+                    .build();
+        } catch (IllegalArgumentException e) {
+            Assert.assertEquals("baseUri and prefix cannot be both null", 
e.getMessage());
+        }
+    }
+
     @Test
     public void erroneousTripletEdgeBuilderTest() {
         try {
@@ -43,7 +107,7 @@ public class EdgeInfoTest {
                     .addPropertyGroups(List.of(TestUtil.pg3))
                     .build();
         } catch (IllegalArgumentException e) {
-            System.err.println(e.getMessage());
+            Assert.assertEquals("Edge triplet is null", e.getMessage());
         }
     }
 
@@ -52,7 +116,7 @@ public class EdgeInfoTest {
         try {
             
e.dstType("person").addPropertyGroups(List.of(TestUtil.pg3)).build();
         } catch (IllegalArgumentException e) {
-            System.err.println(e.getMessage());
+            Assert.assertEquals("AdjacentLists is empty", e.getMessage());
         }
     }
 
@@ -63,7 +127,7 @@ public class EdgeInfoTest {
                     .dstType("person")
                     .build();
         } catch (IllegalArgumentException e) {
-            System.err.println(e.getMessage());
+            Assert.assertEquals("PropertyGroups is empty", e.getMessage());
         }
     }
 
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoLoaderTest.java
 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoLoaderTest.java
new file mode 100644
index 00000000..6ae1398f
--- /dev/null
+++ 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoLoaderTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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 java.net.URI;
+import org.apache.graphar.info.loader.GraphInfoLoader;
+import 
org.apache.graphar.info.loader.impl.LocalFileSystemReaderGraphInfoLoader;
+import 
org.apache.graphar.info.loader.impl.LocalFileSystemStreamGraphInfoLoader;
+import 
org.apache.graphar.info.loader.impl.LocalFileSystemStringGraphInfoLoader;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class GraphInfoLoaderTest {
+
+    @BeforeClass
+    public static void init() {
+        TestUtil.checkTestData();
+    }
+
+    @AfterClass
+    public static void clean() {}
+
+    @Test
+    public void testStringLoader() {
+        final URI GRAPH_PATH_URI = TestUtil.getLdbcSampleGraphURI();
+        GraphInfoLoader loader = new LocalFileSystemStringGraphInfoLoader();
+        try {
+            final GraphInfo graphInfo = loader.loadGraphInfo(GRAPH_PATH_URI);
+            testGraphInfo(graphInfo);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testStreamLoader() {
+        final URI GRAPH_PATH_URI = TestUtil.getLdbcSampleGraphURI();
+        GraphInfoLoader loader = new LocalFileSystemStreamGraphInfoLoader();
+        try {
+            final GraphInfo graphInfo = loader.loadGraphInfo(GRAPH_PATH_URI);
+            testGraphInfo(graphInfo);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testReaderLoader() {
+        final URI GRAPH_PATH_URI = TestUtil.getLdbcSampleGraphURI();
+        GraphInfoLoader loader = new LocalFileSystemReaderGraphInfoLoader();
+        try {
+            final GraphInfo graphInfo = loader.loadGraphInfo(GRAPH_PATH_URI);
+            testGraphInfo(graphInfo);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void testGraphInfo(GraphInfo graphInfo) {
+        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());
+        }
+    }
+}
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoTest.java 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoTest.java
index 20cae797..afb0da71 100644
--- 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoTest.java
+++ 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoTest.java
@@ -20,14 +20,14 @@
 package org.apache.graphar.info;
 
 import java.io.IOException;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.graphar.info.loader.GraphLoader;
-import org.apache.graphar.info.loader.LocalYamlGraphLoader;
+import org.apache.graphar.info.loader.GraphInfoLoader;
+import 
org.apache.graphar.info.loader.impl.LocalFileSystemStreamGraphInfoLoader;
 import org.apache.graphar.info.type.AdjListType;
 import org.apache.graphar.info.type.DataType;
 import org.apache.graphar.info.type.FileType;
-import org.apache.graphar.util.PathUtil;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -38,15 +38,15 @@ public class GraphInfoTest {
     private static GraphInfo graphInfo;
     private static VertexInfo personVertexInfo;
     private static EdgeInfo knowsEdgeInfo;
-    private static String GRAPH_PATH;
+    private static URI GRAPH_PATH_URI;
 
     @BeforeClass
     public static void setUp() {
         TestUtil.checkTestData();
-        GRAPH_PATH = TestUtil.getLdbcSampleGraphPath();
-        final GraphLoader graphLoader = new LocalYamlGraphLoader();
+        GRAPH_PATH_URI = TestUtil.getLdbcSampleGraphURI();
+        GraphInfoLoader loader = new LocalFileSystemStreamGraphInfoLoader();
         try {
-            graphInfo = graphLoader.load(GRAPH_PATH);
+            graphInfo = loader.loadGraphInfo(GRAPH_PATH_URI);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -57,11 +57,22 @@ public class GraphInfoTest {
     @AfterClass
     public static void clean() {}
 
+    @Test
+    public void test() {
+        System.out.println(
+                graphInfo
+                        .getBaseUri()
+                        .resolve(
+                                knowsEdgeInfo.getAdjacentListPrefix(
+                                        AdjListType.ordered_by_source)));
+    }
+
     @Test
     public void testGraphInfoBasics() {
         Assert.assertNotNull(graphInfo);
         Assert.assertEquals("ldbc_sample", graphInfo.getName());
-        Assert.assertEquals(PathUtil.pathToDirectory(GRAPH_PATH), 
graphInfo.getPrefix());
+        Assert.assertEquals(GRAPH_PATH_URI.resolve(".").toString(), 
graphInfo.getPrefix());
+        Assert.assertEquals(GRAPH_PATH_URI.resolve("."), 
graphInfo.getBaseUri());
         Assert.assertNotNull(graphInfo.getEdgeInfos());
         Assert.assertEquals(1, graphInfo.getEdgeInfos().size());
         Assert.assertNotNull(graphInfo.getVertexInfos());
@@ -76,9 +87,7 @@ public class GraphInfoTest {
         Assert.assertEquals("person", personVertexInfo.getType());
         Assert.assertEquals(100, personVertexInfo.getChunkSize());
         Assert.assertEquals("vertex/person/", personVertexInfo.getPrefix());
-        Assert.assertEquals(
-                "vertex/person/vertex_count", 
personVertexInfo.getVerticesNumFilePath());
-        Assert.assertEquals("vertex/person/person.vertex.yaml", 
personVertexInfo.getVertexPath());
+        Assert.assertEquals(URI.create("vertex/person/"), 
personVertexInfo.getBaseUri());
         Assert.assertNotNull(personVertexInfo.getPropertyGroups());
         Assert.assertEquals(2, personVertexInfo.getPropertyGroups().size());
         Assert.assertEquals(1, personVertexInfo.getVersion().getVersion());
@@ -89,14 +98,16 @@ public class GraphInfoTest {
         // group1 id
         PropertyGroup idPropertyGroup = 
personVertexInfo.getPropertyGroups().get(0);
         Assert.assertEquals("id/", idPropertyGroup.getPrefix());
+        Assert.assertEquals(URI.create("id/"), idPropertyGroup.getBaseUri());
         Assert.assertEquals(FileType.CSV, idPropertyGroup.getFileType());
         Assert.assertEquals(
-                "vertex/person/id/", 
personVertexInfo.getPropertyGroupPrefix(idPropertyGroup));
+                URI.create("vertex/person/id/"),
+                personVertexInfo.getPropertyGroupPrefix(idPropertyGroup));
         Assert.assertEquals(
-                "vertex/person/id/chunk0",
+                URI.create("vertex/person/id/chunk0"),
                 personVertexInfo.getPropertyGroupChunkPath(idPropertyGroup, 
0));
         Assert.assertEquals(
-                "vertex/person/id/chunk4",
+                URI.create("vertex/person/id/chunk4"),
                 personVertexInfo.getPropertyGroupChunkPath(idPropertyGroup, 
4));
         Assert.assertNotNull(idPropertyGroup.getPropertyList());
         Assert.assertEquals(1, idPropertyGroup.getPropertyList().size());
@@ -109,15 +120,17 @@ public class GraphInfoTest {
         // group2 firstName_lastName_gender
         PropertyGroup firstName_lastName_gender = 
personVertexInfo.getPropertyGroups().get(1);
         Assert.assertEquals("firstName_lastName_gender/", 
firstName_lastName_gender.getPrefix());
+        Assert.assertEquals(
+                URI.create("firstName_lastName_gender/"), 
firstName_lastName_gender.getBaseUri());
         Assert.assertEquals(FileType.CSV, 
firstName_lastName_gender.getFileType());
         Assert.assertEquals(
-                "vertex/person/firstName_lastName_gender/",
+                URI.create("vertex/person/firstName_lastName_gender/"),
                 
personVertexInfo.getPropertyGroupPrefix(firstName_lastName_gender));
         Assert.assertEquals(
-                "vertex/person/firstName_lastName_gender/chunk0",
+                URI.create("vertex/person/firstName_lastName_gender/chunk0"),
                 
personVertexInfo.getPropertyGroupChunkPath(firstName_lastName_gender, 0));
         Assert.assertEquals(
-                "vertex/person/firstName_lastName_gender/chunk4",
+                URI.create("vertex/person/firstName_lastName_gender/chunk4"),
                 
personVertexInfo.getPropertyGroupChunkPath(firstName_lastName_gender, 4));
         Assert.assertNotNull(firstName_lastName_gender.getPropertyList());
         Assert.assertEquals(3, 
firstName_lastName_gender.getPropertyList().size());
@@ -152,9 +165,7 @@ public class GraphInfoTest {
         Assert.assertFalse(knowsEdgeInfo.isDirected());
         Assert.assertEquals("person_knows_person", knowsEdgeInfo.getConcat());
         Assert.assertEquals("edge/person_knows_person/", 
knowsEdgeInfo.getPrefix());
-        Assert.assertEquals(
-                "edge/person_knows_person/person_knows_person.edge.yaml",
-                knowsEdgeInfo.getEdgePath());
+        Assert.assertEquals(URI.create("edge/person_knows_person/"), 
knowsEdgeInfo.getBaseUri());
         Assert.assertEquals(1, knowsEdgeInfo.getVersion().getVersion());
     }
 
@@ -167,32 +178,33 @@ public class GraphInfoTest {
         Assert.assertEquals(FileType.CSV, adjOrderBySource.getFileType());
         Assert.assertEquals(AdjListType.ordered_by_source, 
adjOrderBySource.getType());
         Assert.assertEquals("ordered_by_source/", 
adjOrderBySource.getPrefix());
+        Assert.assertEquals(URI.create("ordered_by_source/"), 
adjOrderBySource.getBaseUri());
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_source/adj_list/vertex_count",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/vertex_count"),
                 
knowsEdgeInfo.getVerticesNumFilePath(AdjListType.ordered_by_source));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_source/adj_list/edge_count0",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/edge_count0"),
                 
knowsEdgeInfo.getEdgesNumFilePath(AdjListType.ordered_by_source, 0));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_source/adj_list/edge_count4",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/edge_count4"),
                 
knowsEdgeInfo.getEdgesNumFilePath(AdjListType.ordered_by_source, 4));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_source/adj_list/",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/"),
                 
knowsEdgeInfo.getAdjacentListPrefix(AdjListType.ordered_by_source));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_source/adj_list/chunk0",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/chunk0"),
                 
knowsEdgeInfo.getAdjacentListChunkPath(AdjListType.ordered_by_source, 0));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_source/adj_list/chunk4",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/chunk4"),
                 
knowsEdgeInfo.getAdjacentListChunkPath(AdjListType.ordered_by_source, 4));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_source/adj_list/offset/",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/offset/"),
                 knowsEdgeInfo.getOffsetPrefix(AdjListType.ordered_by_source));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_source/adj_list/offset/chunk0",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/offset/chunk0"),
                 
knowsEdgeInfo.getOffsetChunkPath(AdjListType.ordered_by_source, 0));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_source/adj_list/offset/chunk4",
+                
URI.create("edge/person_knows_person/ordered_by_source/adj_list/offset/chunk4"),
                 
knowsEdgeInfo.getOffsetChunkPath(AdjListType.ordered_by_source, 4));
 
         // test ordered by destination adjacency list
@@ -201,32 +213,33 @@ public class GraphInfoTest {
         Assert.assertEquals(FileType.CSV, adjOrderByDestination.getFileType());
         Assert.assertEquals(AdjListType.ordered_by_dest, 
adjOrderByDestination.getType());
         Assert.assertEquals("ordered_by_dest/", 
adjOrderByDestination.getPrefix());
+        Assert.assertEquals(URI.create("ordered_by_dest/"), 
adjOrderByDestination.getBaseUri());
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_dest/adj_list/vertex_count",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/vertex_count"),
                 
knowsEdgeInfo.getVerticesNumFilePath(AdjListType.ordered_by_dest));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_dest/adj_list/edge_count0",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/edge_count0"),
                 knowsEdgeInfo.getEdgesNumFilePath(AdjListType.ordered_by_dest, 
0));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_dest/adj_list/edge_count4",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/edge_count4"),
                 knowsEdgeInfo.getEdgesNumFilePath(AdjListType.ordered_by_dest, 
4));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_dest/adj_list/",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/"),
                 
knowsEdgeInfo.getAdjacentListPrefix(AdjListType.ordered_by_dest));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_dest/adj_list/chunk0",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/chunk0"),
                 
knowsEdgeInfo.getAdjacentListChunkPath(AdjListType.ordered_by_dest, 0));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_dest/adj_list/chunk4",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/chunk4"),
                 
knowsEdgeInfo.getAdjacentListChunkPath(AdjListType.ordered_by_dest, 4));
         Assert.assertEquals(
-                "edge/person_knows_person/ordered_by_dest/adj_list/offset/",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/offset/"),
                 knowsEdgeInfo.getOffsetPrefix(AdjListType.ordered_by_dest));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_dest/adj_list/offset/chunk0",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/offset/chunk0"),
                 knowsEdgeInfo.getOffsetChunkPath(AdjListType.ordered_by_dest, 
0));
         Assert.assertEquals(
-                
"edge/person_knows_person/ordered_by_dest/adj_list/offset/chunk4",
+                
URI.create("edge/person_knows_person/ordered_by_dest/adj_list/offset/chunk4"),
                 knowsEdgeInfo.getOffsetChunkPath(AdjListType.ordered_by_dest, 
4));
     }
 
@@ -236,15 +249,16 @@ public class GraphInfoTest {
         // edge properties group 1
         PropertyGroup propertyGroup = knowsEdgeInfo.getPropertyGroups().get(0);
         Assert.assertEquals("creationDate/", propertyGroup.getPrefix());
+        Assert.assertEquals(URI.create("creationDate/"), 
propertyGroup.getBaseUri());
         Assert.assertEquals(FileType.CSV, propertyGroup.getFileType());
         Assert.assertEquals(
-                "edge/person_knows_person/creationDate/",
+                URI.create("edge/person_knows_person/creationDate/"),
                 knowsEdgeInfo.getPropertyGroupPrefix(propertyGroup));
         Assert.assertEquals(
-                "edge/person_knows_person/creationDate/chunk0",
+                URI.create("edge/person_knows_person/creationDate/chunk0"),
                 knowsEdgeInfo.getPropertyGroupChunkPath(propertyGroup, 0));
         Assert.assertEquals(
-                "edge/person_knows_person/creationDate/chunk4",
+                URI.create("edge/person_knows_person/creationDate/chunk4"),
                 knowsEdgeInfo.getPropertyGroupChunkPath(propertyGroup, 4));
         // edge properties in group 1
         Assert.assertNotNull(propertyGroup.getPropertyList());
diff --git 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoUriTest.java
 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoUriTest.java
new file mode 100644
index 00000000..dc3cc83b
--- /dev/null
+++ 
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoUriTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.net.URI;
+import org.apache.graphar.info.loader.BaseGraphInfoLoader;
+import 
org.apache.graphar.info.loader.impl.LocalFileSystemStringGraphInfoLoader;
+import org.apache.graphar.info.yaml.VertexYaml;
+import org.junit.Assert;
+import org.junit.Test;
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public class GraphInfoUriTest {
+
+    @Test
+    public void testBaseGraphInfo() {
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = 
vertexYamlLoader.load(TestUtil.getBaseGraphInfoYaml());
+        BaseGraphInfoLoader baseGraphInfoLoader = new 
LocalFileSystemStringGraphInfoLoader();
+        VertexInfo vertexInfo = 
baseGraphInfoLoader.buildVertexInfoFromGraphYaml(vertexYaml);
+        Assert.assertEquals(URI.create("vertex/person/"), 
vertexInfo.getBaseUri());
+        // absolute paths
+        Assert.assertEquals(
+                URI.create("vertex/person/id/"),
+                
vertexInfo.getPropertyGroupPrefix(vertexInfo.getPropertyGroups().get(0)));
+        // relative paths
+        Assert.assertEquals(
+                
URI.create("/tmp/vertex/person/firstName_lastName_gender/chunk0"),
+                
vertexInfo.getPropertyGroupChunkPath(vertexInfo.getPropertyGroups().get(1), 0));
+    }
+
+    @Test
+    public void testS3GraphInfo() {
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = 
vertexYamlLoader.load(TestUtil.getS3GraphInfoYaml());
+        BaseGraphInfoLoader baseGraphInfoLoader = new 
LocalFileSystemStringGraphInfoLoader();
+        VertexInfo vertexInfo = 
baseGraphInfoLoader.buildVertexInfoFromGraphYaml(vertexYaml);
+        Assert.assertEquals(URI.create("s3://graphar/vertex/person/"), 
vertexInfo.getBaseUri());
+        // absolute paths
+        Assert.assertEquals(
+                URI.create("s3://graphar/vertex/person/id/"),
+                
vertexInfo.getPropertyGroupPrefix(vertexInfo.getPropertyGroups().get(0)));
+        // relative paths
+        Assert.assertEquals(
+                
URI.create("s3://tmp/vertex/person/firstName_lastName_gender/chunk0"),
+                
vertexInfo.getPropertyGroupChunkPath(vertexInfo.getPropertyGroups().get(1), 0));
+    }
+
+    @Test
+    public void testHdfsGraphInfo() {
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = 
vertexYamlLoader.load(TestUtil.getHdfsGraphInfoYaml());
+        BaseGraphInfoLoader baseGraphInfoLoader = new 
LocalFileSystemStringGraphInfoLoader();
+        VertexInfo vertexInfo = 
baseGraphInfoLoader.buildVertexInfoFromGraphYaml(vertexYaml);
+        Assert.assertEquals(URI.create("hdfs://graphar/vertex/person/"), 
vertexInfo.getBaseUri());
+        // absolute paths
+        Assert.assertEquals(
+                URI.create("hdfs://graphar/vertex/person/id/"),
+                
vertexInfo.getPropertyGroupPrefix(vertexInfo.getPropertyGroups().get(0)));
+        // relative paths
+        Assert.assertEquals(
+                
URI.create("hdfs://tmp/vertex/person/firstName_lastName_gender/chunk0"),
+                
vertexInfo.getPropertyGroupChunkPath(vertexInfo.getPropertyGroups().get(1), 0));
+    }
+
+    @Test
+    public void testFileGraphInfo() {
+        Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new 
LoaderOptions()));
+        VertexYaml vertexYaml = 
vertexYamlLoader.load(TestUtil.getFileGraphInfoYaml());
+        BaseGraphInfoLoader baseGraphInfoLoader = new 
LocalFileSystemStringGraphInfoLoader();
+        VertexInfo vertexInfo = 
baseGraphInfoLoader.buildVertexInfoFromGraphYaml(vertexYaml);
+        Assert.assertEquals(URI.create("file:///graphar/vertex/person/"), 
vertexInfo.getBaseUri());
+        // absolute paths
+        Assert.assertEquals(
+                URI.create("file:///graphar/vertex/person/id/"),
+                
vertexInfo.getPropertyGroupPrefix(vertexInfo.getPropertyGroups().get(0)));
+        // relative paths
+        Assert.assertEquals(
+                
URI.create("file:///tmp/vertex/person/firstName_lastName_gender/chunk0"),
+                
vertexInfo.getPropertyGroupChunkPath(vertexInfo.getPropertyGroups().get(1), 0));
+    }
+}
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
deleted file mode 100644
index 00272042..00000000
--- 
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphLoaderTest.java
+++ /dev/null
@@ -1,61 +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;
-
-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/TestUtil.java 
b/maven-projects/info/src/test/java/org/apache/graphar/info/TestUtil.java
index ab56dc1c..c8c84900 100644
--- 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
@@ -19,6 +19,7 @@
 
 package org.apache.graphar.info;
 
+import java.net.URI;
 import java.util.List;
 import org.apache.graphar.info.type.AdjListType;
 import org.apache.graphar.info.type.DataType;
@@ -40,6 +41,10 @@ public class TestUtil {
         return getTestData() + "/" + LDBC_SAMPLE_GRAPH_PATH;
     }
 
+    public static URI getLdbcSampleGraphURI() {
+        return URI.create(getLdbcSampleGraphPath());
+    }
+
     public static final AdjacentList orderedBySource =
             new AdjacentList(AdjListType.ordered_by_source, FileType.CSV, 
"ordered_by_source/");
     public static final AdjacentList orderedByDest =
@@ -123,7 +128,7 @@ public class TestUtil {
                         .srcChunkSize(100)
                         .dstChunkSize(100)
                         .directed(false)
-                        .prefix("edge/person_knows_person/")
+                        .baseUri(URI.create("edge/person_knows_person/"))
                         .version("gar/v1")
                         .adjacentLists(List.of(orderedBySource, orderedByDest))
                         .addPropertyGroups(List.of(pg3))
@@ -145,4 +150,116 @@ public class TestUtil {
         }
         Assume.assumeTrue("GAR_TEST_DATA is not set", GAR_TEST_DATA != null);
     }
+
+    public static String getBaseGraphInfoYaml() {
+        return "type: person\n"
+                + "chunk_size: 100\n"
+                + "prefix: vertex/person/\n"
+                + "property_groups:\n"
+                + "  - properties:\n"
+                + "      - name: id\n"
+                + "        data_type: int64\n"
+                + "        is_primary: true\n"
+                + "        is_nullable: false\n"
+                + "    prefix: id/\n"
+                + "    file_type: csv\n"
+                + "  - properties:\n"
+                + "      - name: firstName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: lastName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: gender\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "        is_nullable: true\n"
+                + "    prefix: /tmp/vertex/person/firstName_lastName_gender/\n"
+                + "    file_type: csv\n"
+                + "version: gar/v1\n";
+    }
+
+    public static String getS3GraphInfoYaml() {
+        return "type: person\n"
+                + "chunk_size: 100\n"
+                + "prefix: s3://graphar/vertex/person/\n"
+                + "property_groups:\n"
+                + "  - properties:\n"
+                + "      - name: id\n"
+                + "        data_type: int64\n"
+                + "        is_primary: true\n"
+                + "        is_nullable: false\n"
+                + "    prefix: id/\n"
+                + "    file_type: csv\n"
+                + "  - properties:\n"
+                + "      - name: firstName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: lastName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: gender\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "        is_nullable: true\n"
+                + "    prefix: 
s3://tmp/vertex/person/firstName_lastName_gender/\n"
+                + "    file_type: csv\n"
+                + "version: gar/v1\n";
+    }
+
+    public static String getHdfsGraphInfoYaml() {
+        return "type: person\n"
+                + "chunk_size: 100\n"
+                + "prefix: hdfs://graphar/vertex/person/\n"
+                + "property_groups:\n"
+                + "  - properties:\n"
+                + "      - name: id\n"
+                + "        data_type: int64\n"
+                + "        is_primary: true\n"
+                + "        is_nullable: false\n"
+                + "    prefix: id/\n"
+                + "    file_type: csv\n"
+                + "  - properties:\n"
+                + "      - name: firstName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: lastName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: gender\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "        is_nullable: true\n"
+                + "    prefix: 
hdfs://tmp/vertex/person/firstName_lastName_gender/\n"
+                + "    file_type: csv\n"
+                + "version: gar/v1\n";
+    }
+
+    public static String getFileGraphInfoYaml() {
+        return "type: person\n"
+                + "chunk_size: 100\n"
+                + "prefix: file:///graphar/vertex/person/\n"
+                + "property_groups:\n"
+                + "  - properties:\n"
+                + "      - name: id\n"
+                + "        data_type: int64\n"
+                + "        is_primary: true\n"
+                + "        is_nullable: false\n"
+                + "    prefix: id/\n"
+                + "    file_type: csv\n"
+                + "  - properties:\n"
+                + "      - name: firstName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: lastName\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "      - name: gender\n"
+                + "        data_type: string\n"
+                + "        is_primary: false\n"
+                + "        is_nullable: true\n"
+                + "    prefix: 
file:///tmp/vertex/person/firstName_lastName_gender/\n"
+                + "    file_type: csv\n"
+                + "version: gar/v1\n";
+    }
 }


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

Reply via email to